Prebuilt payment flow — Redirect

Redirect integration allows running payments using the prebuilt payment flow.

To accept payments in your application or website via redirect, use POST /purchases/ request to create the Purchase and receive the checkout_url. Redirect the customer to the checkout_url to enter their card details for processing. After the payment is processed, the system will redirect the customer back to your website (take note of success_redirect, failure_redirect).

You have three options to check payment status:

  1. Use success_callback parameter of the Purchase object.

  2. Use GET /purchases/<purchase_id>/ request.

  3. Set up a Webhook using the Developers section of your account or use Webhook API to listen to purchase.paid, or purchase.payment_failure event on your server.

Setting the skip_capture flag to true allows you to separate the authentication and payment execution steps, allowing you to reserve funds on the customer’s card account for some time.

This flag can also enable preauthorization capability, allowing you to save the card without a financial transaction, if possible.

If the customer agrees to store his card for future purchases, there will be an option to pay with a single click next time. To enable this, create a Client object for each of your clients and provide client_id parameter value in your Purchase creation requests.

To create a Purchase or a BillingTemplate, you must specify the Brand ID and API key. You can find both in the Developers section of your account.

Custom payment flow — Direct Post

Direct post integration allows running payments through the custom payment flow.

To accept payments in your application or website, use POST /purchases/ request to create a Purchase.

To capture customers card details use an HTML <form> hosted on your website with method="POST" and action pointing to the direct_post_url of the transaction.

You will also need to fill the form with <input>’s for the fields with card details. As a result, when a customer submits their card details, it will be posted straight to our system, allowing you to customize the checkout as you wish. At the same time, your PCI DSS requirement is only raised to Self-Assessment Questionnaire (SAQ A-EP), as your system doesn’t receive or process card data.

For more details, see the documentation on Purchase’s direct_post_url field.

Tokenization & recurring payments

You can store card tokens and charge the respective cards without user interaction if the payment channel supports tokenization.

When you pass remember_card=on to direct_post_url, the respective Purchase’s ID will serve as a card token. This initial Purchase will have the is_recurring_token field set to true.

To charge the tokenized card once again, create a new Purchase and then call the POST /purchases/{new_purchase_id}/charge/. In the request body, provide "recurring_token": "initial_purchase_id". When the request succeeds (response code 200), the new Purchase will become paid. The token will be persisted in the Purchase’s recurring_token field.

Use "recurring_token": "initial_purchase_id" in all the upcoming POST /purchases/{new_purchase_id}/charge/ requests.

If you wish to delete the recurring token stored for the initial Purchase, use the POST /purchases/{initial_purhcase_id}/delete_recurring_token/ request. Its is_recurring_token will reset to false.

Custom payment flow — Server-to-Server

Server-to-Server (“S2S”) integration allows running payments on the server level without direct interaction between the client’s browser or application and API.

You can build an integration that prevents payers from accessing platform resources directly. In this flow, 3D Secure implementation allows API clients to:

Check 3D Secure enrolment, and if the card is enrolled, receive ACS URL together with all the necessary params for redirection to ACS (PaReq, MD); Redirect the payer to the ACS system of their issuer bank; Receive the payer back and execute the authorization with a separate request.

If the card is not enrolled in 3D Secure, authorization will execute synchronously.

Please note that 3DSv2 which is now the industry standard is fully supported by the S2S flow. While PaReq/PaRes below are 3DSv1 parameters (replaced by creq/cres in 3DSv2 challenge), in case of 3DSv2 proxy ACS solution (where the system is accepting the cardholder navigation using 3DSv1 flow and is performing all parts of 3DSv2 verification and challenge on behalf of merchant) is implemented to maintain API compatibility for older integrations.

