Connect-E Save Payment Method - One off Payment
The save payment method feature was created to give our merchants greater control over their payments.
With this feature a user inputs their card details in the same way; flag that they want to save their payment method; we run 3DS in the same way if applicable; but when executing the payment, the payment method is saved for future use.
To enable the save payment method feature you will need to pass a new customerId
parameter when creating access tokens
and then an additional savePaymentMethod
flag when calling execute payment. The flag will default to false
if not provided and an error will occur if customerId
is not provided when creating the access token.
The customerId
parameter should be generated by the merchant and uniquely identify the customer.
Process Flow
- Merchant creates an access token using the Connect-E REST API with the new payload parameter
customerId: 'CUSTOMER_ID'
. - Merchant loads their payment page containing the Connect-E standard payment iframe.
- Cardholder types their card details into the Connect-E iframe and presses the merchant's pay button.
- Merchant runs the
executePayment
function in the supplied JS SDK passing the new flagsavePaymentMethod: true
as additional information. - If 3D secure is required from the cardholder's bank, the Connect-E JS SDK will load an overlay modal to capture the additional information.
- The promise resolves with the outcome of the transaction, including status code and auth code.
- Confirm the status of the transaction via the Connect-E REST API
Web Payment Example
Payment Complete
- Status Code
- Auth Code
<div id="demo-payment"></div>
<div id="errors"></div>
<button id="testPay" class="btn-primary btn pull-right"
data-loading-text="Processing...">Pay</button>
<div id="demo-result" style="display: none">
<h5>Payment Complete</h5>
<dl>
<dt>Status Code</dt>
<dd id="status-code"></dd>
<dt>Auth Code</dt>
<dd id="auth-code"></dd>
</dl>
</div>
const payConfig = {
paymentDetails: {
paymentToken: /*access token here*/
},
containerId: "demo-payment",
fontCss: ['https://fonts.googleapis.com/css?family=Do+Hyeon'],
styles: {
base: {
default: {
color: "black",
textDecoration: "none",
fontFamily: "'Do Hyeon', sans-serif",
boxSizing: "border-box",
padding: ".375rem .75rem",
boxShadow: 'none',
fontSize: '1rem',
borderRadius: '.25rem',
lineHeight: '1.5',
backgroundColor: '#fff',
},
focus: {
color: '#495057',
borderColor: '#80bdff',
},
error: {
color: "#B00",
borderColor: "#B00"
},
valid: {
color: "green",
borderColor: 'green'
},
label: {
display: 'none'
}
},
cv2: {
container: {
width: "25%",
float: "left",
boxSizing: "border-box"
},
default: {
borderRadius: "0 .25rem .25rem 0"
}
},
expiryDate: {
container: {
width: "25%",
float: "left",
borderRadius: '0rem',
},
default: {
borderRadius: "0",
borderRight: "none"
},
},
cardNumber: {
container: {
width: "50%",
float: "left",
},
default: {
borderRadius: ".25rem 0 0 .25rem",
borderRight: "none"
},
}
}
}
const connectE = new Connect.ConnectE(payConfig, displayErrors);
const btnTestPay = document.getElementById("testPay");
var extraInfo = {
savePaymentMethod: true
};
btnTestPay.onclick = () =>{
btnTestPay.innerText = 'loading';
btnTestPay.setAttribute("disabled", "true");
connectE.executePayment(extraInfo)
.then(function(data) {
document.getElementById("demo-payment").hidden = true;
btnTestPay.remove();
document.getElementById("demo-result").hidden = false;
document.getElementById("status-code").innerText = data.statusCode;
document.getElementById("auth-code").innerText = data.authCode;
}).catch(function(data) {
console.log('Payment Request failed: ' + data);
btnTestPay.innerText = 'Pay';
btnTestPay.removeAttribute("disabled");
if (typeof data === 'string') {
document.getElementById("errors").innerText = data;
}
if (data && data.message) {
document.getElementById("errors").innerText = data.message;
}
}
);
};
function displayErrors(errors) {
const errorsDiv = document.getElementById('errors');
errorsDiv.innerHTML = '';
if (errors && errors.length) {
const list = document.createElement("ul");
for (const error of errors){
const item = document.createElement("li");
item.innerText = error.message;
list.appendChild(item);
}
errorsDiv.appendChild(list);
}
}
#demo-payment iframe { width: 100%; }
#demo-result, #demo-payment, #recurring-demo-payment, #recurring-payment { padding: 5px; }
#errors li { color: #B00; }
iframe.threeDs {
width: 400px;
height: 400px;
margin: 100px 0 0 -175px;
position: fixed;
top: 0;
left: 50%;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.6);
background-color: white;
}
Setup Connect-E Save Payment Method - One off Payment
Create Payment Token / Access Token
You will need to form a payment/access token to scope your upcoming payment first by a call to the Connect-E REST API.
curl \
-X POST \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {API_KEY_JWT}" \
-d '{
"merchantUrl": "{API_KEY_MERCHANT_URL}",
"currencyCode": "826",
"amount": 100,
"transactionType": "SALE",
"orderId": "{MERCHANT_ORDER_ID}",
"orderDescription": "{MERCHANT_ORDER_DESCRIPTION}",
"customerId": "{MERCHANT_CUSTOMER_ID}"
}' \
https://e.test.connect.paymentsense.cloud/v1/access-tokens
{
"id":"g2tfTjSV7ImoPQ-R91yCmdycOzz2nWmfAZBdFsgqmqTWGsZW5CpBaqBTPd96ZsU0Fgrvq-tlHmfjMuYU07awx2aYCwdcHe4iJgc",
"expiresAt":1637772363
}
Note: Please see the Setup Test Account page for test JWT details.
Note: The id
field is the access token.
Load the payment iframe
In order to take a payment, you will now need to use the access token created, with the Connect-E JavaScript SDK.
<script src="https://web.e.test.connect.paymentsense.cloud/assets/js/client.js"></script>
NOTE: We recommend using our asset URL in your website in order to apply the latest bug fixes/features.
In order to load the payment detail capture iframe into your website you will need to define the element for the iframe to append too, and call the SDK.
const config = {
paymentDetails: {
paymentToken: "{ACCESS_TOKEN}"
},
containerId: "demo-payment",
};
const displayErrors = func(errors) {
// Handle errors by appending to your DOM
};
const connectE = new Connect.ConnectE(config, displayErrors);
<div id="demo-payment">
<!-- Connect-E payment iframe will be appended here -->
</div>
NOTE: For more detailed config and callback configuration options, please review the Connect-E Standard - One off payment page.
Submit Payment
After the user has entered their card details into the provided iframe input fields, you need to map the button to trigger the payment processing.
<button id="testPay" class="btn-primary btn pull-right" data-loading-text="Processing...">Pay</button>
const btnTestPay = document.getElementById("testPay");
var extraInfo = {
savePaymentMethod: true
};
btnTestPay.onclick = () => {
connectE.executePayment(extraInfo)
.then(function(data){
/*handle response here*/
}).catch(function(data){
/*handle failure here*/
};
};
When the promise is fulfilled the following object will be passed.
NOTE: For more detailed additional information, please review the Connect-E Standard - One off payment page.
Transaction Result
Property | Description |
---|---|
statusCode
number
|
Indicated the status of the transaction. 0 for a successful transaction. |
authCode
string
|
If the transaction was successful, then the auth code is passed out here. |
message
string
|
This gives a more detailed description of the status of the transaction. |
Status Code
Status Code | Result | Description |
---|---|---|
0 | Successful | The transaction was successful |
3 | Authorizing | The card holder has not completed 3DS, this status will only be seen on the REST API. |
4 | Referred | The card issuer has parked the transaction awaiting contact with the customer before proceeding to authorise or decline the transaction. |
5 | Declined | The transaction was declined by the card issuer or acquiring bank. |
20 | Duplicate Transaction | The transaction which was processed was a duplicate. Ensure each transaction has a unique OrderId. |
30 | Failed | Error executing transaction. |
40 | Processing | The transaction is currently being processed, please check status again. This status will only be seen from the REST API if called before the JavaScript promise resolves or the Webhook is called. |
90 | Revoked | The access token was revoked while the cardholder was completing 3DS authentication. The transaction was stopped before being sent for processing. |
99 | Waiting Pre-execute | The transaction has been paused pre-execution using the waitPreExecute flag; a call to resume the transaction is expected within 15 minutes. |
400 | Invalid Request | The request has failed validation by our servers and the transaction has not been submitted to the gateway. Possible causes for this are invalid transaction type or other data in the request. |
401 | Issue with Access Token | The access token being used is not valid, the transaction has not been submitted to the gateway. This can be caused if the access token has already been used or the 30 minute expiry time has elapsed. |
404 | No Access Token Supplied | No access token has been supplied to Connect-E. Transaction has not been submitted to the gateway |
500 | Internal Server Error | There's been an error submitting the transaction, please check the REST API for the status of the transaction. |
Verify Payment
Although not totally necessary, it is still advised to perform a closing GET request to fetch the full transaction info for your records. In future we may append more information here than will otherwise be provided in the payment execution response.
curl \
-X GET \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {API_KEY_JWT}" \
https://e.test.connect.paymentsense.cloud/v1/payments/{ACCESS_TOKEN}
{
"transactionDateTime":"2021-11-24 16:24:18.863914 +0000 UTC",
"statusCode":0,
"message":"AuthCode: 12345",
"crossReference":"637771113577638811222",
"authCode":"12345",
"cardNumber":"520000******0007",
"expiryDate":"2024-12-31",
"cardType":"MASTERCARD",
"cardName":"John Watson",
"billingAddress":{
"address1":"",
"address2":"",
"address3":"",
"address4":"",
"city":"",
"state":"",
"postcode":"",
"countryCode":""
},
"shippingDetails":{
"Name":"",
"Address":{
"address1":"",
"address2":"",
"address3":"",
"address4":"",
"city":"",
"state":"",
"postcode":"",
"countryCode":""
}
},
"userEmailAddress":"",
"paymentMethodId": "pm_jiVDZeA9QBCoXuAYokiIWw"
}