Standalone Subscription Payments |
This topic contains the following sections:
This article contains details on how to perform a standalone credit card payment on a subscription.
It's possible to perform standalone payments on unpaid invoices (PerformInvoicePayment), and also as "one-off" payments of arbitrary amounts (PerformBalancePayment).
If a subscription has an active payment agreement, invoices will automatically be paid at regular intervals. It shouldn't normally be necessary for the end user to perform standalone payments in this case, although there's no reason why the functionality shouldn't still be offered for them. Standalone payments are most likely to be useful for users who want to pay with a credit card, but who want to do it themselves.
Currently it's always necessary for the customer to have a credit card agreement to perform a standalone payment, but it isn't necessary for that agreement to be associated with the subscription. For details on how to create an agreement that isn't associated with a subscription, see Credit Card Agreements.
The user can pay for an unpaid invoice using the PerformInvoicePayment method. For details on how to retrieve the invoices of a subscription, see Subscription Invoices. Note that the invoice must be in the "invoiced" state for the payment to be possible. It isn't possible to pay an invoice that's already been paid, or an invoice that's been eliminated. If an attempt is made to pay a paid or eliminated invoice, an InvoiceCannotBePaidFault will be thrown. To determine if the invoice is in the invoiced state, verify that the IsPaid field is false and that the EliminationDate field is not set.
To call PerformInvoicePayment you will need an invoice number, a payment agreement ID and a title code. The invoice must belong to the same customer that owns the payment agreement; otherwise a PaymentAgreementSubscriptionMismatchFault will be thrown.
For the following example we'll assume that the customer with the unique number 1000 has a subscription on the title TEST, an unpaid invoice with the unique number 1234, and a payment agreement with the ID 9876.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://tech.infosoft.no/schemas/2012/08"> <soapenv:Header/> <soapenv:Body> <ns:PerformSubscriptionInvoicePaymentRequest> <ns:PaymentAgreementId>9876</ns:PaymentAgreementId> <ns:TitleCode>TEST</ns:TitleCode> <ns:InvoiceNumber>1234</ns:InvoiceNumber> </ns:PerformSubscriptionInvoicePaymentRequest> </soapenv:Body> </soapenv:Envelope>
Assuming the payment goes well, the response should look something like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <SubscriptionInvoicePaymentResponse xmlns="http://tech.infosoft.no/schemas/2012/08"> <PaymentResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <InvoiceNumber>1234</InvoiceNumber> <TitleCode>TEST</TitleCode> <CustomerNumber>1000</CustomerNumber> <CustomerName>TEST PERSON</CustomerName> <CaptureResult>Success</CaptureResult> <AttemptNumber>1</AttemptNumber> <AttemptTime>2015-05-05T10:49:38.2525764+02:00</AttemptTime> <CapturedAmount>500</CapturedAmount> <TaxPercent>0</TaxPercent> <CaptureFaultDescription i:nil="true"/> <SaveFaultDescription i:nil="true"/> <PaymentOrderReference>1</PaymentOrderReference> <ProviderOrderReference i:nil="true"/> <ProviderTransactionReference>5810323</ProviderTransactionReference> <AccountedDate>2015-05-11T00:00:00+02:00</AccountedDate> </PaymentResult> </SubscriptionInvoicePaymentResponse> </s:Body> </s:Envelope>
PerformInvoicePayment can fail with various faults. The faults and underlying reasons are detailed in the below table. For general information, refer to the Payment API error handling article and the Troubleshooting and Logging article.
Fault | Cause |
---|---|
Usually caused by connection issues between the InfoSystems API and the database. | |
This may happen in rare cases where the invoice is being modified elsewhere at the same time that the payment is being performed. | |
No title was found with the given code. | |
No payment agreement was found with the given ID. | |
No invoice was found with the given number, on the given title. | |
The payment agreement and invoice both exist, but the agreement doesn't belong to the customer that owns the invoice. | |
The invoice has been eliminated, has already been paid, or is in some other invalid state. |
Even if no fault is given, it doesn't necessarily mean that the payment was successful. If the payment failed, the CaptureResult field should be something else than Success. The most typical reason for this is that the agreement is somehow invalid. In that case the response should look like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <SubscriptionInvoicePaymentResponse xmlns="http://tech.infosoft.no/schemas/2012/08"> <PaymentResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <InvoiceNumber>1234</InvoiceNumber> <TitleCode>TEST</TitleCode> <CustomerNumber>1000</CustomerNumber> <CustomerName>TEST PERSON</CustomerName> <CaptureResult>ProviderCaptureFailure</CaptureResult> <AttemptNumber>1</AttemptNumber> <AttemptTime>2015-05-05T10:53:53.9623453+02:00</AttemptTime> <CapturedAmount>0</CapturedAmount> <TaxPercent>0</TaxPercent> <CaptureFaultDescription>The call to AutoPay3 failed</CaptureFaultDescription> <SaveFaultDescription i:nil="true"/> <PaymentOrderReference>2</PaymentOrderReference> <ProviderOrderReference i:nil="true"/> <ProviderTransactionReference i:nil="true"/> <AccountedDate i:nil="true"/> </PaymentResult> </SubscriptionInvoicePaymentResponse> </s:Body> </s:Envelope>
Unfortunately it's often quite difficult to determine the reason for the failure. If the CaptureResult is ProviderCaptureFailure, as in the above example, it usually means that there's a problem with the customer's credit card or bank account. However, it could also indicate a error in the configuration of the payment setup, such as an invalid encryption key. If the CaptureResult is SaveFailure it indicates an error in the InfoSystems Payment API, which should be reported as soon as possible.
When the payment fails the CaptureFaultDescription field should contain an error message, but that error message is unlikely to make any sense to the end user. It's recommended that you log failed captures in the same manner as SOAP faults.
The user can perform arbitrary payments using the PerformBalancePayment method. The typical way to implement this will be to let the user enter the amount to pay in a text field, or alternatively to restrict the user to a predetermined list of payment amounts.
To call PerformBalancePayment you will need a payment agreement ID, a title code, a customer number and an amount to pay. The payment agreement must belong to the given customer, and the customer must have a subscription on the given title. The subscription does not need to be currently active.
For the following example we'll assume that the customer with the unique number 2000 has a subscription on the title TEST, and a payment agreement with the ID 8765.
Caution |
---|
As in other parts of the InfoSystems Payment API, the amount should be given in the smallest possible units. This means that the input value of 2500 in the below example translates to e.g. $25.00, if the currency is dollars. |
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://tech.infosoft.no/schemas/2012/08"> <soapenv:Header/> <soapenv:Body> <ns:PerformSubscriptionBalancePaymentRequest> <ns:PaymentAgreementId>8765</ns:PaymentAgreementId> <ns:CustomerNumber>2000</ns:CustomerNumber> <ns:TitleCode>TEST</ns:TitleCode> <ns:Amount>2500</ns:Amount> <!-- Note! Smallest possible units! --> <ns:Signature>INFOSOFT EXAMPLE</ns:Signature> </ns:PerformSubscriptionBalancePaymentRequest> </soapenv:Body> </soapenv:Envelope>
The Signature parameter is optional. It may be used in certain cases as a "source" for changes that are registered in the InfoSystems database, so it's recommended that you set it to a value that identifies the name of your client.
If the payment is successful, the response should be very similar to the one from PerformInvoicePayment:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <SubscriptionInvoicePaymentResponse xmlns="http://tech.infosoft.no/schemas/2012/08"> <PaymentResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <InvoiceNumber>1235</InvoiceNumber> <TitleCode>TEST</TitleCode> <CustomerNumber>2000</CustomerNumber> <CustomerName>TEST PERSON</CustomerName> <CaptureResult>Success</CaptureResult> <AttemptNumber>1</AttemptNumber> <AttemptTime>2015-05-05T11:30:33.1101817+02:00</AttemptTime> <CapturedAmount>25</CapturedAmount> <!-- Note that this field is _not_ given in the smallest possible units. --> <TaxPercent>0</TaxPercent> <CaptureFaultDescription i:nil="true"/> <SaveFaultDescription i:nil="true"/> <PaymentOrderReference>3</PaymentOrderReference> <ProviderOrderReference i:nil="true"/> <ProviderTransactionReference>5810690</ProviderTransactionReference> <AccountedDate>2015-05-11T00:00:00+02:00</AccountedDate> </PaymentResult> </SubscriptionInvoicePaymentResponse> </s:Body> </s:Envelope>
Of note here is the fact that the payment is associated with an invoice with the invoice number 1235 even though we used PerformBalancePayment. This is because whenever this method is used, an ad-hoc invoice is created behind the scenes. If the payment succeeds, the invoice is immediately marked as paid, and will later appear in the invoice history of the subscription. If the payment fails, the invoice is automatically eliminated.
If the subscription has an existing unpaid invoice when the operation is started, it will always be eliminated -- even if the payment fails. This is a consequence of the business rules of the InfoSystems software.
PerformBalancePayment can fail with various faults. The faults and underlying reasons are detailed in the below table. For general information, refer to the Payment API error handling article and the Troubleshooting and Logging article.
Fault | Cause |
---|---|
Usually caused by connection issues between the InfoSystems API and the database. | |
This may happen in rare cases where the invoice is being modified elsewhere at the same time that the payment is being performed. | |
The given amount to pay is smaller than or equal to zero. | |
No title was found with the given code. | |
No payment agreement was found with the given ID. | |
The customer that owns the agreement does not have a subscription (active or passive) on the given title. | |
The requested payment amount is smaller than the configured minimum amount allowed for the title and payment type. |
Note |
---|
Of special note is BalancePaymentTooSmallFault. This will happen if the amount passed to PerformBalancePayment is lower than the lowest amount configured for the title and payment type. The webpage where the user enters the amount to pay should therefore preferably prevent the user from entering amounts that are too small, before the request to PerformBalancePayment is made. Note that there's currently no way to retrieve this minimum amount through the API. |
Almost everything said about capture errors for PerformInvoicePayment applies here as well. As with the other method, it's always necessary to check the CaptureResult field on the PaymentResult to determine if the payment was successful.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <SubscriptionInvoicePaymentResponse xmlns="http://tech.infosoft.no/schemas/2012/08"> <PaymentResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <InvoiceNumber>1236</InvoiceNumber> <TitleCode>TEST</TitleCode> <CustomerNumber>2000</CustomerNumber> <CustomerName>TEST PERSON</CustomerName> <CaptureResult>ProviderCaptureFailure</CaptureResult> <AttemptNumber>1</AttemptNumber> <AttemptTime>2015-05-05T12:30:48.2669918+02:00</AttemptTime> <CapturedAmount>0</CapturedAmount> <TaxPercent>0</TaxPercent> <CaptureFaultDescription>The call to AutoPay3 failed</CaptureFaultDescription> <SaveFaultDescription i:nil="true"/> <PaymentOrderReference>4</PaymentOrderReference> <ProviderOrderReference i:nil="true"/> <ProviderTransactionReference i:nil="true"/> <AccountedDate i:nil="true"/> </PaymentResult> </SubscriptionInvoicePaymentResponse> </s:Body> </s:Envelope>
Note that an invoice with the number 1236 has in fact been created in this case, but since the payment failed it was immediately eliminated. This makes it easy to see past balance payment attempts.