Cashflows Gateway Guide
To enable you to connect your payment processing system with the Cashflows Gateway, we offer our Cashflows Gateway API. By using our Cashflows Gateway API, you can integrate with all of the functionality that comes with our gateway for processing online payments. We take care of many of the technical and security complexities. This can save you time and money.
Our Cashflows Gateway API includes calls for:
A range of transaction types that put you in control. For a smooth customer experience you can send us a request to authorise and capture funds together. Alternatively, you can send a request to reserve funds and defer the final payment until a customer is ready to pay for the service that they’ve received.
Authorisation only. This is useful for reserving or ring-fencing funds for collection (capture) at a later date.
Separate Authorisation and Final capture. You can defer a payment until a customer is ready to pay for a product or service. For more information, see Capture requests.
Mail or telephone (MOTO) payments For more information, see How to request a MOTO payment.
Payment links that can be embedded into invoices, text messages and social media posts. For more information, see Managing payment links.
Refunds and cancellations For more information, see Refund requests and Cancellation requests.
Payments that need to include extra details if a business is a financial organisation. For more information, see Additional details required for financial institutions.
Automating day-to-day tasks with recurring payments. For more information, see Recurring payments.
Securely storing card details for a customer’s online account or for when they return to your website for future purchases. For more information, see Stored card details.
Retrieving the full range of available payment methods that our gateway offers. This includes the logos and icons to display. For more information, see How to retrieve details of supported payment methods.
Fraud prevention checks. Our gateway ensures compliance and validation for each transaction request. It also offers, as standard, an extra security layer with built-in 3-D Secure authentication and authorisation checks. Our gateway includes 3-D Secure services (up to version 2.2). We also have a 3D Secure simulator that you can use for testing your integration.
For recurring transactions Cashflows Gateway supports requests for exemption from strong customer authentication (SCA).
Multiple payment methods for your checkout page. With a single API call you can retrieve the full range of available payment methods that our Cashflows gateway offers. This includes the logos to display. If we add a payment method to the gateway, you can automatically offer it on a website checkout page without any extra development effort. For more information, see How to retrieve details of supported payment methods.
Note
You or the business owner can choose which of the available payment methods to display on the checkout page. This is done in Cashflows Portal. For more information, see the Cashflows Portal guide.
How it works
This section illustrates how our Cashflows Gateway processes a payment when a customer pays for a product or service. This all happens in about one second.
The first diagram shows the high-level payment flow in terms of a shopping experience. The diagram that follows shows more detail with API calls that you’ll be using to integrate your website with our gateway.
A customer starts the checkout process on your website when they choose to pay.
The customer securely enters their card details.
Your website sends a payment request to our online payment servers to initiate the transaction. The request includes the card details.
We receive the request with the card details.
- We check whether it’s a MOTO payment.
If it is a MOTO payment, we process the payment. If it isn’t, we check whether the card is enrolled for 3-D Secure checks.
If the card is enrolled for 3-D Secure, we send you a link to the 3-D Secure page. This is where you need to direct the customer so that they can enter their 3-D Secure details.
If the card is not enrolled for 3-D Secure, we check whether 3-D Secure is required for this card.
If 3-D Secure is required, we decline the payment.
If 3-D Secure is not required, we process the payment.
We notify you about the change of status for the payment.
You fetch the latest status so that you can update the shopper’s order and arrange delivery.
We direct the customer back to your website via a corresponding web page (successful or failed).
Tip
For security reasons, we recommend that you update an order only when you receive the payment status notification from us. A notification from our Cashflows Gateway assures you that a payment request has not been intercepted during transfer.
Here is a diagram to show the payment flow with the key API calls. This guide explains the API calls to use at each stage of the process with example code for you to use.
Important
The capitalisation of API calls is important. Always use the same capitalisation as the examples that we provide.
Protecting customers from fraud
Our Cashflows Gateway has built-in fraud prevention in the form of 3 D Secure (3DS). 3DS is an - industry-standard for ensuring Strong Customer Authentication (SCA). SCA is used by the payments industry to ensure that online transactions are secure and legitimate.
For more information about 3DS, refer to:
3DS requires that some transactions include a challenge to customers to provide extra proof that they are authentic. For some types of low risk transactions, it’s possible to request exemtpion from these extra checks. Our Cashflows Gateway currently supports exemptions for recurring Mastercard and Visa transactions. For more information, see Recurring payments.
Generate your Gateway API signature
As with all API calls you will need to send a request signature with any requests.
To ensure server to server messages have been issued by valid users, request messages must be signed. The Hash
field is a SHA2-512 hash calculated by concatenating your security token with a string of the request
object. If you don’t have your security token please contact your Implementation Manager.
If the signature is incorrect, an error will be returned. Repeated failures will lock your account, if this happens, please contact your Implementation Manager.
SHA2-512 hash of your request. To generate your hash, concatenate the message body of your request to the API key to give one long string.
Warning
Whitespace and new lines in the request object are included in the hash calculation. We use CR-LF for line breaks, however Unix systems often use just LF, and this can affect calculations. If you can’t match signatures but have the correct password hash, remove unnecessary whitespace from your Request nodes.
After applying a SHA2-512 hash, the concatenated string would look like:
3CDF192F6AC67E3A491EF2B60EA9A03C6B408056CE19C3BBC307EB06A4CE1F4081B8D 021B1E9760E7CC18EED479EDBAFF926DADC2953B5F8B25717B8D5CB7609
Finally, add the generated key as the Hash
value in your request:
{
"ConfigurationID": "YOUR_CONFIGURATION_ID",
"Hash": "YOUR_HASH",
"Request": {
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23"
},
"order": {
"orderNumber": "Payment ref D1"
},
"currency": "GBP",
"amountToCollect": "10.00"
},
}
HTTP Headers
When making a request to the Cashflows Gateway you must provide your ConfigurationId
and Hash
in the header of your request. This enables the gateway to identify your business and the configuration options of your integration.
Header parameters:
Parameter |
Description |
Mandatory/Optional |
|
---|---|---|---|
|
Your configuration ID. |
Mandatory |
|
|
A hexadecimal sha512 hash of your password plus the body. |
Mandatory |
|
|
A string describing where a request is sent from, i.e.
|
Optional |
|
|
A string describing where the payment data was collected, i.e.
|
Optional |
The RequestOrigin
and PaymentDataOrigin
are optional fields used to identify the source a transaction and its data. Although not mandatory, we recommend providing both the RequestOrigin
and PaymentDataOrigin
fields to assist Cashflows in supporting your account.
Example RequestOrigin
fields
Origin |
Recommended string |
---|---|
Cashflows Gateway API |
|
WooCommerce |
|
Magento |
|
Example PaymentDataOrigin
fields
Origin |
Recommended string |
---|---|
Hosted Payment Page |
|
WooCommerce |
|
Magento |
|
Example HTTP headers
headers = {
'Hash': 'YOUR_CONFIGURATION_ID',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'RequestOrigin': 'API'
'PaymentDataOrigin': 'HostedPaymentPage'
'Content-Type': 'application/json'
}
Payment methods
When your website is integrated with our gateway, customers see a section in the checkout page where they can choose how they want to pay, for example by card or an alternative method that they prefer.
The Cashflows Gateway API includes a call that you can use to retrieve all of the payment methods that our gateway supports and present them for selection in your website. With a single API call you can automatically retrieve the full list of payment methods, together with logos and icons, instead of having to hard code each one. By using this call and the response results, you can avoid extra work in the future. When we add new payment methods, they will automatically be added to the list of payment options available on your website.
Important
Before you can display any payment methods on a checkout page, you need to enable them in Cashflows Portal.
How to retrieve supported payment methods
The API call to retrieve the payment methods is SupportedPaymentMethods
. This call retrieves from the gateway all supported payment methods at once, including the logos and icons that represent each method, surcharges and so on.
You must encrypt the message with the API key that you collected from Cashflows Portal. For more information, see the Cashflows Gateway integration guide.
Example request:
GET https://gateway-int.cashflows.com/api/gateway/supported-payment-methods
Example response:
{
"data": [
{
"paymentMethod": "Card",
"logo": "https://gateway-int.cashflows.com/assets/payment-method-card.svg",
"issuerList": [],
"supportsTokenisation": true,
"tokenizedCards": [],
"currencies": [
"NoCurrencyCashflows",
"AUD",
"CAD",
"DKK",
"HKD",
"JPY",
"NZD",
"NOK",
"SGD",
"ZAR",
"SEK",
"CHF",
"GBP",
"USD",
"EUR",
"XXX"
],
"description": "Card Simulator"
},
{
"paymentMethod": "CreditCard",
"logo": "https://gateway-int.cashflows.com/assets/payment-method-card.svg",
"issuerList": [],
"supportsTokenisation": true,
"tokenizedCards": [],
"currencies": [
"NoCurrencyCashflows",
"AUD",
"CAD",
"DKK",
"HKD",
"JPY",
"NZD",
"NOK",
"SGD",
"ZAR",
"SEK",
"CHF",
"GBP",
"USD",
"EUR",
"XXX"
],
"description": "Card Simulator"
}
]
}
Payment requests
So that we can process an online payment, your website needs to send an API payment request to our online payment servers to initiate the transaction.
You send us the payment transaction details in an API message. The message needs to submit a payment request to create a payment job with the details of the transaction. For a card payment, the request needs to include the card details.
Important
For a card that is enrolled for 3-D Secure version 2.2, the cardholder name is required.
For all types of payment, we then send you a link to direct the customer to our gateway’s 3-D Secure page. This page is where the customer securely enters their 3-D Secure details. We carry out 3-D Secure checks and, depending on the result of the checks, we accept the transaction for payment processing or decline it with a response code to indicate why.
You must encrypt the message with the API key that you collected from Cashflows Portal. For more information, see the Cashflows Gateway integration guide.
You must use the same hashing technique that we do so that we can match our hash with yours. The hash assures message consistency and protects the payment request from being tampered with during transfer to our Cashflows gateway (a man-in-the-middle attack). For more information, see the Cashflows Gateway integration guide.
The process for submitting a payment request involves the following steps. These steps are described in the sections that follow:
Create a payment job. This is a server-to-server call from your server to ours. After you have submitted the payment job, the Cashflows Gateway API returns a 201 response ‘Payment job created successfully’ (assuming that the request was successful).
Receive the payment job details in the response to the payment job. The API returns specific payment and order information plus a link (action URL) to determine the next stage of the payment processing. For card payments, the next step is usually 3-D Secure checking. Therefore, this link is likely to be a link to a 3-D Secure page. For more information, see How to receive a response to a payment request and redirect a customer.
If 3-D Secure is enabled, use the link to direct the customer to our 3-D Secure page where they can enter their extra security details. For more information, see How to receive a response to a payment request and redirect a customer.
How to create a payment job
To create a payment job, you must provide a payment job request that contains at least the mandatory required fields. To help you track payments, we recommend that you provide more than the mandatory fields in the payment job. As a minimum, consider including:
Payment amount (mandatory)
Currency
Order reference (the reference that you generate)
Customer name
Customer email
Tip
As a starting point to establish and test connectivity, it’s good enough to provide only the mandatory information. You can then add details as required to build out the payment job request. To make it easier for you to identify a payment, we recommend that you include as much information as possible. Our API includes many more details including billing/shipping details, order line details and more.
To create a payment job:
In the request header, provide your configuration ID and a hash. Your configuration ID identifies your application to the gateway and is available in Cashflows Portal.
Concatenate the message body to the API key to give one long string. For example, to use an example API key like this:
845c51f6-1cd5-4338-a586-df752e65d690
To submit to the Cashflows API the following fields and values:amountToCollect": "10.00", "currency": "GBP", "locale": "en_GB"
You would concatenate with the API key to give:845c51f6-1cd5-4338-a586-df752e65d690{"amountToCollect": "10.00", "currency": "GBP", "locale": "en_GB" }
Hash the concatenated string to give, for example:
3CDF192F6AC67E3A491EF2B60EA9A03C6B408056CE19C3BBC307EB06A4CE1F4081B8D 021B1E9760E7CC18EED479EDBAFF926DADC2953B5F8B25717B8D5CB7609
Important
Every field and value that you send, and every parenthesis, must be included in the hash.
The resulting headers must match the format of this example:
ConfigurationId:201226100000131072 Hash:3CDF192F6AC67E3A491EF2B60EA9A03C6B408056CE19C3BBC307EB06A4CE1F40
81B8D021B1E9760E7CC18EED479EDBAFF926DADC2953B5F8B25717B8D5CB7609
Example: Create a new payment job
Sent with: POST https://gateway-int.cashflows.com/api/gateway/payment-jobs
Example payment job request
import requests
import json
# Define the API endpoint
url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs"
# Define the payload (data to send with the request)
payload = json.dumps({
"amountToCollect": "15.50",
"currency": "GBP"
})
# Define the headers
headers = {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
}
# Send the POST request to the API
response = requests.post(url, headers=headers, data=payload)
# Print the response text (or handle it as needed)
if response.status_code == 200:
print("Request was successful!")
print("Response: ", response.json()) # Assuming the server returns JSON data
else:
print(f"Request failed with status code {response.status_code}")
print("Response Text: ", response.text)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpHeaders;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
String payload = "{ \"amountToCollect\": \"15.50\", \"currency\": \"GBP\" }";
// Setting the headers
Map<String, String> headers = new HashMap<>();
headers.put("Hash", "YOUR_SIGNATURE_HASH");
headers.put("ConfigurationId", "YOUR_CONFIGURATION_ID");
headers.put("Content-Type", "application/json");
// Create HTTP client
HttpClient client = HttpClient.newHttpClient();
// Build the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Hash", headers.get("Hash"))
.header("ConfigurationId", headers.get("ConfigurationId"))
.header("Content-Type", headers.get("Content-Type"))
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
// Send the request and get the response
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Print the response
System.out.println(response.body());
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
var payload = "{\"amountToCollect\": \"15.50\", \"currency\": \"GBP\"}";
var client = new HttpClient();
// Setting the headers
client.DefaultRequestHeaders.Add("Hash", "YOUR_SIGNATURE_HASH");
client.DefaultRequestHeaders.Add("ConfigurationId", "YOUR_CONFIGURATION_ID");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
// Sending the POST request
var response = await client.PostAsync(url, content);
// Reading and printing the response
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
}
const axios = require('axios');
const url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs';
const payload = {
amountToCollect: "15.50",
currency: "GBP"
};
const headers = {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
};
axios.post(url, payload, { headers })
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error.response ? error.response.data : error.message);
});
<?php
$url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs';
$data = array(
'amountToCollect' => '15.50',
'currency' => 'GBP'
);
// Convert data array to JSON
$jsonData = json_encode($data);
// Set headers
$headers = array(
'Hash: YOUR_SIGNATURE_HASH',
'ConfigurationId: YOUR_CONFIGURATION_ID',
'Content-Type: application/json'
);
// Initialize cURL session
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
// Execute the request
$response = curl_exec($ch);
// Check for errors
if(curl_errno($ch)) {
echo 'cURL Error: ' . curl_error($ch);
} else {
echo $response; // Print the response
}
// Close the cURL session
curl_close($ch);
?>
require 'net/http'
require 'json'
require 'uri'
# URL for the API endpoint
url = URI.parse('https://gateway-inta.cashflows.com/api/gateway/payment-jobs')
# Payload (data to be sent)
payload = {
amountToCollect: "15.50",
currency: "GBP"
}.to_json
# Headers
headers = {
'Hash' => 'YOUR_SIGNATURE_HASH',
'ConfigurationId' => 'YOUR_CONFIGURATION_ID',
'Content-Type' => 'application/json'
}
# Create a new HTTP request
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.path, headers)
request.body = payload
# Send the request and get the response
begin
response = http.request(request)
# Print the response body
puts response.body
rescue StandardError => e
# Print error message if request fails
puts "Error: #{e.message}"
end
Example payment job message body
{
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23"
},
"order": {
"orderNumber": "Payment ref D1"
},
"currency": "GBP",
"amountToCollect": "10.00"
}
Required fields
Field |
Description |
---|---|
amountToCollect |
The total value of the payment transaction. |
currency |
The transaction currency |
cardHolderName |
The name of the customer. Required for transactions that need to have 3DS checks applied. A request without a cardholderName, will result in an error response. |
Optional fields
Field |
Description |
---|---|
orderNumber |
The order number address of the customer. |
customerEmail |
The email address of the customer. |
locale |
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
If your language is not available, please choose the most appropriate language for your customers. |
Tip
Including optional customer and delivery details in your payment request enables us to display this information in Cashflows Portal, for example in the transaction details and reports. This can make it easier for you to locate payments and help with reconciliation. The extra detail can also help our Customer Support team to find a payment it ever needs investigating.
External 3DS v2 solutions
If you’re using a third party to provide your 3DS v2 solution then you need to also submit these parameters when creating a payment job:
ThreeDSecureVersion
ThreeDSecureCavv
ThreeDSecureEci
ThreeDSecureDSTransId
If you wish to use an external 3DS solution we recommend contacting our support team (techsupport@cashflows.com) to enable the External MPI Provider flag on your account. If this is not enabled, the gateway may attempt to perform 3DS on card transactions using our own solution
If multiple payment methods are enabled while External MPI Provider is enabled, the create payment job request needs to specify the desired payment method with the paymentMethodsToUse
field. All payment details need to be provided in the request, so you must submit all available parameters for that payment request.
Note
Once enabled, the External MPI Provider flag will make Virtual Terminal payments unavailable.
Click to expand example
{
"amountToCollect": "10",
"currency": "GBP",
"parameters": {
"CardNumber": "5400100400099001",
"CardHolderName": "Han Solo",
"CardExpiryYear": "25",
"CardExpiryMonth": "12",
"CardCvc": "123",
"ThreeDSecureVersion": "2.2.0",
"ThreeDSecureCavv": "5dc4a6a39b6730a360e42c3b5f+=",
"ThreeDSecureEci": "02",
"ThreeDSecureDSTransId": "c5b808e7-1de1-4069-a17b-f70d3b3b1645",
"ReturnUrlCancelled": "https://example.com?result=canceled",
"ReturnUrlFailed": "https://example.com?result=failed",
"ReturnUrlSuccess": "https://example.com?result=success"
},
"paymentMethodsToUse": [
"card"
]
}
eWallet external 3DS v2
Valid EwalletType
fields:
ApplePay
GooglePay
SamsungPay
Other
Click to expand example
{
"amountToCollect": "10",
"currency": "GBP",
"parameters": {
"CardNumber": "5400100400099001",
"CardHolderName": "Han Solo",
"CardExpiryYear": "25",
"CardExpiryMonth": "12",
"EwalletType": "ApplePay",
"ThreeDSecureCavv": "5dc4a6a39b6730a360e42c3b5f+=",
"ThreeDSecureEci": "02",
"ReturnUrlCancelled": "https://example.com?result=canceled",
"ReturnUrlFailed": "https://example.com?result=failed",
"ReturnUrlSuccess": "https://example.com?result=success"
},
"paymentMethodsToUse": [
"card"
]
}
PAN CV2less
PAN CV2less payments are streamlined, secure payments that remove the need for a Card Verification Code through the use of stored credentials.
To make a PAN CV2less payment you must use 3DS v2 and pass through the UsingStoredCredentials
option when sending the payment request:
Click to expand example
{
"amountToCollect": "10",
"currency": "GBP",
"parameters": {
"CardNumber": "4510500400099002",
"CardHolderName": "Han Solo",
"CardExpiryYear": "2028",
"CardExpiryMonth": "12",
"ThreeDSecureVersion": "2.1.0",
"ThreeDSecureCavv": "0H4G2ZcW398zA1Q8XyAI70H7nXY=",
"ThreeDSecureEci": "05",
"ThreeDSecureDSTransId": "111dc9c3-6644-4164-9661-3afa0e8f64e1",
"ReturnUrlCancelled": "https://example.com?result=canceled",
"ReturnUrlFailed": "https://example.com?result=failed",
"ReturnUrlSuccess": "https://example.com?result=success"
},
"paymentMethodsToUse": [
"card"
],
"options":[
"UsingStoredCredentials"
]
}
Additional details required for financial institutions
To comply with financial regulations, a payment request from a financial institution needs to include some extra information about the person who is receiving the funds. You need to include the extra details in the recipientDetails object when you create a new payment job, a MOTO payment job a parent payment job, or a recurring payment job.
Note
For MCC 6012 payments, we advise that you check the card type as credit cards are not accepted.
Example request
{
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"currency": {
"amountToCollect": "10.00",
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23",
"cardHolderName": "Jon Snow",
"mcc":"6012",
"recipientDetails": "{\"lastname\":\"Smith\",\"dateOfBirth\":\"1980-07- 29T23:00:00.000Z\",\"postcode\":\"CB21 5XE\",\"primaryAccountNumber\":\"111213313\"}"
}
}
}
Field |
Description |
---|---|
lastname |
The family name or last name of the person who is receiving the funds (2-64 alphabetic characters, including - ). |
dateOfBirth |
The date of birth of the person who is receiving the funds, in the format YYYYMMDD (8 digits). |
postcode |
The postcode of the person who is receiving the funds (2 to 16 alphabetic characters, including spaces). |
primaryAccountNumber |
The account number of the person who is receiving the funds. The account number must be in a valid format which is 1 to 32 alphanumeric characters which can include / and -. The account number cannot include spaces. For a card number, use the first six digits and the last four digits. |
How to receive a response to a payment request and redirect a customer
The gateway receives the payment request and responds with:
A response code (to confirm success or otherwise)
A link that points to the action URL where you should direct the customer.
Here is an example with the action URL, (in this case a 3-D Secure page) highlighted:
If the request is successful, you receive a 201 response.
To receive the response
For a card payment, extract the link (action URL) and use it to take you to the integration environment 3-D Secure simulation page.
Our 3-D Secure simulator provides options for you to simulate different scenarios so that you can test, for example, whether a transaction passes or fails 3-D Secure checks. For more information, see the Cashflows Gateway integration guide.
Response codes
After you have submitted a request to create a payment job, the Gateway API responds with a code. Ideally the response is a success code but can be any of the following.
Code |
Description |
---|---|
201 |
Payment job created successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions |
404 |
Configuration not found. |
406 |
Bad response. |
Example response
When you send a request to create a payment job in our integration environment, you receive back a response that includes a link (action URL). For a card payment, this is usually a link to the 3-D Secure page. This is the link that you need to use to redirect the customer so that they enter their 3-D Secure details. As soon as we have the details that we need, we can process the payment.
Here is an example of the full response with the success response code included:
{
"data": {
"reference": "210221017179873304",
"createDateTimeUtc": "2021-02-18T11:04:38.2907414Z",
"type": "Payment",
"traceReference": "210220121768573008",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment ref D1",
"createDateTimeUtc": "2021-02-18T11:04:38.2907443Z",
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": [
"Card"
],
"currency": "GBP",
"amountToCollect": "10.00",
"expirationDateTimeUtc": "2021-08-18T11:04:38.2907396Z",
"dueDateTimeUtc": "2021-02-18T11:14:38.8761894Z",
"lastUpdateTimeUtc": "2021-02-18T11:04:38.2907435Z",
"lastProcessedTimeUtc": "2021-02-18T11:04:38.2907426Z",
"flags": {
"direct": true
},
"attributes": {},
"paymentStatus": "Pending",
"payments": [
{
"reference": "210221117314091036",
"createDateTimeUtc": "2021-02-18T11:04:38.4842538Z",
"paymentMethods": [
"Card"
],
"status": "Pending",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"steps": [
{
"reference": "210221204311744516",
"createDateTimeUtc": "2021-02-18T11:04:38.8763717Z",
"action": "Start",
"paymentMethods": [
"Card"
],
"status": "Pending",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221017179873304&paymentref=210221117314091036&ordernumber=Payment+ref+D1",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221017179873304&paymentref=210221117314091036&ordernumber=Payment+ref+D1",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221017179873304&paymentref=210221117314091036&ordernumber=Payment+ref+D1&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\"}"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/paymentjobs/210221017179873304",
"type": "application/json"
},
"action": {
"url": "https://gateway-int.cashflows.com/payment/formpost?ref=4ab07d818100e4880130c8e35d25ea1bc381fe26d5ff52c0c5692920446c747de8a6e94459bc22b5184f86645f275caa21e76555ba0c111cc55412948a453b6e",
"type": "text/html"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gatewayapi/documentation/index.html",
"type": "text/html"
}
}
}
}
Payment processing
When you simulate a card payment in our integration environment, the 3-D Secure simulation page is displayed.
When you simulate a successful or failed payment in our integration environment, we send you back a webhook to notify you about the payment status change, for example when the payment changes from Pending to Paid. If you haven’t already done so, you need to tell us where to send these notification webhooks. For more information, see the Cashflows Gateway integration guide.
You can then use the paymentJobReference
and paymentReference
from the notification webhook to check the status of the order, update your system or database and continue with your own business processes for arranging fulfilment.
Tip
For security reasons, we recommend that you update an order only when you receive the payment status notification from us. A notification from our Cashflows Gateway assures you that a payment request has not been intercepted during transfer. For additional security, we recommend matching the references provided by the webhook with the references stored by your system during creation of the payment job.
When we direct customers s back to your website after we finish processing their payments, we direct them back to the confirmation webpage that corresponds to the status of their payment (successful or failed). By default, we use the addresses of the pages (return URLs) that you set up in Cashflows Portal.
If your business has more than one website for selling different things, you can override the default address and tell us to use a different one that you specify in the payment job request.
How to override a default return address
When you use our Cashflows Gateway, we provide default pages to display when we direct a customer back to your website after a successful or failed payment. You can use these default pages, or you can display your own. You just need to set the addresses (return URLs) of the pages that you want us to display instead. You do this in Cashflows Portal. For more information, see the Cashflows Gateway integration guide.
Sometimes you might not want to use our default pages or yours. For example, if your business has more than one website for selling different things, you can override the default page. You can use an individual payment job request to tell us where to direct the customer. The shopper then returns to your website via a webpage that relates to their purchase rather than the default page.
Note
For recurring payments, you don’t need to specify a return URL at all. For more information, see Recurring payments.
To override a default return URL
Include the return URL, for example https://www.mywebshop.com?status=success, in the create payment job request.
Important
Do not update any orders based on this URL. For security reasons, we recommend that you update an order only when you receive the payment status notification (webhook) from us. A notification from our Cashflows Gateway assures you that a payment request has not been intercepted during transfer.
Example
{
"amountToCollect": "10.00",
"currency": "GBP",
"locale": "en_GB",
"order": {
"orderNumber":"Your ref1",
"billingAddress": {
"firstName": "Alex",
"lastName": "Smith"
},
"billingIdentity": {
"emailAddress": "alex@test.com"
}
},
"parameters": {
"returnUrlSuccess":
"https://www.mywebshop.com?status=success",
"returnUrlCancelled": "https://www.mywebshop.com?status=cancelled",
"returnUrlFailed": "https://www.mywebshop.com?status=failed"
}
}
Payment status updates
To notify you about a payment status update, for example when the payment changes from Pending to Paid, we send you back a webhook. The body of the notification webhook includes the paymentJobReference
and paymentReference
.
When you receive a webhook, you need to extract these details and include them in a RetrievePaymentJob API call to get the payment status.
When the payment status has been confirmed, your business systems can be updated to match. For example, if the payment status is Paid, you can store this in your database and proceed with your shipping process.
Tip
For security reasons, we recommend that you update an order only when you receive the notification webhook from us. A notification from our Cashflows Gateway assures you that a payment request has not been intercepted during transfer.
How to receive a notification webhook
We recommend that when you receive a notification webhook from us, you use it to confirm the status of the payment before you update an order.
To receive the payment status:
Extract the
paymentJobReference
andpaymentReference
from the notification webhook.Match these details with the corresponding references that you stored when you created the payment job.
Include them in a RetrievePaymentJob API call.
Gateway webhook notifications are sent from these two IP address: 54.74.58.255
and 52.215.48.101
. Depending on your firewall settings, you may wish to whitelist them.
Example RetrievePaymentJob
GET https://gateway-int.cashflows.com/api/gateway/payment-jobs/{paymentJobReference}/payments/{paymentReference}
Example response with the payment status and amount
"status": "Paid",
"amountToCollect": "10.00"
Required fields
Field |
Description |
---|---|
|
The reference of the payment job to retrieve. |
|
The reference of the payment to retrieve. |
|
Your configuration ID. |
|
A hexadecimal sha512 hash of your password. |
Response codes
Code |
Description |
---|---|
200 |
Payment retrieved successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration, payment job or payment not found. |
How to reply to a notification webhook
When the Cashflows Gateway receives the confirmed paymentJobReference
and paymentReference
, the notification process ends. It starts again when another payment status change occurs. It’s good practice to acknowledge a notification webhook so that we know that you have received it.
Also, if the response does not contain the expected 200 response code and the message body, or if there is no response at all, the gateway keeps trying to send the same notification webhook for as long as a month. Initially, the retries are every minute and then every day and then every week. Therefore, if you don’t acknowledge a notification webhook, the repeated attempts to send it create unnecessary gateway traffic.
To reply to a notification webhook
Send the 200 response with the paymentJobReference and the paymentReference
, for example:
{
"paymentJobReference": "200421017498767380",
"paymentReference": "200421100461508616"
}
Mail or phone (MOTO) payment requests
After we receive the payment request with the card details, we check whether it’s a Mail Order, Telephone Order (MOTO) payment. If it is, we process it without any 3-D Secure checks. By definition, a MOTO payment is made by email or telephone (or an Interactive Voice Response system) and therefore it’s not possible to carry out 3-D Secure checks.
After we have processed the payment, we notify you about the change of status for the payment (for example from Pending to Paid).
How to request a MOTO payment
For a MOTO payment, include the IsMoto option in the payment request.
Example request
{
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23"
},
"order": {
"orderNumber": "Payment ref M1"
},
"options": [ "IsMoto" ],
"currency": "GBP",
"amountToCollect": "5.00"
}
Example response
{
"data": {
"reference": "210221000033558552",
"createDateTimeUtc": "2021-02-18T10:58:51.1499764Z",
"type": "Payment",
"traceReference": "210220104588703824",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment ref M1",
"createDateTimeUtc": "2021-02-18T10:58:51.1499784Z",
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "5.00",
"amountCollected": "5.00",
"paidAmount": "5.00",
"paidDateTimeUtc": "2021-02-18T10:58:52.0469417Z",
"expirationDateTimeUtc": "2021-08-18T10:58:51.1499752Z",
"lastUpdateTimeUtc": "2021-02-18T10:58:52.071243Z",
"lastProcessedTimeUtc": "2021-02-18T10:58:51.1499771Z",
"flags": {
"moto": true,
"direct": true
},
"attributes": {},
"paymentStatus": "Paid",
"payments": [
{
"reference": "210221100167776284",
"createDateTimeUtc": "2021-02-18T10:58:51.3404954Z",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "5.00",
"surchargeAmount": "0",
"paidAmount": "5.00",
"steps": [
{
"reference": "210221221659516928",
"createDateTimeUtc": "2021-02-18T10:58:52.0467157Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "5.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221000033558552&paymentref=210221100167776284&ordernumber=Payment+ref+M1",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221000033558552&paymentref=210221100167776284&ordernumber=Payment+ref+M1",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221000033558552&paymentref=210221100167776284&ordernumber=Payment+ref+M1&status=cancelled",
"cashFlowsAcquiringDetails": "{\"AuthCode\":\"AUTHOK\",\"Arn\":\"74501871049010015672137\",\"Message\":\"Authorised\",\"Status\":\"Successful\",\"IssuerResponseCode\":\"00\",\"CvvAvsResult\":\"200\",\"AcquirerResponseCode\":\"A\",\"TruncatedCardNumber\":\"400000******0002\"}",
"paymentMethodTransactionId": "01S00DAA658"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221000033558552",
"type": "application/json"
},
"action": {
"url": "https://www.mywebshop.com/?paymentjobref=210221000033558552&paymentref=210221100167776284&ordernumber=Payment+ref+M1",
"type": "text/html"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gateway-api/documentation/index.html",
"type": "text/html"
}
}
}
Required field
Field |
Description |
---|---|
|
A flag to indicate that a payment is a MOTO payment. |
|
The number of the card that the customer is paying with. Note: This is mandatory unless a token is being used. |
|
The security code that is usually on the back of the customer’s card. Note: This is mandatory unless a token is being used. |
|
The month when the card expires. Note: This is mandatory unless a token is being used. |
|
The year when the card expires. Note: This is mandatory unless a token is being used. |
|
The total value of the payment transaction. |
|
The total value of the payment transaction. |
|
The transaction currency. |
Optional fields
Field |
Description |
---|---|
|
The name of the customer. Required for transactions that need to have 3DS checks applied. A request without a cardholderName, will result in an error response. |
|
The email address of the customer. |
|
The reference number that you generate to identify an order. |
Response codes
After you have submitted a request to create a MOTO payment job, the Cashflows Gateway API responds with a code. Ideally the response is a success code but can be any of the following.
Code |
Description |
---|---|
201 |
Payment job created successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration not found. |
406 |
Bad response |
Stored card details
Enables customers to store card details for future purchases, if they want to. When they return to your website to buy something, they can use a stored card for a faster checkout. The card details are never revealed at any stage of the payment process. The card details are securely stored in a secure token vault. We convert the card details to a unique series of randomly-generated numbers (known as a token).
You can use API calls to send us a request for a token and then use the token in future payment requests instead of the card details. For more information, see How to request a token. We then send you the token to use in payment jobs for future transactions that use the same stored card. For subsequent payments by the same customer, you send us the token and not the stored card details.
Using a token instead of card details
Our Cashflows Gateway can securely store card details so that they are not revealed at any time during the payment process. If a customer chooses to store their card details on your website, you can send us the card details and ask us to convert them to a unique series of randomly-generated numbers (known as a token). We then validate the card and send you the token to use in payment jobs for future transactions that use the same stored card. For subsequent payments by the same customer, you send us the token and not the stored card details.
This section explains how to:
Ask us to create a token from the card details that you send us. For more information, see How to request a token.
Ask us to create a token during a payment. For example, if a customer wants to pay with a card that they haven’t stored yet (so we haven’t tokenised it yet). For more information, see How to request a token during a payment.
Use a token for a payment instead of the card details. For more information, see How to use a token for a payment.
How to request a token
To request a token, you need to tell us the card details that you would like us to convert to a token (tokenise).
Example Request
POST to https://gateway-int.cashflows.com/api/gateway/card-tokenisation
.
{
"cardNumber": "4000000000000002",
"CardHolderName": "A Smith",
"cardExpiryYear": "21",
"cardExpiryMonth": "10",
"cardCvc": "123"
}
Example Response
{
"data": {
"token": "1000000000030419",
"cardExpiryMonth": "10",
"cardExpiryYear": "21",
"truncatedCardNumber": "400000****0002"
}
}
Required fields
Field |
Description |
---|---|
|
The card number to be converted to a token (tokenised). |
|
The name of the customer. Required for transactions that need to have 3DS checks applied. A request without
a |
|
The year when the card expires in the format YY (2 digits). For example, if the card expires in 2025, set this to 25. |
|
The month when the card expires in the format MM {01-12}. For example, if the card expires in April, set this to 04. |
|
The security code on the back of the card. |
How to request a token during a payment
If a customer wants to pay with a card that they haven’t stored yet (so we haven’t tokenised it yet), you can ask us to tokenise it during the payment process. You add the token request to the payment request by including the option GenerateToken
.
Example request to generate a token
{
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23",
"cardHolderName": "Jon Snow"
},
"order": {
"orderNumber": "Payment ref D1T"
},
"options": ["GenerateToken"],
"currency": "GBP",
"amountToCollect": "10.00"
}
The response provides the result of the 3-D Secure checks and if the payment passes the 3-D Secure checks, it includes you with the requested token.
Example response with the link to the 3-D Secure page:
{
"data": {
"reference": "210221000000135192",
"createDateTimeUtc": "2021-02-18T11:17:27.1270204Z",
"type": "Payment",
"traceReference": "210220104756475984",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment ref D1T",
"createDateTimeUtc": "2021-02-18T11:17:27.1270232Z",
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "10.00",
"expirationDateTimeUtc": "2021-08-18T11:17:27.1270185Z",
"dueDateTimeUtc": "2021-02-18T11:27:27.6829616Z",
"lastUpdateTimeUtc": "2021-02-18T11:17:27.1270223Z",
"lastProcessedTimeUtc": "2021-02-18T11:17:27.1270215Z",
"flags": {
"generateToken": true,
"direct": true
},
"attributes": {},
"paymentStatus": "Pending",
"payments": [
{
"reference": "210221100134352924",
"createDateTimeUtc": "2021-02-18T11:17:27.3627718Z",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"steps": [
{
"reference": "210221221491613700",
"createDateTimeUtc": "2021-02-18T11:17:27.6831162Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\"}"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221000000135192",
"type": "application/json"
},
"action": {
"url": "https://gateway-int.cashflows.com/payment/form-post?ref=4ab07d818100e4880130c8e35d25ea1ba2c0683e11093a397f633206169e119a9f117f236e44a080e0e737832494b8ac1058c297e401acd1001f1a2ef9468837",
"type": "text/html"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gateway-api/documentation/index.html",
"type": "text/html"
}
}
Example response with the token
After 3-D Secure checking is complete, the retrieve payment job provides you with the token (highlighted).
{
"data": {
"reference": "210221000000135192",
"createDateTimeUtc": "2021-02-18T11:17:27.127Z",
"type": "Payment",
"traceReference": "210220104756475984",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment ref D1T",
"createDateTimeUtc": "2021-02-18T11:17:27.127Z",
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "10.00",
"amountCollected": "10.00",
"paidAmount": "10.00",
"paidDateTimeUtc": "2021-02-18T11:19:57.773Z",
"expirationDateTimeUtc": "2021-08-18T11:17:27.127Z",
"dueDateTimeUtc": "2021-02-18T11:27:27.682Z",
"lastUpdateTimeUtc": "2021-02-18T11:19:57.811Z",
"lastProcessedTimeUtc": "2021-02-18T11:17:27.127Z",
"flags": {
"generateToken": true,
"direct": true,
"createdOnMapi": true
},
"attributes": {},
"paymentStatus": "Paid",
"payments": [
{
"reference": "210221100134352924",
"createDateTimeUtc": "2021-02-18T11:17:27.362Z",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"paidAmount": "10.00",
"steps": [
{
"reference": "210221221491613700",
"createDateTimeUtc": "2021-02-18T11:17:27.683Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00"
},
{
"reference": "210221221525168132",
"createDateTimeUtc": "2021-02-18T11:19:57.773Z",
"action": "Process",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221000000135192&paymentref=210221100134352924&ordernumber=Payment+ref+D1T&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\",\"AuthenticationStatus\":\"Y\",\"Xid\":\"pBoZubEx533uMpLNFjuXU0LMRql=\",\"Cavv\":\"aq0zADZ1wIha0IgU3j9FRt0sA2V=\",\"Eci\":\"05\",\"AuthCode\":\"AUTHOK\",\"Arn\":\"74501871049010015672418\",\"Message\":\"Authorised\",\"Status\":\"Successful\",\"IssuerResponseCode\":\"00\",\"CvvAvsResult\":\"200\",\"AcquirerResponseCode\":\"A\",\"TruncatedCardNumber\":\"400000******0002\"}",
"originatingIpAddress": "81.106.197.200, 95.100.156.174, 88.221.51.77",
"originHeader": "https://integration.cashflows.com",
"paymentMethodTransactionId": "01S00DAA6A7",
"token": "1000000000030419"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221000000135192?locale=en_GB",
"type": "application/json"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gateway-api/documentation/index.html",
"type": "text/html"
}
}
}
Required fields
Field |
Description |
---|---|
|
The card number to be converted to a token (tokenised). |
|
The name on the card that the customer is paying with. Required for transactions that need to have 3DS checks applied.
A request without a |
|
The year when the card expires in the format YY (2 digits). For example, if the card expires in 2025, set this to 25. |
|
The month when the card expires in the format MM {01-12}. For example, if the card expires in April, set this to 04. |
|
The security code on the back of the card. |
|
Flag to indicate that this is a request to generate a token. |
How to use a token for a payment
When you have received a token, you can use it in a payment request. You just need to replace the cardNumber field with the token field. We then process the payment as usual.
Example request
{
"type": "Payment",
"locale": "en_GB",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"token":"1000000000030419",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23"
},
"order" : {
"orderNumber": "Payment ref D1UT"
},
"currency": "GBP",
"amountToCollect": "10.00"
}
Example response
{
"data": {
"reference": "210221000033689624",
"createDateTimeUtc": "2021-02-18T11:30:38.7419169Z",
"type": "Payment",
"traceReference": "210220104588703828",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment ref D1UT",
"createDateTimeUtc": "2021-02-18T11:30:38.741919Z",
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "10.00",
"expirationDateTimeUtc": "2021-08-18T11:30:38.7419153Z",
"dueDateTimeUtc": "2021-02-18T11:40:39.2516539Z",
"lastUpdateTimeUtc": "2021-02-18T11:30:38.7419183Z",
"lastProcessedTimeUtc": "2021-02-18T11:30:38.7419176Z",
"flags": {
"direct": true
},
"attributes": {},
"paymentStatus": "Pending",
"payments": [
{
"reference": "210221100167907356",
"createDateTimeUtc": "2021-02-18T11:30:38.8874465Z",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"steps": [
{
"reference": "210221204311875588",
"createDateTimeUtc": "2021-02-18T11:30:39.2518647Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221000033689624&paymentref=210221100167907356&ordernumber=Payment+ref+D1UT",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221000033689624&paymentref=210221100167907356&ordernumber=Payment+ref+D1UT",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221000033689624&paymentref=210221100167907356&ordernumber=Payment+ref+D1UT&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\"}"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221000033689624",
"type": "application/json"
},
"action": {
"url": "https://gateway-int.cashflows.com/payment/form-post?ref=4ab07d818100e4880130c8e35d25ea1bbf867b6a880705a3ec3b702f979abd9acc488c04c93f40cf3cb32634459161dcc4296d0bd680e7a4bf8f9e051c2a5bd0",
"type": "text/html"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gateway-api/documentation/index.html",
"type": "text/html"
}
}
}
Recurring payments
For a recurring payment, your website needs to send us a payment request that includes a unique job number for the parent job under which the recurring child payments will take place. Therefore, you need to first create a parent payment job. Our Cashflows Gateway can then process the payment as usual and reply with a notification webhook to tell you the payment status of the parent job.
The first occurrence of a recurring payment must have 3D Secure checks applied so that we can set up the Recurring Parent Payment Job Reference. We use this reference instead of the card data when subsequent recurring or instalment payments need to be authorised. As part of the authorisation request of these child payments, you must submit the required recurring payment details (recurrenceCriteria) such as the type of recurring payment, the frequency and the end date.
Any recurring child payments do not need notification webhooks. The status of a child payment is returned in the API response. Therefore, using the API response saves you some work and avoids unnecessary webhook traffic.
If you have set up a notification webhook in Cashflows Portal, it gets used by the parent job (as required) but is also used automatically by the child payment jobs (not required). Therefore, instead of specifying the notification webhooks in Cashflows Portal, you need to specify notification webhooks in the create payment job API request for the parent payment. This gives you greater control because you include a notification webhook only when need to (that is in the case of a parent payment). It also means that you don’t need to reply to unnecessary webhooks, as described earlier in How to reply to a notification webhook.
The process for setting up and processing a recurring payment involves the following steps:
Create a parent payment job for the initial transaction The cardholder needs to be present so that they can enter their card details, including security code (CVV) and go through 3-D Secure checks, if applicable. This initial transaction can include a payment or can be for a zero amount (to verify the card). This is also when you specify the notification webhook to use for the status of the parent payment. For more information about creating a parent payment job.
Create the recurring child payment request that includes the unique job number (parentPaymentJobReference) of the parent payment job so that we can retrieve the card details to use for future payments. For more information, see How to create a recurring payment job.
How to create a parent payment job
To set up a recurring payment, you need to create the parent payment job to verify a customer’s card and take a payment. Future recurring payments will be child payment jobs of this parent.
For a parent payment, you also need to specify the notification webhook to use for the status of the parent payment.
You can create a parent payment job via our Cashflows Gateway or via a hosted payment page, if you’re using one. For more information about using a hosted payment page, see the Hosted Payment Pages guide.
When you create a payment job via the Cashflows Gateway, you need to include some additional information in the request to make this payment job into a parent payment job. The request must include the option ‘IsRecurringPaymentJobParent’ as well as the type of recurring payment. The Cashflows Gateway supports the following types of recurring payment:
Subscription: a series of sequential payments for the same amount each time. An example of a recurring subscription payment is a gym membership.
Instalment: a set number of pre-agreed payments with a fixed end date for the final payment.
Unscheduled: a type of recurring payment that’s used for transactions that occur on a non-fixed schedule and/or have variable amounts. An example of an unscheduled recurring payment is automatic top-ups when a cardholder’s balance falls below a certain amount.
Depending on the type of recurring payment that you want to make, you must ensure that you supply the correct recurrence type.
Important
To comply with financial regulations, a payment request from a financial institution needs to include some extra information about the person who is receiving the funds. This includes payment requests for MOTO, parent and recurring transactions. You need to include the extra details in the recipientDetails object. For more information, see Additional details required for financial institutions.
Example request for a recurring subscription payment
import requests
import json
url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs'
data = {
"amountToCollect": "10",
"currency": "GBP",
"options": ["IsRecurringPaymentJobParent"],
"paymentMethodsToUse": ["card"],
"recurrenceCriteria": {
"recurrenceType": "Subscription",
"recurringExpiry": "2022-02-16T13:07:33.92Z",
"recurringFrequency": "28"
}
}
headers = {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
var url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
var data = new
{
amountToCollect = "10",
currency = "GBP",
options = new string[] { "IsRecurringPaymentJobParent" },
paymentMethodsToUse = new string[] { "card" },
recurrenceCriteria = new
{
recurrenceType = "Subscription",
recurringExpiry = "2022-02-16T13:07:33.92Z",
recurringFrequency = "28"
}
};
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("Hash", "YOUR_SIGNATURE_HASH");
client.DefaultRequestHeaders.Add("ConfigurationId", "YOUR_CONFIGURATION_ID");
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
import java.io.*;
import java.net.*;
import javax.net.ssl.HttpsURLConnection;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
String data = "{\n" +
"\"amountToCollect\": \"10\",\n" +
"\"currency\": \"GBP\",\n" +
"\"options\": [\"IsRecurringPaymentJobParent\"],\n" +
"\"paymentMethodsToUse\": [\"card\"],\n" +
"\"recurrenceCriteria\": {\n" +
"\"recurrenceType\": \"Subscription\",\n" +
"\"recurringExpiry\": \"2022-02-16T13:07:33.92Z\",\n" +
"\"recurringFrequency\": \"28\"\n" +
"}\n" +
"}";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Hash", "YOUR_SIGNATURE_HASH");
con.setRequestProperty("ConfigurationId", "YOUR_CONFIGURATION_ID");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
try (OutputStream os = con.getOutputStream()) {
byte[] input = data.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = con.getResponseCode();
System.out.println("Response Code: " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
}
const axios = require('axios');
let data = JSON.stringify({
"amountToCollect": "10",
"currency": "GBP",
"options": [
"IsRecurringPaymentJobParent"
],
"paymentMethodsToUse": [
"card"
],
"recurrenceCriteria": {
"recurrenceType": "Subscription",
"recurringExpiry": "2022-02-16T13:07:33.92Z",
"recurringFrequency": "28"
}
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs',
headers: {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
<?php
$url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs';
$data = json_encode([
'amountToCollect' => '10',
'currency' => 'GBP',
'options' => ['IsRecurringPaymentJobParent'],
'paymentMethodsToUse' => ['card'],
'recurrenceCriteria' => [
'recurrenceType' => 'Subscription',
'recurringExpiry' => '2022-02-16T13:07:33.92Z',
'recurringFrequency' => '28'
]
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Hash: YOUR_SIGNATURE_HASH',
'ConfigurationId: YOUR_CONFIGURATION_ID',
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'uri'
require 'json'
url = URI.parse('https://gateway-inta.cashflows.com/api/gateway/payment-jobs')
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.path,
{
'Hash' => 'YOUR_SIGNATURE_HASH',
'ConfigurationId' => 'YOUR_CONFIGURATION_ID',
'Content-Type' => 'application/json'
})
request.body = {
"amountToCollect" => "10",
"currency" => "GBP",
"options" => ["IsRecurringPaymentJobParent"],
"paymentMethodsToUse" => ["card"],
"recurrenceCriteria" => {
"recurrenceType" => "Subscription",
"recurringExpiry" => "2022-02-16T13:07:33.92Z",
"recurringFrequency" => "28"
}
}.to_json
response = http.request(request)
puts response.body
Example JSON message body
{
"type": "Payment",
"locale": "en_GB",
"options": ["IsRecurringPaymentJobParent"],
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber": "4000********0002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23",
"cardHolderName": "Jon Snow",
"webhookUrl": "https://www.mywebhookurl"
},
"currency": "GBP",
"amountToCollect": "0.00",
"recurrenceCriteria": {
"recurrenceType": "Subscription",
"recurringExpiry": "2034-11-08",
"recurringFrequency": "12"
}
}
Example request for a recurring instalment payment
{
"type": "Payment",
"locale": "en_GB",
"options": ["IsRecurringPaymentJobParent"],
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000********0002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23",
"cardHolderName": "Jon Snow",
"webhookUrl":"https://www.mywebhookurl"
},
"currency": "GBP",
"amountToCollect": "0.00",
"recurrenceCriteria": {
"recurrenceType": "Instalment",
"recurringExpiry": "2023-12-08",
"recurringFrequency": "13",
"Instalments": "13"
}
}
Example request for an unscheduled recurring payment
{
"type": "Payment",
"locale": "en_GB",
"options": ["IsRecurringPaymentJobParent"],
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000********0002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23",
"cardHolderName": "Jon Snow",
"webhookUrl":"https://www.mywebhookurl"
},
"currency": "GBP",
"amountToCollect": "10.00",
"recurrenceCriteria": {
"recurrenceType": "Unscheduled"
}
}
In some of these examples, the payment was a zero-amount authorisation. When you create a parent payment job, the amount can be zero but can also be the amount that you want to collect as the first payment.
In Cashflows Portal, the transaction will show as a recurring parent payment in the Advanced tab of the Transaction details. For more information, see the Cashflows Portal guide.
Example response
{
"data": {
"reference": "210221000411041792",
"createDateTimeUtc": "2021-02-22T17:06:06.9100226Z",
"type": "Payment",
"traceReference": "210220104303388672",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "0.00",
"expirationDateTimeUtc": "2021-08-22T17:06:06.9100204Z",
"dueDateTimeUtc": "2021-02-22T17:16:07.510655Z",
"lastUpdateTimeUtc": "2021-02-22T17:06:06.9100242Z",
"lastProcessedTimeUtc": "2021-02-22T17:06:06.9100234Z",
"flags": {
"recurringParent": true,
"direct": true
},
"attributes": {},
"paymentStatus": "Pending",
"payments": [
{
"reference": "210221100327286784",
"createDateTimeUtc": "2021-02-22T17:06:07.0457549Z",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "0.00",
"steps": [
{
"reference": "210221221533560840",
"createDateTimeUtc": "2021-02-22T17:06:07.5108252Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "0.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.bing.com/?paymentjobref=210221000411041792&paymentref=210221100327286784",
"returnUrlFailed": "https://www.yahoo.co.uk/?paymentjobref=210221000411041792&paymentref=210221100327286784",
"returnUrlCancelled": "https://www.google.co.uk?paymentjobref=210221000411041792&paymentref=210221100327286784&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\"}"
},
"refunds": [],
"captures": []
}
]
},
"links": {
"data": {
"url": "https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221000411041792",
"type": "application/json"
},
"action": {
"url": "https://gateway-int.cashflows.com/payment/form-post?ref=4ab07d818100e4880130c8e35d25ea1be01f7f9452408d235224886e479afa8719b43b45d88251cf73bae8160e1bb551ca61ac1cbeab0c889200fe8199e49109",
"type": "text/html"
},
"documentation": {
"url": "https://gateway-int.cashflows.com/payment-gateway-api/documentation/index.html",
"type": "text/html"
}
}
}
Note
Unless a transaction is flagged as MOTO, you must still redirect the cardholder to complete the 3D Secure checks for the payment using the action URL provided above in the example response.
Required fields
Field |
Description |
---|---|
|
The total value of the payment transaction. |
|
The transaction currency. |
|
A flag to indicate that this payment job is a parent payment job for the purpose of a recurring payment. |
|
The number of the card that the customer is paying with. Note: This is mandatory unless a token is being used. If a token is being used, the field name is token |
|
The year when the card expires in the format YY (2 digits). For example, if the card expires in 2025, set to 25. |
|
The month when the card expires in the format MM {01-12}. For example, if the card expires in April, set to 04. |
|
The security code on the back of the card. |
|
The name on the card that the customer is paying with. Required for transactions that need to have 3DS checks applied. A request without a cardholderName, will result in an error response |
|
A string that can have one of the following values:
|
|
A date in the future after which the recurrence is no longer valid. The date format to use is yyyy-mm-dd, for
example 2022-12-25. Not required for if |
|
The number of days between payments, for example 28. Not required if |
|
The number of instalments. This value must match the value of |
Important
To comply with financial regulations, a payment request from a financial institution needs to include some extra information about the person who is receiving the funds. This includes payment requests for MOTO, parent and recuring transactions. You need to include the extra details in the recipientDetails object. For more information, see Additional details required for financial institutions.
Optional fields
Field |
Description |
---|---|
|
The reference number that you generate to identify an order. |
|
The email address of the customer. |
|
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
Tip: If your language is not available, please choose the most appropriate language for your customers. |
Response codes
After you have submitted a request to create a parent payment job, the Gateway API responds with a code. Ideally the response is a success code but can be any of the following.
Code |
Description |
---|---|
201 |
Parent payment job created successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration not found. |
406 |
Bad response |
How to create a recurring payment job
When you create the child payment job for the recurring payment, you must include the reference to the parent payment job to enable us to retrieve the card details to use for the payment. For more information about creating a parent payment job, see How to create a parent payment job.
When you create a child payment job, the recurrence type must match the original recurrence type provided in the parent payment job. Our gateway does not currently support scheduling. Therefore, you need to initiate the recurring payment with the required amount at the required time.
If you want to manually capture payments see the Manually capture recurring payments section.
Example requests
The payment job request must include the parent payment job number for the default card or card selected by the customer, for example:
Example child recurring subscription payment requests
import requests
import json
url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs'
data = {
"amountToCollect": "10",
"currency": "GBP",
"parentPaymentJobReference": "PARENT_PAYMENT_JOB_REFERENCE"
}
headers = {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
var url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
var data = new
{
amountToCollect = "10",
currency = "GBP",
parentPaymentJobReference = "PARENT_PAYMENT_JOB_REFERENCE"
};
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("Hash", "YOUR_SIGNATURE_HASH");
client.DefaultRequestHeaders.Add("ConfigurationId", "YOUR_CONFIGURATION_ID");
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
import java.io.*;
import java.net.*;
import javax.net.ssl.HttpsURLConnection;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://gateway-inta.cashflows.com/api/gateway/payment-jobs";
String data = "{\n" +
"\"amountToCollect\": \"10\",\n" +
"\"currency\": \"GBP\",\n" +
"\"parentPaymentJobReference\": \"PARENT_PAYMENT_JOB_REFERENCE\"\n" +
"}";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Hash", "YOUR_SIGNATURE_HASH");
con.setRequestProperty("ConfigurationId", "YOUR_CONFIGURATION_ID");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
try (OutputStream os = con.getOutputStream()) {
byte[] input = data.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = con.getResponseCode();
System.out.println("Response Code: " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
}
const axios = require('axios');
let data = JSON.stringify({
"amountToCollect": "10",
"currency": "GBP",
"parentPaymentJobReference": "PARENT_PAYMENT_JOB_REFERENCE"
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs',
headers: {
'Hash': 'YOUR_SIGNATURE_HASH',
'ConfigurationId': 'YOUR_CONFIGURATION_ID',
'Content-Type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
<?php
$url = 'https://gateway-inta.cashflows.com/api/gateway/payment-jobs';
$data = json_encode([
'amountToCollect' => '10',
'currency' => 'GBP',
'parentPaymentJobReference' => 'PARENT_PAYMENT_JOB_REFERENCE'
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Hash: YOUR_SIGNATURE_HASH',
'ConfigurationId: YOUR_CONFIGURATION_ID',
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'uri'
require 'json'
url = URI.parse('https://gateway-inta.cashflows.com/api/gateway/payment-jobs')
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.path,
{
'Hash' => 'YOUR_SIGNATURE_HASH',
'ConfigurationId' => 'YOUR_CONFIGURATION_ID',
'Content-Type' => 'application/json'
})
request.body = {
"amountToCollect" => "10",
"currency" => "GBP",
"parentPaymentJobReference" => "PARENT_PAYMENT_JOB_REFERENCE"
}.to_json
response = http.request(request)
puts response.body
Example JSON for a child recurring subscription payment
{
"amountToCollect": "10.00",
"currency": "GBP",
"locale": "en_GB",
"parentPaymentJobReference" : "PARENT_PAYMENT_JOB_REFERENCE",
"order": {
"orderNumber": "Payment 2"
},
"recurrenceCriteria": {
"recurrenceType":"Subscription",
"recurringExpiry": "2034-11-08",
"recurringFrequency": "12"
}
}
Example JSON for a child recurring instalment payment
{
"amountToCollect": "10.00",
"currency": "GBP",
"locale": "en_GB",
"parentPaymentJobReference" : "PARENT_PAYMENT_JOB_REFERENCE",
"order": {
"orderNumber": "Payment 2"
},
"recurrenceCriteria": {
"recurrenceType":"Instalment",
"recurringExpiry": "2023-12-08",
"recurringFrequency": "13",
"Instalments":"13"
}
}
Example JSON for a child recurring unscheduled payment
{
"amountToCollect": "10.00",
"currency": "GBP",
"locale": "en_GB",
"parentPaymentJobReference" : "PARENT_PAYMENT_JOB_REFERENCE",
"order": {
"orderNumber": "Payment 2"
},
"recurrenceCriteria": {
"recurrenceType":"Unscheduled"
}
}
Important
To comply with financial regulations, a payment request from a financial institution needs to include some extra information about the person who is receiving the funds. This includes payment requests for MOTO, parent and recuring transactions. You need to include the extra details in the recipientDetails object. For more information, see Additional details required for financial institutions.
Example response
The response contains the payment status. There is no need to specify a notification webhook for a recurring child payment job:
{
"data": {
"reference": "200921017221943304",
"createDateTimeUtc": "2020-09-10T14:20:32.5873637Z",
"type": "Payment",
"traceReference": "200920100402698252",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Payment 2",
"createDateTimeUtc": "2020-09-10T14:20:32.5873662Z",
"orderLines": []
},
"orderHistory": [],
"parentPaymentJobReference": "200721021609123852",
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "10.00",
"amountCollected": "10.00",
"paidAmount": "10.00",
"paidDateTimeUtc": "2020-09-10T14:20:33.763025Z",
"expirationDateTimeUtc": "2021-03-10T14:20:32.5873618Z",
"lastUpdateTimeUtc": "2020-09-10T14:20:33.7981683Z",
"lastProcessedTimeUtc": "2020-09-10T14:20:32.5873645Z",
"flags": {
"direct": true
},
"attributes": {},
"paymentStatus": "Paid",
"payments": [
{
"reference": "200921100142737416",
"createDateTimeUtc": "2020-09-10T14:20:32.8319012Z",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"paidAmount": "10.00",
"steps": [
{
"reference": "200921217196650516",
"createDateTimeUtc": "2020-09-10T14:20:33.762769Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://gateway-int.cashflows.com/payment?ref=4ab07d818100e4880130c8e35d25ea1b4131ec54744e457ba541445578fced03c977295fb58cd009e7944c69e6a8876cc1af0b024b99302aea53b8ca09aafe24",
"returnUrlFailed": "https://gateway-int.cashflows.com/payment?ref=4ab07d818100e4880130c8e35d25ea1b4131ec54744e457ba541445578fced03c977295fb58cd009e7944c69e6a8876cc1af0b024b99302aea53b8ca09aafe24",
"returnUrlCancelled": "https://gateway-int.cashflows.com/payment?ref=4ab07d818100e4880130c8e35d25ea1b4131ec54744e457ba541445578fced03c977295fb58cd009e7944c69e6a8876cc1af0b024b99302aea53b8ca09aafe24&status=cancelled",
"cashFlowsAcquiringDetails": "{\"AuthCode\":\"AUTHOK\",\"Arn\":\"74501870254010013958712\",\"Message\":\"Authorised\",\"Status\":\"Successful\",\"IssuerResponseCode\":\"00\",\"CvvAvsResult\":\"000\",\"AcquirerResponseCode\":\"A\"}",
"paymentMethodTransactionId": "01S00CECA74"
Required fields
Field |
Description |
---|---|
|
The total value of the payment transaction. |
|
The transaction currency. |
|
The unique reference number of the parent payment under for this is recurring child payment. |
|
A string that can have one of the following values:
|
|
A date in the future after which the recurrence is no longer valid. The date format to use is yyyy-mm-dd, for
example 2022-12-25. Not required if |
|
The number of days between payments, for example 28. Not required if |
|
The number of instalments. This value must match the value of |
Important
To comply with financial regulations, a payment request from a financial institution needs to include some extra information about the person who is receiving the funds. This includes payment requests for MOTO, parent and recurring transactions. You need to include the extra details in the recipientDetails object. For more information, see Additional details required for financial institutions.
Optional fields
Field |
Description |
---|---|
|
The reference number that you generate to identify an order. |
|
The email address of the customer. |
|
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
Tip: If your language is not available, please choose the most appropriate language for your customers. |
Response codes
After you have submitted a request to create a parent payment job, the Gateway API responds with a code. Ideally the response is a success code but can be any of the following.
Code |
Description |
---|---|
201 |
Payment job created successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration not found. |
406 |
Bad response. |
Manually capture recurring payments
By default Cashflows automatically attempts to capture new payments, including recurring child payments. If you wish to manually capture the recurring payments instead:
Login to Cashflows Portal, then navigate to Configuration.
Select Payment Methods, then select Card.
Disable Auto Capture Recurring Transactions in the configuration section:
Click Save
Warning
If you don’t send the capture request within seven days, there is no guarantee that the customer will still have the funds in their account and so your business may not be paid.
Cancellation requests
If you need to cancel a payment, you can do this in Cashflows Portal, as long as the payment has not been settled (which means that the funds have not been transferred yet). If you cancel a payment, you must cancel the full amount.
When you cancel a payment, you are deleting the request for the funds (the capture request). No funds are ever taken from the card. These requests for funds are batched up and submitted at midnight. Therefore, you can cancel a payment on the same day any time up until midnight. If you need to cancel a payment after midnight (not the same day), the funds will have been transferred and you need to refund the payment instead. For more information, see Refund requests.
Cancelling a payment and cancelling a payment job are not the same thing. If you cancel a payment but not the payment job, you can still use the payment job for submitting more payments in the future.
How to cancel a payment
A request to cancel a payment request can only be processed before midnight on the same day when the payment was processed. You can only cancel a payment job for payments that have not been settled. If a payment has been settled, the only way to reverse it is with a refund. For more information, see Refund requests.
Example request to cancel a payment
The cancel payment has no message body. You just need to include the paymentJobReference
and paymentReference
in the URL, for example:
https://gateway-int.cashflows.com/api/gateway/payment-jobs/210221017490247692/payments/210221117473470476/cancel
Example response
{
"data": {
"reference": "210221117473470476",
"createDateTimeUtc": "2021-02-24T14:05:08.475Z",
"paymentMethods": ["Card"],
"status": "Cancelled",
"amountToCollect": "10.00",
"surchargeAmount": "0",
"paidAmount": "10.00",
"steps": [
{
"reference": "210221221667909660",
"createDateTimeUtc": "2021-02-24T14:05:08.9Z",
"action": "Start",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00"
},
{
"reference": "210221204563402752",
"createDateTimeUtc": "2021-02-24T14:05:30.79Z",
"action": "Process",
"paymentMethods": ["Card"],
"status": "Paid",
"amountToCollect": "10.00"
},
{
"reference": "210221204596957184",
"createDateTimeUtc": "2021-02-24T14:11:07.9139698Z",
"action": "Cancel",
"paymentMethods": ["Card"],
"status": "Cancelled",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210221017490247692&paymentref=210221117473470476&ordernumber=Payment+ref+D1C",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210221017490247692&paymentref=210221117473470476&ordernumber=Payment+ref+D1C",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210221017490247692&paymentref=210221117473470476&ordernumber=Payment+ref+D1C&status=cancelled",
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\",\"AuthenticationStatus\":\"Y\",\"Xid\":\"0Kbcw53GnooWrEjdo1T3f1iBbb0=\",\"Cavv\":\"7EmWGOmKzy1eEJPl89OfUwX9S9T=\",\"Eci\":\"05\",\"AuthCode\":\"AUTHOK\",\"Arn\":\"74501871055010015749357\",\"Message\":\"Authorised\",\"Status\":\"Successful\",\"IssuerResponseCode\":\"00\",\"CvvAvsResult\":\"200\",\"AcquirerResponseCode\":\"A\",\"TruncatedCardNumber\":\"400000******0002\"}",
"originatingIpAddress": "86.167.78.143, 23.200.87.37, 88.221.114.222",
"originHeader": "https://integration.cashflows.com",
"paymentMethodTransactionId": "01S00DB3211",
"paymentMethodVoidTransactionId": "01V00DB322B"
},
"refunds": [],
"captures": []
}
}
How to cancel a payment job
A payment job can remain on the Cashflows Gateway for six months before it expires so it’s good housekeeping to cancel any payment jobs that are no longer in use.
Tip
If you want a payment job to expire sooner than six months, you can set an expiry date when you create the payment job. Here’s an example that includes an expiration date and time:
{
"type": "Payment",
"paymentMethodsToUse": ["creditcard"],
"parameters": {
"cardNumber":"4000000000000002",
"cardCvc": "123",
"cardExpiryMonth": "05",
"cardExpiryYear": "23"
},
"order": {
"orderNumber": "Payment ref D1E"
},
"currency": "GBP",
"amountToCollect": "10.00",
"expirationDateTimeUtc": "2021-01-20T16:50:01"
}
It’s also good practice to cancel a payment job to prevent misuse and ensure that that it can’t be used for any other tasks. When you can cancel a payment job, it will not be possible to submit any more payments using the same payment job.
Note
Cancelling a payment job does not cancel completed payments.
Example request to cancel a payment job
PATCH https://gateway-int.cashflows.com/api/gateway/payment-jobs/{paymentJobReference}/cancel
Example response
{
"data": {
"reference": "210121017238589452",
"createDateTimeUtc": "2021-01-14T10:32:50.506Z",
"type": "Payment",
"traceReference": "210120117364553808",
"configurationId": "200426117314086912",
"domain": "cashflows.com",
"locale": "en_GB",
"timeZone": "Europe/London",
"order": {
"orderNumber": "Your ref",
"createDateTimeUtc": "2021-01-14T10:32:50.506Z",
"billingAddress": {
"firstName": "Alex",
"lastName": "Smith"
},
"billingIdentity": {
"emailAddress": "alex@test.com"
},
"orderLines": []
},
"orderHistory": [],
"paymentMethodsToUse": ["Card"],
"currency": "GBP",
"amountToCollect": "10.00",
"expirationDateTimeUtc": "2021-07-14T10:32:50.506Z",
"lastUpdateTimeUtc": "2021-01-14T15:10:59.0720383Z",
"lastProcessedTimeUtc": "2021-01-14T10:32:50.506Z",
"flags": {
"createdOnMapi": true
},
"attributes": {},
"paymentStatus": "Cancelled",
"payments": [
{
"reference": "210121117372807180",
"createDateTimeUtc": "2021-01-14T10:32:50.677Z",
"paymentMethods": ["Card"],
"status": "Cancelled",
"amountToCollect": "10.00",
"steps": [
{
"reference": "210121217372942352",
"createDateTimeUtc": "2021-01-14T10:32:50.73Z",
"action": "DisplayHostedPage",
"paymentMethods": ["Card"],
"status": "Pending",
"amountToCollect": "10.00"
},
{
"reference": "210121217339387924",
"createDateTimeUtc": "2021-01-14T15:10:59.0479346Z",
"action": "Cancel",
"paymentMethods": ["Card"],
"status": "Cancelled",
"amountToCollect": "10.00"
}
],
"flags": {},
"attributes": {
"returnUrlSuccess": "https://www.mywebshop.com/?paymentjobref=210121017238589452&paymentref=210121117372807180&ordernumber=Your+ref",
"returnUrlFailed": "https://www.mywebshop.com/?paymentjobref=210121017238589452&paymentref=210121117372807180&ordernumber=Your+ref",
"returnUrlCancelled": "https://www.mywebshop.com?paymentjobref=210121017238589452&paymentref=210121117372807180&ordernumber=Your+ref&status=cancelled"
},
"refunds": [],
"captures": []
}
]
}
}
Required fields
Field |
Description |
---|---|
|
The reference of the payment job to cancel. |
|
The reference of the payment to cancel. |
|
Your configuration ID. |
|
A hexadecimal sha512 hash of your password plus the body. |
Optional fields
Field |
Description |
---|---|
|
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
Tip: If your language is not available, please choose the most appropriate language for your customers. |
Response codes
Code |
Description |
---|---|
200 |
Payment or payment job successfully cancelled. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration, payment job or payment not found. |
406 |
Bad response. |
Refund requests
Occasionally it might be necessary to refund a payment, for example if a customer returns an item. You can make a refund via Cashflows Portal. For more information, refer to the Cashflows Portal Guide. Alternatively, you can use an API call to the Cashflows Gateway.
How to request a refund
To refund a payment, you need the paymentJobReference
and paymentReference
of the payment job that was used to make the original payment.
Note
A payment job can include multiple payments. However, you cannot refund in one call more than the amount that was paid using the payment method that is specified in the payment job that the paymentReference
refers to.
Example request
POST to:
https://gateway-int.cashflows.com/api/gateway/payment-jobs/{paymentJobReference}/payments/{paymentReference}/refunds
{
"amountToRefund": "10.00",
"refundNumber" : "Your refund reference"
}
Example response
{
"data": {
"reference": "210123000142606340",
"createDateTimeUtc": "2021-01-14T15:21:56.9346867Z",
"refundNumber": "Your refund reference",
"status": "Completed",
"amountToRefund": "10.00",
"steps": [
{
"reference": "210123100142606340",
"createDateTimeUtc": "2021-01-14T15:21:57.6097637Z",
"action": "Start",
"status": "Completed",
"resultAttributes": {}
}
],
"attributes": {
"cashFlowsAcquiringDetails": "{\"ThreeDSecureVersion\":\"1.0.2\",\"ThreeDSecureVersionReason\":\"3-D Secure v2 not enabled for this merchant.\",\"AuthenticationStatus\":\"Y\",\"Xid\":\"l7TnAA8FZXc4eYiMEvUE1CauPul=\",\"Cavv\":\"jqvNMAuNmkZJdA878z9A7PsPvTR=\",\"Eci\":\"05\",\"AuthCode\":\"116\",\"Arn\":\"\",\"Message\":\"Authorised\",\"Status\":\"Successful\",\"IssuerResponseCode\":\"\",\"CvvAvsResult\":\"222\",\"AcquirerResponseCode\":\"A\",\"TruncatedCardNumber\":\"400000******0002\"}",
"paymentMethodTransactionId": "01R00D76D2C"
}
}
}
Required fields
Field |
Description |
---|---|
|
The reference of the payment job to create a refund for. Integer($int64) |
|
The reference of the payment to create a refund for. Integer($int64) |
|
Your configuration ID. |
|
A hexadecimal sha512 hash of your password plus the body. |
Optional fields
Field |
Description |
---|---|
|
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
Tip: If your language is not available, please choose the most appropriate language for your customers. |
Response codes
Code |
Description |
---|---|
201 |
Refund created successfully. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration, payment job or payment not found. |
406 |
Bad response |
Capture requests
The payment process for a card transaction involves the following stages:
Authorisation
This is when a customer ‘s payment is validated to ensure that they can pay the requested amount. The payment is reserved for you (the business owner) but the funds are not actually taken from the customer ‘s account.
Capture
The bank receives a capture request from you. This indicates to the bank that you are ready to ship goods or provide your services to the customer. The bank then charges the customer ‘s payment card for the goods or services that they are buying. If the bank does not receive a capture request, the bank releases the reserved funds typically after five to seven days.
Our Cashflows Gateway takes care of the capture stage. By default, funds are automatically captured for the payments that we process for you. Cashflows Portal has an option called Auto Capture. When this option is enabled, we send both an authorisation (to reserve the funds on the card) and a capture request (for the funds to be transferred) to the customer’s bank. By default, Auto Capture is enabled but you can disable it at any time.
Depending on the nature of the business, it might be necessary for you to defer the capture of the funds until the customer is ready to pay for the service. For example, if the business offers services that customers book ahead and pay for later when or after they receive the service. Examples of such transactions are appointments for wellbeing or trades services or advance bookings where a deposit is taken.
To defer the capture stage, you need to:
1. Disable Auto Capture in Cashflows Portal. 1. Disable Auto Capture and Auto Capture Recurring Transactions in Cashflows Portal. 2. Create a capture request with an API call within seven days.
Important
If you don’t send the capture request within seven days, there is no guarantee that the customer will still have the funds in their account and so your business may not be paid.
How to disable automatic capture
Note
The steps that follow apply to all transactions. If you want to defer capture for an individual payment, you need to use create a capture request with an API call. For more information, see How to create a capture request.
To disable Auto Capture:
Sign into Cashflows Portal.
From the Cashflows Portal menu, select Configuration.
Select Payment Methods.
Select Enabled to display the card settings.
Clear the Auto Capture check box.
Select Save.
From now on, only an authorisation request will be sent. This will reserve funds on the card but the payment will not be completed. To complete the payment, you need to issue a separate capture request within seven days using an API call via the Cashflows Gateway. For more information, see How to create a capture request.
How to create a capture request
If you disable Auto Capture, we send an authorisation request to reserve funds on the card, but the payment will not be completed. To complete the payment, you need to issue a separate capture request within seven days using an API call via the Cashflows Gateway.
Example request
POST to:
https://gateway-int.cashflows.com/api/gateway/payment-jobs/{paymentJobReference}/payments/{paymentReference}/captures
{
"amountToCapture": "10",
"isFinalCapture": "true"
}
Example response
{
"data": {
"reference": "210123500033554432",
"createDateTimeUtc": "2021-01-14T15:18:27.1360974Z",
"status": "Completed",
"amountToCapture": "10",
"isFinalCapture": true,
"attributes": {
"paymentMethodTransactionId": "01S00D76D1A"
}
}
}
Required fields
Field |
Description |
---|---|
|
The reference of the payment job to capture. |
|
The reference of the payment to create a capture for. |
|
Your configuration ID. |
|
A hexadecimal sha512 hash of your password plus the body. |
Optional fields
Field |
Description |
---|---|
|
Determines the language that messages are displayed in. For example, to set the language to English, use the locale en-GB. Other options are:
Tip: If your language is not available, please choose the most appropriate language for your customers. |
Response codes
Code |
Description |
---|---|
200 |
Payment or payment job successfully cancelled. |
400 |
Request contains errors. |
401 |
Invalid token. |
403 |
Insufficient permissions. |
404 |
Configuration or payment job or payment not found. |
406 |
Bad response. |
Managing payment links
You can use an action URL from a request response as a payment link to send to customers so that they can pay via a to a secure online payment page.
Using our API and some coding, you can take a payment link and:
Embed it into a text message or chat, for example to request a deposit, complete a booking, send a quotation or send a reminder to chase up a payment.
Generate a QR code for an invoice
Turn it into a payment button
PayPal
To process PayPal payments, you first need to email support@cashflows.com to have PayPal enabled on your account. You also need a PayPal business account linked to your Cashflows account.
To link your PayPal business account to your Cashflows account:
Sign in to Cashflows Portal.
Important
You must be signed in as an Owner to make configuration changes within the Cashflows portal.
Log in and select Configuration.
Select Payment Methods.
Select PayPal.
Select Connect PayPal account, follow the instructions if you don’t have a PayPal business account.
Important
Be sure to activate your account by confirming the email address used to create your PayPal account.
Sign in to PayPal with your PayPal username and password.
When you return to Cashflows Portal, you will see the merchant ID that PayPal has assigned:
Select Save.
The changes take effect immediately but you also need to pass PayPal
in the paymentMethodsToUse
field:
"paymentMethodsToUse":
[
"Card",
"PayPal"
],
To preview how PayPal appears on your payment page, you can either:
Use the Virtual Terminal to generate a payment link and open it in your browser, see the Virtual Terminal section for more information.
Or
Use Cashflows Portal and go to Configuration, then Hosted Checkouts, and click on any existing templates.
Important
Your account needs to be enabled for sending Payment Links.
Error codes and warning messages
This section covers potential error code or messages and warnings you may receive from the Cashflows Gateway.
Cashflows Gateway error messages
Error |
Description |
---|---|
|
Cannot recur on a non recurring parent. |
|
The total capture amount exceeds original authorised amount. |
|
Payment has been refused. |
|
Refund has been refused. |
|
Credit payment has been refused. |
|
Capture has an invalid status. |
|
Unable to refund this payment. |
|
Unable to perform credit payment. |
|
Payment has an invalid status. |
|
Refund has an invalid status. |
|
Card payments without 3D Secure are not allowed. |
|
No payment method selected. |
|
The supplied order reference is not unique. |
|
Payment has already been fully refunded. |
|
Payment job is already final. |
|
Payment job can not be cancelled. |
|
Error while communicating. |
|
Payment method not allowed. |
|
The payment method rejected the request. |
|
Invalid amount for payment method. |
|
The validation for recipient detail fields failed. |
|
The total refund amount exceeds original paid amount. |
|
3DSecure Authentication Failed - Payment cannot proceed. |
|
3DSecure Authentication Unavailable - Payment cannot proceed. |
|
3DSecure Authentication Unavailable - Payment cannot proceed. |
|
Invalid customer reference provided. |
|
Direct card payments are not allowed. |
|
Too many attempts. |
|
It is not allowed to set parent frame domains for embedding the payment page. |
|
Unable to create paymentjob without payment methods available. |
Cashflows Gateway warning messages
Warning |
Description |
---|---|
|
Payment has an unexpected status. |
|
The maximum number of stored tokens for a customer has been reached. |
|
Supplied payment page reference does not exists. |