To accept payments in your application or website via S2S:

  1. Ensure the Purchase is created as described in Custom payment flow — Direct Post. As per the Purchase’s direct_post_url field description, you will need to ensure all the necessary criteria are met, including success_redirect/failure_redirect fields defined for Purchase and set to arbitrary valid URLs (they will not receive any redirects in the S2S scenario);

  2. Implement the following request in your server code, appending “?s2s=true” to direct_post_url to form the resulting endpoint (you can obtain the S2S token value from your account manager):

    POST {direct_post_url}?s2s=true
    

    Specify the following headers:

    Content-Type: application/json
    Authorization: Bearer {S2S token}
    

    In the request body, provide the following data in JSON (you can omit some of the fields, then system will use default values; We recommend providing correct values from the user’s browser as it can affect 3D Secure success rate):

    {
      "cardholder_name": "John Doe",
      "card_number": "4444333322221111",
      "expires": "01/23",
      "cvc": "123",
      "remember_card": "on",
      "remote_ip": "8.8.8.8",
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
      "accept_header": "text/html",
      "language": "en-US",
      "java_enabled": false,
      "javascript_enabled": true,
      "color_depth": 24,
      "utc_offset": 0,
      "screen_width": 1920,
      "screen_height": 1080
    }
    
    Field name Required Validation criteria/remarks Default value
    cardholder_nameYLatin letters only (space and apostrophe (’), dot (.), dash (-) symbols are also allowed), max 30 characters
    card_numberYtext, digits only, no whitespace, max 19 characters
    expiresYtext in ‘MM/YY’ format, digits and a slash only (/^\d\/\d$/), max 5 characters
    cvcYnumeric string of 3 or 4 digits
    remember_cardNliteral value “on” to save card, any other string otherwise
    remote_ipYexternal IP of payer’s browser in IPv4 or IPv6 format
    user_agentNUser-Agent as sent by the payer’s browser, max 2048 chargeMozilla/5.0 (X11; Linux x86_64) AppleWebKit/ 537.36 (KHTML, like Gecko) Chrome/ 88.0.4324.96 Safari/ 537.36
    accept_headerNSame as above, max 2048 characterstext/html
    languageNSame as above, max 8 charactersen-US
    java_enabledNbooleanfalse
    javascript_enabledNbooleantrue
    color_depthNinteger in 0-255 range24
    utc_offsetNinteger in -32,768 to 32,767 range0
    screen_widthNinteger in uint64 range1920
    screen_heightNinteger in uint64 range1080
  3. If the card is not enrolled in 3S Secure, then a response will contain the field “status” with one of the following values:

    • “executed” in case of a successful payment authorization;
    • “authorized” in case fund reservation using Purchase.skip_capture was requested;
    • “error” in case of an authorization error.

    Example:

    {"status": "executed"}
    

    You will receive “executed” or “authorized” statuses with a response status code 200 and “error” status - with a status code of 400.

    In all of those cases, it is necessary to set up webhooks for purchase events (purchase.paid, purchase.payment_failure at least) to receive further information about the status of the financial transaction.

  4. If the card is enrolled in 3D Secure, the response will have a status code of 200, the status will be 3DS_required, and the response will contain additional fields:

    {
      "status": "3DS_required",
      "Method": "(POST|GET)",
      "PaReq": "...",
      "MD": "... (can arrive empty)",
      "URL": "http://url.of.acs.bank/",
      "callback_url": "https://..."
    }
    

    It’s necessary to ensure your client’s browser makes a request with the method specified in Method (GET or POST only) to the ACS of issuer bank returned in “URL”, including the values of MD and PaReq as received (use query params in case of GET and request body params in case of POST). Be aware that MD might arrive empty – in that case, you can send it further as an empty string.

    In addition to those, you also need to include the TermUrl parameter in the client’s browser request, pointing to the URL in your system where the customer’s navigation will be expected. Once the payer approves the transaction, he will be redirected using the POST method to that URL with MD and PaRes params in the request body.

  5. Once the client is back to TermUrl in your system and you have received the MD and PaRes, it’s needed to transmit them to the platform to complete the authorization. Send the following request from your server code (no auth headers required):

    POST {callback_url from step 4.}
    
    Content-Type: application/x-www-form-urlencoded
    MD={MD received, if any}&PaRes={PaRes received}
    

    The response will contain the authorization status in JSON format and will be identical to the format described in the previous section.

Testing Integration

It’s possible to test-drive all checkouts using a test Purchase.

For a successful payment, you can use the following card numbers:

  • 4444 3333 2222 1111 - non-3D Secure card
  • 5555 5555 5555 4444 - 3D Secure card

For both cards, please use:

  • any cardholder name
  • any expiry larger or equal to the current month/year
  • CVC = 123

For a failed payment, please change the CVC or expiration date.

When using a 3D Secure enrolled card in S2S checkout, an incorrect CVC will trigger an authorization failure on the S2S callback step (after the customer returns from test ACS). Using a wrong expiry date emulates data validation failure and results in immediate error before that step.