Payment Gateway Developer Documentation
Apple Pay
Apple Pay
Building a Website Integration with Source Allies' Payment Gateway - Apple Pay
Related Pages:
- [Payment Gateway Developer Documentation Overview](/payment-gateway/developer)
- [Credit Card and eCheck Transactions](/payment-gateway/developer/cc-and-echeck)
- [Recurring Payments](/payment-gateway/developer/cc-and-echeck)
- [Google Pay Transactions](/payment-gateway/developer/google-pay)
- \@sourceallies/payment-gateway
- NPM package
- Developer Documentation
### Getting started with Payment Gateway
We recommend following our tutorial for [cedit card and eCheck transactions](/payment-gateway/developer/cc-and-echeck) and [recurring payments](/payment-gateway/developer/cc-and-echeck) before you incorporate Apple Pay.
You will need to include our @sourceallies/payment-gateway NPM package for this tutorial. The developer documentation for @sourceallies/payment-gateway can be found here. Add the following script tag to your payment page:
```html
<script src="https://unpkg.com/@sourceallies/payment-gateway@latest/dist/payment-gateway.umd.js">
</script>
```
You will want to replace `@latest` in the URL with the current version which can be found on the NPM repository here or in the badge below. Including this package allows you to access all of the functions for interfacing with Payment Gateway.
[![npm version](https://badge.fury.io/js/%40sourceallies%2Fpayment-gateway.svg)](https://badge.fury.io/js/%40sourceallies%2Fpayment-gateway)
### Building a Website Integration with Source Allies' Payment Gateway - Apple Pay
Before beginning integrating with Apple Pay, make sure to set up your Apple Pay Credentials. You will need two merchant identifiers: one for testing Apple Pay, and another for Apple Pay in production. These identifiers are setup on the Apple Pay Merchant Identifier page. To create a new Identifier:
1. Click the plus button next to Identifiers
2. Select Merchant IDs
3. Fill in the Description and Identifier (it's recommended for the identifier to be reverse-domain style (eg: com.mysite)
4. Verify Description and Identifier and click Register
Now that you have setup your identifiers you can view them by going back to the Identifiers page (if you are not seeing your merchant IDs, make sure Merchant IDs is selected in the drop down on the right). You can click the name of the identifier to see all the associated credentials. There are five components to a Merchant ID:
- Name: The description you entered during setup. It can be updated.
- Identifier: The identifier you entered during setup. It cannot be updated. This will need to be sent to Source Allies to implement your gateway.
- Apple Pay Payment Processing Certificate: This certificate is for Authorize.Net.
- Merchant Domains: Each domain that will be implementing Apple Pay should be listed here.
- Apple Pay Merchant Identity Certificate: This certificate is used by payment gateway to establish a secure TLS session with Apple Pay.
#### Setting Up Apple Pay Payment Processing Certificate for Authorize.Net
The Apple Pay Payment Processing Certificate is used by Authorize.Net to decrypt Apple Pay's payment nonce. Each Merchant ID can only have one active Apple Pay Payment Processing Certificate. This is why you need to have a test identifier and a production identifier; Authorize.Net's sandbox account and Authorize.Net's live account will need to have their own certificates. Getting Apple Pay set up in Authorize.Net is a fairly simple process. On the left sidebar under Account, you should see a link for Digital Payment Solutions. If you do not, you do not have sufficent privileges on your Authorize.Net account.
To link your Authorize.Net account to its proper identifier:
1. On Authorize.Net live and Authorize.Net sandbox:
1. Click "Digital Payment Solutions" on the left sidebar
2. In the Apple Pay section, click Sign Up (it may say Enabled, if your account is already signed up)
3. Enter your Identifier for the Apple Merchant ID
4. Click download to obtain your Certificate Signing Request (CSR) from Authorize.Net
2. On the Apple Pay Identifiers page for Merchant IDs:
1. Select the appropriate Identifier
2. Under Apple Pay Payment Processing Certificate, click Create Certificate
3. Click Choose File, and select the Certificate Signing Request (CSR) from Authorize.Net and Click Continue
4. Click Activate (you do not need to download the certificate for Authorize.Net)
#### Setting Up Merchant Domains
You will need to specify a merchant domain for every domain you wish to use Apple Pay on. To set up a merchant domain:
1. Go to the Apple Pay Identifiers page for Merchant IDs
2. Select the appropriate Identifier
3. Under Merchant Domains, click Add Domain
4. Type in the fully qualified domain name and click Save
5. Download the domain association text file (After this step, it is safe to navigate away from this page. You can verify later)
6. Host the text file at the address specified by Apple Pay (eg: https://mysite.com/.well-known/apple-developer-merchantid-domain-association.txt)
7. Click Verify (if you have navigated away from the previous page, you can find the Verify button in the Merchant Domains section)
#### Setting Up Apple Pay Merchant Identity Certificate
This certificate is used to establish a secure TLS session between the payment gateway and Apple Pay. Source Allies will send you a Certificate Signing Request (CSR) to you. Once you have this CSR file:
1. Go to the Apple Pay Identifiers page for Merchant IDs
2. Under Apple Pay Merchant Identity Certificate, click Create Certificate
3. Click Choose File, and select the Certificate Signing Request (CSR) from Source Allies and Click Continue
4. Download and send the certificate to Source Allies
5. Click Activate
Once we have added this certificate to our payment gateway, you should be able to submit Apple Pay transactions to us successfully.
#### Setting Up a Test Card with Apple Pay
To test Apple Pay, you will need a Apple Pay test ID and Test card:
1. Go to Apple Pay's User and Access page in App Store Connect to set up a test account:
1. Click testers under the Sandbox heading in the left sidebar
2. Click the plus button
3. Add credential information. The email address must not be associated with another Apple ID
2. To use the tester account on an Apple device:
1. Under System Preferences, click Apple ID
2. Sign out the current user
3. Sign in with the tester ID (Do not use this tester account in the App Store. Doing so makes the tester account a live one.)
3. To add a card to the tester account:
1. Under System Preferences, open Wallet & Apple Pay
2. Add a card from Apple Pay's Sandbox Testing page
## Integrating Apple Pay Transactions
These directions are somewhat derived from Apple's Apple Pay on the Web Demo page. Apple Pay Transactions only work on an Apple device in Safari. The button should only be displayed if using Apple Pay is an option (for all the rules regarding the Apple Pay button, see Apple Pay's Buttons and Marks page and their Displaying Apple Pay Buttons page for CSS styling). To check to see if Apple Pay is an option, there is a class called ApplePaySession that is made available in Safari. To check if Apple Pay is an option, first check that ApplePaySession exists, then run the canMakePayments function like so:
```html
<script>
// This checks if `window.ApplePaySession` and if it can make payments. If both
// of these are true, the user is on Safari so we can add the Apple Pay
// button to the HTML.
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
const applePayButton = document.createElement("button");
applePayButton.setAttribute("id", "apple-pay-button");
applePayButton.classList.add(["apple-pay-button", "apple-pay-button-black"]);
applePayButton.addEventListener("click", runApplePay());
document.appendChild(applePayButton);
}
</script>
```
To set up an Apple Pay Session, add a click event to the Apple Pay button. This event will build a ApplePayPaymentRequest object, and then create an `ApplePaySession` object. The `ApplePayPaymentRequest` contains many features, including line items, supported card networks, merchant capabilities, shipping methods, billing information, etc. The below addition cover the pieces that are required, and also collects billing information.
```html
<script>
// This checks if `window.ApplePaySession` and if it can make payments. If both
// of these are true, the user is on Safari so we can add the Apple Pay
// button to the HTML.
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
const applePayButton = document.createElement("button");
applePayButton.setAttribute("id", "apple-pay-button");
applePayButton.classList.add(["apple-pay-button", "apple-pay-button-black"]);
applePayButton.addEventListener("click", runApplePay());
document.appendChild(applePayButton);
}
// This function will be run when the user clicks the Apple Pay button.
function runApplePay() {
// ...Validate all the fields in the form...
const request = {
countryCode: "US",
currencyCode: "USD",
supportedNetworks: ["visa", "masterCard", "discover"], // credit cards supported
merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], // supports3DS is required
lineItems: [
{
label: "Invoice Payment",
type: "final",
amount: document.getElementById("amount").value
}
],
total: {
label: "YOUR COMPANY NAME",
amount: document.getElementById("amount").value // total amount of transaction
},
requiredBillingContactFields: ["postalAddress"] // for getting billing address through Apple Pay
};
const applePaySession = new ApplePaySession(3, request);
};
</script>
```
Now that you have an `ApplePaySession` instance, it is time to set the event handlers. After the Apple Pay Session is started, these event handlers will be triggered one at a time to pass control back to the web page to perform some tasks. Each of these event handlers will end with a function call to pass control back to the Apple Pay Session. There are six different event handlers:
- onvalidatemerchant (required): handles merchant verificiation
- onpaymentmethodselected (required): called when a payment method is selected
- onshippingcontactselected() (optional): called when a shipping contact is selected
- onshippingmethodselected (optional): called when a shipping method is selected
- onpaymentauthorized (required): called when the user has authorized the Apple Pay payment
- oncancel (required): called when the payment UI is dismissed by the web page or the user
The first event handler to be implemented is onvalidatemerchant. This event handler must be set to a function that takes a single event parameter. The function should call payment gateway with a validation URL from the event. The event will look something like this (please note that if you wish to log the event, you must log it directly with `console.log(event)`. Using something like `JSON.stringify` will not print most of the event):
```javascript
{
bubbles: false,
cancelBubble: false,
cancelable: false,
composed: false,
currentTarget: null,
defaultPrevented: false,
eventPhase: 0,
isTrusted: true,
returnValue: true,
srcElement: ApplePaySession {...},
target: ApplePaySession {...},
timeStamp: 5090,
type: "validatemerchant",
validationURL: "https://apple-pay-gateway-cert.apple.com/paymentservices/startSession"
}
```
Payment Gateway will respond with a `MerchantSession` object that you set to a `merchantSession` variable (you do not declare this variable. `ApplePaySession` does this for you), and then pass back to the `ApplePaySession` instance with its `completeMerchantValidation` method. This can be done by calling the function `paymentGateway.processApplePayValidationRequest`. This function takes in a callback function, the event passed in to `onvalidatemerchant`, the client canonical name, the context, and the environment of Payment Gateway you want to send the request to. The callback function will take in the `XMLHttpRequest` object.
```html
<script>
// This checks if `window.ApplePaySession` and if it can make payments. If both
// of these are true, the user is on Safari so we can add the Apple Pay
// button to the HTML.
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
const applePayButton = document.createElement("button");
applePayButton.setAttribute("id", "apple-pay-button");
applePayButton.classList.add(["apple-pay-button", "apple-pay-button-black"]);
applePayButton.addEventListener("click", runApplePay());
document.appendChild(applePayButton);
}
// Your information to link the payments to your Payment Gateway account.
const gatewayData = {
partnerName: "YOUR PARTNER NAME",
gatewayName: "YOUR GATEWAY NAME"
};
// Specifies the environment to be used when Payment Gateway makes requests. This can be set to "DEV" or "PROD".
const environment = "DEV";
const clientCanonicalName = "yourdomain.com";
const context = window.location.hostname;
// ...Additional code for Apple Pay and HTML manipulations...
// This function will be run when the user clicks the Apple Pay button.
function runApplePay() {
// ...Validate all the fields in the form...
const request = {
countryCode: "US",
currencyCode: "USD",
supportedNetworks: ["visa", "masterCard", "discover"], // credit cards supported
merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], // supports3DS is required
lineItems: [
{
label: "Invoice Payment",
type: "final",
amount: "1.00"
}
],
total: {
label: "YOUR COMPANY NAME",
amount: "1.00" // total amount of transaction
},
requiredBillingContactFields: ["postalAddress"] // for getting billing address through Apple Pay
};
const applePaySession = new ApplePaySession(3, request);
applePaySession.onvalidatemerchant = function (event) {
const processApplePayValidationRequestHandler = function (xmlHttpRequest) {
if (xmlHttpRequest && xmlHttpRequest.status === 200) { // OK response from Payment Gateway.
merchantSession = JSON.parse(xmlHttpRequest.response);
applePaySession.completeMerchantValidation(merchantSession);
} else{
applePaySession.abort();
// You would end up in this error block if the response from Payment Gateway does not have a status of "200".
// You will want to handle this case with custom error handling for your website.
console.error("Bad response.");
}
};
paymentGateway.processApplePayValidationRequest(
processApplePayValidationRequestHandler,
event,
gatewayData,
clientCanonicalName,
context,
environment
);
};
applePaySession.begin();
};
</script>
```
The `merchantSession` should look something like this:
```json
{
"displayName": "mysite.com",
"domainName": "mysite.com",
"epochTimestamp": 1588252389334,
"expiresAt": 1588255989334,
"merchantIdentifier": "1F0D81D856FEFA0B2E213ED3B4236654BE3D1B9F058B5E2567047...",
"merchantSessionIdentifier": "SSH33405E77755640FDB6EC2C98A581B445_916523AAED13435BC...",
"nonce": "671dff7a",
"signature": "345235524a864886f70d010702f0803090020101310d300e061560..."
}
```
Once merchant validation is successful, it is time to implement the onpaymentmethodselected event handler. This event handler is called when the user selects a payment method. It must be set to a function that takes a single event parameter. The purpose of this function is to allow the site to add new line items or change the total if the user's selected payment method affects their total. In this demo, we will assume the same line items and totals:
```html
<script>
// This checks if `window.ApplePaySession` and if it can make payments. If both
// of these are true, the user is on Safari so we can add the Apple Pay
// button to the HTML.
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
const applePayButton = document.createElement("button");
applePayButton.setAttribute("id", "apple-pay-button");
applePayButton.classList.add(["apple-pay-button", "apple-pay-button-black"]);
applePayButton.addEventListener("click", runApplePay());
document.appendChild(applePayButton);
}
// Your information to link the payments to your Payment Gateway account.
const gatewayData = {
partnerName: "YOUR PARTNER NAME",
gatewayName: "YOUR GATEWAY NAME"
};
// Specifies the environment to be used when Payment Gateway makes requests. This can be set to "DEV" or "PROD".
const environment = "DEV";
const clientCanonicalName = "yourdomain.com";
const context = window.location.hostname;
// ...Additional code for Apple Pay and HTML manipulations...
// This function will be run when the user clicks the Apple Pay button.
function runApplePay() {
// ...Validate all the fields in the form...
const request = {
countryCode: "US",
currencyCode: "USD",
supportedNetworks: ["visa", "masterCard", "discover"], // credit cards supported
merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], // supports3DS is required
lineItems: [
{
label: "Invoice Payment",
type: "final",
amount: document.getElementById("amount").value
}
],
total: {
label: "YOUR COMPANY NAME",
amount: document.getElementById("amount").value
},
requiredBillingContactFields: ["postalAddress"] // for getting billing address through Apple Pay
};
const applePaySession = new ApplePaySession(3, request);
applePaySession.onvalidatemerchant = function (event) {
const processApplePayValidationRequestHandler = function (xmlHttpRequest) {
if (xmlHttpRequest && xmlHttpRequest.status === 200) { // OK response from Payment Gateway.
merchantSession = JSON.parse(xmlHttpRequest.response);
applePaySession.completeMerchantValidation(merchantSession);
} else{
applePaySession.abort();
// You would end up in this error block if the response from Payment Gateway does not have a status of "200".
// You will want to handle this case with custom error handling for your website.
console.error("Bad response.");
}
};
paymentGateway.processApplePayValidationRequest(
processApplePayValidationRequestHandler,
event,
gatewayData,
clientCanonicalName,
context,
environment
);
};
applePaySession.onpaymentmethodselected = function (event) {
const applePayPaymentMethodUpdate = {
newLineItems: [],
newTotal: {
label: "YOUR COMPANY NAME",
amount: document.getElementById("amount").value
}
};
applePaySession.completePaymentMethodSelection(applePayPaymentMethodUpdate);
};
applePaySession.begin();
};
</script>
```
Next, we'll implement the onpaymentauthorized event handler. This event handler is triggered when the user approves the payment. It must be set to a function that takes a single event parameter. If you requested billing information previously, the event will look something like this:
```javascript
{
bubbles: false,
cancelBubble: false,
cancelable: false,
composed: false,
currentTarget: null,
defaultPrevented: false,
eventPhase: 0,
isTrusted: true,
payment: {
billingContact: {
addressLines: ["123 StreetTest", "Apt. Test"],
administrativeArea: "IA",
country: "United States",
countryCode: "us",
familyName: "LastTest",
givenName: "FirstTest",
locality: "Test City",
phoneticFamilyName: "",
phoneticGivenName: "",
postalCode: "50236",
subAdministrativeArea: "",
subLocality: ""
},
token: {
paymentData: {
data: "IxSW9vGSjZuTDjRTxLFMVXIOeV9IZUC1CMT9T5mom52qhECUfRxg5HK1mXlJtdHPGKjVQ8ZW1a...",
header: {
ephemeralPublicKey: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf2GIiJzWVRN3SE1eCSEE...",
publicKeyHash: "JUnJAELKQtQQIozW3i/641LcRMU0U4AbxDdlgCP...",
transactionId: "541710803c8432303d57b4caf1e07524df5f1e39e7506ead335ae40324c62..."
},
signature: "TIAGCXqGSIb3DQEHAqCAMISWAQExMIID5jCCA4ugAwIBAgIIaGD2mdnMpw8w1UEAwlQXB...",
version: "EC_v1"
},
paymentMethod: {
displayName: "Visa 0492",
network: "Visa",
type: "debit"
},
transactionIdentifier: "2342AF12D520E5463546C234B..."
}
},
returnValue: true,
srcElement: ApplePaySession {...},
target: ApplePaySession {...},
timeStamp: 12035,
type: "paymentauthorized"
}
```
The purpose of the `onpaymentauthorized` event handler is to allow the website the opportunity to submit the transaction to Authorize.Net and notify Apple Pay that the transaction was accepted by Authorize.Net. To do this, first create a `transactionRequest` object. The transaction request includes the `amount`, the `paymentToken`, and any other information you may have requested from Apple Pay like billing address or shipping address. For a complete list of what can be included in a transaction request, see the `transactionRequest` object inside Authorize.Net's Create an Apple Pay Transaction.
To implement this function, we will use the function `paymentGateway.processApplePayValidationRequest`. This function will take in a callback function, your gateway data, the amount, the customer object, the order object, and the environment of Payment Gateway you want to send the request to. The callback function will take in the `XMLHttpRequest` object.
> If you would like to modify the `transactionRequest` object that is being sent to Authorize.Net, see the advanced usage section.
>
> `paymentGateway.processApplePayTransactionRequest` will add a default line item to the request body sent to Authorize.Net. You can specify your own line items by passing in an additional parameter to `paymentGateway.processApplePayTransactionRequest`. This function also builds the `billTo` object from `paymentData`. You can optionally pass in this object as a parameter as well. See @sourceallies/payment-gateway documentation for more information.
The final call to complete the transaction will look something like this:
```html
<script>
// This checks if `window.ApplePaySession` and if it can make payments. If both
// of these are true, the user is on Safari so we can add the Apple Pay
// button to the HTML.
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
const applePayButton = document.createElement("button");
applePayButton.setAttribute("id", "apple-pay-button");
applePayButton.classList.add(["apple-pay-button", "apple-pay-button-black"]);
applePayButton.addEventListener("click", runApplePay());
document.appendChild(applePayButton);
}
// Your information to link the payments to your Payment Gateway account.
const gatewayData = {
partnerName: "YOUR PARTNER NAME",
gatewayName: "YOUR GATEWAY NAME"
};
// Specifies the environment to be used when Payment Gateway makes requests. This can be set to "DEV" or "PROD".
const environment = "DEV";
const clientCanonicalName = "yourdomain.com";
const context = window.location.hostname;
// ...Additional code for Apple Pay and HTML manipulations...
// This function will be run when the user clicks the Apple Pay button.
function runApplePay() {
// ...Validate all the fields in the form...
const request = {
countryCode: "US",
currencyCode: "USD",
supportedNetworks: ["visa", "masterCard", "discover"], // credit cards supported
merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], // supports3DS is required
lineItems: [
{
label: "Invoice Payment",
type: "final",
amount: document.getElementById("amount").value
}
],
total: {
label: "YOUR COMPANY NAME",
amount: document.getElementById("amount").value
},
requiredBillingContactFields: ["postalAddress"] // for getting billing address through Apple Pay
};
const applePaySession = new ApplePaySession(3, request);
function handleProcessApplePayTransactionResponse(xmlHttpRequest) {
if (xmlHttpRequest && xmlHttpRequest.status === 200) { // OK response from Payment Gateway.
let status = ApplePaySession.STATUS_FAILURE;
const responseBody = JSON.parse(xmlHttpRequest.response);
if(responseBody && responseBody.messages && responseBody.messages.resultCode === "OK") {
status = ApplePaySession.STATUS_SUCCESS;
}
applePaySession.completePayment(status);
// You will want to handle this case with custom success handling for your website.
console.log(responseBody);
} else {
// You would end up in this error block if the response from Payment Gateway does not have a status of "200".
// You will want to handle this case with custom error handling for your website.
console.error("Bad response.");
}
}
applePaySession.onvalidatemerchant = function (event) {
const processApplePayValidationRequestHandler = function (xmlHttpRequest) {
if (xmlHttpRequest && xmlHttpRequest.status === 200) { // OK response from Payment Gateway.
merchantSession = JSON.parse(xmlHttpRequest.response);
applePaySession.completeMerchantValidation(merchantSession);
} else{
applePaySession.abort();
// You would end up in this error block if the response from Payment Gateway does not have a status of "200".
// You will want to handle this case with custom error handling for your website.
console.error("Bad response.");
}
};
paymentGateway.processApplePayValidationRequest(
processApplePayValidationRequestHandler,
event,
gatewayData,
clientCanonicalName,
context,
environment
);
};
applePaySession.onpaymentmethodselected = function (event) {
const applePayPaymentMethodUpdate = {
newLineItems: [],
newTotal: {
label: "YOUR COMPANY NAME",
amount: document.getElementById("amount").value
}
};
applePaySession.completePaymentMethodSelection(applePayPaymentMethodUpdate);
};
applePaySession.onpaymentauthorized = function (event) {
const amount = document.getElementById("amount").value;
const customer = {
email: document.getElementById("email_address").value
};
const order = {
description: "Payment to Source Allies",
invoiceNumber: document.getElementById("invoice_number").value
};
paymentGateway.processApplePayTransactionRequest(
handleProcessApplePayTransactionResponse,
event.payment,
gatewayData,
amount,
customer,
order,
environment/*,
lineItems,
billTo */
);
};
applePaySession.begin();
};
</script>
```
A good response will look something like this:
```json
{
"refId": null,
"messages": {
"resultCode": "OK",
"message": [
{
"code": "I00001",
"text": "Successful."
}
]
},
"sessionToken": null,
"transactionResponse": {
"responseCode": "1",
"rawResponseCode": null,
"authCode": "SL47NA",
"avsResultCode": "Y",
"cvvResultCode": "P",
"cavvResultCode": "2",
"transId": "40047844022",
"refTransID": "",
"transHash": "",
"testRequest": "0",
"accountNumber": "XXXX1111",
"entryMode": null,
"accountType": "Visa",
"splitTenderId": null,
"prePaidCard": null,
"messages": {
"message": [
{
"code": "1",
"description": "This transaction has been approved."
}
]
},
"errors": null,
"splitTenderPayments": null,
"userFields": null,
"shipTo": null,
"secureAcceptance": null,
"emvResponse": null,
"transHashSha2": "",
"profile": null,
"networkTransId": "ERQL94OI6JZQRNCF7Q18U1P"
},
"profileResponse": null
}
```
Declined transactions will look something like this:
```json
{
"refId": null,
"messages": {
"resultCode": "OK",
"message": [
{
"code": "I00001",
"text": "Successful."
}
]
},
"sessionToken": null,
"transactionResponse": {
"responseCode": "2",
"rawResponseCode": null,
"authCode": "",
"avsResultCode": "Y",
"cvvResultCode": "P",
"cavvResultCode": "2",
"transId": "40047885239",
"refTransID": "",
"transHash": "",
"testRequest": "0",
"accountNumber": "XXXX1111",
"entryMode": null,
"accountType": "Visa",
"splitTenderId": null,
"prePaidCard": null,
"messages": null,
"errors": {
"error": [
{
"errorCode": "2",
"errorText": "This transaction has been declined."
}
]
},
"splitTenderPayments": null,
"userFields": null,
"shipTo": null,
"secureAcceptance": null,
"emvResponse": null,
"transHashSha2": "",
"profile": null,
"networkTransId": "0BKWE0WSLF0N2WH79JZUYKL"
},
"profileResponse": null
}
```