Connect-E Wait Pre-execute - Repeat Payment

This section describes how to collect a cardholder's CV2 code in order to create a repeat transaction.

Process Flow

  1. Merchant creates an access token using the Connect-E REST API with the crossReference of another transaction and the new payload flag waitPreExecute: true.
  2. Merchant loads their payment page containing the Connect-E repeat payment iframe.
  3. Cardholder types their CV2 into the Connect-E iframe and presses the merchant's pay button.
  4. Merchant runs the executePayment function in the supplied JS SDK.
  5. 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.
  6. The Connect-E JS SDK will return a promise object containing transaction execution info, the resulting status code should be 99 (Waiting).
  7. Merchant calls the new resume endpoint in the Connect-E REST API within 15 minutes (We cannot execute beyond this).
  8. Merchant makes an optional call to the transaction details endpoint in the Connect-E REST API to confirm the transaction status.

Recurring Payment Example

<div id="recurring-demo-payment"></div>
<div id="recurring-errors"></div>
<button id="recurring-test-pay" class="btn-primary btn pull-right" data-loading-text="Processing...">Pay</button>
<div id="recurring-demo-result" style="display: none">
    <h5>Payment Complete</h5>
    <dl>
        <dt>Status Code</dt>
        <dd id="recurring-status-code"></dd>
        <dt>Auth Code</dt>
        <dd id="recurring-auth-code"></dd>
    </dl>
</div>

const config = {
  onIframeLoaded: () => { console.log("iframe loaded") },
  paymentDetails: {
      paymentToken: /*access token here*/
  },
  containerId: "recurring-demo-payment",
  fontCss: ['https://fonts.googleapis.com/css?family=Do+Hyeon'],
  styles: {
      cv2: {
          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',
              backgroundColor: '#fff',
              borderColor: '#80bdff',
              outline: '0',
              boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)'
          },
          error: {
              color: "#B00",
              borderColor: "#B00"
          },
          valid: {
              color: "green"
          },
          label: {
              display: 'none'
          },
          container: {
              width: "50%",
              float: "left",
              paddingLeft: "5px",
              boxSizing: "border-box"
          },
      },

  },
  text: {
      cv2: {
          label: "CVV",
          placeholder: "CVV"
      }
  }
};

const recurringPayment = new Connect.ConnectERecurringPayment(config, displayErrors);

const btnRecurringTestPay = document.getElementById("recurring-test-pay");
btnRecurringTestPay.onclick = () =>{
  btnRecurringTestPay.innerText = 'loading';
  btnRecurringTestPay.setAttribute("disabled", "true");
  recurringPayment.executePayment()
      .then(function(data) {
          document.getElementById("recurring-demo-payment").hidden = true;
          btnRecurringTestPay.remove();
          document.getElementById("recurring-demo-result").hidden = false;
          document.getElementById("recurring-status-code").innerText = data.statusCode;
          document.getElementById("recurring-auth-code").innerText = data.authCode;
      }).catch(function(data) {
              console.log('Payment Request failed: ' + data);
              btnRecurringTestPay.innerText = 'Pay';
              btnRecurringTestPay.removeAttribute("disabled");
              if (typeof data === 'string') {
                  document.getElementById("recurring-errors").innerText = data;
              }
              if (data && data.message) {
                  document.getElementById("recurring-errors").innerText = data.message;
              }
          }
      );
  };

function displayErrors(errors) {
  const errorsDiv = document.getElementById('recurring-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 { 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;
}

Find cross reference

Before we can perform a repeat payment, we must perform an initial payment with a set of card details.

When fetching a payment from the Connect-E REST API you may notice a crossReference field which can be used to scope repeat payments.


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}
        

{
    ...
    "crossReference":"637771113577638811111",
    ...
}
        

Create 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}",
    "crossReference": "{CROSS_REFERENCE_FROM_PREVIOUS_PAYMENT}",
    "waitPreExecute": true
  }' \
  https://e.test.connect.paymentsense.cloud/v1/access-tokens
        

{
    "id": "z9xBb0waUd5TjsjmU1rDsDAnJ_ZMniL3nnHbKK3pL7vNJ-bgfx31LTgWoePnLdWMFUbZEKOhwQHLLN",
    "expiresAt": 1637839484
}
        

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: "recurring-demo-payment",
};

const displayErrors = func(errors) {
    // Handle errors by appending to your DOM
};

const recurring = new Connect.ConnectERecurringPayment(config, displayErrors);
        
<div id="recurring-demo-payment">
    <!-- Connect-E recurring payment iframe will be appended here -->
</div>

NOTE: For more detailed config and callback configuration options, please review the Connect-E - Standard Repeat Payment page.

Submit Payment

After the user has input their CV2 into the provided iframe input field, you need to map the button to trigger the payment processing.

<button id="recurring-test-pay" class="btn-primary btn pull-right" data-loading-text="Processing...">Pay</button>

const btnRecurringTestPay = document.getElementById("recurring-test-pay");

btnRecurringTestPay.onclick = () => {
    recurring.executePayment()
        .then(function(data){
            /*handle response here*/
        }).catch(function(data){
            /*handle failure here*/
        };
};
        

When the promise is fulfilled the following object will be passed.

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.
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.

Resume Payment

If your wait pre-execute transaction completed successfully you should have received a status code of 99 indicating the transaction is paused, you must now resume the transaction by performing an API 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}" \
  https://e.test.connect.paymentsense.cloud/v1/payments/{ACCESS_TOKEN}/resume
        

{
    "authCode":"1",
    "acsUrl":"",
    "paReq":"",
    "md":"6378400647906619404111",
    "statusCode":0,
    "message":"AuthCode: 1",
    "stepUpUrl":"",
    "jwt":""
}
        

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-25 11:32:59.897382 +0000 UTC",
    "statusCode":0,
    "message":"AuthCode: 1",
    "crossReference":"6378400647906619404111",
    "authCode":"1",
    "cardNumber":"520000******0056",
    "expiryDate":"2024-12-31",
    "cardType":"MASTERCARD",
    "cardName":"Test ",
    "billingAddress":{
        "address1":"",
        "address2":"",
        "address3":"",
        "address4":"",
        "city":"",
        "state":"",
        "postcode":"",
        "countryCode":""
    },
    "shippingDetails":{
        "Name":"",
        "Address":{
            "address1":"",
            "address2":"",
            "address3":"",
            "address4":"",
            "city":"",
            "state":"",
            "postcode":"",
            "countryCode":""
        }
    },
    "userEmailAddress":""
}