Web Content Display

Open Payment Gateway - OPG

This documentation guides you through optile's Open Payment Gateway (OPG) features for frontend checkout and backend use cases. It provides important information about integration scenarios, testing possibilities, and references.

For a Glossary of Terms, go to the end of this document. 

Open Payment Gateway - OPG

This documentation guides you through optile's Open Payment Gateway (OPG) features for frontend checkout and backend use cases. It provides important information about integration scenarios, testing possibilities, and references.

For a Glossary of Terms, go to the end of this document. 

Please sign in to view further details of this article. Login

Web Content Display

First Steps

Every potential checkout webpage includes information about the purchase, payment amount, customer details, plus a few additional details. This information is always issued from your server-side system via HTTP POST Request. This is what we call a LIST Request.

To test these features, you need an account for our website. If you do not have an account, please email support@optile.net and we will create one for you. You can start experimenting with OPG Sandbox as soon as you get your optile account details.

Try your first LIST Request by following these 4 steps:

1. Configure your OPG Sandbox
  • In the portal, go to the Dashboard and open the Provider Contracts section
  • Choose Test Adapter "TESTPSP". Make sure you add a valid URL eg (http://www.dummyvalidurl.com)
  • Select "Countries and networks", eg Germany (DE), France (FR), and payment methods VISA, MasterCard, SEPA Direct Debit, PayPal, and Carte Bleue
  • In the country-methods matrix at the end of the dialog, select Carte Bleue to be available in France but not Germany
  • Access the Routing App from the Merchant Portal, and activate the routes per country by choosing a routing strategy.
2. Generate a Sandbox Payment Token

You must generate a Token to authenticate your system against the Payment Gateway API.

To generate a Sandbox token:

  • Go to the portal dashboard, open "Tokens" and generate a Sandbox Payment Token. It will be used later to authenticate your system against the Payment Gateway.
  • Copy and save the value immediately. For security reasons, it will not be shown again and cannot be recovered. You can create a new one if necessary.
3. Install a tool for manual testing

We suggest that you use one of the browser plugins listed in Tools for Manual Testing so you can submit JSON POST requests easily by hand.

4. Do a LIST Request

Use the following values to submit your first LIST Request with the chosen tool:

  • URL: https://api.sandbox.oscato.com/api/lists
  • HTTP Method: POST
  • Basic Authentication User Name: [Your merchant code]
  • Basic Authentication Password: [Your sandbox payment token]
  • Header Content Type: application/vnd.optile.payment.enterprise-v1-extensible+json
  • Header Accept: application/vnd.optile.payment.enterprise-v1-extensible+json
  • Request Body Content: Copy and paste the content on the side to the tool that you're using. This content is just an example; make sure that it stays in JSON Format.

Find out more about authentication and version headers in API Access.

For your request you should receive a successful HTTP 200 response with a list of available payment methods for this transaction (attribute networks.applicable).

If you configured your OPG Sandbox as described above, Carte Bleue will not show in this list.

5. Visualize the LIST

Follow the steps below to visualize the content of a generated LIST with a default style, using optile's Hosted Payment Page:

  • Examine the LIST Response and take the content of the links.self attribute. That's the URL of the LIST Resource:

    https://api.sandbox.oscato.com/pci/v1/59722056cb4280f9550078e3lffpph128vffgueil7chn475bs

  • Append it as query parameter listUrl to the following URL of the Hosted Payment Page, and open it in a browser:

    https://resources.sandbox.oscato.com/paymentpage/v3/responsive.html?listUrl=https://api.sandbox.oscato.com/pci/v1/59722056cb4280f9550078e3lffpph128vffgueil7chn475bs

Note: You have 30 minutes to make a successful CHARGE. After 30 minutes, you will get an error and you should create a new LIST Session (That's also why the link above will not work).

Play Around

Make another LIST Request, with an incremented transactionId (it's technically not required but it is good practice to keep them unique) and change the attribute country to FR. Submit again. Now you should see a similar list in the response, but this time with Carte Bleue because we configured it earlier for France only.

Also, you can copy the logo URL (attribute links.logo) of one of the networks and open it in a browser. The logo of that payment method will show.

Take one of the credit cards in the list and open the URL from links.localizedForm in a browser. You will see a snippet of a simple HTML form without any styling. If you like, you can open the HTML source code. This snippet is another building-block provided by OPG to generate the payment page.

To see an out-of-the-box example of how a payment page is rendered, see our Demo. You can also play around with the country parameter that should go into the LIST Request as well as several parameters offered by our AJAX Integration JavaScript library.

Example of LIST Request
{
  "transactionId": "tr101",
  "country": "DE",
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2016"
  },
  "style" : {
    "hostedVersion":"v3"
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}

Example of LIST Response
{
"links": {
  "self": "https://api.sandbox.oscato.com/pci/v1/5a4f43dabc12312dfef5752blt5et3mnk2abc123u0fm79bud2"},
"timestamp": "2018-01-05T09:22:31.355+0000",
"operation": "LIST",
"resultCode": "00000.11.000",
"resultInfo": "4 applicable and 0 registered networks are found",
"returnCode": {
  "name": "OK",
  "source": "GATEWAY" },
"status": {
  "code": "listed",
  "reason": "listed" },
"interaction": {
  "code": "PROCEED",
  "reason": "OK" },
"identification": {
  "longId": "5a4f43d7148b512dfef5752blt5et3mnk226k45uu0fm79bud2",
  "shortId": "02694-35736",
  "transactionId": "id_h0010" },
"networks": {
  "applicable": [{
    "code": "MASTERCARD", ... }]
... }

Web Content Display

Tools for Manual Testing

To see your optile payment (Sandbox) credentials working, or to experiment with requests and responses, we recommend a simple tool for submitting POST requests before you start implementing. Use these First Steps as your starting point.

Depending on your preferred environment, we recommend:

1. Insomnia

Free and open source, compatible with Windows, Mac and Linux operating systems. Download from the official page.

2. Firefox Add-On: RESTer

Get it from Firefox Add-ons

RESTer

3. Chrome App: Advanced REST Client

Get it from Chrome Web Store

4. Command line tool: cURL

Mac and Linux operating systems should have cURL available by default.

How to install cURL on Windows:

  1. Go to http://curl.haxx.se/download.html
  2. Download Win32 or Win64 Generic with SSL
  3. Copy curl.exe into a system path, e.g. C:\Windows\System32

Get your Merchant Code and Payment Token together, and run this command:

Command
curl --user [YOUR MERCHANT CODE]/[YOUR TOKEN]: --header "Accept:application/vnd.optile.payment.enterprise-v1-extensible+json" --data "transactionId=222&country=DE&payment.amount=9.99&payment.reference=Order-111&payment.currency=EUR&customer.number=333" -k https://api.sandbox.oscato.com/api/lists

Note that this request does not use JSON as content type for the input but (implicitly) application/x-www-form-urlencoded. If successful, the result will be JSON script and start like this (depending on your configuration):

JSON Result Example
{
"links": {
  "self": "https://api.sandbox.oscato.com/pci/v1/5a4fabc1238b512dfef5752blt5et3mnk226k4abc12379bud2"},
"timestamp": "2018-01-05T09:22:31.355+0000",
"operation": "LIST",
"resultCode": "00000.11.000",
"resultInfo": "4 applicable and 0 registered networks are found",
"returnCode": {
  "name": "OK",
  "source": "GATEWAY"}
...
}

Web Content Display

API Access

API Types and Authentication

In our API Reference you will find a complete and formal documentation of all API calls. Please note the distinction between Client API and Server API. Endpoints in the Client API are designed to be accessed by frontends, eg web browsers, without authentication. For example the CHARGE Request exists in a frontend accessible version. The Server API is for calls from your servers, such as the LIST Request.

Server API calls require HTTPS Basic Authentication with these credentials:

  • Login Name: [your merchant code]
  • Password: [your payment token]

To generate payment tokens, you access the Merchant Portal (requires access rights). Contact our support team at support@optile.net for help with permissions.

Do not make requests to the Server API from a browser or any other client under control of the end customer, because it would expose your credentials.

API Changes

In your contract with optile we state that new API response parameters can be added in any release without explicit warning. This will not affect the existing functionality and not require further action from you. Your system only needs to be robust against additional response attributes.

For example, if you use Java with the Jackson parser for JSON, please set the FAIL_ON_UNKNOWN_PROPERTIES to false (see the official Jackson parser documentation and additional details on Stackoverflow).

Of course we will never rename any request or response parameters and never introduce new mandatory request parameters without the contractual notice periods. So with a robust system as described above you are safe.

You are contractually obliged to implement your API integration in a way that it is robust against additional response parameters.

Accept and Content Type Headers

For every request, you should set two HTTP headers:

  • Content Type indicates the content format of your input
  • Accept indicates the content format you expect to receive in the reply

For both please use the value: application/vnd.optile.payment.enterprise-v1-extensible+json

This implies communication via JSON. For the level and version part (enterprise-v1-extensible in this case) we may allow custom contractual agreements and hence additional values in the future.

CORS support in Sandbox

Although the Sandbox and Live environment APIs are generally the same, there is one slight technical difference to allow for particular testing and demonstration scenarios:

The Sandbox environment will generally allow Cross-origin resource sharing (CORS), by providing the shown additional HTTP headers in the reply >>

The Live environment only allows CORS  for the very few Client Payment API calls (see above at Authentication and the API Reference). In all other cases CORS will not return the aforementioned headers -- so a LIST Request from a browser (for example) is not possible.

As long as you do not try to sidestep the rules from the Basic Authentication and try to initiate server-to-server calls from a browser, there is nothing to worry about; you will see no difference between Sandbox and Live environment APIs.

HTTP Headers for CORS
Access-Control-Allow-Origin:  *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Authorization

Web Content Display

DEMO

This is a simple demo of a dynamically created payment page using optile's AJAX Integration.

  • Try changing the Country to see how it adapts the payment methods and language
  • Smart Network Switch enables auto-detection of credit-card brands based on the number entered
  • Live validation performs validity checks while typing
  • Switch to mobile version loads the mobile-optimized checkout and gives you an impression on how it would look on a smartphone
  • In real life you can...
    • ...apply custom styling
    • ...change the payment-method configurations with a click
    • ...and much more.

 

Web Content Display

Integration Scenarios

Simple integration includes the scenarios shown below:

Integration Scenario Origin of the Payment Page Destination of Payment Details PCI Requirement
Simple Integration
Hosted Payment Page redirect URL from optile optile / OPG SAQ A
Selective Native with AJAX Payment Page is generated by the merchant server using optile's AJAX Library + iFrame by optile optile / OPG SAQ A
Display Native with AJAX Merchant Server using optile's AJAX Library optile / OPG SAQ A-EP

By contrast, advanced integration includes:

Integration Scenario Origin of the Payment Page Destination of Payment Details PCI Requirements
Advanced Integration
Selective Native Payment Page is generated by the merchant server + iFrame by optile optile / OPG

SAQ A

Display Native The merchant server generates the payment page optile / OPG SAQ A-EP
Pure Native The merchant server generates the payment page Merchant Server SAQ D
Pure Native with Client Side Encryption The merchant server generates the payment page optile / OPG SAQ A-EP

 

Web Content Display

Integration Scenarios Comparison

The Payment Gateway gives merchants a lot of flexibility. It allows multiple ways to integrate the frontend part of the payment processes (compared to backend interactions, which follow a standard path). Each integration scenario has different advantages, regarding effort, conversion, user experience, and security certification.

We generally recommend the AJAX Integration. It provides very good user-experience with minimum implementation effort, and it can be combined with Selective Native integration to minimize PCI requirements on your side. But a different integration scenario will make more sense for some merchant requirements: for integration with mobile devices or other devices that do not rely on web browser rendering eg Smart TVs, we offer special mobile integration scenarios.

Visualization

Integration Scenarios Taxonomy

Comparison of Features and Implementation Effort
  Hosted Selective Native via AJAX Selective Native Display Native via AJAX Display Native Pure Native with CSE Pure Native
PCI DSS              
Required SAQ A A A A-EP A-EP A-EP D


Features

             
Payment Page generation on optile side browser browser or server side browser browser (or other client) or server side server side server side
Resulting view redirect or include in iFrame native HTML with partial iFrames native HTML with partial iFrames native HTML native HTML or other UI native HTML or other UI native HTML or other UI
Splitting method selection from details entering possible? yes yes yes yes yes yes yes
In-page Account Validations yes yes yes yes yes yes yes
User Experience good very good very good very good perfect perfect perfect
Payment Details Submission to OPG to OPG to OPG to OPG to OPG to OPG to merchant server


Integration Effort

             
Method LIST Rendering auto auto implement auto implement implement implement
In-page Account Validations auto auto (configurable) implement partly, web service provided auto
(configurable)
implement, web service provided implement, web service provided implement, web service provided
CHARGE Submission auto auto implement auto implement implement implement
Result Processing and Redirection auto auto implement auto implement, indicator provided implement, indicator provided implement, indicator provided
Internationalisation auto auto auto auto implement, texts provided implement, texts provided implement, texts provided
Styling default CSS, override recommended style of shop, CSS override for partial iFrames recommended style of shop, CSS override for partial iFrames recommended style of shop, example CSS provided style of shop style of shop style of shop

 

Web Content Display

Simple Integrations

Web Content Display

Hosted

In Hosted integration, the OPG creates a fully hosted HTML payment page when you submit the LIST Request. This is the fastest way to get optile integrated to your shop, because you can either redirect your customers to it or embed it within an iFrame on your own page. In any of these cases you can provide your own CSS stylesheet to give it the same look and feel as your own website.

While this requires the lowest implementation effort by you, Hosted integration has limited flexibility.

This integration needs SAQ A -- the lowest PCI compliance standard. Download the SAQ A requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you comply with the requirements. This signed SAQ is your "Attestation of Compliance (AoC)", which may be requested at any time by your acquiring bank or PSP. For help with this, contact support@optile.net. We're always happy to help. 

Note: If you will not be offering credit card payments, you do not have to do anything regarding PCI compliance.

This is how it works:

1. You initialize the payment from your backend (LIST Request). Set the parameter style.hostedVersion to v3 to get the most recent version of the hosted payment page (v3). It features a full responsive design and high-resolution payment-method logos. The legacy version (v2) can be accessed by setting style.client to "RESPONSIVE" instead.

2. Based on the information given, OPG generates a web page with all the payment methods that can be used to pay this particular transaction. As a reply, you get a URL to this generated page.
Example Reply (extract)

{
  "links": {
    "self": "https://api.oscato.com/api/lists/e909b8f7-97fd-463e-9069-313632a9b8cc"
  },
  "resultInfo": "6 applicable and 0 registered networks are found",
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "redirect": {
    "url": "https://api.oscato.com/paymentpage/v3/responsive.html?listId=e909b8f7-97fd-463e-9069-313632a9b8cc",
    "method": "GET",
    "suppressIFrame": false
  }
...
}

Hosted

In Hosted integration, the OPG creates a fully hosted HTML payment page when you submit the LIST Request. This is the fastest way to get optile integrated to your shop, because you can either redirect your customers to it or embed it within an iFrame on your own page. In any of these cases you can provide your own CSS stylesheet to give it the same look and feel as your own website.

While this requires the lowest implementation effort by you, Hosted integration has limited flexibility.

This integration needs SAQ A -- the lowest PCI compliance standard. Download the SAQ A requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you comply with the requirements. This signed SAQ is your "Attestation of Compliance (AoC)", which may be requested at any time by your acquiring bank or PSP. For help with this, contact support@optile.net. We're always happy to help. 

Note: If you will not be offering credit card payments, you do not have to do anything regarding PCI compliance.

Please sign in to view further details of this article. Login

Web Content Display

Selective Native with AJAX

Selective Native can be implemented using our AJAX Library, or as a native solution. In both cases, the logic behind the implementation is the same; the only difference is that native integration needs the development of your own JavaScript code, while AJAX integration uses a library provided by optile.

Here's an overview of how our AJAX library communicates with the OPG and especially the Selective Native iFrames. You can use the session "AJAX library Integration" as a reference to our AJAX library.

optile's AJAX Integration Library enables seamless integration of the OPG payment checkout into your own websites, with minimum effort.

Essentially, the JavaScript library takes over a major part of the communication with optile's OPG and creates the actual user interface for checking out. You can read about the general communication flow with OPG in our Getting Started Overview. In the AJAX integration scenario, you only need the initial LIST Request implemented in your server system, and a Notification Listener.

A Selective Native with AJAX integration requires only PCI DSS SAQ A compliance. Download the PCI DSS SAQ A requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you are compliant. This signed SAQ is also your "Attestation of Compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We're always happy to help.

Selective Native gives a level of security for credit and debit cards in the payment page that means you need only be PCI A compliant, as opposed to PCI A-EP which requires more effort. Compared to the Hosted scenario, Selective Native integration gives more flexibility over the look and feel of the page -- so you can align it more easily to your corporate design and optimal conversion rates.

Selective Native can be implemented natively on your side, or combined with our own AJAX Library. So if you are using our AJAX library, no extra implementation effort is needed; simply change the integration parameter in the LIST Request to SELECTIVE_NATIVE. For Hosted Integration Selective Native is not necessary, because the whole hosted page already comes from a PCI-certified optile domain.

Technical Concept

Selective Native replaces those parts on the payment page with iFrames, where necessary. This means that all credit and debit card forms will be in small iFrames that come from a fully PCI-certified optile domain. The card data entered by a user cannot be read from the surrounding page. That said, all other parts of the page are yours, with the corresponding visual style. Even the small iFrame forms can be styled by providing a CSS file.

This is how the form inside the iFrame would be embedded into the payment page:

Here we've shown you how to handle the Selective Native iFrames at a high level. Use our AJAX Library Integration as a reference if you want to implement this part on your own.

Communication Flow

Here is an overview of the client-server and inter-frame communication messages when you use our AJAX library:

You initialize the payment from your backend (LIST Request).

  1. The long ID of the generated method LIST is passed back to the customer's browser, with the full list of methods and all resources (images, HTML input forms, etc). At this point, you hand the long ID over to our AJAX Integration JavaScript library, and specify the HTML container element.
  2. The JavaScript library now builds the whole payment selection form inside the given HTML container element. This way, it is fully integrated into your website.
  3. Your customer can now submit their payment details and be redirected to next page (your success or cancel page, or an external page like PayPal). Your backend will receive a status notification about the payment result.

Note: This approach uses client-side payment page generation. But if you implement this yourself, you could also generate it on the server-side. For more information on how to build this scenario, go to AJAX Integration.

Selective Native with AJAX

Selective Native can be implemented using our AJAX Library, or as a native solution. In both cases, the logic behind the implementation is the same; the only difference is that native integration needs the development of your own JavaScript code, while AJAX integration uses a library provided by optile.

Here's an overview of how our AJAX library communicates with the OPG and especially the Selective Native iFrames. You can use the session "AJAX library Integration" as a reference to our AJAX library.

optile's AJAX Integration Library enables seamless integration of the OPG payment checkout into your own websites, with minimum effort.

Essentially, the JavaScript library takes over a major part of the communication with optile's OPG and creates the actual user interface for checking out. You can read about the general communication flow with OPG in our Getting Started Overview. In the AJAX integration scenario, you only need the initial LIST Request implemented in your server system, and a Notification Listener.

A Selective Native with AJAX integration requires only PCI DSS SAQ A compliance. Download the PCI DSS SAQ A requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you are compliant. This signed SAQ is also your "Attestation of Compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We're always happy to help.

Please sign in to view further details of this article. Login

Web Content Display

Display Native with AJAX

In Display Native integration, the LIST response contains open input forms for credit cards (in contrast to iFrames used in Selective Native), but card-sensitive data is sent directly to the OPG and never passes through your server systems. In this way, you still have full control over the page styling but you don't need the higher PCI compliance level, only the lower level. In this specific scenario, optile's AJAX library enables seamless integration with the OPG payment checkout into your own websites, with minimum effort.

Essentially, the JavaScript library takes over a major part of the communication with optile's OPG and creates the actual user interface for checking out. You can read about the general communication flow with OPG in our Getting Started Overview. In the AJAX integration scenario, you only need the initial LIST Request implemented in your server system, and a Notification Listener. Use the session AJAX library Integration as a reference just in case you cannot use our AJAX library and have to implement this part on your own.

If any of your website elements will need to process cardholder data (because you offer credit card payments to your customers), you must ensure that you comply with all PCI DSS SAQ A-EP requirements. Download the PCI DSS SAQ A-EP requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you are compliant. This signed SAQ is also your "Attestation of compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We're always happy to help. 

Here is how communication works in this scenario :

You initialize the payment from your backend (LIST Request).

  1. The ID of the generated method LIST is passed back to the customer's browser where you hand it over to our AJAX Integration JavaScript library and specify the HTML container element.
  2. The JavaScript library will now automatically get the full list of methods and all resources (images, HTML input forms, etc) and build the whole payment selection form inside the given HTML container element. This way it is fully integrated into your website.
  3. Your customer can now submit their payment details and be redirected to the next page -- your success or cancel page, or an external page like PayPal. Your backend will receive a status notification about the payment result in all cases.

For more information on how to build this scenario, go to AJAX Integration.

Display Native with AJAX

In Display Native integration, the LIST response contains open input forms for credit cards (in contrast to iFrames used in Selective Native), but card-sensitive data is sent directly to the OPG and never passes through your server systems. In this way, you still have full control over the page styling but you don't need the higher PCI compliance level, only the lower level. In this specific scenario, optile's AJAX library enables seamless integration with the OPG payment checkout into your own websites, with minimum effort.

Essentially, the JavaScript library takes over a major part of the communication with optile's OPG and creates the actual user interface for checking out. You can read about the general communication flow with OPG in our Getting Started Overview. In the AJAX integration scenario, you only need the initial LIST Request implemented in your server system, and a Notification Listener. Use the session AJAX library Integration as a reference just in case you cannot use our AJAX library and have to implement this part on your own.

If any of your website elements will need to process cardholder data (because you offer credit card payments to your customers), you must ensure that you comply with all PCI DSS SAQ A-EP requirements. Download the PCI DSS SAQ A-EP requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you are compliant. This signed SAQ is also your "Attestation of compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We're always happy to help. 

Please sign in to view further details of this article. Login

Web Content Display

Advanced Integrations

Web Content Display

Selective Native

Selective Native can be implemented as a native solution or by using our AJAX Library. In both cases, the logic behind the implementation is the same; the only difference is that a native integration requires the development of your own JavaScript code, while an AJAX integration uses a library provided by optile.

For an overview of Selective Native, go to Selective Native with AJAX.

For a detailed explanation of how to implement Selective Native, go to Selective Native Integration.

Selective Native

Selective Native can be implemented as a native solution or by using our AJAX Library. In both cases, the logic behind the implementation is the same; the only difference is that a native integration requires the development of your own JavaScript code, while an AJAX integration uses a library provided by optile.

For an overview of Selective Native, go to Selective Native with AJAX.

For a detailed explanation of how to implement Selective Native, go to Selective Native Integration.

Please sign in to view further details of this article. Login

Web Content Display

Display Native

In Display Native integration, the LIST response contains open input forms (in contrast to iFrames used in Selective Native) for credit cards, but card-sensitive data is sent direct to the OPG and never passes through your server systems. In this way, you can have full control over page styling but you need a lower PCI-compliance level. Also note that from a user experience standpoint you can achieve similar results through the AJAX Integration with even less implementation effort.

If you plan to offer credit-card payments to your customers, and your website elements will process cardholder data, you must comply with all the PCI DSS SAQ A-EP requirements. Download the PCI DSS SAQ A-EP requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you comply. This signed SAQ is also your "Attestation of compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We are always happy to help.

These requirements must be checked, signed, and submitted for revision if needed. Need assistance? Please contact us.

For users without web browser rendering (eg native mobile apps) there is Half-Native Integration a variation of Display Native integration.
Display Native Integration

  1. You initialize the payment from your backend (LIST Request) and, based on the information provided, OPG replies with a JSON structure containing all possible payment methods that can be used for this particular transaction (LIST Response). With every network, there is also an HTML snippet representing the corresponding form where the customer needs to fill in their payment account details (eg credit card number etc).
     
  2. With this information you can build your own payment page. Your implementation should not be aware of the payment networks in advance. Everything should be fetched and generated at runtime. This way, you can activate additional payment networks by configuration only (ie without changing your implementation).
     
  3. The payment account details are then submitted directly to OPG via the CHARGE Request. Since your server does not touch the sensitive payment-account details, you do not have to be PCI compliant.
Note

Redirect Networks such as PayPal, Sofortüberweisung, etc. do not require payment account details in advance. The corresponding form and the subsequent CHARGE request will be empty in this case. Instead, the redirect URL will point to the external page provided by that network (eg the PayPal login screen). After this step, the customer will be redirected back to your system. For you this is transparent, you do not need to do anything about those networks in your implementation explicitly (see also the details on the CHARGE Request). In this scenario the Status Notification is important because the CHARGE reply goes direct to the client and not to the Merchant's server system.

Read more about how to analyze the LIST Response.

Localized Forms

To implement optile's localized forms snippets returned from the original List response, please see Localized Forms section.

Display Native

In Display Native integration, the LIST response contains open input forms (in contrast to iFrames used in Selective Native) for credit cards, but card-sensitive data is sent direct to the OPG and never passes through your server systems. In this way, you can have full control over page styling but you need a lower PCI-compliance level. Also note that from a user experience standpoint you can achieve similar results through the AJAX Integration with even less implementation effort.

If you plan to offer credit-card payments to your customers, and your website elements will process cardholder data, you must comply with all the PCI DSS SAQ A-EP requirements. Download the PCI DSS SAQ A-EP requirements. You must sign the self-assessment questionnaire (SAQ) to confirm that you comply. This signed SAQ is also your "Attestation of compliance (AoC)", which may be requested at any time by your acquiring bank. If you have any questions, contact us at support@optile.net. We are always happy to help.

These requirements must be checked, signed, and submitted for revision if needed. Need assistance? Please contact us.

Please sign in to view further details of this article. Login

Web Content Display

Pure Native

Native integration means you build the payment checkout page yourself, based on the information provided by the LIST response, on your server side. It gives you full control and seamless integration into your pages.

In native scenarios, you can send the payment data submitted by your customers, to your own servers first, instead of having it sent directly to OPG. This depends on whether you want to see sensitive payment data and if you are permitted to do so by your PCI DSS certification.

Pure Native integration lets you pass sensitive data through any of your servers that process cardholder data. In this scenario the merchant must have PCI SAQ D certification.

These requirements must be checked, signed, and submitted for revision if necessary. Need help? Please contact us.

Pure Native Integration

For the LIST Request and payment-page rendering, this scenario is like the Display Native scenario except that here, the sensitive payment-account details go from the payment checkout page to your own servers first, where they can be stored or analyzed by your custom logic. From there, the CHARGE Request is submitted to OPG.

Note that under credit-card industry regulations, you are only allowed to process credit-card details on your servers if you have the appropriate PCI DSS certification. This covers not only storage of data but also in-memory processing.

Read more about how to analyze the LIST Response.

Localized Forms

If you wish to implement optile's localized forms snippets returned from the original List response, go to Localized Forms section.

Pure Native

Native integration means you build the payment checkout page yourself, based on the information provided by the LIST response, on your server side. It gives you full control and seamless integration into your pages.

In native scenarios, you can send the payment data submitted by your customers, to your own servers first, instead of having it sent directly to OPG. This depends on whether you want to see sensitive payment data and if you are permitted to do so by your PCI DSS certification.

Pure Native integration lets you pass sensitive data through any of your servers that process cardholder data. In this scenario the merchant must have PCI SAQ D certification.

These requirements must be checked, signed, and submitted for revision if necessary. Need help? Please contact us.

Please sign in to view further details of this article. Login

Web Content Display

Pure Native with CSE

The flow of Pure Native with Client-Side Encryption is very similar flow to the Pure Native scenario but with one important difference: payment data is encrypted by the client (web browser or application) and sent to the OPG, so your servers have no access to it. This means that this scenario needs only SAQ A-EP certification not PCI D as in Pure Native integration. These requirements must be checked, signed, and submitted for revision if necessary. If you have any questions, please contact us.

The native integration means that you build the payment checkout page yourself, based on the information provided by the LIST response, on your server side. It gives you full control and seamless integration into your pages.

Process Flow of Client-Side Encryption

optile will provide you with a public key for encryption in advance. You should store this key because, later on or during the process, the software-client of the user (eg web page in browser, but possibly also mobile clients) will use it.

The payment process is initialized with the LIST Request. You can build the payment page server-side or client-side, just like the other integration scenarios. But, optile's AJAX library is not ideal for building the client-side payment page for client-side encryption, since it submits payment data direct to the OPG instead of your custom endpoint. If you want to use it anyway, you can request a development version of the library and then adjust it to your needs.

For this flow to comply with PCI A-EP level compliance, the payment-account data (eg card data, SEPA IBAN etc) entered by the customer must be encrypted by the client so that only optile can decrypt it. To make that happen, this flow uses the public key referred to above, and the algorithms and data structures described below. Next, you have a choice: you can use the timestamp of encryption and/or the ID of the LIST session for encryption, to assure that the card data is being used for this specific payment session.

In a web context, optile will provide a JavaScript library providing a function that handles the encryption for you. Your client can then send the encrypted data anywhere to your systems. As your server systems will not be able to decrypt the data without access to optile's private key, this flow requires only PCI A-EP certification instead of PCI D. Your system will then send the encrypted account-data to the OPG via the CHARGE Request (in the context of the corresponding LIST session).

In this scenario, there is a simultaneous response to your server systems, with all relevant information. The OPG will also send the Status Notification that your server systems would need in other integration scenarios, but it is less significant here because we are already using reliable server-to-server communication. In a web context, your systems then typically respond to the client with an HTTP redirect, depending on the transaction result.

Here is a view of the process:

  1. The LIST Request and payment-page rendering are very similar to a Pure Native implementation.
  2. But, sensitive account-data are encrypted on the customer-client before being sent to your servers.
  3. From there, the CHARGE Request is submitted and the data can only be decrypted by the OPG.
  4. Your systems will receive status notifications and redirection URLs as in a standard Pure Native scenario.

Note that under credit-card industry regulations, you must ensure that you have the appropriate PCI DSS certification for processing credit-card details on your servers. This covers not only storage of data, but also in-memory processing. Owing to the nature of the Client-Side Encryption, PCI A-EQ level certification is required.

Read more about how to analyse the LIST Response.

Localized Forms

To implement optile's localized forms snippets returned from the original List response, go to Localized Forms.

Pure Native with CSE

The flow of Pure Native with Client-Side Encryption is very similar flow to the Pure Native scenario but with one important difference: payment data is encrypted by the client (web browser or application) and sent to the OPG, so your servers have no access to it. This means that this scenario needs only SAQ A-EP certification not PCI D as in Pure Native integration. These requirements must be checked, signed, and submitted for revision if necessary. If you have any questions, please contact us.

The native integration means that you build the payment checkout page yourself, based on the information provided by the LIST response, on your server side. It gives you full control and seamless integration into your pages.

Please sign in to view further details of this article. Login

Web Content Display

Mobile Integration

There are several ways to integrate the payment page into a native mobile client like iOS or Android-based devices. This section also applies devices or applications that do not rely on web-browser rendering, such as smart TV apps.

The challenge of non-web devices is that the data from the LIST Response cannot be integrated direct, because the input forms for the payment methods are described in HTML. Owing to the smaller screen estate for smartphones, and touch-interaction paradigms, extra adjustments in the user interface can also be beneficial.

So, there are 3 main approaches to mobile integration:

  • WebViews: An HTML-based view is integrated into the app. It could be optile's hosted page (which is mobile responsive out-of-the-box) or a custom-designed page by the merchant. In the latter case, all considerations about the web Integration Scenarios apply.
  • Half-Native: Native forms are pre-defined and selected for display based on the LIST Response. This can be based on the Display Native Scenario with Charge submission direct to OPG, or Pure Native with Charge submission to your server first.
  • Dynamic Native: A JSON representation of the required data for each payment method will be added to the LIST response so that native forms can be built more easily (planned).

See the comparison below plus more information about Half-Native integration:

Mobile Features and Implementation
  Half-Native WebView
with optile Hosted Page
WebView
with Merchant Hosted Page


Features

     
Payment page integration native WebView WebView
Payment user flow arbitrary 1 page arbitrary
In-page account validations yes yes yes
"Implement once" for new methods no yes yes
User experience excellent very good very good
Payment account submission to Payment Gateway
(or Merchant)
to Payment Gateway to Payment Gateway
(or Merchant)
PCI DSS certification needed by merchant SAQ A-EP
(D if submission to Merchant)
SAQ A/A-EP SAQ A-EP
(D if submission to Merchant)


Integration Effort

     
Method LIST Rendering implement auto implement, library provided
In-page Account Validations implement, web API provided auto implement, library provided
CHARGE Submission implement auto implement, library provided
Result Processing and Redirection implement auto implement, library provided
Internationalisation provided through API auto implement, library provided
Styling native shop style default CSS, override possible custom CSS

 

Web Content Display

Half-Native Integration

The Half-Native integration is typically used for devices or applications that do not rely on web-browser rendering, such as native smartphone or smart TV apps. Here, the data from the LIST Response cannot be integrated direct, because the input forms for the payment methods are described in HTML.

As a consequence there could be a translation client-side from the HTML elements into native UI interaction elements. This would preserve the 'implement once' principle but needs a certain budget. Edge cases that need some extra JavaScript logic, such as interactive forms for installment plan selection, are not straight-forward to translate.

The idea of Half-Native therefore is that you, as a merchant developer, prepare the user-interface snippets that correspond to the HTML form snippets provided by the LIST Response in advance. In other words, you prepare all relevant input forms that may occur beforehand natively, eg in terms of the iOS or Android platform.

After your system issued a LIST Request the client will evaluate the response of the client. Then it only shows those natively prepared input forms that were selected by the Payment Gateway for this payment session.

When your customer enters the necessary payment data, the client typically submits it direct to the Payment Gateway via a CHARGE Request -- in the same way as for the Display Native Scenario.  An immediate response and a Status Notification will be sent to your server system.

A corresponding communication sequence looks like this:

Alternatively, the payment session could be initialized as Pure Native and the CHARGE Request issued to your server systems first. But this would affect your required PCI certification.

Separate Method Selection

Another use-case for Half-Native integration is to split the method selection from the actual entering of the account data by the user, ie divide the common payment page into two separate steps.

Here, you could add some simple logic to show the radio buttons and logos on the first part of the payment page, with the second part of the payment page showing the logo and forms of a previously selected payment method with or without the possibility to still switch to a different payment method.

To support this, OPG offers an easy way to store the user selection from the first part in the LIST Session object. This is especially relevant if you want to render the second part as a Hosted Page because it will respect the selected method and show it as preselected (among the other methods).

Every method offered in a LIST Session has the attribute selected and is also a resource with a separate endpoint. Its URL is given as the links.self attribute like this:

Example JSON Code
{
...,
  "code": "VISA",
  "selected": false,
  "links": {
    "self": "https://api.sandbox.oscato.com/api/lists/57a06162e4b0a803efa9e1d1l/VISA",
  ...
  }
...

If the user selects one method, your system can issue a PUT or PATCH request to that resource to update its selected attribute like this:

Example request

  • URL: https://api.sandbox.oscato.com/api/lists/57a06162e4b0a803efa9e1d1l/VISA
  • Method: PUT
  • Basic Authentication: Not required except for Native Scenarios

The selected status of all other methods in that LIST will become false as a result. So note that other attributes cannot be changed.

Your system can also use the URL of the corresponding LIST object to display it in a hosted fashion later (as the second part), and the selected method will be prechecked and expanded there.
Body Content
{
  "selected": true
}

Web Content Display

JSON Forms

For non-web clients (eg native mobile app, smart TV app, or desktop-based CRM system) a JSON representation of input forms for payment methods and registered accounts is a better solution for building these forms natively without HTML-rendering.

In Display and Pure Native integration, the LIST request can be executed passing extra query parameters to return a JSON representation of the input fields instead of HTML snippets. This means that the non-web devices noted above -- those not capable of HTML-rendering -- can still render the necessary input forms.

When executing a LIST request (any variation, POST, GET or PUT), the requested URL can contain the parameter view, with options to enable or disable form representation methods.

For example, a LIST request (POST) could look like:

https://api.sandbox.oscato.com/api/lists?view=jsonForms,-htmlForms

With regard to the query parameters, please note:

  • If jsonForms is present, the JSON forms are enabled.
  • If -htmlForms is present, the HTML forms are not shown. That means: The attributes links.form and links.localizedForm are not present.
  • If there are conflicting or unknown arguments like view=jsonForms,-jsonForms or view=abc then the request will fail as invalid.
  • If any query parameter is present other than view it will be ignored.

If JSON forms are enabled (view=jsonForms), the LIST response object will contain a form representation in JSON format. This means:

  • For each applicable method (network) there is a new attribute structure named localizedInputElements (not inside the links structure, but outside on the same level)
  • This structure is a range of objects, and each object represents one input field as follows:
    • name (mandatory): the name of the parameter represented by this input field (as used inside an account object in a consecutive CHARGE request)
    • label (mandatory): the localized human readable label that should be displayed with the input field
    • type (optional): represents the input type / restrictions that can be enforced by the client. These types are allowed:
      • string (default): one line of text without special restrictions. For example: holder name
      • numeric: numbers from 0 to 9, space delimiters and dash ("-") are allowed. For example: card number
      • integer: only numbers from 0 to 9. For example: CVC
      • checkbox: values "true", "false", or undefined (non-existent).
      • select: a list of possible values is given in an additional options attribute (see below). For example: expiration date.
    • options (optional, present for "select" types): a range of objects with attributes:
      • value (mandatory)
      • label (optional. If not present, value should be displayed to the user.)
  • If the form definition for a network is not yet present in OPG, an empty object will be returned.
Example of LIST response:
...,
{
  "code": "ONLINE_BANKING_CZ",
  "label": "Online Banking for Czech Republic",
  "method": "ONLINE_BANK_TRANSFER",
  "grouping": "ONLINE_BANK_TRANSFER",
  "registration": "NONE",
  "recurrence": "NONE",
  "redirect": true,
  "links": {
    "logo": "https://resources.sandbox.oscato.com/resource/network/DEMO_SK/cs_CZ/ONLINE_BANKING_CZ/logo.png",
    "self": "https://api.sandbox.oscato.com/pci/v1/5984364ccb425d1b77fc727dlijdpkm1bfr5malib51eacl3f9/ONLINE_BANKING_CZ",
    "lang": "https://resources.sandbox.oscato.com/resource/lang/DEMO_SK/cs_CZ/ONLINE_BANKING_CZ.properties",
    "operation": "https://api.sandbox.oscato.com/pci/v1/5984364ccb425d1b77fc727dlijdpkm1bfr5malib51eacl3f9/ONLINE_BANKING_CZ/charge",
    "validation": "https://api.sandbox.oscato.com/pci/v1/5984364ccb425d1b77fc727dlijdpkm1bfr5malib51eacl3f9/DEMO_SK/cs_CZ/ONLINE_BANKING_CZ/standard/validate"
  },
  "localizedInputElements": [
    {
      "name": "bic",
      "label": "Banka",
      "type": "select",
      "options": [
        {"value": "GIBACZPXXXX", "label": "?eská spo?itelna, a.s."},
        {"value": "FIOBCZPPXXX", "label": "Fio banka, a.s."},
        {"value": "KOMBCZPPXXX", "label": "Komercni banka, a.s."},
        {"value": "BREXCZPPXXX", "label": "mBank S.A., organiza?ní složka"},
        {"value": "RZBCCZPPXXX", "label": "Raiffeisenbank, a.s."},
        {"value": "ZUNOCZPPXXX", "label": "Zuno Bank AG"},
      ]
    }
  ],
  "button": "button.charge.label",
  "selected": false
},
...

JSON Forms

For non-web clients (eg native mobile app, smart TV app, or desktop-based CRM system) a JSON representation of input forms for payment methods and registered accounts is a better solution for building these forms natively without HTML-rendering.

In Display and Pure Native integration, the LIST request can be executed passing extra query parameters to return a JSON representation of the input fields instead of HTML snippets. This means that the non-web devices noted above -- those not capable of HTML-rendering -- can still render the necessary input forms.

Please sign in to view further details of this article. Login

Web Content Display

Frontend Checkout

Web Content Display

Checkout Flow Overview

optile Flexible Checkout Architecture

The OPG offers great flexibility throughout the checkout process. The diagram above gives an overview of optile's Flexible Checkout Architecture. The checkout process starts in your shop and ends when you make a Charge and display the thank-you page to you customer, or when you dispatch the order and close the transaction with a deferred charge. Here is the full Flexible Checkout Architecture diagram.

The Interactive Checkout Flow Diagram

Especially for developers we created also a systematic view of all combinations of optile's checkout API flows. Switch between combinations in the selection box at top center. The diagram represents the relationship between a (typical) user journey and the corresponding API requests (with limited details).

Click here to open the Interactive Checkout Flow diagram in a new tab. Loading can take a few seconds, so please be patient...

Launch the interactive diagram in a new tab

Regular Checkout

optile supports two main types of a regular checkout:

  • Regular checkout with immediate charge: Your customer arrives at the checkout page via the regular web browser, or via a remote checkout initiated by your Call Center where the list of products to be purchased is displayed. The customer is then directed to the payment page. The payment page is rendered based on how you choose to handle optile's LIST Request, ie by a simple or advanced integration scenario with the OPG (more information about Integration scenarios). On the payment page your customer enters their payment data and confirms the order. Once the customer confirms the order, the CHARGE takes place and the customer will be redirected to the thank-you page. You can choose to close the sale once you make the order ready for delivery as a deferred charge.
  • Regular checkout with Summary Page: Your customer follows the path described above, but the customer is presented with a summary page after they enter their payment details. The summary page gives your customer the opportunity to review their order and check their delivery address and payment details before they confirm the purchase. Presenting the summary page requires a Delayed Payment Submisison (DPS) which involves caching sensitive data, and a few challenges. Your system can temporarily cache payment data via a PRESET Request. Once your customer confirms the order from the summary page, the CHARGE takes place and they will be redirected the thank-you page. You may choose to close the sale once you make the order ready for delivery as a deferred charge.

Checkout Flow Overview

optile Flexible Checkout Architecture

The OPG offers great flexibility throughout the checkout process. The diagram above gives an overview of optile's Flexible Checkout Architecture. The checkout process starts in your shop and ends when you make a Charge and display the thank-you page to you customer, or when you dispatch the order and close the transaction with a deferred charge. Here is the full Flexible Checkout Architecture diagram.

Please sign in to view further details of this article. Login

Web Content Display

Express Checkout

Apart from the regular checkout optile supports "quick checkout" flows that allow the user to skip data entry and therefore constitute a streamlined and conversion optimized customer experience:
  • Express Checkout (for first-time customers): On the shopping cart page you already give your customers the option to use a specific Express method such as PayPal Express or Amazon Pay. If they choose one of them then they are directed to that provider or provider interaction elements to make the payment with a user account they already have there. Once the customers confirm on the provider side, their data such as shipping address are shared with your system. Your system would typically present a summary page for the customer to confirm in the fashion of Delayed Payment Submisison (DPS). The detailed Express Checkout documentation you can find in this separate space.
  • One-Click Checkout (for returning customers): You can speed up and improve the checkout experience for your return customers by sending these customers direct from the checkout page to the summary page. On the summary page, you show them their registered address and payment details and then the customer just needs to confirm the order. In this process you can perform the Charge by skipping the payment page. Again, you close the sale once you make the order ready for delivery. To offer the One-Click Checkout, you need to give your customers the option to register their account details on their initial purchase. Currently One-Click checkout is currently based on Payment Account Registrations.

Express Checkout

Apart from the regular checkout optile supports "quick checkout" flows that allow the user to skip data entry and therefore constitute a streamlined and conversion optimized customer experience:

Please sign in to view further details of this article. Login

Web Content Display

Payment Page: LIST Request

Every regular payment checkout starts with a LIST Request: your system provides information about the purchase (especially payment amount), customer details, and maybe some additional data. It authenticates by sending your optile OPG credentials via HTTP Basic Authorisation (encrypted, of course, through HTTPS). The LIST Request is therefore always issued from your server-side systems, never from a customer's browser.

A valid LIST Request creates a LIST object. It responds with the applicable payment methods (networks) for this checkout and can also be seen as a kind of payment session of the user in which he or she can do multiple CHARGE attempts.

A typical LIST Request looks like this:

  • URL: https://api.sandbox.oscato.com/api/lists
  • Method: POST
  • Authentication:
    • Login Name: registered company code
    • Password: generated API token

Explanations for some parameters in the request body:

  • transactionId is the alphanumeric identifier for this transaction, assigned by you as a merchant.
  • country is the "transaction country". It specifies which country-specifc OPG configuration and therefore payment method selection should be used. Typically it is the location of the current shop but it may also be the origin of the customer. Country codes according to ISO 3166-1 alpha-2 are used.
  • integration defines which integration scenario the payment session is initialized for, see also below. Valid values are: HOSTED, SELECTIVE_NATIVE, DISPLAY_NATIVE (default) and PURE_NATIVE.
  • customer.number is the alphanumeric identifier of your customer, assigned by you as a merchant.
  • payment.reference is the short text that customers will see on their account statement.
  • style.hostedVersion with v3 will enable new version of payment page (for HOSTED integration scenarios) and return high-resolution method logos (64px height).
  • callback.returnUrl is the URL the customer should be redirected to, after the payment was successful, typically on the merchant's site.
  • callback.cancelUrl is where the customer should be redirected to if he or she cancels on a redirect page (such as PayPal), or a payment attempt was denied and is not recommended to retry (Interaction Code ABORT).

The full data model with all possible parameters can be found in our API Reference.

Read about the LIST Response if you want to render the payment page yourself.

We highly recommend to always pass the customer number and email, even if you have to use dummy values, because many popular providers require this.
Example LIST Request
{
  "transactionId": "tr101",
  "country": "DE",
  "integration": "HOSTED",
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2017"
  },
  "style": {
    "hostedVersion": "v3"
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
	"notificationUrl":"https://dev.oscato.com/shop/notify.html"
  } }

Specifying the Integration Scenario

You can specify the integration scenario in the LIST Request, using the parameter integration. The selected scenario will impact the operation URLs in the response object. If no integration parameter is specified, the LIST Request will default to Display Native.

These are valid parameters:

  • HOSTED (Hosted)
  • SELECTIVE_NATIVE (Selective Native)
  • DISPLAY_NATIVE (Display Native, default. Legacy value: NATIVE_WITHOUT_PCI)
  • PURE_NATIVE (Pure Native. Legacy value: NATIVE_WITH_PCI)
Example LIST Request with integration parameter
  • URL: https://api.sandbox.oscato.com/api/lists
  • Method: POST
  • Authentication:
    • Login Name: registered company code
    • Password: generated API token
Duplicate Charges

After a successful CHARGE is executed on a LIST object, the LIST will no longer be valid. This means that any other CHARGE on it will be declined, with the Interaction Code ABORT and Reason DUPLICATE_OPERATION. This is to protect customers and merchants from accidentally executing duplicate payments.

To provide a good customer experience, however, you should detect that case (via Interaction Codes passed as GET query parameters) on the page the customer is redirected to (indicated by the cancelUrl) and inform the customer that the payment was successful and that only the repetition was declined. Otherwise the customer may think the payment failed.

Continue reading the LIST Request Details.
Example LIST Request with Hosted Integration Scenario
 {
  "transactionId": "tr101",
  "country": "DE",
  "integration": "HOSTED",
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2017"
  },
  "style": {
    "hostedVersion": "v3"
  },
  "callback": {
     "returnUrl": "https://dev.oscato.com/shop/success.html",
     "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
     "notificationUrl":"https://dev.oscato.com/shop/notify.html"

  }
}
Modifying response with preselection parameter

With the preselection sub-parameters, you can dynamically influence the LIST Response as follows:

  • deferral: enables Deferred Payments or Payouts
  • networks: Filters the response to:
    • REGISTERED: only accounts that were previously registered for the current customer
    • APPLICABLE: only networks that are to be entered by the customer, not registered accounts.
    • ANY (default): Both kinds
  • direction: Specifies the kind of transaction, namely:
    • CHARGE (default): A payment transaction with a subsequent CHARGE Request
    • PAYOUT: A Payout to the customer
Example
 {
...,
  "country": "DE",
  "preselection": {
    "deferral": "DEFERRED",
    "networks": "REGISTERED",
    "direction": "PAYOUT"
  },
  "customer": {
  ...

Payment Page: LIST Request

Every regular payment checkout starts with a LIST Request: your system provides information about the purchase (especially payment amount), customer details, and maybe some additional data. It authenticates by sending your optile OPG credentials via HTTP Basic Authorisation (encrypted, of course, through HTTPS). The LIST Request is therefore always issued from your server-side systems, never from a customer's browser.

Please sign in to view further details of this article. Login

Web Content Display

Re-using a LIST Session

In some use cases there is no need to start a new LIST session if the current one is still valid. Furthermore, the OPG supports the update of parameters of a LIST session without the need for reloading.
New LIST Request v reading existing LIST

A valid LIST can be seen as a payment session of the user. To enable payment conversion tracking through optile, and to benefit from dynamic reactions of the payment page, we advise that you do not issue LIST Requests "blindly" but use existing LIST Objects if possible.

The object is a resource hosted by OPG. It is identified by the LIST's longId and can be requested any time again via HTTP GET like this:

https://api.sandbox.oscato.com/api/lists/[longId of LIST]

A LIST object remains valid for executing charges until either:

  • a successful or pending (!) CHARGE through this list was executed, or
  • 30 minutes have passed (this will also trigger a Status Notification), where the timer starts counting from 0 again with any CHARGE attempt.

After that, the LIST object will become invalid for security reasons and no further CHARGE will be possible. In Display Native integrations, a GET on an expired LIST resource will return an HTTP 404 (not found) error. In Pure Native integrations, the object can be retrieved but its Status Code will be expired.

What this means for your implementation:

Use an existing LIST resource while it is still valid. In cases where your customer reloads the payment page, do not issue a new LIST Request, re-use the existing one. Only this will enable proper conversion tracking on your payment checkout through optile. You can double-check the validity through a GET request on the LIST resource (see above) and/or listen to "expired" notifications. Only issue a new LIST Request if it has expired.

Updating a LIST Session

For some business cases it may be necessary to change the information provided in the initial LIST Request, for example if customers change the products in their shopping cart after they have been on the payment page but not yet completed the payment. It means that for the same "user session", an update of an existing LIST resource is required. For a new "user session", generate a new LIST, as described above.

LIST updates may lead to incorrectly charged amounts if your implementation is not accurate. Also, some payment networks may drop out of the LIST result when new information is given (eg if they only apply to a certain payment amount range). Therefore, the customer may not be able to complete the payment with an already selected network.

The update is performed REST-style by sending an HTTP PUT to an existing LIST resource. The data structures payment, products and customer can be replaced as a whole. Other mandatory fields still have to be provided but cannot be changed.

Example Request for LIST Session Update
  • URL: https://api.sandbox.oscato.com/api/lists/ce3eec14-e186-4b7c-94a1-fde802412e69
  • Method: PUT
  • Authentication:
    • Login Name: DEMO
    • Password: BAtXa7yubR8ipuT

Note: LIST session updates can only be performed from the server-side system ("backend") and it needs your payment authentication credentials. After performing a LIST update, you may need to reflect resulting changes to the customer client (eg browser). Therefore, the LIST result should be read by the client again by passing it on from your server system, or by retrieving the LIST object direct from the Payment Gateway again, and showing the updated payment page. Also notice that the JSON structure is basically the same for a LIST request or update.

Example JSON Code
 {
    "transactionId": "tr101",
    "country": "DE",
    "customer": {
        "number": "42"
    },
    "payment": {
        "amount": 22.22,
        "currency": "EUR",
        "reference": "Shop 101/20-03-2017"
    }
}
Making a method checked by default

A LIST also holds information indicating which of the methods should be checked when the payment page is loaded. In the LIST Response, each object in networks.applicable and accounts, representing a payment method ("network"), has a boolean flag selected. If set to true this method should be displayed with a checked radio button and expanded form. optile's Hosted payment page and AJAX library respect this value.

You can modify the flag by sending a PUT request to the method resource. Its URL is given explicitly in the self attribute within the method object.

Example request for default checking:

  • URL: https://api.sandbox.oscato.com/api/lists/57bab64ee4b03ec79899332el/VISA
  • Method: PUT
  • Authentication: Not required (except for Pure Native integration)

As a consequence the selected property of all other methods in the list will become false. Note: other properties of a method cannot be changed through this API.

The selected attributes of all methods will be false by default, and we advise you to preselect the first method, as our AJAX library and Hosted Payment Page do.

Code
{
  "selected": true
}

Re-using a LIST Session

In some use cases there is no need to start a new LIST session if the current one is still valid. Furthermore, the OPG supports the update of parameters of a LIST session without the need for reloading.

Please sign in to view further details of this article. Login

Web Content Display

Extended LIST Request

Sometimes you can improve the checkout experience by making more parameters available to the customer. For example, the products list could have more details about the goods ordered; or the customer might need to clearly specifiy their address. Some information may be required for risk management -- some invoice providers may restrict their offers if billing and shipping addresses are different, for example.

At the moment, the OPG accepts a long list of parameters in the LIST request, which you can find in our API Reference in the Server Payment API dropdown.

Products

The given products will be shown to the customer in some networks, eg PayPal and Invoices.

product.amount reflects the price with respect to quantity. Therefore a quantity of 2 and amount of 25.00 means that a single product cost 12.50.

quantity defaults to 1.

Client Info

The parameter clientInfo is optional, as is every sub-attribute within. But, if you provide any part of the object but not userAgent or acceptHeader, the following defaults will be used for these attributes if empty:

  • userAgent: Mozilla/5.0
  • acceptHeader: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8

These are widely accepted values. But just in case a PSP uses them for additional logic like risk management, we recommend that you set these attributes to the real values from the customer's original HTTP request.

Customer

While customer.number is the only required parameter, you should also consider customer.email. This enables basic identification that some providers use for risk management.

Phone numbers can be passed either by providing all three fields, countryCode, areaCode and subscriberNumber, or by providing a single unstructuredNumber.
You can provide an additional name structure in the billing section, but the general name defined as child of customer should be enough in most cases.

Addresses are specified better by the parameter addresses, which can cover shipping, billing, residential or other relevant address.

customerScore is an optional rating of the customer's trustworthiness from 0 to 1000 (where 1000 is fully trusted). This can influence risk checks such as 3D Secure, the requirement for a verification code (CVV/CVC) for registered cards, and others in future if the provider supports it. The rating values can be customized, but in a standard configuration a value below 300 enforces a 3D Secure check, a value above 700 disables it, and values in between let the provider decide in accordance with agreed defaults. Currently this is only supported by WorldPay.

Multi shipping

One interesting use case is where a customer wants different products to be delivered to different addresses. A merchant could assign certain products to be delivered to the customer's home, some to be delivered to the customer's office, and some even to be collected at a physical store. This scenario can be achieved by several parameters:

  • A unique id for every customer address
  • A list of additionalAddresses to specify several addresses with the same type, for example home and office shipping
  • A merchantAddress (Boolean) to link one of the addresses as the physical store of the merchant
  • A shippingAddressId to link each product item with its address
Extended LIST Request Example
 {
  "transactionId": "tr101",
  "country": "DE",
  "integration": "PURE_NATIVE",
  "payment": {
    "amount": 34.90,
    "currency": "EUR",
    "reference": "Shop 101/20-03-13"
  },
  "products": [{
    "code": "B003X6UEXQ",
    "name": "Tron Legacy BluRay",
    "quantity": 2,
    "amount": 25.00,
    "shippingAddressId": "addr-id-001"
  },{
    "code": "C003X6U523",
    "name": "The Lawnmower Man DVD",
    "quantity": 3,
    "amount": 9.90,
    "shippingAddressId": "addr-id-002"
  }],	
  "clientInfo": {
    "ip": "00.00.111.2",
    "ipv6": "0000:0000:0011:0011:1122:1122:0101:0101",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/54.0",
    "acceptHeader": "text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8"
  },
  "customerScore": 250,
  "customer": {
    "number": "002345",
    "email": "john.doe@example.com",
    "birthday": "2001-12-31T00:00:00.000Z",
    "name": {
      "title": "Prof.",
      "firstName": "John",
      "lastName": "Doe"
    },
    "addresses": {
      "billing": {
        "street": "Downing Street",
        "houseNumber": "10",
        "zip": "80333",
        "city": "München",
        "state": "Bayern",
        "country": "DE"
       },
      "shipping": {
        "name": {
          "firstName": "John",
          "lastName": "Doe"
        },			
        "street": "Baker Street",
        "houseNumber": "221b",
        "zip": "80333",
        "city": "München",
        "country": "DE",
        "id": "addr-id-001"
      },
      "additionalAddresses": [
        {
          "street": "Merchantstr.",
          "houseNumber": "1000",
          "zip": "80333",
          "city": "Munich",
          "state": "Bayern",
          "country": "DE",
          "companyName": "Merchant Ltd",
          "id": "addr-id-002"
        }
      ]
    },
    "phones": {
      "company": {"unstructuredNumber": "(0)89 1060 120-00"},
      "home": {"unstructuredNumber": "089 5060 120-55"},
      "mobile": {"unstructuredNumber": "0177 44004400"}
    }
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl":"https://dev.oscato.com/web/acb123"
  }
}

Extended LIST Request

Please sign in to view further details of this article. Login

Web Content Display

More LIST Use Cases

Web Content Display

Delayed Payment Submission

If your customer reviews and confirms their order on a separate summary page, the customer's payment data (entered in a previous step) must be cached in the interim. The sensitive nature of payment data combined with strict PCI DSS regulations mean that caching customer payment-data must be done carefully.

With Delayed Payment Submission, optile does exactly that. Instead of a CHARGE request, your system can temporarily cache payment data via a PRESET request. This is different from a registration, as it is only temporarily stored -- to respect data privacy principles. After the customer has confirmed the order on the final summary page, your system can issue the corresponding CHARGE request (without payment data).

This will trigger an immediate payment or a deferred payment, depending on your configuration. In a deferred payment, the payment would be preauthorized only, and your system should send a final CLOSING request when the order is shipped. Next, the actual payment capture is triggered.

The diagram shows how the user journey (on the left) relates to OPG API calls (on the right). Note how the CLOSING request from the Deferred CHARGE is separate from the Delayed Payment Submission.

Delayed Payment Submission sequence diagram

Payment Account Validation

As soon as the customer submits their payment account data to the gateway (PRESET call), it can be validated for accuracy of format and also for existence of the account, availability of funds, and other risk checks. This means that if something goes wrong, the shop can give immediate feedback to the customer and offer alternative payment options to minimize user dropout.

This is configurable through the backend, so please contact us. The options are:

  • NONE: No check will be made
  • VALIDATION (default): An optile-internal check on formal validity of the account number will be made
  • PROVIDER_CHECK: The internal verification (see above) will be made first. If this is positive, a check with the provider will be made, if available, that does not reserve the funds. For card providers, this means a zero-value authentication. For other methods it can mean a dedicated risk check with customer data. If no such provider check is available, none will be made and the transaction will be processed as usual.
  • PREAUTHORIZATION: The internal verification (see above) will be made first. If this is positive, and the method and provider permits it, the corresponding funds will be reserved (preauthorized). If a reservation is not available, there will be a fallback to the non-reserving provider check as explained above. Again, if this is not available either, the transaction will be processed as usual.

LIST Request

As shown in the delayed payment submission diagram, the first step is to submit a LIST Request. For Delayed Payment Submission, an extra LIST parameter is needed: the optional Boolean value presetFirst. If this is set to true optile OPG will know that the payment submission should be preset, not charged direct. A summaryUrl must also be provided in the callback object if presetFirst is set to true. This way optile OPG can direct the customer to the desired summary page after the PRESET.

Delayed Payment Submission works with all Integration scenarios. After the LIST response is returned, follow the standard approach for rendering the payment methods, for example Native Integration, Selective Native, or it is rendered by the AJAX library.

LIST Request with presetFirst and summaryUrl
{
  "transactionId": "tr101",
  "integration": "SELECTIVE_NATIVE",
  "country": "DE",
  "presetFirst": true,
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2016"
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "summaryUrl": "https://dev.oscato.com/shop/success.html",
    "notificationUrl": "https://dev.oscato.com/shop/notify.html"
  }
}

PRESET Request

When the customer enters their details on the payment page and makes a submission, there should be a PRESET request (to the operation URL) using the customer's data.

In all integration scenarios except Pure Native, this will go direct to the OPG from the customer's client. It should contain the account data structure similar to the CHARGE request.

The AJAX library will handle this correctly on button click.

For a Selective Native integration without the AJAX library, the inter-frame communication must be triggered as described there, and an operation_response_event will be sent to reflect the server response.

PRESET Request
 {
  "account": {
    "holderName": "test",
    "number": "4111111111111111",
    "expiryMonth": "12",
    "verificationCode": "333",
    "expiryYear": "18"
  }
}

The response to a successful PRESET call will show that the customer should be redirected to the summary page URL that was given in the corresponding LIST request. Again, the AJAX library will hande this. When implementing a Hosted or AJAX-dependent integration scenario, you might also want to receive, in the PRESET response, a full masked account data to show your customer which payment card has been used. In these cases, a simple GET on the LIST session can be done (GET on its self link); it will respond to the current session status and the preset account.

The operation URL of the returned object is where the subsequent CHARGE should be going to (see below).

Since the PRESET step also performs the configured validations if available (see above), the transaction could also be declined at this stage. A provider may, for example, decline to offer Invoice payments for this customer. This will be indicated by the Interaction Codes.

In most cases, the customer should then be returned to the payment page so that the existing LIST resource is reloaded and the remaining payment options presented again. In this example, Invoice may have been removed from the list, but the customer can still select another more secure method.

PRESET Response (Pure Native)
 {
  "links": {
    "operation": "https://api.sandbox.oscato.net/api/lists/abc123abc123abc123/charge"
  },
  "resultInfo": "Network and account are preset",
  "status": {
  "code": "preset",
  "reason": "preset"
  },
  "redirect": {
    "url": "https://dev.oscato.com/shop/success.html",
    "method": "GET",
    "parameters": [
      {"name": "shortId","value": "06598-63085"},
      {"name": "interactionReason","value": "OK"},
      {"name": "resultCode","value": "00000.11.000"},
      {"name": "longId","value": "58454da9e4b0a473f4675a96c"},
      {"name": "transactionId","value": "tr10687"},
      {"name": "interactionCode","value": "PROCEED"}
    ],
  },
  "network": "VISA",
  "maskedAccount": {
    "displayLabel": "41 *** 1111 12 | 18",
    "holderName": "test",
    "number": "41 *** 1111",
    "expiryMonth": 12,
    "expiryYear": 18
  },
  "interaction": {
  "code": "PROCEED",
  "reason": "OK"
  },
  "resultCode": "00000.11.000",
  "returnCode": {
    "name": "OK",
    "source": "GATEWAY"
  },
  "identification": {
  "longId": "abcd1234abc123",
  "shortId": "06598-63085",
  "transactionId": "tr101"
  },
  "timestamp": "2016-12-05T11:21:13.089+0000"
}

CHARGE Request

At this stage of the process, the customer is on the summary page generated by your shop system. Typically, this page would ask the customer to confirm the payment based on the summary presented. If the customer agrees, your server-side system should then make a CHARGE request using the operation URL returned in the PRESET response.

It looks like this: https://api.sandbox.oscato.com/api/lists/{LIST-longId}/charge

The ID to be referenced in this CHARGE URL is that of the LIST, not the PRESET resource.

As the data has already been preset, no account information needs to be provided in the CHARGE Request body. In fact, only an empty JSON body {}  is provided as the request. This is also the reason why the CHARGE can (and should) go through your server-side system. There is no sensitive payment-data present here.

After the CHARGE call, your system should redirect the customer to the URL given in the response as redirect.url. In the success case, this will be the original success URL as specified in the LIST request (the thank-you page).

CHARGE Response
{
  "links": {
    "payout": "https://api.sandbox.oscato.net/api/charges/58454db9e4b0a473f4675a97c/payout",
    "self": "https://api.sandbox..oscato.net/api/charges/58454db9e4b0a473f4675a97c"
  },
  "timestamp": "2016-12-05T11:21:29.729+0000",
  "operation": "CHARGE",
  "resultCode": "00000.TESTPSP.000",
  "resultInfo": "Approved",
  "pspCode": "TESTPSP",
  "returnCode": {
    "name": "OK",
    "source": "PSP"
  },
  "status": {
    "code": "charged",
    "reason": "debited"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "clearing": {
    "amount": 19.99,
    "currency": "EUR"
  },
  "identification": {
    "longId": "58454db9e4b0a473f4675a97c",
    "shortId": "15043-34925",
    "transactionId": "tr10687",
    "pspId": "VISA.DEBIT.1480889314499"
  },
  "redirect": {
    "url": "https://dev.oscato.com/shop/success.html",
    "method": "GET",
.....

Delayed Payment Submission

If your customer reviews and confirms their order on a separate summary page, the customer's payment data (entered in a previous step) must be cached in the interim. The sensitive nature of payment data combined with strict PCI DSS regulations mean that caching customer payment-data must be done carefully.

With Delayed Payment Submission, optile does exactly that. Instead of a CHARGE request, your system can temporarily cache payment data via a PRESET request. This is different from a registration, as it is only temporarily stored -- to respect data privacy principles. After the customer has confirmed the order on the final summary page, your system can issue the corresponding CHARGE request (without payment data).

This will trigger an immediate payment or a deferred payment, depending on your configuration. In a deferred payment, the payment would be preauthorized only, and your system should send a final CLOSING request when the order is shipped. Next, the actual payment capture is triggered.

Please sign in to view further details of this article. Login

Web Content Display

Payment Account Registration

At the (initial) checkout, payment accounts (eg cards) can be stored with the used payment provider for future use -- typically with provider tokens managed by optile. At the same time, this sensitive data will be stored (in a PCI-compliant manner) within the Payment Gateway to allow provider switching and therefore give you more independence from individual payment providers. See Secure Storage.

There are 2 kinds of registration: Regular and Recurring.

Regular Account Registration

If customers return to your shop, they will see their previously registered payment accounts and do not need to enter their information again. This can increase conversion, especially with credit and debit cards or SEPA direct-debit bank accounts. For credit cards, the verification code (CVV, CVC, etc.) must still be entered by the customer because PCI DSS regulations prohibit the storage of this data. (If the payment provider in the background accepts this, as most acquirer interfaces do, this can also be omitted by using the Dynamic Verification Code feature).

Recurring Registration

This kind of registration can be used to trigger Recurring Charges from your backend without customer interaction. This feature must be supported by the Payment Service Provider but does not require the verification code for any subsequent charges.

Payment page with a registered account (regular)

Customer Agreement on Payment Page

You can configure both types of registration. Since they need the customer's agreement, you should provide checkboxes in the payment page. If registration was enabled on optile's side, you simply start a payment session with a regular LIST Request. In AJAX and Hosted integration scenarios, the payment page will then be rendered automatically and the CHARGE Request submitted correctly, so you won't need the following information.

If your system evaluates the LIST Response itself, there will be 2 attributes for each network: registration and recurrence, which correspond to the 2 registration types.

Depending on the configuration, these attributes can have the following values:

  • NONE No checkbox should be displayed, the network is not registered
  • OPTIONAL Checkbox should be displayed and can be checked by the user
  • OPTIONAL_PRESELECTED Same as OPTIONAL, but checkbox should be pre-checked
  • FORCED No checkbox should be displayed, but the account is registered anyway
  • FORCED_DISPLAYED Same as FORCED, but a non-clickable and pre-checked checkbox should be displayed

Checkbox Rendering

In the OPTIONAL case, you can include an additional checkbox next to the network form, like this in the HTML source:

<input type="checkbox" id="allowRecurrenceVISA" name="allowRecurrence" value="true">
<label for="allowRecurrenceVISA">I authorize recurring charges on my account</label>

In the FORCED case, you can include an additional hidden value, as shown below, if you have a Display Native integration and need to pass the parameter from the client direct to OPG:

<input type="hidden" name="autoRegistration" value="true">

Checkboxes should look similar to those shown on the right. Note: a separate checkbox is needed for each payment network, because some networks do not support account registration and/or recurring charges.

LIST response with registration checkbox attributes

...,
{
  "method":"CREDIT_CARD",
  "registration":"FORCED",
  "code":"VISA",
  "label":"Visa",
  "recurrence":"FORCED_DISPLAYED",
  "links":{
    "logo":"https://api.sandbox.oscato.com/resource/network/DEMO/de_DE/VISA/logo.gif",
    "operation":"https://api.sandbox.oscato.com/api/lists/2885c861-fae4-4fc1-add4-a856c1012e21/VISA/charge",
    "form":"https://api.sandbox.oscato.com/resource/form/VISA/standard.html",
    "validation":"https://api.sandbox.oscato.com/api/pci/2885c861-fae4-4fc1-add4-a856c1012e21/DEMO/de_DE/VISA/validate",
    "localizedForm":"https://api.sandbox.oscato.com/resource/form/DEMO/de_DE/VISA/standard.html",
    "lang":"https://api.sandbox.oscato.com/resource/lang/DEMO/de_DE/VISA.properties"
  }
},
...

Payment page with registration checkboxes

Submitting the CHARGE

When the customer submits the payment data, the information indicating which checkboxes have been checked must be passed in the CHARGE Request. This is done through the parameters autoRegistration and allowRecurrence, which can have the values true or false (default). See the example.

Again, AJAX and Hosted integration scenarios already do this for you.

CHARGE request with registration flags
{
  "account": {
    "holderName": "Walter Smith",
    "number": "4111111111111111",
    "verificationCode": "123",
    "expiryMonth": "2",
    "expiryYear": "2017"
  },
  "autoRegistration": true,
  "allowRecurrence": true
}

Receiving Registration Credentials

A CHARGE request like this will process the initial payment as usual. If the customer has not yet been registered, they will be registered at this stage together with the payment account, and the following Status Notification will be sent:

  • Concerning entity = customer: This will be sent only once to your system with both attributes, customerRegistrationPassword and customerRegistrationId. These values should be stored on your side because they will enable you to use the payment accounts of this customer from within the Secure Storage again later.
  • Concerning entity = account: This will contain payment network and accountRegistrationId which we will see again when manipulating individual registered payment accounts (as opposed to the whole customer registration). But in most cases you should not store this, because you will receive and use these IDs implicitly in the context of the use cases such as Account Update and Registration Page or Setting a Preferred Payment Account.
  • Concerning entity = payment: This is the normal notification that only contains the customerRegistrationId which your system will receive for any payment by a registered customer.
For security reasons you will not be able to retrieve the full payment account data again. You can only see a masked representation of the data (eg 41** **** **** 1111), and you will be able to trigger subsequent charges only to your benefit. This minimizes risk of abuse through third parties.

Using a Regular Account Registration

If you enabled regular account registration (autoRegistration flag), the next time the customer does a checkout, you can submit the customerRegistrationId and -password with the next LIST Request as shown on the right (see customer.registration).

Using a Recurring Registration

If the initial CHARGE Request enabled a recurring registration (allowRecurrence flag), you will be able to trigger subsequent charges from the backend (ie without further customer interaction) using the customerRegistrationId and -password. Find out more about Recurring Charges.
LIST request for a registered customer

{
  "transactionId": "tr101",
  "country": "DE",
  "customer": {
    "number": "42",
      "email": "john.doe@example.com",
      "registration": {
        "id": "555dd649e4b086337cd4d18dq",
        "password": "h5dhgn7gd3bhlkwykxgnhrd2346nm0ew6d"
      }
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2015"
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}

As a result, you will get back not only networks.applicable in the LIST response, but also a list of accounts, which represent previously registered payment accounts. This contains only regular account registrations, not accounts that were (only) registered for recurring.

These payment accounts should be displayed above the selection of payment methods. The response will provide information such as a localizedForm and displayLabel to do this in the regular fashion.

LIST response with account list
{
  ...
  "timestamp": "2015-03-21T12:57:55.762+0000",
  "operation": "LIST",
  "resultCode": "00000.11.000",
  "resultInfo": "5 applicable and 1 registered networks are found",
  ...
  "accounts": [{
     "links": {
       "operation": "https://api.sandbox.oscato.com/api/lists/555dd651e4b088681fe/accounts/555dd649e4b086337c/charge",
       "logo": "https://resources.sandbox.oscato.com/resource/network/ABC123/de_DE/VISA/logo.png",
       "form": "https://resources.sandbox.oscato.com/resource/form/VISA/registered.html",
       "localizedForm": "https://resources.sandbox.oscato.com/resource/form/ABC123/de_DE/VISA/registered.html",
       "lang": "https://resources.sandbox.oscato.com/resource/lang/ABC123/de_DE/VISA.properties"
     },
     "code": "VISA",
     "label": "VISA",
     "maskedAccount": {
       "displayLabel": "41 *** 1111    02 | 2017",
       "holderName": "Martin Tester",
       "number": "41 *** 1111",
       "expiryMonth": 2,
       "expiryYear": 2017
     }}
  ],
  "networks": {
    "applicable": [{
        "code": "VISA",
         ... }]
  }
}	

Payment Account Registration

At the (initial) checkout, payment accounts (eg cards) can be stored with the used payment provider for future use -- typically with provider tokens managed by optile. At the same time, this sensitive data will be stored (in a PCI-compliant manner) within the Payment Gateway to allow provider switching and therefore give you more independence from individual payment providers. See Secure Storage.

Please sign in to view further details of this article. Login

Web Content Display

Account Update and Registration Page

Updating and Registering Payment Accounts is a LIST Request feature that allows customers to manage payment data associated with their accounts. The feature is initiated by the merchants in their backend, and it gives customers more control over their saved payment methods.

This functionality lets the customer:

  • Update registered accounts (expiration date of credit and debit cards)
  • Delete registered accounts (except the last recurring registration)
  • Register new payment accounts without first making a payment
  • Set preferred payment account (separate documentation)
The request works in a similar way to the LIST Request but with these important differences:
  • A property updateOnly, which exists at root level, must be set to true
  • When updating a customer's payment methods, the customer's registration details must be included to identify the customer in question

In the pane on the right, there is a sample LIST Request with updateOnly specified.

  • URL: https://api.sandbox.oscato.com/api/lists or https://api.live.oscato.com/api/lists
  • Method: POST
  • Authentication: Merchant Code and Token are needed
Example of Update Request
 {
  "transactionId": "tr1068735466d34",
  "country": "DE",
  "updateOnly": true,
  "customer": {
    "number": "4278",
    "email": "john.doe@example.com",
    "registration": {
      "id": "584578ebe4b0583916a67e6ee",
      "password": "UbHkTMmYhU1byjDe"
    }
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "summaryUrl": "https://dev.oscato.com/shop/success.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}

Compared to a normal LIST Response there are the following differences:

Registered Accounts: Only accounts that are allowed to be updated will be returned. If the account cannot be updated, it will not be shown. Where the payment account is updatable, the operationUrl returned in the LIST Response will point to an "update" instead of "charge" endpoint (for backwards compatibility with the existing integrations), eg "operation": "https://api.sandbox.oscato.com/pci/v1/5832ec78e4b0b0d86234c04bl/accounts/5832ebe41652164c14b86719a/update"

The associated formUrl / localizedFormUrl points to a form snippet with an expiration date and verification code, or there will be equivalent iFrame links for Selective Native.

Applicable Networks: Only payment networks with standalone registration capability will be shown. Their operationUrl points to a "register" instead of "charge" endpoint, eg https://api.sandbox.oscato.com/pci/v1/5832ec78e4b0b0d86234c04bl/SEPADD/register

A new attribute operationType at the top level of the response object enables the client to see that this is an Account Update Request and then handle any desired follow-on action, such as displaying delete links for saved accounts.

The possible values of the operationType property are:

  • CHARGE
  • PRESET
  • PAYOUT
  • UPDATE
Below is a snippet from the LIST Response:
 {
  "links": {
    "self": "https://api.sandbox.oscato.com/pci/v1/588f0d4d16526507caceb575lbi1tm58fp1vt9asq425f3u9i3",
    "customer": "https://api.sandbox.oscato.com/api/customers/5889b7ab1652e1e7030f7ae8u"
  },
  "timestamp": "2017-01-30T09:54:21.835+0000",
  "operation": "LIST",
  "resultCode": "00000.11.000",
  "resultInfo": "4 applicable and 5 registered networks are found",
  "returnCode": {
    "name": "OK",
    "source": "GATEWAY"
  },
  "status": {
    "code": "listed",
    "reason": "listed"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "identification": {
    "longId": "588f0d4d16526507caceb575lbi1tm58fp1vt9asq425f3u9i3",
    "shortId": "10055-11601",
    "transactionId": "tr10687"
  },
  "accounts": [
    {
      "links": {
        "form": "https://resources.sandbox.oscato.com/resource/form/MASTERCARD/update.html",
        "logo": "https://resources.sandbox.oscato.com/resource/network/ABC123/de_DE/MASTERCARD/logo.png",
        "self": "https://api.sandbox.oscato.com/pci/v1/588f0d4d16526507caceb575lbi1tm58fp1vt9asq425f3u9i3/accounts/5889ce431652e1e7030f7b45a",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/ABC123/de_DE/MASTERCARD.properties",
        "operation": "https://api.sandbox.oscato.com/pci/v1/588f0d4d16526507caceb575lbi1tm58fp1vt9asq425f3u9i3/accounts/5889ce431652e1e7030f7b45a/update",
        "localizedForm": "https://resources.sandbox.oscato.com/resource/form/ABC123/DE/de_DE/MASTERCARD/update.html",
        "validation": "https://api.sandbox.oscato.com/pci/v1/588f0d4d16526507caceb575lbi1tm58fp1vt9asq425f3u9i3/ABC123/de_DE/MASTERCARD/update/validate"
      },
      "code": "MASTERCARD",
      "label": "MasterCard",
      "maskedAccount": {
        "displayLabel": "51 *** 5100    03 | 2019",
        "holderName": "xcvbxcv",
        "number": "51 *** 5100",
        "expiryMonth": 3,
        "expiryYear": 2019
      },
      "lastSuccessfulChargeAt": "2017-01-26T11:59:59.135+0000",
      "selected": false
    }
    .....
   ]
   "networks": {
     "applicable": [{
       "code": "PAYPAL",
       "label": "PayPal",
       "method": "WALLET",
       "grouping": "WALLET",
       "registration": "OPTIONAL",
       "recurrence": "NONE",
       "redirect": true,
       "links": {
         "form": "https://resources.sandbox.oscato.com/resource/form/PAYPAL/standard.html",
         "logo": "https://resources.sandbox.oscato.com/resource/network/ABC123/de_DE/PAYPAL/logo.png",
         "self": "https://api.sandbox.oscato.com/pci/v1/588f117e16522490c20d0aaflnmhcm4cl9870ebtm1no90tsuv/PAYPAL",
         "lang": "https://resources.sandbox.oscato.com/resource/lang/ABC123/de_DE/PAYPAL.properties",
         "operation": "https://api.sandbox.oscato.com/pci/v1/588f117e16522490c20d0aaflnmhcm4cl9870ebtm1no90tsuv/PAYPAL/register",
         "localizedForm": "https://resources.sandbox.oscato.com/resource/form/ABC123/DE/de_DE/PAYPAL/standard.html",
         "validation": "https://api.sandbox.oscato.com/pci/v1/588f117e16522490c20d0aaflnmhcm4cl9870ebtm1no90tsuv/ABC123/de_DE/PAYPAL/standard/validate"
      },
      "button": "button.update.label",
      "selected": false
     },
    ....
   ]
 },
 "operationType": "UPDATE"
}

accounts are the saved payment accounts for the customer in question, and networks.applicable are the payment methods available for this merchant configuration.
Integration Examples

To demonstrate the Update LIST process, we have split the examples into different documents based on integration type:

  • Native integration uses the concept of a localised form to display the data
  • Selective Native integrations will retrieve and display an iFrame instead of a localized form, but the approach is similar
  • Hosted Integration will handle the Update LIST on your behalf and while it is the easiest to integrate with, it offers the least control.
Set Preferred Payment Account

In an Update LIST, a customer can also set one of their registered accounts as preferred for future use. See Set preferred payment account.

Account Update and Registration Page - Native Integration

Native integration requires some extra steps to update a LIST.  Below, we show you how to:

  • Register a new payment method for an existing customer
  • Update an existing registered payment method
  • Delete an existing registered network
Register a new payment method for an existing customer

Please follow the code examples in the pane on the right.

Step 1. Make the LIST Request passing the parameters updateOnly = true and account registration (id and password) object.

Example LIST Request
 {
  "transactionId": "tr1068735466d37",
  "country": "DE",
  "updateOnly": true,
  "customer": {
    "number": "4278",
    "email": "test.Customer@optile.net",
    "registration": {
      "id": "584578ebe4b0583916a67e6eu",
      "password": "UbHkTMmYhU1byjD5"
    }
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "summaryUrl": "https://dev.oscato.com/shop/success.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}

Step 2. Read the operation links from the applicable networks section of the response.
The operation link is the location of the POST Request that will register the new method. For convenience, a link to a localised form snippet will be provided. This snippet can be presented to the customer so they can enter their new details.

Example LIST Response

  "networks": {
  "applicable": [{
    "code": "MASTERCARD",
    "label": "MasterCard",
    "method": "CREDIT_CARD",
    "grouping": "CREDIT_CARD",
    "registration": "OPTIONAL",
    "recurrence": "NONE",
    "redirect": false,
    "links": {
      ...
      "operation":"https://api.sandbox.oscato.com/pci/v1/58469340e4bae1b32d2fd83fl1r6ee4de1c0srn7loiieafh2e/MASTERCARD/register",
      "localizedForm":"https://resources.sandbox.oscato.com/resource/form/ABC123/DE/de_DE/MASTERCARD/update.html",
...

Step 3. After the customer enters the details of the new card, make a POST Request to the operation URL above and register a new MasterCard to the customer based on the new details provided.


{
  "account": {
  "holderName": "test name",
  "number": "5555555555554444",
  "expiryMonth": "12",
  "verificationCode": "333",
  "expiryYear": "18"
  }
}

After the request, a response will be shown that is similar to the one below.


{
  "resultInfo": "Approved",
  "interaction": {
   "code": "RELOAD",
   "reason": "UPDATED"
  }
}

If another LIST Request is repeated with the same body as in Step 1, the newly registered card will be visible in the accounts and can be presented to the customer at the frontend. Hosted and AJAX integrations do this automatically.


....
"resultInfo": "3 applicable and 4 registered networks are found",
....
"accounts": [
  {
   "links": {
    ....
   },
"code": "MASTERCARD",
"label": "MasterCard",
"maskedAccount": {
"displayLabel": "55 *** 4444 12 | 18",
"holderName": "test",
"number": "55 *** 4444",
"expiryMonth": 12,
"expiryYear": 18
},
....

 

Register a new payment method for a new customer

Please follow the code examples in the pane on the right.

Step 1. Make the LIST Request passing the parameters updateOnly = true but this time without passing an account registration object.

Example LIST Request
 {
  "transactionId": "tr1068735466d37",
  "country": "DE",
  "updateOnly": true,
  "customer": {
    "number": "4278",
    "email": "test.Customer@optile.net",
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "summaryUrl": "https://dev.oscato.com/shop/success.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}
Step 2. Follow the steps as shown above for a Registration of New Payment Method for Existing Customer.
Update an existing registered payment method

Here, we update the expiration month and year of the registered card shown in the example above.

Step 1. As usual, begin with a LIST Request. This is the same as the LIST Request in the example above but it is shown here for completeness.

{
    "transactionId": "tr1068735466d37",
    "country": "DE",
    "updateOnly": true,
    "customer": {
        "number": "4278",
        "email": "test.Customer@optile.net",
        "registration": {
           "id": "584578ebe4b0583916a67e6eu",
           "password": "UbHkTMmYhU1byjD5"
          }
         },
      "callback": {
        "returnUrl": "http://somesite.com/success.html",
        "cancelUrl": "http://somesite.com/cancel.html",
        "notificationUrl": "http://somesite.com/notification.html"
    }
}

Step 2. To update card details, select the relevant registered account from the accounts section of the LIST Response. The localized form is presented to the customer so they can update their registered accounts details.

Note: We are querying the existing accounts here, not the applicable networks. Applicable networks are relevant for registering new accounts. Updates to card details happen at account level.

....
"accounts":
 {
  "links":
  {
   ....
   "operation": "https://api.sandbox.oscato.com/pci/v1/5846a5f6e4b0e1b32   d2fd85alnocmstnce3hnpc030kc6n72gp/accounts/5846a0bce4b02797fa4af8b1a/   update",
   "localizedForm": "https://resources.sandbox.oscato.com/resource/form/   VINCEMCCGMBH/DE/de_DE/MASTERCARD/update.html"
}
"code": "MASTERCARD",
"label": "MasterCard",
"maskedAccount": {
   "displayLabel": "55 *** 4444 12 | 18",
   "holderName": "test",
   "number": "55 *** 4444",
   "expiryMonth": 12,
   "expiryYear": 18
   }

Step 3. Provide the localized form to the customer and, from the LIST Response, call the relevant operation URL (highlighted above). The customer then submits their updated data. See the JSON updating the expiry date in the pane on the right.


{
   "account": {
    "holderName": "test",
    "number": "5555555555554444",
    "expiryMonth": "3",
    "verificationCode": "333",
    "expiryYear": "20"
    }
}
This will return the following JSON

{
  "resultInfo": "Approved",
  "interaction": {
   "code": "RELOAD",
   "reason": "UPDATED"
  }
}
Making another LIST Request for the same customer will show that the expiry date has changed

 


....
"accounts": [
{
"links": {
   ....
 },
"code": "MASTERCARD",
"label": "MasterCard",
"maskedAccount": {
"displayLabel": "55 *** 4444 03 | 20",
"holderName": "test",
"number": "55 *** 4444",
"expiryMonth": 3,
"expiryYear": 20
},
....

 

Delete an existing registered network

An existing registered payment method can be deleted as long as it is not currently being used in a recurring payment subscription.

This example closely follows the example above, except that a DELETE request is called instead of a POST, and the address is slightly different (ie it does not contain the updated part). For completeness, the relevant JSON snippets are given -- although in some cases they will be the same as the snippets above.

Step 1. Make a LIST Request

{
    "transactionId": "tr1068735466d37",
    "country": "DE",
    "updateOnly": true,
    "customer": {
        "number": "4278",
        "email": "test.Customer@optile.net",
        "registration": {
           "id": "584578ebe4b0583916a67e6eu",
           "password": "UbHkTMmYhU1byjD5"
          }
         },
      "callback": {
        "returnUrl": "http://somesite.com/success.html",
        "cancelUrl": "http://somesite.com/cancel.html",
        "notificationUrl": "http://somesite.com/notification.html"
    }
}

 

Step 2. In the corresponding LIST Response, select the self link of the payment method to be removed. 

....
"accounts":
{
 "links":
  {
   ....
   "self": "https://api.sandbox.oscato.com/pci/v1/588f1b3016526507caceb58cltd243ska6ht4lopvqgardruh4/MASTERCARD
   ....
  }
"code": "MASTERCARD",
"label": "MasterCard",
"maskedAccount":
{
"displayLabel": "55 *** 4444 12 | 18",
"holderName": "test",
"number": "55 *** 4444",
"expiryMonth": 3,
"expiryYear":20
}

 

Step 3. Make a DELETE request on the self link of the account to remove. 

After the DELETE method is called, you will receive a response confirming de-registration.

{
  "resultInfo": "Account registration type is updated",
   "interaction": {
   "code": "RELOAD",
   "reason": "UPDATED"
  }
}

 

Your servers will also receive a notification confirming that entity = account has accountStatus = deregistered.

A quick LIST Request will confirm that the registered payment method has been removed from the accounts object.


"resultInfo": "3 applicable and 3 registered networks are found",

 

Account Update and Registration Page - Selective Native Integration

Selective Native integrations retrieve and display an iFrame instead of a localized form, but the approach is similar to Native integration. Please sign in to read how a Selective Native integration scenario deals with the Update LIST.

For details on handling this iFrame, go to Selective Native.


{
    "transactionId": "tr1068735466d37",
    "country": "DE",
    "integration": "SELECTIVE_NATIVE",
    "updateOnly": true,
    "customer": {
        "number": "4278",
        "email": "test.Customer@optile.net",
        "registration": {
           "id": "584578ebe4b0583916a67e6eu",
           "password": "UbHkTMmYhU1byjD5"
          }
         },
      "callback": {
        "returnUrl": "http://somesite.com/success.html",
        "cancelUrl": "http://somesite.com/cancel.html",
        "notificationUrl": "http://somesite.com/notification.html"
    }
}

The iFrame to display will be presented in LIST Response for each 


"accounts": [
  {
  "links": {
   ....
   "iFrame": "https://resources.sandbox.oscato.com/paymentpage/iframe.html?listId=585914bc1652e8259d578c09lb74jsr4lfom4irgg7d73qb5pt&accountId=5857c6c91652031c165ec19fa",
   "logo": "https://resources.sandbox.oscato.com/resource/network/VINCEMCCGMBH/de_DE/MASTERCARD/logo.png",
   "self": "https://api.sandbox.oscato.com/pci/v1/585914bc1652e8259d578c09lb74jsr4lfom4irgg7d73qb5pt/accounts/5857c6c91652031c165ec19fa",
....

 

To delete an account in a Selective Native implementation, a HttpDelete request can be made to the self url from the frontend.

For more detailed information, see the Native Integration example.
Selective Native integration operates in a similar way to Native Integration, but instead of displaying a localised form, the merchant will present the customer with an iframe where card details can be edited.
Account Update and Registration Page - Hosted Integration

Hosted integration will handle the Update LIST on your behalf and is the easiest way to integrate, but it offers the least control. Please sign in to read how the Hosted integration scenario deals with the Update LIST.


{
    "transactionId": "tr1068735466d34",
    "country": "IE",
    "integration":"HOSTED",
    "updateOnly": true,
    "customer": {
        "number": "4278",
        "email": "test.Customer@optile.net",
        "registration": {
           "id": "584578ebe4b0583916a67e6eu",
           "password": "UbHkTMmYhU1byjD5"
          }
         },
      "callback": {
        "returnUrl": "http://somesite.com/success.html",
        "cancelUrl": "http://somesite.com/cancel.html",
        "notificationUrl": "http://somesite.com/notification.html"
    }
}

 

The LIST Response will include a redirect URL where all payment methods can be managed. See the screenshots below.

 


"redirect": {
   "url": "https://resources.lsandbox.oscato.com/paymentpage/checkout-auto.html?listId=58491623e4b086f92f55dc29lk9pdi4hdnpqq2htdn651rucd2&liveValidation=true&smartSwitch=true",
   "method": "GET",
   "suppressIFrame": false
   },
"operationType": "UPDATE"
}>
User Experience

Select the relevant payment method via the radio button, enter the updated information and press Save. To delete the payment method, select the relevant radio button, click Delete and confirm your choice.

Add a new payment method

To add a new payment method: select Add new account, and fill in the relevant details. Click Save.

Account Update and Registration Page

Updating and Registering Payment Accounts is a LIST Request feature that allows customers to manage payment data associated with their accounts. The feature is initiated by the merchants in their backend, and it gives customers more control over their saved payment methods.

This functionality lets the customer:

  • Update registered accounts (expiration date of credit and debit cards)
  • Delete registered accounts (except the last recurring registration)
  • Register new payment accounts without first making a payment
  • Set preferred payment account (separate documentation)

Please sign in to view further details of this article. Login

Web Content Display

Set Preferred Payment Account

A Recurring Charge is always triggered by specifying the registered customer through an API request, but not the registered payment account that should be used. This means OPG will select the payment account in the background. It means that you, the merchant, do not have to manage your customers' registered payment accounts yourself. With the "Set Preferred" feature, your customer can choose which of their payment accounts is their preferred one. The preferred payment account would then be debited at the next Recurring Charge.

The feature can also be applied to standard account registrations.  But this only meabs that the preference determines which registered account will be at the top of the list on the payment page during the next checkout. The customer can still select another payment method.

At the moment, this feature can be accessed natively; AJAX library and Hosted Payment Page support will be added on request.

Integration

To let your customers set their preferred account, your system must initialize an Update LIST with the parameter updateOnly: true. As in any other LIST Request, the request body can determine if recurring payment account registrations should be returned by setting the parameter channel to RECURRING. Otherwise normal account registrations will be returned.

In any case the LIST Response will show the respective registered accounts, as in the example below.

LIST Response for Registered Accounts Selective Native Integration

...
  "accounts": [{
    "links": {
      "iFrame": "https://resources.sandbox.oscato.com/paymentpage/iframe.html?listId=585ab060e4b0f1217e9f4b3alr54bifbfla76esesbesj4k7ot&accountId=585a98bae4b091f43e2a0295a",
      "logo": "https://resources.sandbox.oscato.com/resource/network/DEMO_SK/de_DE/VISA/logo.png",
      "self": "https://api.sandbox.oscato.com/pci/v1/585ab060e4b0f1217e9f4b3alr54bifbfla76esesbesj4k7ot/accounts/585a98bae4b091f43e2a0295a",
      "lang": "https://resources.sandbox.oscato.com/resource/lang/DEMO_SK/de_DE/VISA.properties"
    },
    "code": "VISA",
    "label": "Visa",
    "maskedAccount": {
      "displayLabel": "40 *** 1112    08 | 2018",
      "holderName": "Jane Doe",
      "number": "40 *** 1112",
      "expiryMonth": 8,
      "expiryYear": 2018
    },
    "selected": false,
    "iFrameHeight": 35
    },
    ...
  ],
...

This list should be visualized for the user in the common way. See LIST Response, Update LIST. To make a payment account the preferred one, your system makes a simple POST request to the setpreferred endpoint of that account. The URL is the self link as given in the response plus an appended /setpreferred.

So the request for the example above would be:

  • URL: https://api.sandbox.oscato.com/pci/v1/585ab060e4b0f1217e9f4b3alr54bifbfla76esesbesj4k7ot/accounts/585a98bae4b091f43e2a0295a/setpreferred
  • Method: POST
  • Authentication: Not required (protected by the LIST ID)
  • Body: {}

Further details on the behavior of setpreferred

  • If the account was registered for standard registration and for Recurring Charges, the preference will apply to both. This means that the next Recurring Charge request by that customer would trigger a payment with that account, and it would show up as a first entry in the payment page of the checkout flow.
  • If the preferred payment account gets deleted for one type of registration, the preference will still stay for the other type of registration.
  • If the preferred account is deleted, the account that was the preferred account before will be reset as the preferred account again. OPG-internally; the account  preferences are listed in the order that they were set as 'preferred'.
  • If none of the registered accounts were ever set as a preferred account, then the list is organized by time of registration: the most recently registered account will be top of the list.
  • If the customer adds a new payment account, the previous preferred payment account will remain. In other words, the new account does not automatically become the preferred account unless no preferred account had been set (see above).

Set Preferred Payment Account

A Recurring Charge is always triggered by specifying the registered customer through an API request, but not the registered payment account that should be used. This means OPG will select the payment account in the background. It means that you, the merchant, do not have to manage your customers' registered payment accounts yourself. With the "Set Preferred" feature, your customer can choose which of their payment accounts is their preferred one. The preferred payment account would then be debited at the next Recurring Charge.

The feature can also be applied to standard account registrations.  But this only meabs that the preference determines which registered account will be at the top of the list on the payment page during the next checkout. The customer can still select another payment method.

Please sign in to view further details of this article. Login

Web Content Display

Delete Payment Account

If you want to allow customers to remove their registered account again, the typical solution is to provide an explicit Account Update and Registration Page. However, you can also integrate this functionality into the normal Payment Page of a checkout context, or trigger it entirely from your backoffice.

To get all of the customer's registered payment accounts, and enable delete, your system sends a LIST request with the additional "allowDelete": true parameter, as shown in the pane on the right.

Note:

  • This feature is supported by Hosted and AJAX integrations that will automatically render corresponding buttons. See below.
  • If you are using an Advanced integration scenario your system should trigger the account deletion in a second step after the LIST, similar to the description of the Account Update and Registration Page issuing HTTP DELETE requests.
  • The account registration data registration.id and registration.password must be sent in the LIST request.
  • The allowDelete parameter can also be used to switch off the possibility of account deletion on the Account Update and Registration Page by setting it to false. Otherwise account deletion will be available by default.

When using our Hosted page or AJAX library, every registered account will render an additional "Delete" button at their side, as shown below. Naturally, you can mofidy its style via your custom CSS stylesheet.

 

When a customer clicks the Delete button, the following dialog appears:

 

The button-label and user-messages are localized, so if you are using the payment page for a language supported by optile, they will show correctly.

LIST Request with allowDelete


{
  "transactionId": "tr101",
  "country": "DE",
  "integration": "HOSTED",
  "allowDelete": true,
  "customer": {
    "number": "42",
    "email": "john.doe@example.com",
    "registration": {
      "id": "5a5cd871abc123409a2b4abcu",
      "password": "abc8Yqaabc123C2s"
    }
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "Shop 101/20-03-2016"
  },
  "style" : {
    "hostedVersion":"v3"
  },
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html"
  }
}

Delete Payment Account

If you want to allow customers to remove their registered account again, the typical solution is to provide an explicit Account Update and Registration Page. However, you can also integrate this functionality into the normal Payment Page of a checkout context, or trigger it entirely from your backoffice.

Please sign in to view further details of this article. Login

Web Content Display

Secure Storage

optile's Secure Storage is an internal component that holds sensitive payment-account data in a double-encrypted, PCI-compliant way. It is used for payment account registrations and allows provider fallback. It cannot be accessed directly by the merchants, but it can be used by providing the customerRegistrationPassword in the LIST requests. This acts as one of the encryption keys of sensitive data. If, for example, there is a standard account registration with one provider (meaning the provider token is stored and used by optile), but the provider experiences downtime, optile will use the customerRegistrationPassword that was provided by the merchant to access an alternative provider (if configured for the merchant), even if it does not have an account registration yet.

This explains why checkouts with registered payment accounts will work most of the time -- by supplying customerRegistrationId only, then existing provider registrations can be used. But to access Secure Storage, decrypt sensitive account data, and do failover routing without existing provider registrations, the customerRegistrationPassword should be stored safely by your system and always supplied for payment sessions.

Secure Storage

Please sign in to view further details of this article. Login

Web Content Display

Payout Page

The Payment Gateway offers a dynamic Payout Page that works in a similar way to the Payment Page. It can be used to make payments to the user, and offers a convenient interactive way for the user to choose "payment" account or network to transfer the money to. The same principles apply as for the payment checkout. The initialization happens with a LIST Request, followed by a PAYOUT Request (in contrast to a CHARGE). Entered Accounts can be registered and used (they are actually shared with payment accounts). The payout also can be deferred, requiring an additional CLOSING step from the merchant backend.

The JavaScript library of the AJAX Integration can be used to render the payout page. This results in a flow similar to the payment checkout:

The main difference is that you provide the parameter preselection.direction with the value PAYOUT in the LIST Request. See example.

This shows that a LIST for PAYOUT (as opposed to CHARGE) is requested. The effect is that all forms and endpoints for further actions that are returned will be coined towards a payout.

Apart from that, the flow is the same. The subsequent PAYOUT Request is also structured as a CHARGE and will be handled by the JavaScript library, unless you chose a native integration.

LIST Request with Payout Parameter

...
"country": "DE",
"preselection": {
  "direction": "PAYOUT"
},
"customer": {
...
Credits

After a LIST is initialized for payout using the parameter preselection.direction = PAYOUT, any payment method returned in the list response can be deployed for credit operations. The payout URL can be found in the operation parameter and it will have this structure:

  • Sandbox: https://api.sandbox.oscato.com/api/lists/{listId}/{network}/payout
  • Live: https://api.live.oscato.com/api/lists/{listId}/{network}/payout
  • Basic Authentication: Merchant ID and Token

The credit is completed by sending a POST request to the operation URL, and sending the proper payment account in the JSON body. This process works in a similar way to a charge operation in a regular LIST request.

Example of payout operation

POST to https://api.sandbox.oscato.com/api/lists/5a218abc123b512afef4f87glf4djckdjaih37abc1231n9ft9/MASTERCARD/payout
Basic Authentication
{
"autoRegistration": false,
"allowRecurrence": false,
"account": {
  "holderName": "John Doe",
  "number": "5500000000000004",
  "expiryMonth": "02",
  "expiryYear": "2019",
  "verificationCode": "555"
  }
}


Deferred Mode

The LIST for PAYOUT can also be requested in deferred mode, meaning that the customer submission of account details (the PAYOUT Request) does not yet trigger the money transfer. Instead, a consecutive CLOSING Request is needed, typically issued by the Merchant system after a staff member has reviewed the transaction. At this point, the transaction will be made through the configured providers.

For technical information on how to initialize and close deferred transactions, see Deferred Payments. The only difference for payouts is that there will be no reservation of funds on the payer's side.

Payout Page

The Payment Gateway offers a dynamic Payout Page that works in a similar way to the Payment Page. It can be used to make payments to the user, and offers a convenient interactive way for the user to choose "payment" account or network to transfer the money to. The same principles apply as for the payment checkout. The initialization happens with a LIST Request, followed by a PAYOUT Request (in contrast to a CHARGE). Entered Accounts can be registered and used (they are actually shared with payment accounts). The payout also can be deferred, requiring an additional CLOSING step from the merchant backend.

Please sign in to view further details of this article. Login

Web Content Display

AJAX Library Integration

Including the JavaScript Library

The most recent AJAX Integration package can be downloaded here (login required): op-payment-widget-2.1.10.zip (~860 KB).

The zip file contains the following folders and files:

  • dist: The completely built and ready-to-use JavaScript and CSS files
  • example: An example HTML file in two versions, one linking the minified resources (JS & CSS) the other the development versions
  • node_modules: All node (npm) dependencies required to build the AJAX library
  • src: development source (based on node.js with the browserify addon)
  • package.json: list of build and runtime dependencies, and development scripts
  • README.md: A starting point for developers (node.js experience recommended)

The dist folder contains these files:

File  Description
op-payment-widget-2.x.x.js The readily built and readable JavaScript library.
op-payment-widget-2.x.x.min.js The minified version for production usage.
op-payment-widget.js A copy of the versioned file. Intended for optile-side hosting, we recommend merchants to use versioned files.
op-payment-widget-2.x.x.css The responsive CSS for the widget
op-payment-widget-2.x.x.min.css The minified version for production usage
op-payment-widget.css A copy of the versioned file. Intended for optile-side hosting, we recommend merchants to use versioned files.
responsive.html The HTML source of optile's hosted payment page, can be used as example to get started with development.

 

You can integrate the respective JavaScript and CSS files into an HTML page using the HTML header standard way.

Note that you also have to include the jQuery JavaScript framework yourself. If you want to support legacy browsers like Internet Explorer 6-8, Opera 12.1x or Safari 5.1+, we recommend a 1.12.x version for maximum compatibility (the latest 1.x version at the time of writing is 1.12.4).

We also recommend to set the viewport meta tag to enable the responsive UX, see example on the right.

HTML linking / including JavaScript and CSS

<head>
  <code class="language-markup"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"></code>
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
  <script type="text/javascript" src="../op-payment-widget-dist/op-payment-widget-2.1.18.min.js"></script>
  <code class="language-markup"><link rel="stylesheet" type="text/css" href="../op-payment-widget-dist/op-payment-widget-2.1.18.min.css"></code>
  <!-- ... -->
</head>

Handling the LIST object ID

The LIST Request needs to be initiated from your backend, because it needs to contain your sensitive OPG credentials. These should never be processed through the customer's browser. Read about this call in our LIST Request article.

As a result a LIST object will be generated in OPG that contains all information to generate the payment checkout user interface (i.e., payment page). The only important part of the LIST Response is the link to this object (containing its ID).

On the right pane you can find an example LIST Response with the link to the object >>

LIST Response

{
  "links": {
    "self": "https://api.sandbox.oscato.com/pci/v1/ce3eec14-e186-4b7c-94a1-fde802412e69"
  },
    ...
}

This URL to "self" or the contained LIST object ID (in this example: ce3eec14-e186-4b7c-94a1-fde802412e69) has to go back to the customer's browser and from there to the AJAX Integration Library. There are two ways of doing this:

  1. Redirect the browser to a (possibly static) HTML page that integrates the library and pass one of these LIST object identifiers as a GET parameter named listUrl or listId.
    Examples:
    http://www.ubuy.com/checkout/payment.html?listUrl=https%3A%2F%2Fapi.sandbox.oscato.com%2Fpci%2Fv1%2Fce3eec14-e186-4b7c-94a1-fde802412e69
    http://www.ubuy.com/checkout/payment.html?listId=ce3eec14-e186-4b7c-94a1-fde802412e69
     
  2. Generate the HTML page on server side that contains the listUrl or listId parameter in the initialization call of the library. Find an example in the initialization call section below.

 

In order to have the payment checkout forms automatically injected into the current HTML DOM, you have to initialize the library.

You do so by specifying the HTML element you want to inject into first. Typically this is a <div> element. In the example it has the Id paymentNetworks and is referenced by jQuery syntax $('#paymentNetworks'). Then you trigger the checkoutList call from there.

An example call looks like this >>

JavaScript Initialization Call

$('#paymentNetworks').checkoutList({
  payButton: "submitBtn",
  baseUrl: "https://api.sandbox.oscato.com/pci/v1/",
  smartSwitch: true,
  developmentMode: false });

These are the options you can provide in the call to configure and tune the payment checkout:

baseUrl String optional

The URL of the optile OPG service that will handle all the AJAX calls. It depends on the OPG version and enviroment you are using.

Sandbox:  https://api.sandbox.oscato.com/pci/v1/.

Live: https://api.live.oscato.com/pci/v1/.

Not required if listUrl is used.

listId String optional

The ID of the LIST object as returned by the LIST Response. If not provided in the JavaScript call, the library will look for a GET query parameter called listId and use its value if found.

Not required if listUrl is used.

listUrl String optional

The URL to the generated LIST object as returned by the LIST response. If not provided in the JavaScript call, the library will look for a GET query parameter calles listUrl and use its value if found.

This value overrides any given listId and baseUrl parameters.

payButton String mandatory The ID of the HTML element of the submit button defined by merchant.
payButtonContainer String optional The ID of the HTML element that contains the submit button. Used with methods that require proprietary provider buttons, which will then replace the standard payment button dynamically.
smartSwitch Boolean optional

Boolean value to enable the "Smart Network Switch" feature for cards. "Smart Network Switch" automatically detects the credit card scheme by its card number while typing. Default is false.

For payment methods other than cards it is meaningless.

abortFunction Function optional

Custom function to deal with ABORT interaction code of the response object. If set, it will replace the redirect defined in callback.cancelUrl.

Attention: even if an abortFunction is set, it is still required to have a callback.cancelUrl in place. This is to guarantee a proper response case the custom function fails to execute.

proceedFunction Function optional

Custom function to deal with PROCEED interaction code of the response object. If set, it will replace the redirect defined in callback.returnUrl and callback.summaryUrl. Note that this function replaces two possible redirections (return on success and summary page), so you have to act on the OPG response object to construct a proper replacement for a success or summary.

Attention: even if a proceedFunction is set, it is still required to have a callback.returnUrl and callback.summaryUrl in place. This is to guarantee a proper response case the custom function fails to execute.

Furthermore, intrinsic redirect networks cannot have their behavior changed. When using a custom proceedFunction, you will have to process the response object to build the redirect manually.

Property
Type
M / O
Description

If the AJAX Integration library is correctly initialized and provided with a valid listId it will fetch all resources needed to build the payment forms from OPG automatically and inject it into the current HTML DOM.
Note that a generated LIST object expires after 30 minutes. Also it will only allow one successful Charge. See LIST Request for details.

The mobile version of the AJAX integration library depends on a special structure of the HTML file, which is due to the underlying jQuery Mobile framework. Start from using the provided sample file, or use Hosted Integration instead
Finalize your payment checkout page

Some hints to finalize your payment checkout page:

  • To adapt the styling to your needs, we suggest to edit the (un-minified) CSS stylesheet provided in the beginning of this section.
  • Make sure the provided icon hint.png is properly referenced and shows as a question mark icon next to the verification code input of credit cards, as well as the other icons in the desktop variant.
  • Use the development version of the library, which is available for enterprise merchants, to do your own advanced customizations of behavior and generated markup structure.
  • Further Payment Flow
  • After the users' choice of payment method is complete they will be automatically redirected (returnUrl / cancelURL / external PSP page) or get a response from your custom functions. In the case the browser goes to an external page for payment, they will still in the end be directed to the given returnURL or cancelURL.

Your backend will get a secure asynchronous notification about the current transaction status, which your system should listen to. See Status Notification for additional information.

Example HTML

<!DOCTYPE html>
<html>
<head>
  <title>Hosted Payment Page</title>
  <meta charset="utf-8">
  <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <script type="text/javascript" src="op-payment-widget-2.0.0.min.js"></script>
  <link rel="stylesheet" type="text/css" href="op-payment-widget-2.0.0.min.css">
  <script type="text/javascript">
    function initPaymentPage() {
      var dict = {};
      $('#paymentNetworks').checkoutList({
        payButton: "submitBtn",
        baseUrl: "https://api.sandbox.oscato.com/pci/v1/",
        abortFunction: function() {
          console.log("Error")
        },
        proceedFunction: function() {
          console.log("Success")
        }
}); }
// Initialize the payment page
      $(document).ready(function() {
        initPaymentPage(); });
  </script>
</head>
<body>
  <div id="paymentNetworks">
  </div>
  <button id="submitBtn" type="button"></button>
</body>
</html> 
Native Form Rendering

If you wish to implement natively the optile's localized forms snippets returned from the original LIST Response, please refer to the Native Form Rendering article for details.

AJAX Library Integration

Please sign in to view further details of this article. Login

Web Content Display

Provider Buttons

optile's AJAX library also handles the communication with providers who require proprietary JavaScript (such as checkout.js for PayPal).

During a regular payment flow, the optile widget builds a list of payment methods and listens to a button-submit to process the next step (for example, capture a payment). This button is designed and implemented by the merchant, so to make this possible, it must have the ID submitBtn, which is linked to the AJAX initialization function checkoutList when building the payment page. However, providers such as PayPal impose the use of their own payment button, which has specific styling elements that cannot be changed by merchants. If you include such a provider in the list of available networks, you have the additional challenge of switching between a merchant's and a provider's payment buttons.

To solve this challenge, the optile AJAX library replaces this button on demand: if a user selects a provider like PayPal, its proprietary button is loaded. If any other method is clicked, the merchant button is loaded. This is done by defining a <div> with ID submitButtonContainer which will be used as container to submitBtn and the provider's button. The checkoutList function must be initialized with the parameter payButtonContainer pointing to this container defined by the merchant, as seen in the second example in the pane on the right.

After these initialization steps, the payment page will look like the example below:

Left: Submit button for other payment networks. Right: PayPal proprietary button.

From an integration point of view, this is the only change needed to start using PayPal checkout. On the Provider Contract configuration side, a new parameter JAVASCRIPT_INTEGRATION should be set to true, but you can request this change direct from our support team if you wish.

Submit Button Container:

<div id="submitBtnContainer">
  <button hidden="hidden" id="submitBtn" type="button"></button>
</div>

JavaScript Initialization:

$("#paymentNetworks").checkoutList({
  payButton: "submitBtn",
  payButtonContainer: "submitBtnContainer",
  ...
});

Delayed Payment Submission (Summary Page)

optile's Delayed Payment Submission offers a unique solution: payment data is collected and cached ('PRESET') so the merchant has the chance to build a summary of the order before triggering the next step. With payment services that provide their own libraries, the summary page presents another two-fold challenge: First, the placement of the payment button has to happen there; and second, the proper process communication between optile and these third party libraries must be handled.

To overcome these obstacles, the optile AJAX widget (the same one used for the Payment Page) must also be included in the merchant Summary Page and properly initialized with a different set of parameters. Its current implementation supports PayPal checkout, Apple Pay and Google Pay, and future updates will cover new methods. As you saw in the payment page, the library makes use of the initialization function checkoutList, but now with different parameters and extra handler functions:

  • summaryPage:true tells the library that the current context is a summary page
  • summaryPageHandler: optional functions that can be implemented by the merchant for better control of the payment process
    • doOperation: after an end-user clicks the provider-specific payment button, it will be triggered to handle the CHARGE process request to the OPG.
    • onResult: handles result object after success or error sent back from the OPG.

See the pane on the right for examples of these functions.

Example of Summary Page initialization

function loadSummaryPage(inputData) {
  $("#paymentNetworks").checkoutList({
    payButton: "submitBtn",
    payButtonContainer: "submitBtnContainer",
    listUrl: inputData.links.self,
    summaryPage: true,
    summaryPageHandler: {
      doOperation: function(data, callBack) {
        $.ajax({
          type: data.method,
          dataType: "json",
          data: JSON.stringify(data.operationData ? data.operationData : {}),
          contentType: "application/json",
          url: data.url
        }).done(callBack)
      },
      onResult: summaryPageHandlerOnResult
    }
  });
}

Summary Page Handler Functions

The idea behind the summary-page handler functions is to give merchants the opportunity to intervene in the payment process, by implementing their own way of handling the trigger and result processing of a transaction. In this way, you can introduce custom logic that starts other parallel processes in your systems; and you get better control of the payment flow without needing to rely only on the functionality provided by optile. For example, with doOperation a merchant can send a signal to its backend saying that an item is being taken from stock. With onResult, you can define custom behavior of your user-interface based on the possible Interaction Codes sent by the OPG.

PayPal exception handling

There are some exceptional scenarios in which the merchant needs to cancel the payment operation mid-transaction. For example, it's possible that after triggering a CHARGE via doOperation a merchant sees that the item being ordered is no longer available. Ideally, the payment operation would be stopped before the end-user executes the payment on PayPal, meaning the PayPal popup should be closed by a trigger from the merchant systems. Since the introduction of PayPal checkout.js, such control is expected to happen in the frontend. To make this happen, the library has an exception handler that closes the popup. In practice, a merchant can trigger a popup-close by throwing a Javascript exception: throw new error.

For example, a merchant backend system can return an error to the frontend, which would then throw an error during doOperation execution to close the popup.

Example implementation of onResult handler

function handlerOnResult(data) {
  console.log("Result Data: ", data);
  switch (data.interaction.code) {
    case "PROCEED":
      $("#paymentNetworks").empty();
      $("#submitBtnContainer").hide();
      showGlobalSuccessMessage("Payment is done!")
      break;

    case "ABORT":
      $("#paymentNetworks").empty();
      $("#submitBtnContainer").hide();
      if (data.error instanceof Error) {
          showGlobalErrorMessage("Payment is aborted by Client!")
      } else {
          showGlobalErrorMessage("Payment is aborted!");
      }
      break;

    case "TRY_OTHER_ACCOUNT":
    case "RETRY":
      showGlobalErrorMessage("interaction." + data.interaction.code + "." + data.interaction.reason);
      break;
    case "TRY_OTHER_NETWORK":
    case "RELOAD":
      $("#paymentNetworks").empty();
      $("#submitBtnContainer").html('');
      //loadSummaryPage(data);
      window.setTimeout(function() {
        showGlobalErrorMessage("interaction." + data.interaction.code + "." + data.interaction.reason);
      }, 2000);
      break;
  }
}

Provider Buttons

optile's AJAX library also handles the communication with providers who require proprietary JavaScript (such as checkout.js for PayPal).

Please sign in to view further details of this article. Login

Web Content Display

Display & Pure Native Integration

Web Content Display

LIST Response

After submitting a LIST Request you will receive the LIST response.

  • If you chose AJAX Integration, you will only be interested in the link.self return parameter (and status information, to check if it worked).
  • If you use Hosted Integration you will get a very simplistic response and only be interested in the redirect return parameter.
  • Only where you use Native Integration will you need to analyze the list of available networks for this transaction in order to build the checkout payment page. Read the details linked below to see how.
The networks available are contained as an array in the response parameter networks.applicable. If you have registered payment accounts (eg credit card) from a customer, these will be contained in accounts (as masked data).

If you use Pure Native integration, the response will contain a few extra attributes -- see below. The idea is that this advanced data will be handled only by the merchant's server systems, whereas the Display Native data (above) could safely be passed to a browser for rendering the page in the frontend.

Display the payment networks

We will provide all the resources needed for display and charge of every payment network. With these resources you can easily generate a payment page of your own, the one the customer sees, within the frame of your corporate design.

The important links are:

  • localizedForm: Links to an HTML form snippet detailing what information is needed from the customer to charge this network (eg credit card number). The language of the labels is dictated by the LIST Request's country or style.language parameters. The input fields depend heavily on the network. Their name attributes already correspond to the parameter names needed for the consecutive CHARGE. Only the ${formId} placeholder in "id" attributes needs to be replaced before displaying the form -- to avoid conflict with existing elements on the page.
  • operation: The information entered on the form should be submitted to this OPG URL. It differs from network to network. Note: For Pure Native scenarios, you would submit to your own server first, and from there to the OPG. For Display Native scenarios, the submission comes directly from the browser. We recommend an AJAX request instead of form submission for this.
  • logo: URL of a logo that can be displayed for this network
  • validation: The custom validation service we provide for this network. The form data can be posted here asynchronously to receive live feedback on whether the information is considered valid.

You create the payment checkout page (most likely but not necessarily in HTML) dynamically and per transaction, with this data. Do not hard-code payment-network forms to keep the power of the 'implement once' principle. When the page is built, deliver it to the client (ie the browser), which displays it to your customer.

Visualization (red are parameters or resources to fetch; green are calls to execute):

Example LIST Response for Display Native integration
 {
  "links": {
    "self": "https://api.sandbox.oscato.com/api/lists/abcd1234abcd1234abcd1234abcd1234"},
  "timestamp": "2017-07-13T08:09:18.788+0000",
  "operation": "LIST",
  "resultCode": "00000.11.000",
  "resultInfo": "1 applicable and 0 registered networks are found",
  "returnCode": {"name": "OK", "source": "GATEWAY"},
  "status": {"code": "listed", "reason": "listed"},
  "interaction": {"code": "PROCEED", "reason": "OK"},
  "identification": {
    "longId": "abcd1234abcd1234abcd1234abcd1234",
    "shortId": "abcde-12345",
    "transactionId": "id000001"},
  "networks": {
    "applicable": [{
      "code": "MASTERCARD",
      "label": "MasterCard",
      "method": "CREDIT_CARD",
      "grouping": "CREDIT_CARD",
      "registration": "OPTIONAL",
      "recurrence": "NONE",
      "redirect": false,
      "links": {
        "form": "https://resources.sandbox.oscato.com/resource/form/MASTERCARD/standard.html",
        "logo": "https://resources.sandbox.oscato.com/resource/network/ABC123/en_EN/MASTERCARD/logo2x.png",
        "self": "https://api.sandbox.oscato.com/api/lists/abcd1234abcd1234abcd1234abcd1234/MASTERCARD",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/ABC123/en_EN/MASTERCARD.properties",
        "operation": "https://api.sandbox.oscato.com/api/lists/abcd1234abcd1234abcd1234abcd1234/MASTERCARD/charge",
        "localizedForm": "https://resources.sandbox.oscato.com/resource/form/ABC123/DE/en_EN/MASTERCARD/standard.html",
        "validation": "https://api.sandbox.oscato.com/pci/v1/abcd1234abcd1234abcd1234abcd1234/ABC123/en_EN/MASTERCARD/standard/validate"
      },
      "button": "button.charge.label",
      "selected": false
    }]
  },
  "operationType": "CHARGE"
}

LIST Response

After submitting a LIST Request you will receive the LIST response.

  • If you chose AJAX Integration, you will only be interested in the link.self return parameter (and status information, to check if it worked).
  • If you use Hosted Integration you will get a very simplistic response and only be interested in the redirect return parameter.
  • Only where you use Native Integration will you need to analyze the list of available networks for this transaction in order to build the checkout payment page. Read the details linked below to see how.

Please sign in to view further details of this article. Login

Web Content Display

Native Form Rendering

In Native integrations and non-PCI applicable payment networks in Selective Native integrations, the LIST Responses will contain localized form snippets that can be used to integrate into your payment page.

Please sign in for an overview of how to do this for the Native and Selective Native integration scenarios.

In Native intregrations, and in non-PCI applicable payment networks in Selective Native integrations, the LIST Responses will contain localized form snippets that can be used to integrate into your payment page.

Below is an overview of how to do this for the Native and Selective Native integration scenarios.

Getting snippets from OPG

To retrieve the relevant localised form snippets, your system will make a LIST request specifying the integration type and country. See the example on the right.

Example LIST Request
{
  "transactionId": "tr10687",
  "country": "GB",
  "integration": "SELECTIVE_NATIVE",
  "updateOnly": false,
  "customer": {
    "number": "11",
    "email": "john.doe@example.com",
    "registration": {
      "id": "586e73261652031c165ed473u",
      "password": "1Xz5NpCk7Comh737"
    }
  },
  "payment": {
    "amount": 19.99,
    "currency": "EUR",
    "reference": "tesRef1234"
  },
  "callback": {
    "returnUrl": "https://myReturnUrl.com/pending.html",
    "cancelUrl": "https://myReturnUrl.com/cancel.html",
    "notificationUrl": "https://myReturnUrl.com/notification.html"
  }
}

The LIST Response will contain a list of applicable networks. Each of these contains information about the configured payment method. Network information will contain a series of links that allow the integrating developer to present the payment option at the frontend; but this does not apply to credit cards in a Selective Native integration.

The most important link at this stage is the localised form. This is the form content you can present to the end customer so that their payment details can be captured. As the LIST Request contains a country element, these form snippets will already be translated to the appropriate language.
Other links used during the process will be the validation link for validation, operation link for the charge, logo for display purposes. You can also refer to activate methods-frontend integration for using the self link for reloading the form Activate Request -- but we do not cover this in our example here.

See the example from the associated LIST Response excerpt for SEPADD:

Example LIST Response excerpt for SEPADD
{
  "links": {
    "self": "https://api.sandbox.oscato.com/pci/v1/58c1768a1652684dd6a48a80lrf6p4m7omoivilf2vsp5hcg0g",
    "customer": "https://api.sandbox.oscato.com/api/customers/586e73261652031c165ed472u"
  },
  "timestamp": "2017-03-09T15:36:42.941+0000",
  "operation": "LIST",
  "resultCode": "00000.11.000",
  "resultInfo": "7 applicable and 2 registered networks are found",
  "returnCode": {
    "name": "OK",
    "source": "GATEWAY"
  },
  ...
  "networks": {
    "applicable": [
    ...,
    {
      "code": "SEPADD",
      "label": "SEPA",
      "method": "DIRECT_DEBIT",
      "grouping": "DIRECT_DEBIT",
      "registration": "OPTIONAL",
      "recurrence": "NONE",
      "redirect": false,
      "links": {
        "form": "https://resources.sandbox.oscato.com/resource/form/SEPADD/standard.html",
        "logo": "https://resources.sandbox.oscato.com/resource/network/MERCHANTXYZ/de_DE/SEPADD/logo.png",
        "self": "https://api.sandbox.oscato.com/pci/v1/58c1768a1652684dd6a48a80lrf6p4m7omoivilf2vsp5hcg0g/SEPADD",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/MERCHANTXYZ/de_DE/SEPADD.properties",
        "operation": "https://api.sandbox.oscato.com/pci/v1/58c1768a1652684dd6a48a80lrf6p4m7omoivilf2vsp5hcg0g/SEPADD/charge",
        "localizedForm": "https://resources.sandbox.oscato.com/resource/form/MERCHANTXYZ/DE/de_DE/SEPADD/standard.html",
        "validation": "https://api.sandbox.oscato.com/pci/v1/58c1768a1652684dd6a48a80lrf6p4m7omoivilf2vsp5hcg0g/MERCHANTXYZ/de_DE/SEPADD/standard/validate"
      },
      "button": "button.charge.label",
      "selected": false
    }],
  },
  "operationType": "CHARGE"
}

To view the form snippet as is, simply copy the localizedForm URL and paste it into a browser. The result will look something like this:

If you view the source of this URL, you will see that it is not a complete HTML page but only the inner contents of a form. Note also that there are placeholders in the form of {form-id} and these will be used later to identify the form and input snippet. This is covered later in this document.

HTML Code of the Form

<fieldset class="account">
  <div id="${formId}-row1" class="row row1">
    <div class="col col1"><label for="${formId}-iban">IBAN</label></div>
    <div class="col col2"><input id="${formId}-iban" type="text" name="iban" class="text iban" autocomplete="off"></div>
    <div class="col col3"><span id="${formId}-iban-message" class="message"></span></div>
  </div>
  <div id="${formId}-row2" class="row row2">
    <div class="col col1"><label for="${formId}-bic">BIC</label></div>
    <div class="col col2"><input id="${formId}-bic" type="text" name="bic" class="text bic" autocomplete="off"></div>
    <div class="col col3"><span id="${formId}-bic-message" class="message"></span></div>
  </div>
  <div id="${formId}-row3" class="row row3">
    <div class="col col1"><label for="${formId}-holderName">Account holder</label></div>
    <div class="col col2"><input id="${formId}-holderName" type="text" name="holderName" class="text holderName" autocomplete="off"></div>
    <div class="col col3"><span id="${formId}-holderName-message" class="message"></span></div>
  </div>
</fieldset>

Presenting the forms on screen

Developers who have chosen a Native or Selective Native integration will have total control over where they present the form snippets. What follows serves only as a demonstration of how to do this; you are free to implement this at the frontend as you wish.
After retrieving the LIST Response, the associated payment networks should be presented at the frontend programmatically so that methods can be added or removed on the merchant configuration portal without the need for changes in the payment frontend of the integrated site.

In this simple example, all payment methods in a radio button list are displayed. When the radio button is selected, some JavaScript will fire and the associated paymentInputPlaceholder div containing the localised form snippet will be displayed. Some information from the LIST Response data values in these HTML controls are also populated; this is so they can be accessed later in the process. In this example, a Pay button is used for triggering the selected payment request; it is placed beneath the radio buttons.

Example of Form Snippet Implementation

<!-- Loop through the applicable networks returned in the LIST Response.
The below uses MVC with HTML5 but you are free to implement this as you wish this is for ILLUSTRATION ONLY!
-->

foreach (var network in Model?.ApplicableNetworks?.OrderBy(x => x.label))

{
  <!-- Div to hold the title of the payment method and a radio button group to allow this be selected-->
  <div class="PaymentItem row" style="border:0px solid black;">
    <div class="col-xs-9 PaymentHeaderItem">
      <div class="col-xs-3" style="vertical-align:middle;">
        <span>
          <input type="radio" name=paymentNetworks
            data-recurrence="@network.recurrence"
            data-networkMethod="@network.method"
            value="@network.code.Replace(" ", "")" />
          <img src="@network.links.logo" />
        </span>
      </div>
      <div class="col-xs-6" style="vertical-align:middle;">
        @network.label
      </div>
    </div>
    <!-- The placeholder that will be displayed when the associated radio button is selected -->
    <div class="paymentInputPlaceholder" id="@network.code.Replace(" ", "")">
      <div class="col-xs-9 paymentTitle">
        @{
          // These are variables associated with displaying the 'register for later' checkbox
          bool registrationPossible = network.registration.ToLower() != "none";//none means the network does not support registration
          bool displayEnabled = network.registration.ToLower() != "forced";// forced means the backend is configured to always register this payment option, no user selection allowed
          bool registrationOptionalChecked = network.registration.ToLower() == "optional_preselected";
          bool checkedValue = (displayEnabled == true || registrationOptionalChecked == true);
          }

        <!-- Display the check box if it is a method that supports registration and the user is logged in -->
        @if (User.Identity.IsAuthenticated && registrationPossible)
        {
          <div style="vertical-align:text-bottom">
            <label style="vertical-align:bottom">
              <input type="checkbox"
                id="@(network.code.Replace(" ", "") + "Register")"
                value=@checkedValue
                enabled=@displayEnabled >
              @Resource.RegisterPaymentMethod <!--Local Resource containing 'Register this paymnet method' text-->
            </label>
          </div>
        }

        <!-- As this sample uses a selective native integration there may be credit cards that we
        need to display in a frame as opposed to a form to avoid being in PCI scope -->
        @if (network.method.Equals("credit_card", StringComparison.OrdinalIgnoreCase))
        {
          <iframe id="@(network.code.Replace(" ","")+"Frame")" frameborder="0" seamless=""
            src="@network.links.iFrame" height="@(network.iFrameHeight+10)"
            style="width:90%; overflow:hidden;  border:0px groove black"></iframe>
        } else {
		
        <!-- Display the contents of the localised form here. I have built a form around the snippet
		but that may not be totally necessary and is up to the implementing party to design this as they wish.
		Important points to note though is that I'm noting the validation, self and operation links form the
		LIST Response here for future use in my jquery/JavaScript
        -->

          <form id="@(String.Format("{0}{1}",network.code.Replace(" ",""),"Form"))"
            action="@network.links.operation" method="post"
            class="formSnippet"
            data-snippetId="@(String.Format("{0}{1}", network.code, "Snippet"))"
            data-listSelf="@network.links.self"
            data-validationUrl="@network.links.validation">
            <div class="optileHtmlSnippet"
              id="@(String.Format("{0}{1}", network.code, "Snippet"))"
              data-code="@(network.code.Replace(" ",""))"
              data-src="@network.links.localizedForm" >
            </div>
          </form>
        }
      </div>
    </div>
  </div>
}

<!-- Submit button for all payment options -->
<div class="row" style="padding-top:10px; float: left;">
  <button class="submitBtn btn btn-primary" value="Pay">@Resource.Pay</button>
</div>

Populating form snippets

As noted earlier, localised form snippets contain placeholders to identify the associated form. Before these snippets can be properly used, these snippets must be replaced with the relevant value.
To do this, inject the name of the payment method into the localised form at the frontend. Although there are different approaches for doing this, in this example you simply place all localised forms inside a div named ‘optileHtmlSnippet' then on the document load calling function, replace all form name placeholders with the form name. You can find the function opTemplateEngine we used in this example in the JavaScript file ‘template-engine.min.js

JavaScript Code to Load HTML Snippets into Placeholders

// Load htmlSnippets into placeholders
$(".optileHtmlSnippet").each(function () {
  /* Get the custom attribute from the div that contains the address of the localised
  form returned in the LIST Response */
  var src = $(this).attr("data-src");
  var currentElement = $(this);
  $.get(src, function (response) {
    var code = currentElement.attr("data-code");
    /* Load the form snippet into the div with the placeholders replaced
    The opTemplateEngine is another JavaScript file that contains this logic */
    var endHtmlSnippet = opTemplateEngine(response, {formId:code});
    // Set the current elements html to the html where placeholders have been replaced
    currentElement.html(endHtmlSnippet);
  });
});

After this step is applied, the form snippet will now have the placeholders replaced. See the example below for SepaDD.

Before:

	<div id="${formId}-row1" class="row row1">

	   <div class="col col1"><label for="${formId}-iban">IBAN</label></div>

	   <div class="col col2"><input id="${formId}-iban" type="text" name="iban" class="text iban" autocomplete="off"></div>

	   <div class="col col3"><span id="${formId}-iban-message" class="message"></span></div>

	</div>

After:

	<div id="SEPADD-row1" class="row row1">

	   <div class="col col1"><label for="SEPADD-iban">IBAN</label></div>

	   <div class="col col2"><input id="SEPADD-iban" type="text" name="iban" class="text iban" autocomplete="off"></div>

	   <div class="col col3"><span id="SEPADD-iban-message" class="message"></span></div>

	</div>
Displaying Registration checkboxes

If you wish to display checkboxes that let the user specify the payment method to be saved for future use, you must render this at the frontend, outside the form snippet.
In this example, a checkbox is rendered to handle this. Before rendering the checkbox and setting the desired value, the original LIST Response should be checked for each payment method to see if registration is supported. This is because some payment methods do not support registration.

The value in the LIST Response that illustrates this is the Registration property of the applicable network.

Example LIST Response
{
...
  "code": "SEPADD",
  "label": "SEPA",
  "method": "DIRECT_DEBIT",
  "grouping": "DIRECT_DEBIT",
  "registration": "OPTIONAL",
  "recurrence": "NONE",
  "redirect": false,
...
}

The possible values of this registration value can be seen in the console API but can also be summarised as:

  • NONE – Registration is not supported
  • OPTIONAL – Registration may be selected
  • FORCED – Registration must be selected but not displayed
  • OPTIONAL_PRESELECTED – Registration is optional but defaults to selected
  • FORCED_DISPLAYED – Registration must be selected and displayed

Some logic must be in place in the frontend, to decide if the checkbox is rendered or not.

Example Logic for Frontend

@{
  // These are variables associated with displaying the 'register for later' checkbox

  bool registrationPossible = network.registration.ToLower() != "none";//none means the network does not support registration

  // forced means the backend is configured to always register this payment option, no user selection allowed

  bool displayEnabled = network.registration.ToLower() != "forced" && network.registration.ToLower() != "forced_displayed";
  bool registrationOptionalChecked = network.registration.ToLower() == "optional_preselected";
  bool checkedValue = (displayEnabled == true || registrationOptionalChecked == true);
}
<!-- Display the check box if it is a method that supports registration and the user is logged in -->


@if (User.Identity.IsAuthenticated && registrationPossible) {
  <div style="vertical-align:text-bottom">
    <label style="vertical-align:bottom">
      <input type="checkbox"
        id="@(network.code.Replace(" ", "") + "Register")"
        value=@checkedValue

        enabled=@displayEnabled>
    @ Resource.RegisterPaymentMethod
	<!--Local Resource containing 'Register this payment method' text-->
    </label>
  </div>
}

This information can then be retrieved on the Charge and included as part of the CHARGE Request.

Example Code

//Get register value
var registerCheckbox = $('input[name=paymentNetworks]:checked').val() + "Register";
var allowPaymentRegistration = $('#' + registerCheckbox).prop('checked');

Display Recurring charges checkboxes

This uses the same approach as above, but uses instead the recurrence property in the LIST Response to drive the logic.

Validation

There was a validation link in the original LIST Response for each applicable payment method. In this example, this information is loaded as a data value attribute in the snippet div.

On form submit, a jQuery function is needed to perform validation and should be implemented if the selected payment method is not an iFrame. Refer to Selective Native for iFrame validation in a Selective Native integration.

In this example, the implementation of the localised form validation is simply an Ajax call to validate the information contained in the selected form snippet. If there are errors, they will be rendered at the appropriate place in the form. Again, please note this example is for illustration only; you are free to implement this any way you choose.

Example JavaScript Code for Validation

var validationPassed = validateFormInput(validationUrl, data, formSnippetId);
// Use the validation URL from the LIST Response to validate the submitted form data
function validateFormInput(validationUrl, data, formId) {
  // if there is no data to validate then mark it as passed
  if(data == null) {
    return true;
  }

  var jsonString = (JSON.stringify(data))
  var result = null;
  $.ajax({
    url: validationUrl,
    async: false, // forcing the validation to fire before continuing with form processing
    type: 'post',
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    data: jsonString,
    success: function (response) {
      result = response.valid;
      if(!response.valid) {
      // Loop through each field's validation response
        $.each(response.messages, function(formInput) {
          var snippetInputId = "#" + formId + "-" + formInput + "-message";
          if(response.messages[formInput].type.toLowerCase() == "error") {
            /* Display this error in the relevant place - the message placeholder will
            always be '${formId}-{inputFieldName}-message' */
            $(snippetInputId).text(response.messages[formInput].message);
            $(snippetInputId).css({ "color": 'red'});
          } else {
            $(snippetInputId).text("");
          }
        });
      }
    },
    error: function (response) {
      console.log("FAILURE trying to run validation : " + JSON.stringify(response));
      result = false;
    }
  });
  return result;
}

It may be worth looking at the underlying validation request and response that this sample code generates. The validation request will look different, depending on the selected payment method. But, in the case of SEPADD as shown in this example, it will serialize to something similar to that shown below. Z's are inserted in the iban to simulate what you will see in the LIST Response if there is an error.

"{"iban":"DE89370400440532013000","bic":"ZZZPBNKDEFFZZZ","holderName":"Jane Doe"}"

The response to the request above will look similar to the code opposite>>

Example JSON Response

{
  "valid": false,
  "messages": {
    "holderName": {
      "type": "INFO",
      "message": "Valid"
    },
    "iban": {
      "type": "ERROR",
      "message": "Invalid IBAN!"
    },
    "bic": {
      "type": "INFO",
      "message": "Valid"
    }
  }
}

The important thing to note is this: There will be a valid object at root level, then information about each field that was checked, and whether or not validation was passed. This information can then be used to render a meaningful error message to the user at the frontend.

Charge

Assuming validation was passed and the CHARGE can be made...you can do this via a request to the operation URL returned in the original LIST Request. In this example, the operation URL was saved as a data property in display div.

The CHARGE will always need an account object. This information can be retrieved from the localised form via jQuery/JavaScript. See the example opposite.

Example JavaScript Code

var radioButton = $('input[name=paymentNetworks]:checked').val();
var radioButtonClass = $('input[name=paymentNetworks]:checked').attr("data-networkMethod");
if (radioButtonClass.toLowerCase() === "credit_card" || radioButtonClass.toLowerCase() === "frame") {
  var frameToPostToName = $('input[name=paymentNetworks]:checked').val() + "Frame";
  var frameToPostTo = document.getElementById(frameToPostToName).contentWindow;

  // Make post to frame
  frameToPostTo.postMessage({ "type": "payment_action", "request": { "allowRecurrence": allowRecurringPayment, "autoRegistration": allowPaymentRegistration } }, opg_origin);
} else {
  // All non credit cards handled here
  var formSnippetId = $('input[name=paymentNetworks]:checked').val();
  var formToPostToName = $('input[name=paymentNetworks]:checked').val() + "Form";
  var formId = '#'+formToPostToName;
  var actionUrl = $(formId).attr("action");
  var validationUrl = $(formId).attr("data-validationUrl");
  var listSelf = $(formId).attr("data-listSelf");
  var snippetId = $(formId).attr("data-snippetId");
  var data = cleanData($(this).serializeFormJSON($(formId).serializeArray()));

  // Make a validation call and only proceed if it passes, the display of errors will be handled in the validateFormInput method
  var validationPassed = validateFormInput(validationUrl, data, formSnippetId);

  if(validationPassed) {
  // Assume there is a form snippet rendered for this payment option
  // if there isnt the post data will simply be empty
  var postRequest = {};
  postRequest.account = data;
  postRequest.allowRecurrence = allowRecurringPayment;
  postRequest.autoRegistration = allowPaymentRegistration;
  var jsonString = (JSON.stringify(postRequest))

$.ajax({
    url: actionUrl,
    type: 'post',
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    data: jsonString,
    success: function (response) {
        if(response['resultInfo']) {
            if(response['interaction']['code'].toLowerCase() == "proceed"
            || response['interaction']['code'].toLowerCase() == "reload") {
                // The result of a charge can be a redirect of type GET or POST.
                // and may or may not contain parameters
                if(response['redirect'] != null) {
                    if(response['redirect']['method'].toLowerCase() == "get") {
//Redirect to provided redirect url and provide any params
                        var parameters = response["redirect"]["parameters"];
                        var redirectUrl = response['redirect']['url'];
                        if(parameters != null) {
                            redirectUrl = redirectUrl+"?"+jQuery.param(parameters);
                        }
                        window.location.href = redirectUrl;
                    } else {
                        //Make a post using redirect parameters as input
                        var postData = keyPairToJson(response["redirect"]["parameters"]);
                        $.redirectPost(response['redirect']['url'], postData);
                    }
                } else if(response['interaction']['code'].toLowerCase() == "reload") {
                    var elementToUpdate = $('#' + snippetId);
                    var srcToLoad = "";
                    var formData = null;
                    var formToPostToName = $('input[name=paymentNetworks]:checked').val() + "Form";
                    $.get(listSelf, function (response) {
                        // set new form action url
                        $('#'+formToPostToName).attr('action', response.links.operation);
                        // set new form validation url
                        $('#'+formToPostToName).attr('data-validationUrl', response.links.validation);
                        srcToLoad = response.links.localizedForm; // get form source
                        formData = response.formData; // get form data
                        $(".submitBtn").prop("disabled", false); //enable pay button again

                        // Load localised activated form
                        $.get(srcToLoad, function (response) {
                            var formToPostToName = $('input[name=paymentNetworks]:checked').val() + "Form";
                            var selectedForm = '#'+formToPostToName;
                            var snippetId = $(selectedForm).attr("data-snippetId");
                            var elementToUpdate = $('#' + snippetId);
                            var code = elementToUpdate.attr("data-code");

                            // Load the form snippet into the div
                            var htmlToInjectIntoSnippet = opTemplateEngine(response, {formId:code});

                            // Find the name of the postcreate function to call. This will always be in the fieldset of the injected localised form if it is present
                            var postCreateFunctionName = $('#' + code +"-fieldset").attr("postCreate");
                            if(postCreateFunctionName != null) {
                                // manually inject the postcreate function call with the formData from the response
                                htmlToInjectIntoSnippet = htmlToInjectIntoSnippet.replace("<script>","<script> "+ postCreateFunctionName +"("+JSON.stringify(formData)+");");
                            }
                            elementToUpdate.html(htmlToInjectIntoSnippet);
                        });
                    });
                }
            } else {
                //show error
                $("#paymentError").text(response['resultInfo']);
                $("#paymentError").show();
            }
        }
    },
    error: function (response) {
        $("#paymentError").text(response['resultInfo']);
        $("#paymentError").show();
    }
   });
  }
}
});

If successful, the response can be analyzed and the desired actions performed. In most cases this will be a redirect to a summary page, but in the case of activate networks some other actions may be needed.

Redirect methods in Selective Native

Redirect methods will also return localised forms from the LIST Request. They can be rendered in a similar fashion to standard localised forms. If the implementation is properly ‘implement once' then you don't need to do any further work to render these payment methods.

The only extra step needed is at the frontend, which handles the CHARGE event.

An extra piece of logic can be inserted to detect if the response is a redirect and then make the associated GET or POST Request. See the JavaScript example above.

Presenting saved payment methods

The same approach can be used for displaying saved payment methods, these being the registered methods returned in the LIST Response.

Native Form Rendering

In Native integrations and non-PCI applicable payment networks in Selective Native integrations, the LIST Responses will contain localized form snippets that can be used to integrate into your payment page.

Please sign in for an overview of how to do this for the Native and Selective Native integration scenarios.

Please sign in to view further details of this article. Login

Web Content Display

Provider Buttons

An increasing number of providers / methods require their own client-side JavaScript to render their proprietary buttons and/or initialize the payment process in the Payment Page. PayPal is a classic example. If you are using the optile AJAX integration, everything will be handled for you. But if you want to render the payment page natively yourself (by using a Selective Native, Display Native, or Pure Native integration), optile offers an abstraction for you. It lets you integrate these proprietary "frontend methods" without dealing with provider details, thereby following the implement-once principle. Here we show you how.

Payment page rendering

Whichever integration scenario you have chosen, your system starts with the LIST request. If you are using the Delayed Payment Submission flow with a Summary Page before purchase, you can find out more under Delayed Payment Submission (this is easier to integrate because you don't need a proprietary button on the Payment Page). In other cases, your system renders the Payment Page by using the building components taken from the LIST response and should place the (regular) payment button in a dedicated container (eg <div>). When the user selects one of these proprietary "frontend" methods, your system should call a generic JavaScript code from optile (see below) which will place the proprietary provider button into this container. (If you are using the full AJAX library, this container corresponds to the one given as the payButtonContainer parameter in the checkoutList initialization call). At the same time, your system should hide the normal payment button. The user will probably notice that the button has been replaced, but this is unavoidable because these kinds of providers don't let you use your own generic pay button.

JavaScript initialization on method selection

Your system now needs to know if it should call a JavaScript function when the user selects a method. For this, it looks into the HTML form snippet that was returned by the LIST response for this method or registered account. In any event, the form snippets should be integrated into your payment page, in accordance with our dynamic payment page rendering standards. Keep in mind that the form may not be visible to the customer (eg for PayPal) but it should still be loaded. If this snippet contains a <fieldset> tag with the attribute initcustomsubmitbtn then this gives you the JS function name (as a string) to call.

You can easily find the tag with this attribute (if it exists) with a CSS selector like fieldset[initcustomsubmitbtn]. When used in a JavaScript implementation that supports these selectors, this returns all fieldset elements that contain the attribute named initcustomsubmitbtn.

If there is no matching tag then there is no proprietary button for this method, and the regular payment button should be shown again.

HTML snippet with JS function name

<fieldset initcustomsubmitbtn="functionName">
  ...
</fieldset>

If the function is given, it should be called as soon as the user selects the corresponding method. In other words, your system calls eval with the value of initcustomsubmitbtn and 3 parameters.

The 3 parameters are:

Example call of given JS function

eval("functionName")(networkObject, buttonContainer, paymentCallback)
  • networkObject: The JS object from the LIST response for the selected network. See the example.
Network object
{
    "code": "PAYPAL",
    "label": "PayPal",
    "method": "WALLET",
    "grouping": "WALLET",
    "registration": "OPTIONAL_PRESELECTED",
    "recurrence": "NONE",
    "redirect": true,
    "links": {...},
    "button": "button.charge.label",
    "selected": false,
    "contractData": {...}
}
  • buttonContainer: a pointer to an HTML button container, as shown in the example on the right. Could also be a special "inner" container that only holds the proprietary buttons. See Button display below.
  • paymentCallback: is called to handle the payment response. It should take only one argument which will contain the (CHARGE or PRESET) response from the OPG.
Button container example

<div id="submitBtnContainer">
  <button id="submitBtn" style="display: none;" type="button">My button</button>
  <span id="paymentLoadingIcon" class="payment-in-progress" style="display: none;"> </span>
</div>

Calling the initialization function will create the proprietary button and bind any subsequent click event on it. Naturally, it does not execute the payment at this point. This function acts as middleware between the payment page and the provider's proprietary JavaScript.

A click on the provider button will trigger the payment process as per the behavior defined in its own JavaScript code. The result will be given asynchronously to your given callback function (in the format of an OPG CHARGE or PRESET response) so that you can (typically) redirect the user accordingly.

On mobile devices, PayPal (for example) typically redirects immediately on mobile devices. On a desktop, the result is delivered once the user has completed the checkout in the provider popup. For your implementation, however, it makes no difference. It should just follow the redirect or react on issues (based on the Interaction Codes).

Button display

As mentioned above, your system should hide the normal payment button when the user selects a method that has its own proprietary button. We suggest you use CSS to make sure that all buttons appear at the same place so there is consistency for the user. However, they will be different, because they are provider-specific. Providers usually do not allow the buttons to be changed visually.

In a nutshell, every time the user selects a new method, your system must evaluate again which buttons to show or hide. As a general rule, the decision goes like this:

Every time the selected payment method changes, hide all buttons inside the container. Note that they cannot consist of a <button> tag but could simply be a <div> for example. Then either call the JS function to show the proprietary button, or show the generic pay button. You could also group all proprietary buttons into another (inner) container within the (outer) container (in which the regular payment button is located). This gives you clear separation between regular and proprietary buttons. In this case you would pass the inner container to the function given in initcustomsubmitbtn.

Delayed Payment Submission

You should include optile's AJAX library in the Summary Page, as described under https://www.optile.io/opg#1842448 (again, look under Delayed Payment Submission). This will render any proprietary payment button, if required, or just handle the button click for you. In any case it leaves you with full rendering possibilities, so you should use it on the Summary Page even if you don't use it for Payment Page rendering. It does not make a difference at this point which integration scenario was used to render the Payment Page earlier as long as the LIST object contains a preset payment account.

Provider Buttons

An increasing number of providers / methods require their own client-side JavaScript to render their proprietary buttons and/or initialize the payment process in the Payment Page. PayPal is a classic example. If you are using the optile AJAX integration, everything will be handled for you. But if you want to render the payment page natively yourself (by using a Selective Native, Display Native, or Pure Native integration), optile offers an abstraction for you. It lets you integrate these proprietary "frontend methods" without dealing with provider details, thereby following the implement-once principle. Here we show you how.

Please sign in to view further details of this article. Login

Web Content Display

CHARGE Request

The CHARGE Request triggers the actual payment which was initialized through the preceeding LIST Request. This can be issued from browsers or other clients or servers, depending on the integration scenario. The CHARGE Request submits the customer's payment details ("account data"). As an option it can contain flags if the account data should be stored in OPG's Secure Storage, eg for Recurring Registration or re-usable Account Registration. For all the other data (eg amount), the OPG will take from the related LIST Request (which is required before a CHARGE).

You only need to implement the Frontend CHARGE Request yourself in Native Integration scenarios.

The customer's sensitive payment-account data originates from the customer's client. That's why we call it a Frontend CHARGE (as opposed to triggering a Recurring Charge which would be a Backend Charge). Under PCI regulations, the sensitive data takes different paths depending on the Native Integration scenario that's in place:

Display Native: The data is transferred from the payment checkout page in the customer's client (eg browser) direct to the OPG. Your server-side systems never touch the data and therefore don't have to be PCI-certified.

Pure Native: The data is transferred from the payment checkout page to your own server-side systems. From there it is submitted to OPG (server to server). This means your system may store the data itself. In the case of credit cards, your system must comply with some PCI DSS standards and you must be certified.

The endpoint for the CHARGE Request is given as operation attribute for the method in question, in the LIST Response.

Example Frontend CHARGE Request
  • URL: https://api.sandbox.oscato.com/api/lists/ce3eec14-e186-4b7c-94a1-fde802412e69/VISA/charge
  • Basic Authentication: ABC123:BAtXa7yubR8ipuT
  • Method: POST
  • Headers
    • Content Type: application/vnd.optile.payment.enterprise-v1-extensible+json
    • Accept: application/vnd.optile.payment.enterprise-v1-extensible+json
Example of Account Data
 {
  "account": {
    "holderName": "John Doe",
    "number": "4111111111111111",
    "verificationCode": "123",
    "expiryMonth": "12",
    "expiryYear": "2021"
  }
}

JSON CHARGE Request Body
In some cases, like redirect networks without an inpage form such as PayPal, no data is submitted during the CHARGE Request. But you still need to supply an empty JSON object {}, not an empty request body.
In Display Native scenarios you do not authenticate the CHARGE Request to avoid having your credentials in the browser. The call is protected by the token identifying the LIST resource (AKA "longId" or "LIST ID"). It is randomly generated and valid for 30 minutes.
Handling the CHARGE Response

The CHARGE Response is returned to the system that issued the request. This is often the customer client (eg browser); in Pure Native scenarios it is typically the merchant backend. At the same time, a Status Notification is sent from the OPG to the merchant backend (as specified in the notificationUrl), containing the same status information. It can be used as a reliable source of status information for the merchant. On the other hand, the CHARGE reply should be evaluated in terms of feedback to the customer and how to direct them further.

Masked Account data

After a successful charge request, the response body will also contain a masked account used for the charge. This can be used for giving the end customer a better summary of the payment process. The data can be found inside the maskedAccount parameter in the response body. See the example in the pane on the right. 

It is important to note that when using client-side charges (via our AJAX library, for example) the masked account data will not be sent on the response.

Example of Successful Charge

Header

HTTP/1.1 200 OK
Content-Type: application/vnd.optile.payment.simple-v1-extensible+json; charset=utf-8
Content-Length: <length>

JSON
{
  "links": {
    "payout": "https://api.sandbox.oscato.com/api/charges/59f756bfa6cd3d345d2d39a3c/payout",
    "self": "https://api.sandbox.oscato.com/api/charges/59f756bfa6cd3d345d2d39a3c"
  },
  "timestamp": "2017-10-30T16:43:43.723+0000",
  "operation": "CHARGE",
  "resultCode": "00000.TESTPSP.000",
  "resultInfo": "Approved",
  "pspCode": "TESTPSP",
  "returnCode": {
    "name": "OK",
    "source": "PSP"
  },
  "status": {
    "code": "charged",
    "reason": "debited"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "clearing": {
    "amount": 450.00,
    "currency": "EUR"
  },
  "identification": {
    "longId": "59f756bfa6cd3d345d2d39a3c",
    "shortId": "14052-58040",
    "transactionId": "id_h0017",
    "pspId": "VISA.DEBIT.1509106088565"
  },
  "redirect": {
    "url": "http://localhost:3000/html/success.html",
    "method": "GET",
    "parameters": [
      {"name": "shortId", "value": "14052-58040"},
      {"name": "interactionReason", "value": "OK"},
      {"name": "resultCode", "value": "00000.TESTPSP.000"},
      {"name": "longId", "value": "59f756bfa6cd3d345d2d39a3c"},
      {"name": "transactionId", "value": "id_h0017"},
      {"name": "interactionCode", "value": "PROCEED"},
      {"name": "amount", "value": "450.00"},
      {"name": "reference", "value": "sandbox testing"},
      {"name": "currency", "value": "EUR"}]
  },
  "customer": {
    "number": "69",
    "email": "john.doe@example.com",
      "name": {
        "firstName": "John",
        "lastName": "Doe"
      }
  },
  "network": "VISA",
  "maskedAccount": {
    "displayLabel": "41 *** 1111    02 | 2020",
    "holderName": "John Doe",
    "number": "41 *** 1111",
    "expiryMonth": 2,
    "expiryYear": 2020
  }
}

Redirect after Success

A typical successful CHARGE response looks like this:

If the request is accepted and the Interaction Code in the response indicates PROCEED, the response will contain the redirect structure with information on where the user should be redirected. Only in Pure Native scenarios, where you did not provide the callbacks in the LIST Request, must you generate the redirect in your backend yourself.

There are two reasons for redirection after a successful request:

  1. Payment was completed successfully. In this case the redirect will lead to the merchant's success page.
  2. Payment was initiated but more information is needed from customer, eg 3D secure code for Visa or MasterCard, or authentication and confirmation at the site of a redirect network such as PayPal or Sofort. In this case, the redirect will lead to the acquirer or PSP website to continue the interaction with the customer.

Regardless of the reason, the task of your system is simply to redirect the customer's browser according to the information provided in the redirect section.

The key-value pairs provided in the parameters section should be attached as GET-Parameters to the given url. This enables the next page to display additional information about the payment status. For example, it may provide data for the remittance account in the case of invoice or prepaid payment networks (see Status Notifications for a list of possible keys relating to remittance accounts).

For Hosted Integrations in an iFrame especially, the suppressIFrame flag indicates whether the redirect should happen in the top frame of the browser (true), hence suppressing a potential iFrame. This is required for explicit redirect methods, such as PayPal, or redirects to one of your pages. It should therefore be the default, as it is in optile's hosted page and AJAX library. Only if false is explicitly given should the redirect  be in the current frame. This can be useful for hosted white label pages by third-party providers.

The bottom response parameters timestamp, operation, resultCode, and identification are intended for enterprise merchants only; you may not need them.

Retry Payment

If there was a potentially recoverable error during payment, the following Interaction Codes may appear in the response:

  • TRY_OTHER_NETWORK
  • TRY_OTHER_ACCOUNT
  • RETRY

In this case, no redirect section is contained in the CHARGE response >>

In this case you should inform the customer of the failed payment. Depending on the Interaction Code the customer should be asked to select another payment method or provide correct account information.

  • TRY_OTHER_NETWORK Re-read the LIST object and render the payment page again accordingly, because the used network is probably not available anymore.
  • TRY_OTHER_ACCOUNT  A different payment account should be requested from the customer (it can be the same method, eg Visa credit card, but a different account number would be expected). The LIST Object has not changed.
  • RETRY There is some other problem that may require updated account details, or to retry this later. The LIST Object has not changed.
Example of Retry Payment Response
 {
  "info": "Invalid holder name",
  "interaction": {
    "code": "RETRY",
    "reason": "UNKNOWN"
  }
}

Localized Error Messages

When integrating our services natively, localized messages can be exhibited by mapping the interaction codes returned by OPG with the respective values provided by our live environment in a resource JSON file:

https://resources.sandbox.oscato.net/resource/lang/MERCHANT_CODE/language/paymentpage.json

In this URL, two parameters need to be adapted:

  • MERCHANT_CODE: your Merchant Code
  • language: a language code as defined by ISO 3166-1 alpha-2.

The resource file lists the interaction codes and reasons, with their related descriptions as organized in the table Possible Interaction Code Values, plus translation for other page elements such as button labels and titles. An extract of the file from https://resources.sandbox.oscato.net/resource/lang/DEMO_SK/en/paymentpage.json is shown in the right pane.

We are continuously working to provide more languages in these resource files, but where a specific language is still not available, OPG will automatically fallback to English.

Extract of Interaction Codes from JSON resource file

{
...
  "button.delete.label": "Delete",
  "button.charge.label": "Pay",
...
  "interaction.RETRY.ACCOUNT_NOT_ACTIVATED": "The account / card seems to be not activated yet. Please activate it or try a different one.",
  "interaction.RETRY.EXCEEDS_LIMIT": "The account exceeded its limit. Please use a different one.",
  "interaction.RETRY.EXPIRED_SESSION": "The payment session has expired. Please go back and return to this step.",
...
}

Reload to Proceed

For some methods with a multi-step flow, eg Installment, the Interaction Code RELOAD will be returned. As with TRY_OTHER_NETWORK the LIST should be reloaded in this case and displayed again. See ACTIVATE Request for background information.

Redirect to Abort

In some cases (duplicate payment, system failure, fraud detection, session expiration, etc.) the response will advise to interrupt payment process via Interaction Code ABORT.

This will be coupled with a redirect to merchant's Cancel Page, if the cancelUrl parameter was given in the LIST Request.

As with successful payment processing, if a redirect section is found in the response, you should simply redirect the customer's browser accordingly.

If the reason was a duplicate payment (interaction reason DUPLICATE_OPERATION), ie a Charge on a List object after there was already a successful Charge on that List, we recommend that you add a hint for the customer on the Cancel Page saying that the payment was already done and that only the repetition failed. Otherwise the customer may think the entire payment was denied.

Example of Interrupted Payment Response
 {
  "info": "Allowable retries exceeded",
  "interaction": {
    "code": "ABORT",
    "reason": "FRAUD"
  },
  "redirect": {
    "url": "https://dev.oscato.com/shop/cancel.html",
    "method": "GET",
    "parameters": [
      {"name": "transactionId", "value": "tr101"},
      {"name": "returnCode", "value": "FAILED"},
      {"name": "interactionCode", "value": "ABORT"},
      {"name": "interactionReason", "value": "FRAUD"},
      {"name": "referenceId", "value": "aa1aa-1bb-123-aac-abc"},
      {"name": "longId", "value": "aa1aa-1bb-123-aac-abc"},
      {"name": "shortId", "value": "14335-64676"}
    ],
    "suppressIFrame": false
  }
}

CHARGE Request

The CHARGE Request triggers the actual payment which was initialized through the preceeding LIST Request. This can be issued from browsers or other clients or servers, depending on the integration scenario. The CHARGE Request submits the customer's payment details ("account data"). As an option it can contain flags if the account data should be stored in OPG's Secure Storage, eg for Recurring Registration or re-usable Account Registration. For all the other data (eg amount), the OPG will take from the related LIST Request (which is required before a CHARGE).

Please sign in to view further details of this article. Login

Web Content Display

Validation API

Validation API can be used to validate the payment information entered by the user during checkout. It can also be used for "live validation", i.e. you can validate user input while the user is typing. For that, send the validation request with the data that the user has already entered. This is relevant for Native integrations.

The validation response contains user-friendly messages that should be displayed in front of the input fields, for example "Correct", "Invalid expiration year", "Missing card number" etc. The messages appear in the language that was specified in the LIST Request.

You can get the validation API endpoint from links object within the LIST Response. The endpoint is unique for each of the payment networks returned.

Example LIST Response

{
  "networks": {
    "applicable": [{
      "code": "VISA"
      ...
      "links": {
        ...
        "validation": "https://api.sandbox.oscato.com/pci/v1/0a15894e-732c-4afb-a6ec-2edd7be4edb8/DEMO/de_DE/VISA/standard/validate"
      }
    },
    ...
  ],
  ...
}
Validation Request Example
  • URL: https://api.sandbox.oscato.com/pci/v1/0a15894e-732c-4afb-a6ec-2edd7be4edb8/DEMO/de_DE/VISA/standard/validate
  • Method: POST
  • Basic Authentication:
    • Login Name: Merchant Code
    • Password: Payment Token
  • Headers:
    • Acceptapplication/vnd.optile.payment.simple-v1-extensible+json
    • Content-Typeapplication/vnd.optile.payment.simple-v1-extensible+json
Example Validation Request Content

{
  "holderName": "Jane Doe",
  "expiryYear": "2019",
  "expiryMonth": "3",
  "verificationCode": "123",
  "number": "4111111111111111"
}

The JSON parameters to be sent are equal to the input field names of the HTML payment form snippets linked in the LIST Response. For example, the validation request for a Visa credit card should have parameters that match the form snippet on the right pane (notice that the name attribute is equivalent to the parameter name to be sent in the JSON request body:

Commonly used parameter names are listed below (this list is not exhaustive and may change with new payment networks):

  • holderName
  • number
  • expiryMonth
  • expiryYear
  • verificationCode
  • bic
  • iban
Payment Form Snippet for Visa

<input id="VISA-holderName" type="text" name="holderName" class="text holderName" autocomplete="off">
<select id="VISA-expiryYear" name="expiryYear" class="select expiryYear">
<select id="VISA-expiryMonth" name="expiryMonth" class="select expiryMonth">
<input id="VISA-verificationCode" type="text" name="verificationCode" class="text verificationCode" autocomplete="off">
<input id="VISA-number" type="text" name="number" class="text number" autocomplete="off">
Validation response examples

Validation passed

HTTP 200 OK
"valid": true is only returned if all parameters are valid.
Valid Response

{
  "valid": true,
  "messages": {...}
}
If the entered values do not pass validation

Empty field value or invalid input value:

HTTP 200 OK
Examples of invalid input
Missing input
{
  "valid": false,
  "messages": {
    "expiryYear": {
      "message": "Please enter year of expiration"
      "type": "ERROR"
    },
    ...
  }
}

Invalid field value
{
  "valid": false,
  "messages": {
    "holderName": {
      "message": "Card Holder Invalid!"
      "type": "ERROR"
    },
    ...
}
If your request is malformed

Invalid format of JSON in the request:

HTTP 500
Invalid Format of JSON in the Request

{
  "interaction": {
    "reason": "SYSTEM_FAILURE"
    "code": "ABORT"
  },
  "resultInfo": "Internal error: Unexpected character [...]"
}
{

HTTP 500

{
  "interaction": {
    "reason": "SYSTEM_FAILURE"
    "code": "ABORT"
  },
  "resultInfo": "Internal error: Unrecognized field [...]"
}

Validation API

Validation API can be used to validate the payment information entered by the user during checkout. It can also be used for "live validation", i.e. you can validate user input while the user is typing. For that, send the validation request with the data that the user has already entered. This is relevant for Native integrations.

Please sign in to view further details of this article. Login

Web Content Display

Activate Request

For some payment methods with a multi-step flow, most of all instalments, the LIST Response will return the endpoint for an ACTIVATE Request instead of the CHARGE Request. With that, your system will provide a first set of data. Based on this, the LIST object will be updated, and will now include a new input form for the user. It should be reloaded and displayed. The actual CHARGE endpoint will also be contained and should be called as a second step now.

If a method uses the Activation flow and you do not rely on the optile's AJAX or Hosted Integration to take care of it, your implementation should detect this case as follows.

The initial handling of the payment page stays as is. The provided form will be shown to the customer, the entered data submitted to the operation endpoint given in the LIST Response.

If the method uses the Activation Flow you will notice that the endpoint ends in activate instead of charge, but you do not need to detect that in your implementation. The part your system should pay attention to will come in the response.

If the customer can proceed with the checkout, the response will be something like >>

Activation Response

{
  "resultInfo": "Calculation performed successfully.",
    "interaction": {
      "code":"RELOAD",
      "reason":"ACTIVATED"
    }
}

The Interaction Code RELOAD tells your system to reload the LIST Object (via GET on the LIST Resource) and generate the payment page again with its content. The provided form of the activated network has now changed and will request additional information from the customer.

In order to not confuse the customer, the selected flag for this method will now be true, indicating that this method should be preselected and expanded when generating the payment page again.

From there the regular CHARGE process applies again: The form content gets submitted to the operation endpoint given in the LIST Object (which will now end in charge), and the response should be evaluated.

Example of Payolution Installments SEPA:
Step 1: LIST Request

URL: https://api.sandbox.oscato.com/api/lists

Example SEPA Installments LIST Request

{
  "integration" : "DISPLAY_NATIVE",
  "transactionId" : "76jknb5qh39rt4r2vqqoeitte91",
  "country" : "DE",
  "callback" : {
    "returnUrl" : "https://dev.oscato.com/shop/success.html",
    "cancelUrl" : "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl" : "https://dev.oscato.com/shop/notify.html"
  },
  "customer" : {
    "number" : "012345",
    "email" : "whitelist-test@payolution.com",
    "name": {
      "firstName":"Markus",
      "lastName" :"Mustermann"
    },
    "addresses": {
      "billing":{
        "street": "Schlossstraße",
        "houseNumber":"26",
        "city":"Berlin",
        "zip":"12163",
        "country":"DE"
      }
    }
  },
  "clientInfo":{
    "ip":"127.0.0.1"
  },
  "payment" : {
    "reference" : "shop 3490/20-05-14",
    "amount" : 500,
    "currency" : "EUR",
    "invoiceId" : "1110-234-918735",
    "longReference" : {
      "essential" : "Shop #3490 ",
      "extended" : "Thank you for your purchanse!",
      "verbose" : "Support at +49 89 3330303"
    }
  }
}

Expected Response

{
  "links": {
    "self": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l"
  },
  "timestamp": "2016-11-14T10:41:04.919+0000",
  "operation": "LIST",
  "resultCode": "00000.11.000",
  "resultInfo": "1 applicable and 0 registered networks are found",
  "returnCode": {
    "name": "OK",
    "source": "GATEWAY"
  },
  "status": {
    "code": "listed",
    "reason": "listed"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "identification": {
    "longId": "582994c0e4b0b0d86230c524l",
    "shortId": "15738-35982",
    "transactionId": "76jknb5qh39rt4r2vqqoeitte91"
  },
  "networks": {
    "applicable": [{
      "code": "INSTALLMENT_SEPA",
      "label": "Kauf auf Raten",
      "method": "DIRECT_DEBIT",
      "grouping": "DIRECT_DEBIT",
      "registration": "NONE",
      "recurrence": "NONE",
      "redirect": false,
      "links": {
        "form": "https://resources.sandbox.oscato.com/resource/form/INSTALLMENT_SEPA/standard.html",
        "logo": "https://resources.sandbox.oscato.com/resource/network/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA/logo.png",
        "self": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA.properties",
        "operation": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA/activate",
        "localizedForm": "https://resources.sandbox.oscato.com/resource/form/MOEBELIX_AT/DE/de_DE/INSTALLMENT_SEPA/standard.html",
        "validation": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA/standard/validate"
      },
      "button": "button.activate.label",
      "selected": false
    }]
  }
}
Step 2: Use the Activation URL (operation URL in the LIST Response)

URL: https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA/activate

Method: POST

Example Activation Request

{
"account" : {
  "customerBirthDay" : "1",
  "customerBirthYear" : "1991",
  "customerBirthMonth" : "1",
  "optIn" : "true"
  }
}

Expected Activation Response

{
  "resultInfo": "Calculation performed successfully.",
  "interaction": {
    "code": "RELOAD",
    "reason": "ACTIVATED"
  }
}

Step 3: Reload LIST

URL: link.self (you find that link in the LIST Response)

Example: https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l

Method: GET which return the Installment Plans

Example Reload List

{
  "links": {
    "self": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l"
  },
  "resultInfo": "1 applicable and 0 registered networks are found",
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "networks": {
    "applicable": [{
      "code": "INSTALLMENT_SEPA",
      "label": "Kauf auf Raten",
      "method": "DIRECT_DEBIT",
      "grouping": "DIRECT_DEBIT",
      "registration": "NONE",
      "recurrence": "NONE",
      "redirect": false,
      "links": {
        "form": "https://resources.sandbox.oscato.com/resource/form/INSTALLMENT_SEPA/activated.html",
        "logo": "https://resources.sandbox.oscato.com/resource/network/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA/logo.png",
        "self": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA.properties",
        "operation": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA/charge",
        "localizedForm": "https://resources.sandbox.oscato.com/resource/form/MOEBELIX_AT/DE/de_DE/INSTALLMENT_SEPA/activated.html",
        "validation": "https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/MOEBELIX_AT/de_DE/INSTALLMENT_SEPA/activated/validate"
      },
      "button": "button.charge.label",
      "selected": true,
      "formData": {
        "installments": {
          "originalPayment": {
            "amount": 500,
            "currency": "EUR"
          },
          "plans": [{
            "id": "c363bb5d-f831-4c98-8482-cdbc8abc00a4",
            "schedule": [{
              "amount": 167.84,
              "date": "2016-12-04T23:00:00.000+0000"
            },{
              "amount": 167.84,
              "date": "2017-01-04T23:00:00.000+0000"
            },{
              "amount": 167.84,
              "date": "2017-02-04T23:00:00.000+0000"
            }],
           "currency": "EUR",
           "installmentFee": 0,
           "totalAmount": 503.52,
           "nominalInterestRate": 4.95,
           "effectiveInterestRate": 5.05,
           "creditInformationUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d0PcuR2eVe5q/CreditInformation.pdf",
           "termsAndConditionsUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d15t21a5zw8r/TermsAndConditions.pdf",
           "dataPrivacyConsentUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d2t7hcATneYD/DataPrivacyConsent.pdf"
         },{
         "id": "c03e403e-a1c0-4082-8dcd-42399e5665ea",
         "schedule": [{
           "amount": 84.43,
           "date": "2016-12-04T23:00:00.000+0000"
         },{
           "amount": 84.43,
           "date": "2017-01-04T23:00:00.000+0000"
         },{
           "amount": 84.43,
           "date": "2017-02-04T23:00:00.000+0000"
         },{
           "amount": 84.43,
           "date": "2017-03-04T23:00:00.000+0000"
         },{
           "amount": 84.43,
           "date": "2017-04-04T22:00:00.000+0000"
         },{
           "amount": 84.43,
           "date": "2017-05-04T22:00:00.000+0000"
         }],
         "currency": "EUR",
         "installmentFee": 0,
         "totalAmount": 506.58,
         "nominalInterestRate": 4.95,
         "effectiveInterestRate": 5.06,
         "creditInformationUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d3iBeZYNpTI5/CreditInformation.pdf",
         "termsAndConditionsUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d4k3JJ3ilyEp/TermsAndConditions.pdf",
         "dataPrivacyConsentUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d5PIp6I9jORR/DataPrivacyConsent.pdf"
         },{
         "id": "4fda7671-8565-4dc8-9105-2c2a54fadfbe",
         "schedule": [{
           "amount": 56.63,
           "date": "2016-12-04T23:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-01-04T23:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-02-04T23:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-03-04T23:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-04-04T22:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-05-04T22:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-06-04T22:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-07-04T22:00:00.000+0000"
         },{
           "amount": 56.63,
           "date": "2017-08-04T22:00:00.000+0000"
         }],
         "currency": "EUR",
         "installmentFee": 0,
         "totalAmount": 509.67,
         "nominalInterestRate": 4.95,
         "effectiveInterestRate": 5.05,
         "creditInformationUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d6bWXLcTWp5Q/CreditInformation.pdf",
         "termsAndConditionsUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d7zXd7FoIceb/TermsAndConditions.pdf",
         "dataPrivacyConsentUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d89Jj4fIYI72/DataPrivacyConsent.pdf"
       },{
         "id": "17ee461d-8e1d-4f8f-b1d2-95ff3ad24e91",
         "schedule": [{
           "amount": 42.74,
           "date": "2016-12-04T23:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-01-04T23:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-02-04T23:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-03-04T23:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-04-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-05-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-06-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-07-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-08-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-09-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-10-04T22:00:00.000+0000"
         },{
           "amount": 42.74,
           "date": "2017-11-04T23:00:00.000+0000"
         }],
         "currency": "EUR",
         "installmentFee": 0,
         "totalAmount": 512.88,
         "nominalInterestRate": 4.95,
         "effectiveInterestRate": 5.08,
         "creditInformationUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6d9ETOlzIfSMw/CreditInformation.pdf",
         "termsAndConditionsUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6daYpicMFJ0eA/TermsAndConditions.pdf",
         "dataPrivacyConsentUrl": "https://documents.sandbox.oscato.com/MOEBELIX_AT/PAYOLUTION/582994d8c3a614600a9bb6dbV4AgV5fise/DataPrivacyConsent.pdf"
         }]
        }
      }
    }]
  }
}
Step 4: CHARGE Request

URL: https://api.sandbox.oscato.com/pci/v1/582994c0e4b0b0d86230c524l/INSTALLMENT_SEPA/charge (use the operation URL from the Reloaded LIST in Step3)

Method: POST

CHARGE Request Example >>

You need to choose the planID of the desired Installment Plan in Step 3.
Example CHARGE Request

{
  "account" : {
    "installmentPlanId" : "c03e403e-a1c0-4082-8dcd-42399e5665ea",
    "holderName" : "Jane Doe",
    "bankCode" : "PBNKDEFF",
    "iban" : "DE89370400440532013000"
  }
}
Handling Activate networks in selective Native/Native integration

If one chooses to implement Sepa Instalments in a Selective Native or Native implementation, then there is a small amount of effort required to render the process on the front end.

After the initial LIST Request is made with Selective Native or Native as the implementation parameter the LIST Response  will contain a series of applicable networks each with an associated localized form (or frame if it is selective native and a credit card network).  These html snippets (or iframes in selective native) should then be used to render the front end presented to the customer for each payment network.

These localised forms will contain {form-id} placeholders that need to be replaced with the network.code (highlighted in fig 1) value of the payment network. This can be accomplished easily using JavaScript. See the section 'Populating form snippets' in the Localized Form document for a simple approach to illustrate this. Also ‘network code' and ‘self' link should be saved as data attributes in the html element displaying the localised form as they will be needed later in the sepa-installment process.

After this replacement happens a form  asking the customer to enter his/her date of birth will be displayed. If the year of birth field is empty it means that the JavaScript in the html snippet didn't execute and you should recheck your placeholder injection.

On submit the front end should make a call to the operation url returned in the previous LIST Response (illustrated earlier in this article). Opposite is some sample javascript to illustate this submit process.

Example JarvaScript Submission Process

// .... Other code here.....
var data = $(this).serializeFormJSON($(formId).serializeArray());

var postRequest = {};
postRequest.account = data;

// Note the optIn checkbox saves as ‘on' rather than true but request expects a boolean
if(postRequest.account.optIn != null)
 postRequest.account.optIn = true;

var jsonString = (JSON.stringify(postRequest))

$.ajax({
  url: actionUrl, // the operation link for this network from original LIST
  type: 'post',
  contentType: "application/json; charset=utf-8",
  dataType: 'json',
  data: jsonString,
  success: function (response)
  {
  // .... Other code here.....



//******* Serialise a form's values *******

$.fn.serializeFormJSON = function (a) {
  var o = {};
  //var a = this.serializeArray();
  $.each(a, function () {
    if (o[this.name]) {
    if (!o[this.name].push) {
      o[this.name] = [o[this.name]];
    }
      o[this.name].push(this.value || '');
    } else {
      o[this.name] = this.value || '';
        }
    });
    return o;
};

On the call-back the response should be checked to see if it was successful. If the response was successful it will prompt that the form should be reloaded. This can be accomplished by using the self link for the payment network returned in the original response (see example above).

If it was unsuccessful then this information can be displayed to the user.

After the reload ((*) in JavaScript sample opposite) the form will now be in an activated state and the operation from the new RELOAD response will be the end CHARGE URL (see sample JSON earlier in this section). This can be used for the end submit action for the next form request. The ACTIVATION (reload) response will also contain a series of instalments that need to be used to populate dropdown values in the new localised form html snippet.

Repeat the {form-id} replacement process to load the network code into the localised form snippet and additionally at this stage, because the activated SEPA-Instalment form needs the drop down of potential rates to be populated and handled, an additional piece of JavaScript is required ((**) in JavaScript sample opposite). This is accomplished by finding the name of the postCreate function in the form snippet that is associated with the localised snippet's fieldset. There is a placeholder for formData there that can be populated with the instalments returned by the last LIST Request ((***) in JavaScript sample opposite).

At this stage the completely rendered form snippet will be displayed on the frontend and the included JavaScript will handle the form changes.

JavaScript

$.get(listSelf, function (response) {
  // (*) Set new form action url
  submitAction = response.links.operation;  // url to submit to
  srcToLoad = response.links.localizedForm; // get form source
  formData = response.formData; // get form data

  // Load localised activated form
  $.get(srcToLoad, function (response) {
    var formToPostToName = $('input[name=paymentNetworks]:checked').val() + "Form";
    var selectedForm = '#' + formToPostToName;
    var snippetId = $(selectedForm).attr("data-snippetId");
    var elementToUpdate = $('#' + snippetId);

    // (**) Load the form snippet into the div
    var htmlToInjectIntoSnippet = opTemplateEngine(response, {formId:code});

    // Find the name of the postcreate function to call. This will always be in the fieldset of the injected localised form if it is present
    var postCreateFunctionName = $('#' + code + "-fieldset").attr("postCreate");

    if(postCreateFunctionName != null) {
      // (***) Inject the postcreate function call with the formData from the response
      htmlToInjectIntoSnippet = htmlToInjectIntoSnippet.replace("<script>", "<script> " + postCreateFunctionName + "(" + JSON.stringify(formData) + ");");
    }

    elementToUpdate.html(htmlToInjectIntoSnippet);
  });
});

On submittal of the above form it's data should be serialised and submitted as part of the CHARGE Request. The process will then be complete. See opposite for sample Javascript to handle this.

JavaScript for CHARGE Request

// Submit
var data = $(this).serializeFormJSON($(formId).serializeArray());
// ...... other code ......
var postRequest = {};
postRequest.account = data;
// ...... other code ......

var jsonString = (JSON.stringify(postRequest))

$.ajax({
  url: actionUrl,
  type: 'post',
  contentType: "application/json; charset=utf-8",
  dataType: 'json',
  data: jsonString,
  success: function (response)
  {
        // ...... handle response here ......

Activate Request

For some payment methods with a multi-step flow, most of all instalments, the LIST Response will return the endpoint for an ACTIVATE Request instead of the CHARGE Request. With that, your system will provide a first set of data. Based on this, the LIST object will be updated, and will now include a new input form for the user. It should be reloaded and displayed. The actual CHARGE endpoint will also be contained and should be called as a second step now.

Please sign in to view further details of this article. Login

Web Content Display

Selective Native Integration

This section is intended to cover a complete Native implementation of the Selective integration scenario, without using a library. For instructions on how to use our library in your implementation, go to AJAX Library Integration.

LIST Response

If you implement this yourself, you should first be aware of the behavior of the LIST Response when it generates the payment page (client- or server-side).

For each method in accounts or networks.available that falls under the scope of PCI DSS (ie credit and debit cards), the LIST Response will not provide the links form and localizedForm. This means that your system will not be able to include the HTML snippets for the corresponding forms, even if you forget to change the implementation.

Instead, it will provide the URL to the iFrame in links.iFrame and the suggested height of the iFrame (in px) in the iFrameHeight attribute. So an object representing a payment method would look something like this:

Your system should place the iFrame into the payment page with these parameters >>

Example of LIST Response

...
  "networks": {
    "applicable": [{
      "code": "VISA",
      "label": "Visa",
      "method": "CREDIT_CARD",
      "grouping": "CREDIT_CARD",
      "registration": "OPTIONAL",
      "recurrence": "NONE",
      "redirect": false,
      "links": {
        "iFrame": "https://resources.sandbox.oscato.com/paymentpage/iframe.html?listId=57c03359e4b0c50a7e8007cfl&network=VISA",
        "logo": "https://resources.sandbox.oscato.com/resource/network/UBUY/de_DE/VISA/logo.png",
        "self": "https://api.sandbox.oscato.com/api/lists/57c03359e4b0c50a7e8007cfl/VISA",
        "lang": "https://resources.sandbox.oscato.com/resource/lang/UBUY/de_DE/VISA.properties"
      },
      "button": "button.charge.label",
      "selected": false,
      "iFrameHeight": 165
      },
      ...]
  },
...
Inter-Frame Communication

Web browsers will not allow direct access into the iFrames from the outside (the surrounding page). But in the standard version of Selective Native, the submit button is still outside, on the payment page. We therefore need predefined messages that can be exchanged between the frames.

Briefly, the essential messages are:

  • validation_response_event Sent from the iFrame to the outer page to reflect whether there is valid account information entered so that the outer page can enable/disable the Pay button (for optimized user experience).
  • payment_action Sent from the outer page to the iFrame as soon as the Pay button is pressed, telling the iFrame to do a final validation and submit the payment operation request.
  • operation_response_event Returns the response of a payment operation request from the iFrame to the outer page.

Inter frame communication

Live Validation and Payment Button

To provide an excellent user experience, Live Validation of the data entered by the user should be enabled (in the iFrames it is enabled by default), and the Pay button should be disabled for as long as the entered data is not formally valid.

This means that your page should decide whether to enable or disable the button, every time the user selects a payment method and the payment page is generated. If the selected method has a plain form (without iFrame) and contains a <fieldset> element or it contains an iFrame form, disable the button for now. If there is data entered already, do a validation right away (see below). Otherwise, enable the button which is required for methods that do not require any input on this page (eg PayPal).

Your page should do a Live Validation of the entered data for methods with plain forms, for example when the user stops typing for a moment or leaves the input field. This is particularly important because your payment button will be disabled in the first place in these cases. If the response signals "valid": true then the payment button should be enabled, otherwise disabled (again) and the hints shown next to the corresponding input field(s).

Inter-Frame communication comes into play if the selected method is subject to PCI and therefore provides an iFrame instead of a plain embeddable form. By default, the iFrame will do Live Validation itself and display hints accordingly in the form. The iFrame will also send the result to the outer page in the form of an validation_response_event. Your page should listen to this message and enable/disable the payment button accordingly.

Here is some JavaScript / jQuery example code >>

Note that event.data["response"] contains the full data structure of the Live Validation Response. This means, for example, that event.data["response"]["valid"] corresponds to the valid attribute from the direct API response.

You can disable Live Validation of the iFrames by requesting them with a liveValidation=false query parameter. For example:

https://resources.sandbox.oscato.com/paymentpage/iframe.html?listId=57c03359e4b0c50a7e8007cfl&network=VISA&liveValidation=false
If you have not implemented Live Validation in your page, you should do this to save bandwidth for your users and the OPG.
JavaScript / jQuery Example Code

// The expected origin of the iFrames:
// Differentiate between Live and Sandbox here!
var opg_origin = 'https://resources.sandbox.oscato.com/';

// Listener for validation_response_event message:
window.addEventListener("message", function (event) {
  if (event.origin === opg_origin) {
    if (event.data["type"] === "validation_response_event") {
      var response = event.data["response"];
      if (response["valid"]) {
        // Adjust the ID of your submit button accordingly:
        $("#submitBtn").prop("disabled", false);
      } else {
        $("#submitBtn").prop("disabled", true);
      }
    }
  }
}
Method Detection (Smart Switch)

With Smart Switch your customers do not have to select their credit card brand, it will be detected automatically.

To enable this feature with Selective Native you open the iFrame of a credit card form with the added parameters smartSwitch=true and networks (plural, not network) with a list of credit cards codes (corresponding to the credit cards of your configuration). For example:

https://resources.sandbox.oscato.com/paymentpage/iframe.html?listId=57c03359e4b0c50a7e8007cfl&smartSwitch=true&networks=VISA,MASTERCARD,AMEX

An iFrame that is integrated like this will detect the credit card scheme of the entered number, during typing, and send the detection result to the parent frame in the form of a detection_response_event. It can be consumed as the other response events and always has the following structure >>

The method attribute will reflect the detected method from the list that was given as URL parameter. If none of those were detected, the value will be null.

JSON Credit Card Codes Example

{
  "type": "detection_response_event",
  "response": {
    "method":"VISA"
  }
}
Payment Execution

The payment_action message should be sent from the outer page to the iFrame when the Pay button is pressed, telling it to do a final validation (using the same call as Live Validations). If final validation succeeds, submit the card data direct to the OPG for payment. At this point, you should disable the Pay button and, ideally, show a spinner to indicate that the user now needs to wait for feedback. When the response arrives, the result will be sent as a separate message from the iFrame to the outer page again.

If the validation fails, there will be a validation_response_event message as shown above. These situations should be very rare if you implemented the enabled/disabled  Pay button correctly. This is because the button will only be enabled if the validation succeeded already (see above), although it could still happen, eg due to race conditions. In any case there is nothing to do at this point because the Pay button should be disabled after the payment action, and stay disabled. Only the updated validation hints will be shown in the iFrame.

If the validation succeeds, the iFrame will execute the payment operation (eg CHARGE) and the response will be sent as operation_response_event message from the iFrame to the outer page. This means that on the page there should be a listener for this event, taking the response data and reloading or redirecting the user according to CHARGE Response.

Only one response event will be sent as a result of a payment_action.

Here is some JavaScript / jQuery example code you can use to get started. It is an extension of the above example code >>

For message type operation_response_event, event.data["response"] will hold the entire CHARGE Response. That means you can get the Interaction Code with event.data["response"]["interaction"]["code"], or the potential redirect URL with event.data["response"]["redirect"]["url"] and so forth.

With this data at hand, all that is left to do is react to the response, as described under CHARGE Request.

Advanced Use Cases

Specific Actions:

Besides the payment_action message, the following messages can also be sent to the iFrame:

  • validation_action Will trigger an explicit Validation of the payment account data currently present in the form and will cause a validation_response_event as soon as the validation was completed (see above).
  • operation_action Will trigger the payment operation directly (i.e., without extra validation) with the currently entered payment account data and this will cause an operation_response_event as soon as the operation was completed (see above). This could be used instead of the payment_action if the iFrame does Live Validation in order to avoid the delay of one extra validation.

Since the payment_action we have described combines these two actions, two different response events can result.

Action IDs

In principle, all requests are subject to race conditions. Therefore your page can assign IDs to actions that will be returned with the corresponding response event. This way your implementation could detect messages that overtook other messages.

You can set and read this ID in the attribute action_id, so you could:

selected_iframe.postMessage({"type": "validation_action", "action_id": "42"}, opg_origin);

You can access the value in the response event through event.data["action_id"] and thereby match the response to its original request.

If your implementation does not make repeated action requests, this would not be neccessary.

Example JavaScript Code

// The expected origin of the iFrames:
// Differentiate between Live and Sandbox here!
var opg_origin = 'https://resources.sandbox.oscato.com/';

// Sending the opg_submit message on button click:
// Replace "#submitBtn" with the actual ID of your submit button here!
$("#submitBtn").onclick = function() {
  // Get iFrame for the currently selected radio button. Only works for non-grouped forms:
  selected_iframe = $("#paymentNetworks input[type=radio][name=paymentType]:checked ~ .formContainer iframe").contentWindow;
  selected_iframe.postMessage({"type": "payment_action"}, opg_origin);
  // Disable Pay button and show a spinner to indicate to the user that this may take a while...
}

window.addEventListener("message", function (event) {
  if (event.origin === opg_origin) {
    // Listener for operation_response_event message:
    if (event.data["type"] === "operation_response_event") {
      var response = event.data["response"];
      if (response["interaction"]["code"] == "PROCEED" || response["interaction"]["code"] == "ABORT") {
        // Continue with redirecting
        // ...
      } else {
        // Continue with reloading and displaying error message
        // ...
      }

    // Now the validation listener from above follows:
    } else if (event.data["type"] === "validation_response_event") {
      var response = event.data["response"];
      if (response["valid"]) {
        // Adjust the ID of your submit button accordingly:
        $("#submitBtn").prop("disabled", false);
      } else {
        $("#submitBtn").prop("disabled", true);
      }
    }
  }
});
Styling and translating frames

The frame snippets presented to the user can be styled and translated. To do this, simply pass in the desired language and cssOverride URL in the style attribute in the original LIST Request. Afterwards, the frame will have its contents translated and style applied. See the screenshot below for a simple example of where the frame has been translated to French and has been styled to a dark gray background and heavy bold text.

Example CSS

"style":
{
  "language": "fr_FR",
  "cssOverride": "https://ADDRESS_HERE/CSS_FILE_NAME.css",
},

The css file in this example simply contains the following:

body
{
  background-color: darkgray;
  font-weight: 900;
}

Implementing Payment Methods outside the scope of PCI

If you wish to use Selective Native to integrate other payments methods (other than credit cards) then you could use optile's localized forms snippets returned from the original LIST Response. Find out more about implemeting these localized forms.

Implementing Recurring Charge and Payment Registration for Selective Native Frames

Because the frame that handles payment does not contain checkboxes for registering payments or allowing an input payment method to be used in recurring payments, these must be handled outside the frame.

The checkbox must be rendered after the frame. Then, on submit, the values of these checkboxes can be used in the frame's post message request to specify whether this payment method is to be registered or used for recurring charges. In the example opposite the values allowRecurringPayment and allowPaymentRegistration will have been retrieved from the checkboxes via JavaScript.

For a broader overview, go to displaying registration checkboxes in Localized Forms. 

JavaScript Code

// make post to frame
frameToPostTo.postMessage({
  "type": "payment_action",
  "request": {
    "allowRecurrence": allowRecurringPayment,
    "autoRegistration": allowPaymentRegistration }},
  opg_origin);

Selective Native Integration

This section is intended to cover a complete Native implementation of the Selective integration scenario, without using a library. For instructions on how to use our library in your implementation, go to AJAX Library Integration.

Please sign in to view further details of this article. Login

Web Content Display

Client-Side Encryption

Here we provide a detailed view of the integration process for Client-Side Encryption into your services. For an introduction to out Client-Side Encryption flow, go to Integration Scenarios session Pure Native with CSE.

OPG Integration

Integration package content

The integration packages are available as zip files here:

Inside each, next to the root files with development meta information, you will find these folders:

  • demo: an html file you can view locally to interactively test the encryption of custom account data with public keys (see below). There is no server/OPG interaction here.
  • dist: the actual distributable encryption library in ready-to-use minified format:
    • op-client-side-encryption1.x.y.min.js The versioned filename which we recommend to use in order to easily keep track of version changes.
    • op-client-side-encryption.min.js A copy without versioning in its file name to represent the latest version. Could be used for on-the-fly upgrades of the library, which requires more careful management.
  • src: the development source files
LIST Request

For the LIST Request, use the same integration parameter as for Pure Native integration:

"integration": "PURE_NATIVE"

If you submit encrypted account data using any other integration scenario (including the default), you will get this error: "Unrecognized JSON property 'encryptedAccount'…"

Get the Payload

After the user has entered their payment-account data, the client is expected to build a JSON object from it and then encrypt it. The attribute names contained in this object are the same as the input field names used in the equivalent HTML form from optile's form-based API. In other words, the object should have the same attributes as those in the optile account object used for CHARGE Requests.

The most common attributes for Charges are:

  • number
  • holderName
  • verificationCode
  • expiryMonth
  • expiryYear
  • IBAN
  • BIC

This payload should be encrypted as shown opposite.

Card Account Data Example Object

{
  "holderName": "John Doe",
  "number": "5500000000000004",
  "verificationCode": "123",
  "expiryMonth": "12",
  "expiryYear": "2022"
}

Encrypt with the optile JavaScript Library

The minified JavaScript encryption library can be included in your web page, either by loading it direct in a <script> tag, or through require or import. In technical terms, the library provides an asynchronous API to encrypt user data in accordance with the standards below.

The library exports the function: opEncrypt(accountPayload, publicKey, [timestamp], [listId])

This function returns a Promise Object (also called a "thenable"), which resolves to the encrypted string through its callback. This string is the encrypted data structure that you can send through your server to the OPG. We chose this implementation path to make the library compatible for a wide variety of use-cases, including server-side use and advanced client-use scenarios that benefit from an asynchronous programming style.

Input Parameters
  • accountPayload: the JavaScript object (not a string) with any of the attributes available in the optile account object used for CHARGE Requests
  • publicKey: the public key in JSON Web Key (JWK) format (as JavaScript object), which you already received from optile
  • timestamp (optional): the timestamp of the encryption. If it is not given, or given as null, the current client time is used as default and added to the payload. Input format is ISO, eg "2017-09-26T08:41:01.859Z"
  • listId (optional): the longId of the OPG LIST session on which the Charge would be executed. As it is an optional parameter, listId will also not be included into the payload if it is not given.
Return Value

The function returns a Promise instance which resolves to a string containing the JSON Web Encryption (JWE) encoded account data. This string is the data that can be passed on to the OPG.

Example Usage

function submitCard(timestamp, listId) {
  // listId needs to identify the LIST session to be used for this transaction
  // timestamp is used to identify the encryption time
  opEncrypt(
    {
      "holderName":       document.getElementById("holderName").value,
      "number":           document.getElementById("number").value,
      "verificationCode": document.getElementById("verificationCode").value,
      "expiryMonth":      document.getElementById("expiryMonth").value,
      "expiryYear":       document.getElementById("expiryYear").value
    },
    {
      "kty": "RSA",
      "n": "2UEvEj1-cUxF5ri-pXUhHIn-QNxiz6B4lWWvnK-RqZrMQQ_VSYiUfgkosydIp4-zrKzI5PbkWar1dYo3PcAfkZn1ZNTdxC4sMb3TEWJmbKZHh9C6fD4YsY6euTrSBKMC-aa1a7r0nUEzFQ6-7bKAfoOQKkrvIq6ecbTlcqNOAJX6aFJJ1bWmp7gTtG4ncYgtf_Q8nszgSMbe8hiIly4nwYwAxtdjxuOypcEx7I350VdCzTz-eN0rAnclT_-cv8P8J-JkS3yJVUlWeKaGeTtZB5-ZJHpDEUpOb9yc_NHKuxj5L9A-FemVUq606tBTG92yQU711Crf03CQ8-jbZyudkNYVQ",
      "e": "AQAB"
    },
    timestamp,
    listId
  ).then((encrypted_payload) => {
      // encrypted_payload contains the data to be sent to your server.
      // Send via asynchronous HTTP, for example,
      // or as a form submit with a hidden field "optile_encrypted":
      document.getElementById("optile_encrypted").value = encrypted_payload;
      document.getElementById("sendform").submit();
  }).catch((error) => {
      // handle errors may encountered during encryption
      console.log(error);
  });
}

Server-Side CHARGE Request

Your server sends the payment-account data in an (authenticated) CHARGE Request to the OPG. The parameter to hold that data string is called encryptedAccount (which replaces the account object of a regular CHARGE Request). Note: registration flags are still given, unencrypted.

The LIST session for this CHARGE transaction needs to correspond to the listId used during encryption. For security, the encrypted card data will not work with any other LIST sessions. The response from the OPG will be the same as with an unencrypted CHARGE Request.

Never send unencrypted card data to your server systems.

Example CHARGE Request Body

{
  "encryptedAccount": "VGhpcyBpcyB0aGUgZW5jcnlwdGVkIGFjY291bnQgZGF0YSBpbi...",
  "allowRecurrence": true
}


Encryption Details

If you want to build your own encryption client, you will need these extra details. You don't need these details if you simply want to use the JavaScript encryption library provided by optile.

The encrypted content is transmitted as a RFC7516 JWE (JSON Web Encryption) data structure in JWE Compact Serialization format. All of the user's input (see above) is encoded in key/value pairs in the encrypted JWE JSON payload. optile only supports AES256-GCM with RSA-OAEP as the encryption scheme. Therefore, the JOSE header will always look like this:

{ "alg": "RSA-OAEP", "enc": "A256GCM" }

It's base64 representation will accordingly always be:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ

As specified by RFC7516...

  • the JOSE header
  • the RSA-OAEP encrypted symmetric content encryption key
  • the randomly chosen encryption initialization vector
  • the AES256-GCM encrypted payload JSON object literal with the above JOSE header passed into the encryption operation as "additional authenticated data"
  • and the resulting AES256-GCM authentication tag output…

…are each base64-encoded and concatenated using a "." character as separator. The resulting string is the one that must be sent to your server and then passed on to the OPG.

Client-Side Encryption

Here we provide a detailed view of the integration process for Client-Side Encryption into your services. For an introduction to out Client-Side Encryption flow, go to Integration Scenarios session Pure Native with CSE.

Please sign in to view further details of this article. Login

Web Content Display

Backend Use Cases

Web Content Display

Refunds & Cancellations

A Charge that is successfully processed can, in general, be refunded up to 6 months after it has been issued (although the conditions of PSPs may vary). Partial and multiple refunds are possible with the OPG if they are also supported by the PSP. If the Charge is in the status pending / processing_scheduled it can be canceled instead of refunded, which has different implications. See the end of this chapter.

After a CHARGE Request is completed, you have a transaction that can be refunded by issuing a POST request its payout URL, which references its longId. The following example shows you how:

Payout requests generally only need a payment data structure that includes the amount to be refunded. With some PSPs, you may also be able to submit an empty payout request translating to a full refund. But with other PSPs this does not work for partial refunds that have been issued beforehand—therefore, we do not recommend it. To stay on the safe side, always specify the amount to be refunded.

In some cases you may have to specify which products are refunded (eg if you use invoice payments). To do that, you can specify a products array after the payment structure, similar to the product information you provide in an extended LIST Request. It is important to note that most PSPs will give you an error if you try to refund products that were not specified during the initial checkout.

First partial refund example

Suppose the initial checkout Charge had an amount of 19.99 € and got the longId value 26d5b179-a3b5-4aa3-ad98-3074b41e7d2b. From there, you build the payout URL and post an amount less than the original amount (partial refund) as follows:

Example Request
  • URL: https://api.sandbox.oscato.com/api/charges/26d5b179-a3b5-4aa3-ad98-3074b41e7d2b/payout
  • Basic Authentication: UBUY:BBtXa7yubR8ipuT
  • Method: POST
Example Partial Refund Request
{
  "payment": {
    "amount": 5.00,
    "currency":"EUR",
    "reference":"Refund 472"
  }
}
Example Response
{
  "interaction":{
    "reason":"OK",
    "code":"PROCEED"
  },
  "resultInfo":"Approved",
  "links":{
    "self":"https://api.sandbox.oscato.com/api/payouts/fced7bd9-5489-4466-988c-83d2548a075a"
  }
}

Note that in Pure Native integrations you will get a more elaborate response like:

{
  "links": {
    "self": "https://api.sandbox.oscato.com/api/payouts/54aea1bae4b005fbaf09f5f4o"
  },
  "timestamp": "2015-01-08T15:26:51.838+0000",
  "operation": "PAYOUT",
  "resultCode": "00000.WIRECARD.0",
  "resultInfo": "Approved",
  "status": {
    "code": "paid_out",
    "reason": "refund_credited"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "clearing": {
    "amount": 5,
    "currency": "EUR"
  },
  "identification": {
    "longId": "54aea1bae4b005fbaf09f5f4o",
    "transactionId": "tr101",
    "providerId": "C979816142073082263267"
  }
}
Second, remaining Refund

We issue a second refund that covers the remainder of the Charge amount—after which the customer will have been fully refunded.

Example Request
  • URL: https://api.sandbox.oscato.com/api/charges/26d5b179-a3b5-4aa3-ad98-3074b41e7d2b/payout
  • Basic Authentication: UBUY:BBtXa7yubR8ipuT
  • Method: POST

If your PSP does not support partial or multiple refunds for a one payment transaction, you should receive an error like: "Multi-refund is not supported".

Example Remaining Refund Request
{
  "payment": {
    "amount": 14.99,
    "currency": "EUR",
    "reference": "Refund 473"
  }
}
Example Response
{
  "interaction":{
    "reason":"OK",
    "code":"PROCEED"
  },
  "resultInfo":"Approved",
  "links":{
    "self":"https://api.sandbox.oscato.com/api/payouts/bef25df3-0d24-412c-805c-fd686821ef6e"
  }
}
Third, exceeding Refund

If your refund amount exceeds the amount originally charged, you will get an error from the OPG. To demonstrate, we issue a third "partial" refund on the same Charge, that was already fully refunded.

Example Request
  • URL: https://api.sandbox.oscato.com/api/charges/26d5b179-a3b5-4aa3-ad98-3074b41e7d2b/payout
  • Basic Authentication: UBUY:BBtXa7yubR8ipuT
  • Method: POST

Where you need to create an 'exceeding Refund' and your PSP supports it, the validation on the OPG should be turned off. Please contact us in this case.

Example Exceeding Refund Request
{
  "payment": {
    "amount": 20.00,
    "currency":"EUR",
    "reference": "Refund 474"
  }
}
Example Response
{
  "links": {
    "self": "https://api.sandbox.oscato.com/api/payouts/54aea1dce4b005fbaf09f5f5o"
  },
  "timestamp": "2015-01-08T15:27:24.854+0000",
  "operation": "PAYOUT",
  "resultCode": "50100.11.000",
  "resultInfo": "Effective balance of charge process is less than requested payout amount",
  "status": {
    "code": "failed",
    "reason": "refund_failed"
  },
  "interaction": {
    "code": "RETRY",
    "reason": "UNKNOWN"
  },
  "identification": {
    "longId": "54aea1dce4b005fbaf09f5f5o",
    "transactionId": "tr101"
  }
}
Include refunded Products

Some PSPs ask you to list the products which are to be refunded. Make sure the product.code and amount (ie quantity) of the refunded products match those from the original CHARGE Request. If the Payment Gateway finds a product with the same code but the amount does not match, it will return an error.

Example Request
  • URL: https://api.sandbox.oscato.com/api/charges/26d5b179-a3b5-4aa3-ad98-3074b41e7d2b/payout
  • Basic Authentication: UBUY:BBtXa7yubR8ipuT
  • Method: POST

The products list behaves exactly as in the extended LIST Requests. The quantity is optional and defaults to 1, and the amount is the sum after considering the quantity.

The response and behavior in respect of partial ('multi') refunds is equivalent to those from simple Refund scenarios.

Example Refund with Product List
{
  "payment": {
    "amount": 22.40,
    "currency": "EUR",
    "reference": "Refund 202/01"
  },
  "products": [{
    "code": "B003X6UEXQ",
    "name": "Tron Legacy BluRay",
    "quantity": 1,
    "amount": 12.50
  },{
    "code": "C003X6U523",
    "name": "The Lawnmower Man DVD",
    "quantity": 1,
    "amount": 9.90
  }]
}

Cancellation

Refunds can be applied if a Charge has been processed by the provider. But there are situations where a Charge is queued on the provider side (or optile side) before it gets processed. The reason for this is often a provider-internal batch processing schedule. In this situation, the provider typically allows you to cancel this transaction. In optile's status space, such a transaction will have Status Code pending and the Status Reason processing_scheduled.

Canceling such a transaction means it will not be processed by the provider—so generally no processing fees will apply, and the end customer will not see any related transaction on their account statements (as opposed to refunds where a debit and a credit will typically be visible). In most cases, a cancellation can only be done completely. If you want to return a partial amount, you can wait until the Charge was processed and then do a partial refund instead.

To request the cancellation, send an HTTP DELETE request (without a body) to the CHARGE resource (as accessible by its links.self URL).

Example Request

  • URL: https://api.sandbox.oscato.com/api/charges/26d5b179-a3b5-4aa3-ad98-3074b41e7d2b
  • Basic Authentication: UBUY:BBtXa7yubR8ipuT
  • Method: DELETE

A successful cancellation will return an HTTP 2xx return code. Otherwise it means it failed.

A cancellation can fail if, for example, the transaction was already locked by the provider because it is about to be processed. The best strategy in such a situation is to wait until the payment is processed, then issue a normal refund.

Note: This cancellation is similar to the cancellation of a Deferred Charge, but the underlying situation/status of the transaction is different.

Refunds & Cancellations

A Charge that is successfully processed can, in general, be refunded up to 6 months after it has been issued (although the conditions of PSPs may vary). Partial and multiple refunds are possible with the OPG if they are also supported by the PSP. If the Charge is in the status pending / processing_scheduled it can be canceled instead of refunded, which has different implications. See the end of this chapter.

After a CHARGE Request is completed, you have a transaction that can be refunded by issuing a POST request its payout URL, which references its longId. The following example shows you how:

Please sign in to view further details of this article. Login

Web Content Display

Recurring Charges

To set up repeat charges by the customer without requiring the customer to re-order each time, you can trigger Recurring Charges from your backend. As a prerequisite, you need the customer's agreement; a registered customer with at least one registered payment account, and you need to register the credentials in the Secure Storage component of the Payment Gateway. We describe this in more detail in Payment Account Registration.

In every integration scenario, you will get the customerRegistrationId and customerRegistrationPassword via Status Notification when you register a customer for the first time (by registering their first payment account).

The customerRegistrationPassword will only be sent ONCE by a notification with entity=customer by which it should be stored. But the customerRegistrationId is still sent with entity=payment.

Trigger Recurring Charges from your Backend

If a customer has payment accounts registered for recurring charges, you can trigger those recurring charges by posting to:
/api/customers/<customerRegistrationId>/charge

You do not have to specify the channel, it is set to RECURRING by default for this type of call.

Provide the password via customer.registration.password. Registration ID is passed via URL path and is not required in this scenario.

Example Request

URL: https://api.sandbox.oscato.com/api/customers/aff7a069-b77a-4023-b5ae-ad4f48596ce4/charge

  • Basic Authentication: UBUY/BBtXa7yubR8ipuT:
  • Method: POST
Notifications and recurring payments
  1. As mentioned above, there is an additional Boolean attribute hasRecurringAccount=true|false in the notification with entity=customer. If this customer has given the recurring mandate (via allowRecurrence=true in the CHARGE Request) and not revoked it (by removing the recurring account) hasRecurringAccount will show true; otherwise false.
    • Note: true does not guarantee the a recurring charge will work (or has ever worked), it just means that a mandate was given.
  2. When there is a change in recurring charge status, a new notification will be sent.
  • Example 1: If the customer had a registered "frontend" account, then registers a new account for recurring charges, there will be another notification.
  • Example 2: If the customer already had a recurring account and registers another one, there will not be a notification (because status will remain true, ie no change)
  1. While an account registration is pending, it will be not affect the recurring charges. The registration state can only change after the registration is successful. This may mean a notification for a newly registered customer (with regId and regPwd) will be sent. Soon afterwards, another notification with updated hasRecurringAccount info may also follow.
Example Recurring Charges Request

{
  "transactionId": "S-321-012",
  "country": "DE",
  "payment": {
    "amount": 9.90,
    "currency": "EUR",
    "reference": "Your Subscription 321"
  },
  "customer": {
    "email": "john.doe@example.com",
    "registration": {
      "password": "h5dhgn7gd3bhlkwykxgnhrd2346nm0ew6v"
    }
  },
  "callback": {
    "returnUrl": "https://my.ubuy.com/shop/success.html",
    "cancelUrl": "https://my.ubuy.com/shop/cancel.html",
    "notificationUrl": "https://ubuy.com/shop/notification.html"
  }
}

Recurring Charges

To set up repeat charges by the customer without requiring the customer to re-order each time, you can trigger Recurring Charges from your backend. As a prerequisite, you need the customer's agreement; a registered customer with at least one registered payment account, and you need to register the credentials in the Secure Storage component of the Payment Gateway. We describe this in more detail in Payment Account Registration.

Please sign in to view further details of this article. Login

Web Content Display

Automated Denial Management

If a Recurring Charge is triggered by your server system and is denied, the OPG can retry this charge via the Automated Denial Management (ADM) app. The ADM can be configured in the Merchant Portal to automatically trigger a recurring charge at specified interval. The ADM can also be configured the number times a charge should be retried. There are a number of default settings in the ADM app to help you determine the best stratergy to decrease denied charges. The ADM app can significantly reduce your denied charges and implementation efforts. Your system will still receive Notifications with full details for every charge attempt.

Case 1: A recurring Charge attempt is rejected, but scheduled for retry on the OPG
  • The Status Code will be pending and the reason code retry_scheduled.
  • The Interaction Code and reason will be PROCEED - SCHEDULED, because on merchant side no action has to be taken. The returnCode.name will indicate why the transaction was unsuccessful to allow statistical analysis.
  • The date and time of the next retry will be given in the notification, as a parameter named autoRetryAfter instead of retryAfter, but in the same format.
  • declinesCount in the notification will state the number of rejections that have occurred for this payment request yet, starting with 1.
Case 2: A retried Charge is ultimately rejected (i.e., OPG decided not to pursue any more retry attempts)
  • The Status Code will be declined and the reason code debit_declined.
  • The Interaction Code and reason will be the original codes that resulted from the final payment attempt.
  • No autoRetryAfter or retryAfter value will be returned.
  • declinesCount in the notification will state the number of rejections that have occurred for this payment request.
Case 3: A retried Charge is successful
  • The Status Code will be charged and the reason code debited, as with a normal successful Charge
  • The Interaction Code and reason will be the original codes that resulted from this payment attempt, i.e. PROCEED and OK.
  • No autoRetryAfter or retryAfter value will be returned.
  • declinesCount in the notification will state the number of rejections that have occurred for this payment request until now (and therefore in total).
Configuration

The precise retry schedules can be individually fine-tuned in their configuration depending on the Interaction Reason Code.

The defaults are:

Interaction Reason  Code              Retries schedule plan
EXCEEDS_LIMIT Retries take place on the [1st], the [15th], then the [1st] and the [15th] of the next month of the initial transaction date.
UNKNOWN

The rerty schedule is planned after these days of the initial transaction date:

[+1d] [+2d] [+3d] [+4d] [+7d]

TEMPORARY_FAILURE

The retry is scheduled after hours and days of the initial transaction time & date as follows:

[+2h] [+4h] [+6h] [+8h] [+10h] [+12h] [+16h] [+20h] [+1d] [+2d] [+3d] [+4d] [+5d]

Stopping automated Retries

In some cases it makes sense to stop the OPG from repeating charges, e.g., if payments have arrived through another channel. You can do so by sending an HTTP DELETE to the Charge resource (in OPG1: the retry entity associated with the Charge resource).

Example Request

  • URL: https://api.sandbox.oscato.com/api/charges/efdfc6c7-a803-4f8b-8e30-ef6d9b3d6b6e
  • Basic Authentication: UBUY/BBtXa7yubR8ipuT:
  • Method: DELETE

As a reply you will get an HTTP 200 status code with an empty body. This indicates that the OPG will not repeat the scheduled charges for the referenced initial Charge any more.

This will also trigger a Status Notification with these values (among others):

  • statusCode = canceled
  • reasonCode = debit_canceled
  • interactionCode = ABORT
  • interactionReason = UNKNOWN
ADM and Failover Routing

If you dig into the logic of ADM in the context of Fallback Routing (i.e., different providers that can be used for recurring charges), you will run into some conceptual challenges, because different providers could return different decline reasons.

Here is how OPG handles a situation like this under the hood:

Let's assume a recurring CHARGE for a registered customer that has 2 registered payment accounts (VISA and MASTERCARD). Let say that VISA has two PSP registrations for recurring charges, PROVIDER1 and PROVIDER2; and MASTERCARD only one via PROVIDER1.

In the first step, the OPG will try to process via VISA card, as in this example, this network has higher priority for some reason. If the processing via PROVIDER1 fails, the OPG will analyse the result. If the failure is 'recoverable' (Result Codes like 'provider not available' or 'provider internal error') the OPG will try to process via PROVIDER2. If the error is not recoverable the OPG will skip the processing via the other route (other provider registration) of the current registered account (in this case VISA) and will try to process with another registered account (in this case MASTERCARD). The OPG will also analyse the error result code to apply this information to the denial state of the registered account. 

As an example, let us say that processing with VISA card was tried and failed for both PSP registrations. For PROVIDER1 with Result Code 'provider not available' (recoverable) and for PROVIDER2 with 'exceeds limit'  (not recoverable). OPG will calculate an interaction code for the last try (here: PROVIDER2) and use it to increase the payment account's denials counter by 1 and change the account's denial state. This will also block the payment account if its denials counter reaches its limit (system default: 10). If the payment was successful the OPG would reset the account's denial counter to 0.

After that the OPG will try to process the transaction with the other registered account (MASTERCARD). Let say this try also fails with the Result Code 'provider not available' . As before, the OPG will derive the interaction code, use it for denial management, and return it to the merchant.

Now the transaction processing failed for both registered accounts VISA with Result Code 'exceeds limit'  (second result code, coming from PROVIDER2) and MASTERCARD with 'provider not available'. The last try will be taken as final execution result. Based on this result the OPG will derive the final interaction code and use the ADM to find the suggested next retry time. As a result ADM could return: 'in 2 hours'. The OPG will increase the rejection counter for this payment process (which is seperate from the payment account mentioned before) and will schedule the retry event, via the scheduler component, in 2 hours.

After 2 hours the scheduler will fire a retry-event and we will try to process this CHARGE again. If this try also fails, the OPG will retry with the same logic again until ADM blocks the next retry and finishes this CHARGE process with actual denial handler's 'failure result interaction code'.

Automated Denial Management

If a Recurring Charge is triggered by your server system and is denied, the OPG can retry this charge via the Automated Denial Management (ADM) app. The ADM can be configured in the Merchant Portal to automatically trigger a recurring charge at specified interval. The ADM can also be configured the number times a charge should be retried. There are a number of default settings in the ADM app to help you determine the best stratergy to decrease denied charges. The ADM app can significantly reduce your denied charges and implementation efforts. Your system will still receive Notifications with full details for every charge attempt.

Please sign in to view further details of this article. Login

Web Content Display

Deferred Payments

With Deferred Payments the checkout flow happens in two separate steps. Initially, a "reservation" (preauthorization) of the payment amount is made without actually transferring it. Later, a trigger of the real transfer takes place (capture). In optile terminology, this latter step is called "closing".

The reservation has a different commitment and duration depending on the payment network and/or the issuing bank. For credit cards, a reservation ("preauthorization") typically lasts 30 days whereas a successful closing of this amount is guaranteed for 10 days. For PayPal the reservation lasts 29 days although for a direct debit a successful closing is not guaranteed.

The same process is used for invoice payments. Typically the closing is called as soon as the products are shipped out to the customer. In retail businesses this can take days or even weeks. For Open Invoice Providers this is the signal that the payment is due, whereupon they should transfer it to you and start waiting for the invoice payment of the end customer.

The diagram below shows the deferred payment based on the AJAX Integration scenario:

Initialize a Deferred Payment

If a payment network supports deferrals then it needs to be configured in case you want the deferred payment to be enabled. The configuration would be done by our staff individually per merchant (within the limitations of that network).

You can enable the payment networks that are in "deferred", "non-deferred" or "any" mode, as explained below in the LIST Request, by adding the preselection.deferral parameter with one of the following values:

  • DEFERRED Only networks which support deferred payments are listed. They are set in deferred mode for subsequent charges
  • NON_DEFERRED (default) All networks which support immediate payment collection are listed. They are set in non-deferred mode when a CHARGE Request hits them
  • ANY All networks are returned. If they support both modes, they are returned in deferred mode.

Note: The system default is set to "non-deferred"; therefore, if a payment network is configured to be in "deferred" mode and the value is not specified in the preselection.deferral parameter in the LIST Request, then the LIST Response would not include this payment network.

Example Deferred Payment LIST Request

{
  "transactionId": "T345",
  "country": "DE",
  "integration": "PURE_NATIVE",
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  },
  "payment": {
    "amount": 29.99,
    "currency": "EUR",
    "reference": "ubuy T345/20-08-2013"
  },
  "preselection": {
    "deferral": "DEFERRED"
  },
  "callback": {
    "returnUrl": "https://www.ubuy.com/shop/success.html",
    "cancelUrl": "https://www.ubuy.com/shop/cancel.html",
    "notificationUrl": "https://www.ubuy.com/backend/notify"
  }
}

As with a normal LIST Request, you will get back all available networks together with their operation URL, which in Native Integration you interpret according to LIST Response.

It is possible to see the status code in the PURE_NATIVE integration scenario only, not with the other integration scenarios for security reasons. You could use the PURE_NATIVE integration parameter for testing reasons, but normally you would use the integration scenario that applies to your case. 

Make the Reservation

Now you can submit the customer's account details to the operation URL of the selected network. If the network is in deferred mode, this results in the "reservation" of the amount and a DEFERRED CHARGE object will be created. The Status Notification for this will return the statusCode = preauthorized.

This DEFERRED CHARGE could either be canceled or closed in a second step, see below. Both actions are triggered from server-side.

You can mix deferred payments with methods that can't be deferred. Your system can detect by the status code if the payment was already processed or a closing is still needed.

For security, only in "Pure Native" integration scenarios will your backend receive the required closing URL directly in the LIST reply as shown on the right side. In other cases it can be constructed, see below.

Example Deferred Payments LIST Response

{
  "interaction": {
    "reason": "OK",
    "code": "PROCEED"
  },
  "redirect": {
    "method": "GET",
    "parameters": [{
      "name": "transactionId",
      "value": "tr345"
    },
	  ...
    ],
    "url": "https://dev.oscato.com/shop/success.html",
    "suppressIFrame": false
  },
  "resultInfo": "Approved",
  "links": {
    "self": "https://api.dev.oscato.com/api/charges/06ae3329-a7ea-42aa-9bd1-52f7987f3727",
    "closing": "https://api.dev.oscato.com/api/charges/06ae3329-a7ea-42aa-9bd1-52f7987f3727/closing"
  }
}

Cancel the Reservation

Whenever your system realizes that a payment is no longer required, because, for example, you cannot deliver the goods, it should cancel the (remaining) reservation. Otherwise your customer may not be able to use the blocked funds on their account until they expire (ie after 10 days). For some payment networks (Open Invoice methods, for example) these requested funds may never expire. Future payments may therefore lead to rejections if high amounts are left open.

To cancel a reservation, issue an HTTP DELETE request on the DEFERRED CHARGE resource. In "Pure Native" scenarios you get the URL to "self" already with the CHARGE reply.

Generally it is constructed like this:

https://api.sandbox.oscato.com/api/charges/[longId of DEFERRED CHARGE]

As a result, the reservation will be canceled through the provider and the transaction will transition to the status code canceled / preauthorization_canceled. This will be reflected in the response, which returns the DEFERRED CHARGE object again. Note that this DEFERRED CHARGE object is not actually deleted, you can fetch its status any time and it remains visible in My Transactions in the portal, for example.

It is possible to close a payment partially and cancel the remaining amount. To do that, you would have to delete/cancel the DEFERRED CHARGE after the partial closing has been made. This would automatically cancel the rest of the amount.

The cancellation will always "cancel everything that was not captured yet". It does not take parameters like an amount. Therefore all closings should be performed first, and then the cancellation (of the rest) if necessary.

This order should be in line with most merchants' workflows, especially since cancellations of preauthorizations are not time-critical.

Close the Transaction

To complete (capture) the transaction and actually trigger the payment, you issue a POST request from your backend to the closing URL. It can be constructed like this:

https://api.sandbox.oscato.com/api/charges/[longId of DEFERRED CHARGE]/closing

In simple cases, the request contains only an empty  JSON object {} which means that the closing will be performed on the full amount.

But the closing can also be performed partially and multiple times. You can do this if, for example, an order has to be split into different shipments. In this case, you can submit a different amount and also a list of products covered by this payment.

Example Closing Request

{
  "payment": {
    "amount": 10.99,
    "currency": "EUR",
    "reference": "Partial Delivery tr345/1"
  },
  "products": [{
    "code": "B003X6UEXQ",
    "name": "Tron Legacy BluRay",
    "amount": 10.99
  }]
}

A successful CLOSING operation will create a CHARGE object on the optile side, which represents the actual capture of the funds. It has a different ID from the original DEFERRED CHARGE object, and your system will receive a response and a notification about its status. If your system issues multiple partial closings, the resulting CHARGE objects will all have different IDs.

A CHARGE object in the response directly includes its own PAYOUT link. Your system should issue PAYOUTS on the ID(s) of the corresponding resulting CHARGE(s), not on the preceding DEFERRED CHARGE object.

For invoice payments, a partial CLOSING is the signal to expect less money transferred, eg due to a return of goods by the customer.

A CLOSING operation on a DEFERRED CHARGE creates a CHARGE object for the capture. On this CHARGE object a PAYOUT can be issued to refund.
Example Closing Response

{
  "links": {
    "payout": "https://api.sandbox.oscato.com/api/charges/5955242a16525bcc727abeedc/payout",
    "self": "https://api.sandbox.oscato.com/api/charges/5955242a16525bcc727abeedc"
  },
  "timestamp": "2016-08-29T16:00:43.315+0000",
  "operation": "CLOSING",
  "resultCode": "00000.TESTPSP.000",
  "resultInfo": "Approved",
  "pspCode": "TESTPSP",
  "returnCode": {
    "name": "OK",
    "source": "PSP"
  },
  "status": {
    "code": "charged",
    "reason": "debited"
  },
  "interaction": {
    "code": "PROCEED",
    "reason": "OK"
  },
  "clearing": {
   "amount": 10.99,
   "currency": "EUR"
  },
  "identification": {
    "longId": "5955242a16525bcc727abeedc",
    "shortId": "06015-18360",
    "transactionId": "T345",
    "pspId": "MASTERCARD.DEBIT.1498572745446"
  },
  "customer": {
    "number": "42",
    "email": "john.doe@example.com"
  }
}

 

Deferred Payments

With Deferred Payments the checkout flow happens in two separate steps. Initially, a "reservation" (preauthorization) of the payment amount is made without actually transferring it. Later, a trigger of the real transfer takes place (capture). In optile terminology, this latter step is called "closing".

Please sign in to view further details of this article. Login

Web Content Display

Chargebacks

Chargeback is the revocation of a payment, which was already successfully processed, without merchant involvement (as opposed to a voluntary Payout). Chargebacks tend to occur when a credit card holder contacts the issuing bank and declares that a debit on their card is unauthorized. The OPG also allows chargebacks for SEPA direct debits if the transaction gets declined by an involved institution at a later stage, typically some days after the direct debit request.

Chargebacks are by definition asynchronous. Therefore, the OPG will send a Status Notifications to inform your system about them. This is a big simplification for you implementation, because every payment provider delivers this information differently, and often only passively, meaning active polling is needed.

Before an actual chargeback takes place, a payment provider can also request clarifications from the merchant, or announce a scheduled chargeback while still giving the merchant a chance to intervene.

These stages are modeled and described under Status and Reason Codes. Below is an representation of their possible transitions:

Chargebacks

Chargeback is the revocation of a payment, which was already successfully processed, without merchant involvement (as opposed to a voluntary Payout). Chargebacks tend to occur when a credit card holder contacts the issuing bank and declares that a debit on their card is unauthorized. The OPG also allows chargebacks for SEPA direct debits if the transaction gets declined by an involved institution at a later stage, typically some days after the direct debit request.

Please sign in to view further details of this article. Login

Web Content Display

Fallback Routing

The payment gateway intelligently tries to recover failed payment attempts by falling back to different available providers or payment networks wherever possible.

The Fallback Routing happens in the background, without interaction with the customer or merchant. It is the first attempt of recovering issues that is returned by the provider and therefore takes place before other measures, like prompting the customer with the LIST again after a failed Frontend CHARGE Request (section "Retry payment") or Automated Denial Management.

How it works

In general, certain Return Codes from providers are considered recoverable errors, for example, technical failures or configuration problems. Others, like stolen credit card, exist independently of the provider and are not considered recoverable in this context. See Return Codes for a full list.

If a recoverable error is detected, the payment gateway will look for an alternative provider contract that is also configured to be used to process this transaction. This means it needs to support the same parameters, like selected payment network and given country.

Frontend Charges

For frontend charges with customer interaction, fallback routing is straightforward. If the provider declines the transaction for a recoverable reason, the payment data as provided by the customer will be used to immediately try again with another provider. If one attempt succeeds or all available routes fail, the CHARGE Response and Status Notification with the result from the last attempt will be sent to the merchant.

Backend Charges

Charges without customer interaction, ie Recurring Charges, are handled differently because the Payment Gateway is not allowed to store credit card verification numbers (CVC and CVV) and cannot therefore simply turn to a new provider as a fallback. From a providers' perspective, it would be an initial payment attempt requiring the verification number, which cannot be provided.

Therefore the payment gateway depends on past registrations by that customer, with alternative providers. If those are present, they will be used.

If no route through available registrations succeeds, the payment gateway will fall back to alternative registered payment accounts, another credit card that is stored, for example. If those are found, the whole story will be repeated with these accounts, ie looking for alternative providers again.

Note: Asynchronous Providers

Since a direct reply with error information is required instantaneously for fallback routing, the logic does not work after an asynchronous provider or payment network is contacted. 'Asynchronous' in this context means only a temporal pending status is returned to the payment gateway, the final result arrives later. This is the case for providers like Adyen or Dotpay, or for redirection networks where the customer is sent to an external page.

But if no technical connection to the asynchronous provider could be established in the first place, owing to a provider downtime for example, Fallback Routing will be triggered because the OPG is able to act instantly.

Fallback Routing

The payment gateway intelligently tries to recover failed payment attempts by falling back to different available providers or payment networks wherever possible.

The Fallback Routing happens in the background, without interaction with the customer or merchant. It is the first attempt of recovering issues that is returned by the provider and therefore takes place before other measures, like prompting the customer with the LIST again after a failed Frontend CHARGE Request (section "Retry payment") or Automated Denial Management.

Please sign in to view further details of this article. Login

Web Content Display

Gambling Restrictions

The OPG supports additional requirements which are often needed by merchants in the gambling industry, and certain wallet payment methods, PayPal for example.

1:1 Relationship

This feature can be enabled by our support team for a specific payment method and merchant division. We will ensure that:

  • customers of this merchant division can only use one account for this payment method, and
  • no other customer of this merchant division can use the same account for this payment method.

This means that a payment transaction with the corresponding payment method will be declined by the Payment Gateway if:

  • a customer tries to pay with a method repeatedly but uses a different payment account IDs (eg PayPal email), or
  • a customer tries to pay with an account of that payment method which has been used by a different customer of that merchant previously.

Note: For some wallet payment methods (eg PayPal) the account ID used can always be changed by the customer during checkout on the web pages of the method. This means that the Payment Gateway can only decline a transaction after the customer has clicked "Pay" on the wallet page.

Examples:
  1. John pays into his gambling account using PayPal. He uses his PayPal account john_doe@supermail.com. One month later he wants to pay in again. When he comes to the PayPal page, he changes the email account ID to johnny432@mail.org. After he confirmed the payment on the PayPal page, the transaction is declined by the Payment Gateway and he is redirected to an explanation on the merchant page.
  2. Mary pays into her gambling account with her PayPal account mary123@coolmail.net. For some reason, she has a second account with the same gambling merchant, and there she also wants to pay with her PayPal account mary123@coolmail.net. After she confirmed the payment on the PayPal page, the transaction was declined by the Payment Gateway and she was redirected to an explanation on the merchant page.
Technical Communication

The communication between your system and the Payment Gateway would look like this:

First your system gets a CHARGE Response and corresponding Status Notification with:

  • Interaction Code: PROCEED
  • Interaction Reason: PENDING

When the customer has completed the checkout on the wallet site, your system will get another Status Notification. If successful, there will be the usual PROCEED/OK indication. If the transaction is declined owing to these configured restrictions, it will contain:

  • Interaction Code: TRY_OTHER_NETWORK
  • Interaction Reason: NETWORK_FAILURE

...plus a human readable error message in the resultInfo attribute.

Questions
  • Do unsuccessful payment attempts count?

No. If a customer tries to pay with the payment method and does not succeed, they can repeat the payment with the same method again but a different account ID (eg PayPal email).

  • What happens if the feature gets turned off temporarily then on again later?

The payment account IDs used are only recorded while the feature is turned on. In other words, the feature only checks against payments in the past that were made while the feature was turned on.

Example:

The feature is turned on and John pays in (for the first time) with his PayPal account john_doe@supermail.com.

Then the feature is turned off again by the merchant.

Next, John tries a payment with his second PayPal account, johnny432@mail.org. The payment succeeds.

Also Mary, with her seperate gambling account, makes a first-time payment with her PayPal account mary123@coolmail.net, and the payment succeeds.

After that, the restriction feature gets turned on again.

John can now only make payments with his PayPal account john_doe@supermail.com again (or some other method, of course). johnny432@mail.org would be declined. But if he had a second gambling account, he could use his PayPal account johnny432@mail.org.

Mary can make another payment with any PayPal account. Also, anybody else could use Mary's PayPal account mary123@coolmail.net for a payment into their gambling account.

  • How does the feature work if there are multiple merchant divisions?

The feature can be turned on and off per division separately. The feature will double-check all payments of all divisions where the feature is enabled.

Example:

Merchant M has 3 Divisions: D1, D2 and D3. The feature is enabled for D1 and D2, but not D3.

Mary pays with her regular PayPal account mary123@coolmail.net in D1. When she also tries to pay with this PayPal account in her seperate gambling account in D2, it will be declined because PayPal account mary123@coolmail.net was used already in a different gambling account at Merchant M.

But she can use a different PayPal account now to pay in D2, eg peterpoor@fastmail.com.

Note: The underlying assumption in this example is that the two seperate gambling accounts of Mary in D1 and D2 each have a different customer.number delivered to the Payment Gateway. If it were the same, she could pay in D2 with the same PayPal account as in D1, and only with that PayPal account.

In any case, Mary can use her PayPal account from D1, mary123@coolmail.net again to pay in D3 because the feature is not enabled there.

  • If a transcation is declined by this OPG feature, does the transaction still occur in with the wallet method eg PayPal?

No. Technically the Payment Gateway will never confirm the execution of the payment, so there will be no completed transaction in the wallet method account.

 

Web Content Display

References & Resources

Web Content Display

ID and Object Types

Every payment transaction creates a resource on optile side (REST API style). It can optionally have ID(s) assigned by the merchant, and it will get an optile generated ID. By storing the optile generated ID your system can issue future actions on that transaction. This can be a simple read (GET), but sometimes updates or cancellations are possible (PUT or DELETE). It can also be actions beyond the REST paradigm, such as a CLOSING on a DEFERRED CHARGE object. See our API Reference for a full list.

optile will always pass on the merchant assigned IDs to the payment providers, so that the merchant can access them easily also in the provider user interfaces, if required. However, this comes to limitations in case the provider requires a special format of IDs. In this case optile will act as a translator in order to fulfill the specific provider requirements. Also the provider will typically have their own ID for transactions. It will not be necessary for your system to keep track of those, but they can be used for individual investigations.

IDs and object types are rocket science, but to give you an overview on one glance we have summarized them here.

Transaction ID Types

A transaction object contains these IDs:

  • Assigned by optile (will alway be present):
    • longId The optile generated ID (uniqueness guaranteed) for consecutive operations
    • shortId An optile generated string that's rather short and "almost unique" (i.e. not guaranteed for all times) that can be used for simplified human to human communication, e.g., over the phone
  • Assigned by your system:
    • transactionId (mandatory for LIST requests) The primary, merchant-assigned ID (no uniqueness required or checked by optile)
    • invoiceId (optional) An additional merchant assigned ID, mostly used by invoice based payment methods
  • Assigned by payment providers (will not always be present):
    • pspId An ID assigned by the payment provider (if the transaction reached the provider)
    • institutionId An ID assigned by the banking institution in the background (if the transaction reached the institution and the ID is revealed by the PSP in front of it)

You will find these attributes inside the identification section of a transaction object (for authenticated server-to-server requests), except invoiceId which is inside the payment section.

Transaction Object Types

Type Created through... Allows Merchant IDs Allows followup actions
LIST LIST request

transactionId, invoiceId

Read, update, cancel, and:

On a payment page: CHARGE or PRESET or ACTIVATE

On an account update page: UPDATE, REGISTER

DEFERRED CHARGE CHARGE on a LIST (in deferred mode)

transactionId (planned), invoiceId, pspId / institutionId

Read, CLOSING, cancel
CHARGE CHARGE on a LIST,  CLOSING on a DEFERRED CHARGE or Standalone Charge

transactionId (planned), invoiceId, pspId / institutionId

Read, PAYOUT, cancel (in few statuses)
DEFERRED PAYOUT PAYOUT on a CHARGE (in deferred mode)

transactionId (planned), invoiceId, pspId / institutionId

Read, CLOSING, cancel
PAYOUT PAYOUT on a CHARGE, CLOSING on a DEFERRED PAYOUT

transactionId (planned), invoiceId, pspId / institutionId

Read
ACTIVATE ACTIVATE on a LIST (for few methods)

invoiceId, pspId / institutionId

Read. The followup CHARGE is issued on the LIST object.

Note that the operations PRESET and cancel do not create separate transaction objects, that's why there are no corresponding objects listed here. They are only modifications on existing resources.

Example transaction object part

  ...
  "identification": {
    "longId": "5a7da245148b514ac4b3946ec",
    "shortId": "04040-80938",
    "transactionId": "tr10004",
    "pspId": "VISA.DEBIT.1518007534249"
  },
  ...

Other ID and Object Types

Apart from the resources that represent payment transactions there are also other object types and IDs, most notably for customer and payment account registrations:

  • CUSTOMER objects: Are created by CHARGEs with account registration. They are identified by the customerRegistrationId. They can be used to issue Recurring Charges.
  • ACCOUNT objects: A registered customer can have multiple registered payment accounts, which are identified by their accountId. They will be used implicitly for payments with registered accounts or updates or deletions of accounts. They can be also used explicitly to set preferred accounts. Or, after a LIST with "channel": "RECURRING" there can be Recurring Charges issued directly to a registered account.

ID and Object Types

Every payment transaction creates a resource on optile side (REST API style). It can optionally have ID(s) assigned by the merchant, and it will get an optile generated ID. By storing the optile generated ID your system can issue future actions on that transaction. This can be a simple read (GET), but sometimes updates or cancellations are possible (PUT or DELETE). It can also be actions beyond the REST paradigm, such as a CLOSING on a DEFERRED CHARGE object. See our API Reference for a full list.

optile will always pass on the merchant assigned IDs to the payment providers, so that the merchant can access them easily also in the provider user interfaces, if required. However, this comes to limitations in case the provider requires a special format of IDs. In this case optile will act as a translator in order to fulfill the specific provider requirements. Also the provider will typically have their own ID for transactions. It will not be necessary for your system to keep track of those, but they can be used for individual investigations.

IDs and object types are rocket science, but to give you an overview on one glance we have summarized them here.

Please sign in to view further details of this article. Login

Web Content Display

Status Notifications

Status Notifications are messages sent from the OPG to your server system. They push information about payment status changes (and other details) as soon as they are available, so that your system is always up to date. Alternatively you can also query regularly for transaction status changes using our Report API. However, for efficiency reasons we highly recommend to read this section carefully and implement a listener for the notifications.

Technically the Notifications are normal HTTP(S) GET requests with a bunch of query parameters (as they would come from a browser). They are sent to a URL defined by the merchant, either by configuration or passing a notificationUrl parameter in the LIST Request. In other words, the OPG acts like it would request a web page from your server system and delivers the status paramters this way.

When a payment operation is triggered, there will be both, a synchronous reply to that request, and an asynchronous notification. In AJAX, Hosted and Display Native integrations the reply will arrive at the customer's client (e.g., browser), whereas the notification will directly arrive at the merchant servers. Therefore it is safe to trust the notifications, as they never go through the customer's client.

The notification is sent out by the OPG first, then immediately followed by the reply. Due to network latencies there is no guarantee that the notification will also arrive first. However, reply and notification will contain the same status information. Therefore no additional synchronization between client and server is needed for frontend payments at this point.

The client should simply react on the reply, displaying the result to the customer. The merchant backend should trust the notification (Only in Pure Native scenarios this difference is obsolete, because the reply also goes to the backend and can be used instead of the first notification).

Artificially synchronizing the client with the server after the payment to wait for the notification may lead to complications in case of a notification delay (e.g., due to network reasons). Therefore we do not recommend it.

There is one exception though: If an asynchronous PSPs is used (e.g., Adyen), the Interaction Code in the reply could be PENDING (and also a notification with the Status Code  pending will arrive). In this case the customer should be asked to wait. Typically after a few seconds (in rare cases maybe even half a minute) a new notification will arrive at the merchant server with an updated Status Code. Only for these cases there should be some kind of synchronization with the customer's client.

It is important to listen to status notifications, also after a payment is completed, using the Status Codes to note events like chargebacks.

For security reasons we recommend to implement the notification listener of your live system in a way that it only accepts notifications from OPG via IP filtering.
Status Entities

Note that a notification can concern different things as indicated by the value of the entity attribute:

  • payment: The payment transaction (relevant for successes, chargebacks, etc.)
  • customer: The customer registration (as a consequence of account registration)
  • account: The customer's account registration (network name and account registration ID, as a consequence of account registration)
  • session: The frontend payment session (relevant when deciding whether to issue a new LIST Request or update an old one)

In the simplest implementation you will only need the payment notifications. Therefore do not confuse the entities.

Regardless of whether you process a notification or not, please acknowledge the receipt always with an HTTP 200 OK. Otherwise the Payment Gateway's guaranteed message delivery will repeat them (see below), therefore putting unneccesary load on yours and our system.
Notification Parameters
Name Type Appearance Description
transactionId String 1 ID as given by the merchant. Stays the same for the whole transaction "chain", for example the initial LIST and consecutive CHARGE and CLOSING operations.
longId String 1 ID of the specific transaction object (LIST, CHARGE, DEFERRED CHARGE, PAYOUT) as assigned by OPG (uniqueness guaranteed).
shortId String 1 Short ID of the transaction as assigned by OPG. Intended for simplified support communication.
entity String 1 Data entity described by this notification. Either paymentcustomeraccount, or session. Each entity has different Status Code spaces.
statusCode String 1 The transaction's current Status Code
reasonCode String 1 Additional information about the transaction status, see Status Codes
interactionCode String 1 How your system should react, see Interaction Codes
interactionReason String 1 Additional information on the suggested reaction, see Interaction Codes
returnCodeName String 0..1 Detailed provider response in optile's unified Return Code space. Intended for detail analysis in hindsight. Return Codes are subject to change. Therefore the stable interactionCode and statusCode should be used for runtime processing instead.
returnCodeSource String 0..1 Source of the transaction outcome, in most cases the GATEWAY itself or the connected PSP behind it, see Return Codes
pspCode String 0..1 The PSP used for processing
institutionCode String 0..1 The banking institution (that may be behind the PSP) used for processing.
resultCode String 1 Combined result code containing component and qualifier, see Result Codes. We recommend to use the simpler Status and Interaction Codes for most use cases, or the unified Return Codes for detailed analysis instead.
resultInfo String 1 Textual result info to the relevant operation. If returnCodeSource = GATEWAY the message is generated by the OPG, if returnCodeSource = PSP or an institution name, the message contains the original error string sent by the PSP or institution. In most cases resultInfo will not be generated by the OPG but from a PSP or institution. Mostly intended for debugging.
customerRegistrationId String 0..1 Identifies the customer registered on OPG side. If your system provides this in future requests, the registered payment accounts of the customer can be accessed.
customerRegistrationPassword String 0..1

The merchant's key to OPG's Secure Storage space for a registered customer. It's sent only once, on new registration of the customer (with entity=customer). If provided in future requests it can be used to decrypt sensitive payment account data again, for example for performing a provider switch.

hasRecurringAccount String 0..1 Indicates if a registered customer gave a recurring mandate that is still valid, so that you know whether you can do recurring charges on that customer. This is a boolean attribute (values true or false) included in the notification with entity=customer.
network String 0..1 Code of the payment network used in processing
amount Decimal 0..1 Processed payment amount
currency String 0..1 Processed payment currency
reference String 0..1 Payment reference text used (as given by merchant)
retryAfter Datetime 0..1 Suggestion when the merchant should trigger a rejected Recurring Charge again.
autoRetryAfter Datetime 0..1 When the OPG will retry this rejected Recurring Charge again, in case ADM is enabled.
rejectionCount Integer 0..1 How often this Recurring Charge attempt has been rejected already. Starts with 1 at first rejection.
notificationId String 1 Identifier for this notification. Stays the same for repetitions of a Notification due to the guaranteed delivery. Can be used to detect duplicates. To determine the order of Notifications use timestamp.
timestamp Datetime 1 Stays the same for repetitions of a Notification due to the guaranteed delivery. Can be used to determine the order of Notifications (reception order could be broken due to due to network issues for example).
previousStatusCode String 1 Provided when the status of the transaction changed. Indicates the previous Status Code so that the precise status transition can be derived.
previousReasonCode String 1

Same as previousStatusCode, only for the Status Reason Code, see Status Codes.

Note: not all parameters will always be present since status notifications could be pushed in different cases. For example, in case an account is registered, a status notification would be pushed without the "amount" parameter since it is independent from the amount. Also, the order of parameters is not fixed.

Additional payment network dependent data

mandate data: Was introduced for SEPA network and returns information about the official mandate data that was used for a transaction.

remittanceAccount[n] data: Provide this to your customers so they can complete their payment in case of invoice or prepaid methods. Only the fields required for the payment will be provided. For example a bank account together with a reference text (aka descriptor) could be identified, where the customer should transfer their money to. There could be more than one possible remittance account (indicated by [n] below, starting with remittanceAccount[0]).

Name Type Appearance Description
mandate.reference String 0..1 Mandate reference used for this SEPA transaction. Can be different from the value suggested by the merchant if the PSP uses his own IDs.
mandate.creditorId String 0..1 Creditor ID used for this transaction. Can be different from the Merchant's ID if the PSP uses his own ID.
mandate.authentication.date String 0..1 When the mandate was issued according to the merchant.
mandate.authentication.city String 0..1 Where the mandate was issued according to the merchant.
remittanceAccount[n].networkCode String 0..1  
remittanceAccount[n].holderName String 0..1 Account holder name
remittanceAccount[n].iban String 0..1 International Bank Account Number
remittanceAccount[n].bic String 0..1 ISO 9362 (SWIFT) bank identification code
remittanceAccount[n].number String 0..1 Account number
remittanceAccount[n].bankCode String 0..1 National bank code
remittanceAccount[n].bankName String 0..1 Bank name
remittanceAccount[n].accountId String 0..1 An ID of the account that is not a number, e.g. email for PayPal accounts
remittanceAccount[n].reference String 0..1 Descriptor for the money transfer (German "Verwendungszweck")
remittanceAccount[n].comment String 0..1 A dynamic note from the provider that could contain legal information and therefore should be displayed.
remittanceAccount[n].termDays String 0..1 Number of days the customer has by contract to transfer the money (in case of invoice: after the goods were delivered).
Legacy Data

If you have not implemented the notification listener already, do not worry about these values, which are either deprecated or not fully in place, yet.

Name Type Appearance Description
returnCode String 0..1 Deprecated, use interactionCode and interactionReason instead. Don't confuse with returnCodeName.
referenceId String 0..1 Deprecated, same as longId
referredTransactionPassword String 0..1 Password for sensitive data temporary saved during current transaction

 

Example Notification URL
https://ubuy.com/listener/notifications.do?transactionId=yourTransactionID&resultCode=00000.OPTILE.000&statusCode=charged&reasonCode=debited&referenceId=427a2bc8-216f-4a89-bf15-1edf90b800b8&longId=427a2bc8-216f-4a89-bf15-1edf90b800b8&shortId=07999-56867&timestamp=2012-03-21T12:27:24.791+01:00&network=VISA&amount=29.70&currency=EUR&reference=payment_reference_from_provider&interactionCode=PROCEED&interactionReason=OK&notificationId=2255968806107622
Guaranteed Message Delivery

The delivery of notifications is guaranteed (for any interface version). This means:

  1. A notification delivery is considered successful if the target host (merchant server system) replies with an HTTP 2xx status code within a specified timeout allowance, currently 10 seconds (but may be subject to change).
  2. If a notification fails, it is repeated in progressively increasing time intervals until successful. The first repetition happens after 2 minutes, then 5, 10, 15, and further.
  3. The last delivery attempt takes place around 24 hours after the first try. If this also fails the error is considered permanent and the Payment Gateway stops repeating this notification.

Please consider the following implications of guaranteed delivery:

  1. If a notification is correctly received by a merchant server system, but the response takes longer than the OPG's timeout, the message would be regarded as failed and repeated later. Therefore the merchant backend will receive the same notification twice, i.e., a duplicate. Duplicates can be detected using the notificationId, which will stay the same across all repetitions.
  2. If a notification (e.g., conveying a PENDING Interaction Reason) fails, and a few seconds later a new notification (e.g., with OK Interaction Reason) is successfully delivered, the first one will be re-sent 2 minutes later. In the given example this means the PENDING notification would arrive after the OK message. This information, of course, is not correct anymore. Therefore the notification order should be checked based on their timestamp. For example, the timestamp of the last notification could be saved and only notifications with higher timestamp will be processed in the future.

Note: These examples are unlikely, especially example 2, but they could occur. Therefore we recommend a clean implementation regarding these cases in the long run.

Also, if some kinds of notifications are ignored by your system (e.g., with entity = session, because you do not need payment conversion tracking), please let the system still return an HTTP 200 OK, so that the guaranteed delivery does not take effect.

Status Notifications

Status Notifications are messages sent from the OPG to your server system. They push information about payment status changes (and other details) as soon as they are available, so that your system is always up to date. Alternatively you can also query regularly for transaction status changes using our Report API. However, for efficiency reasons we highly recommend to read this section carefully and implement a listener for the notifications.

Please sign in to view further details of this article. Login

Web Content Display

HTTP Request Inspector

The HTTP Request Inspector is a development tool that you can use to test the Status Notifications that are sent out by the OPG.

You can create your own listener and access it, as long as you use the same browser (authorization via cookies). You can also save the assigned token to access it from somewhere else in the future. In the listener you will see all HTTP requests that came in with all their content. You can also set how the listener should respond to requests. You could, for example, return an HTTP error code like 500 to test optile's Guaranteed Message Delivery.

 

HTTP Request Inspector

The HTTP Request Inspector is a development tool that you can use to test the Status Notifications that are sent out by the OPG.

You can create your own listener and access it, as long as you use the same browser (authorization via cookies). You can also save the assigned token to access it from somewhere else in the future. In the listener you will see all HTTP requests that came in with all their content. You can also set how the listener should respond to requests. You could, for example, return an HTTP error code like 500 to test optile's Guaranteed Message Delivery.

 

Please sign in to view further details of this article. Login

Web Content Display

Interaction, Status, & Return Codes

After an operation, the OPG provides different information in form of codes or messages that can be used by the merchant systems to understand what might be the next operation step and what is the current state of an operation. These codes and messages should not be presented to end customers due to their technical content.

There are 4 different code types sent during a payment session: Interaction codes, status codes, return codes, and result codes, plus a longer message delivered through the result info field.

The matrix below summarizes them:

Code Description
Interaction Codes Informs what the frontend system or backend shop system should do after an operation. Example: proceed after a successful payment.
Status Codes Describes the current status of an operation. Example: charged after a successful transaction.
Return Codes Unified detail representation of payment providers' responses for deeper analysis.
Result Codes Contains the payment provider's native code, if available. Can be useful for further investigations of the nature of a specific operation result.
Result Infos Text message as complement to the codes. If returnCodeSource = GATEWAY the message is generated by the OPG, if returnCodeSource = PSP or an institution name, the message contains the original error string sent by the PSP or institution. In most cases resultInfo will not be generated by the OPG but from a PSP or institution.

In the next sections you can find detailed information about all codes described above, and in which situations they should be used.

Web Content Display

Interaction Codes

Interaction Codes are recommendations for the merchant system frontend on how to proceed after a transaction. They are especially relevant after submitted CHARGE Requests because there may be ways to redirect a transaction if a problem is identified and in consequence reduce denials.

In the case of frontend payments, interaction codes give information on how the end customer should proceed, and a corresponding page and message should be displayed.

In the case of backend payments (e.g., Recurring Charges or closing of Deferred Payments) they indicate the next step to be performed by the merchant system.

The interaction code is actually composed of two parts: the code itself and a reason, which expands its meaning and can be used for more refined decision.

When in a payment session, a merchant must use the interaction code to decide on how to interact, i.e. how to react after a payment step is done. The merchant user interface (for frontend sessions) or server (for backend sessions) only needs to use the interaction codes to decide which step should be taken in the payment flow, meaning it will be able to decide if a proceed, reload, retry, etc is applicable in a given moment.

Interaction Codes are designed to lead a merchant shop system to the appropriate action in a payment session. However, they are not a comprehensive reflection of all the statuses a payment may have. This information is present in the Status Codes, which bring a deeper understanding of the current status of a transaction. Keep in mind that the Status Codes don't need to be evaluated during a session, but they can be helpful case a merchant wants to investigate the details of a particular scenario while troubleshooting or testing. 

Possible Interaction Code Values
Code Reason Description
PROCEED  

The operation worked as expected.

  OK

The operation was completed successfully, for example a successfully initialized LIST or executed CHARGE. Therefore you should check the payment status now.

  PENDING

The status is still unknown. Wait for the next notification.

  SCHEDULED

Scheduled for specific point in time, not yet submitted. For example ADM retry or scheduled for batch processing.

  TAKE_ACTION You as a merchant need to take action to proceed with this transaction, typically manually confirm or decline it on the provider side where it could be held back for reasons such as risk or others.
ABORT  

The operation failed and there is no point in retrying. If a CHARGE fails like this, also alternative payment attempts in the same LIST session should not be allowed. Do not confuse this with the "aborted" status.

  NO_NETWORKS

The LIST does not have any applicabe networks (methods) or registered accounts anymore, because they were all declined. (In backend cases this would be SYSTEM_FAILURE)

  FRAUD

Fraud detected, do not allow any more Charge/Payout attempts (for frontend RISK_DETECTED may be returned instead)

  RISK_DETECTED

Blocked by risk management, it's suggested to not trust this customer.

  DUPLICATE_OPERATION

Probably a duplicate frontend Charge was issued on a LIST, meaning that the payment was already successful the first time. Then you should not show an error but indicate the successful payment to the user. For recurring backend charges a duplicated request may be declined by the provider, you should check your system logic.

  INVALID_ACCOUNT

Invalid account (backend denial handling)

  CHARGEBACK

A previously successful payment was revoked by customer

  INVALID_REQUEST The request to the OPG was not valid and therefore could not be executed. There is nothing the end customer can do about it. It has to be fixed on the merchant side.
  SYSTEM_FAILURE

There is a technical issue with this operation which the end customer cannot resolve. It could be on the merchant side, for example an invalid request (that was not covered by the code above), OPG side, or provider side. If the Update of a LIST fails like this, the LIST itself may still be valid.

TRY_OTHER_NETWORK  

The customer should choose a different network (method). The previously attempted method is removed from the LIST. Reload it, so that the method will not be present anymore.

  BLOCKED

Network (AKA "method") is blocked by merchant configuration or denial handler (e.g., due to numerous chargebacks)

  NETWORK_FAILURE

Currently there is no working route for this network available or the network is down globally. This includes misconfiguration on OPG or provider side.

  INVALID_REQUEST

This method or provider needs data that is not or incorrectly provided by the request (e.g., missing billing address etc.).

  RISK_DETECTED

A restriction to (possibly more secure) methods has taken place due to suspicion of fraud .

  ADDITIONAL_NETWORKS

The system has detected more (sub-) networks the customer needs to choose from.

TRY_OTHER_ACCOUNT  

The payment account exists, but was not accepted. Offer to try another account, same network (AKA "method") is allowed. Reload the LIST so the used account will not show anymore in case it was a registered one.

  BLOCKED

Account is blocked by merchant configuration or payment provider (e.g., due to excessive retries or chargeback)

  BLACKLISTED

Account is blacklisted by external source (e.g., PSP or scoring provider)

  CUSTOMER_ABORT

The customer has chosen to abort this operation.

  INVALID_ACCOUNT

Invalid account data, account unknown, deactivated, etc.

  EXCEEDS_LIMIT

This payment account does not provide sufficient funds.

  EXPIRED_ACCOUNT

Account is expired, a different account should be used (applies to frontend payments).

RETRY  

Retry with this network, but with corrected account data (typically frontend) or at another time (typically backend).

  TRUSTED_CUSTOMER

Specific data is incorrect and a trusted customer is detected. It would be safe to give a hint what field contains an error, based on the Return Code.

  UNKNOWN_CUSTOMER

Specific data is incorrect but the customer is unknown (maybe fraud). The user should get a general message about account error without hints. Applies to frontend only, backend equivalent is DECLINED.

  ACCOUNT_NOT_ACTIVATED

Payment account exists, but needs to be activated first.

  EXPIRED_SESSION

LIST or third party payment session has expired, restart if customer is available.

  DECLINED

Account data seems correct, but payment is not accepted due to various reasons (check Return Code). Rejections and Failures (as opposed to Declines) would instead be NETWORK_FAILURE, SYSTEM_FAILURE, etc.

  EXPIRED_ACCOUNT

Account is expired. Applies to backend payments. Retry the Recurring Charge after the expiration date was updated or registered accounts were added.

  EXCEEDS_LIMIT

Account is valid but at the moment has exceeded its limits, i.e., there are insufficient funds (applies to backend operations, ADM is recommended)

  TEMPORARY_FAILURE Provider, network (AKA "method") or adapter experiences a temporary failure. Occurs mostly for backend, where a retry later is recommended. Since this is not possible in frontend, this situation would often cause a TRY_OTHER_NETWORK there.
RELOAD   The LIST object was updated based on the submitted data. Reload and display the resulting payment page again.
  ACTIVATED A method has been used that requires a multi-step flow, e.g. Installments. See ACTIVATE Request. This is not an error but expected behavior for some methods.

 

Interaction Codes

Interaction Codes are recommendations for the merchant system frontend on how to proceed after a transaction. They are especially relevant after submitted CHARGE Requests because there may be ways to redirect a transaction if a problem is identified and in consequence reduce denials.

In the case of frontend payments, interaction codes give information on how the end customer should proceed, and a corresponding page and message should be displayed.

In the case of backend payments (e.g., Recurring Charges or closing of Deferred Payments) they indicate the next step to be performed by the merchant system.

Please sign in to view further details of this article. Login

Web Content Display

Status Codes

Status Codes describe the current state of an operation, they provide a basic information which your server system should listen to. They are sent in LIST and CHARGE responses as well as via Status Notifications.

The whole Status is composed of a Status Code and a Reason Code, which provides further information inside a group of Codes.

Note that a status can concern different scopes as indicated by the value of the entity attribute:

  • payment: The payment transaction (relevant for successes, chargebacks, etc.)
  • customer: The customer registration (as a consequence of account registration)
  • account: The account registration under a customer (also result of account registration)
  • session: The frontend payment session (relevant when deciding whether to issue a new LIST Request or update an old one)

Status Codes are complemented by Interaction Codes that offer recommendations on what to do next in a frontend payment session, especially to reduce declines in problematic situations.

Conceptually the status codes can be seen in a hierarchy as visualized below:

Payment Statuses

Concerning entity = payment

Status Code Reason Code Comment
charged debited Charge successful. Also applies to Closings of Deferred Charges but not Deferred Charges themselves (see below).
^ debited_partial A Charge or Closing that was successful but partially refunded.
^ payment_received Charge successful (after customer had to complete the payment seperately, such as with the Sofort Banking method)
paid_out refund_credited Payout completed. This can apply to a Refund transaction or the initial Charge when completely paid out.
^ credited ^
pending debit_requested Operation pending (e.g., because customer has been redirected to a PSP confirmation page or the PSP processes the request asynchronously). In most cases you can wait for further notification. Only processing_paused may require action, please check!
^ refund_requested ^
  payout_requested ^
^ payment_demand_requested ^
^ payment_demanded ^
^ credit_requested ^
^ retry_scheduled A recurring payment attempt failed, but optile has scheduled a retry for the future. This status and behaviour is a part of Automated Denial Management.
^ processing_scheduled The payment request was received and is currently queued on provider or optile side with the possibility to cancel it before it gets processed (see Refunds & Cancelations).
^ processing_paused The payment request was received and is currently held back on provider side. Typically the merchant needs to manually confirm this transaction with the provider to proceed.
failed debit_failed

The processing was denied (maybe not even attempted), because a technical problem is present (on provider or maybe merchant side).

Examples: Downtime, wrong request format, missing account data (assuming this is due to a faulty implementation on merchant side)

^ refund_failed ^
^ payment_demand_failed ^
^ credit_failed ^
declined debit_declined

The processing was denied, because seemingly there is no willingness or ability of the account holder to actually pay.

Examples: Insufficient Funds, Risk Management, Blacklisting, Invalid account data (assuming this is due to incorrect input from customer)

^ refund_declined ^
^ payment_demand_declined ^
^ credit_declined ^
rejected rejected

The processing was denied, because it is not allowed due to current configuration or general agreement with the provider.

Examples: Currency or Country not allowed, payment feature not enabled.
aborted debit_aborted Operation aborted by customer (do not confuse with interaction code ABORT)
^ payment_demand_aborted For example, a prepayment is not done within 3 months, or actions on redirected page not completed within 30 minutes.
charged_back charged_back Amount charged back from the merchant account due to customer complaint or dispute.
information_requested information_requested Charge disputed by customer: e.g., customer claimed a transaction cancelation directly at PSP. PSP requests information (from the merchant) about the transaction to accept or reject the claim.
dispute_closed dispute_closed DEPRECATED - Starting from OPG v2.0.6 a transaction in status information_requested can only transition to charged_back or back to its previous status (most likely charged).
^ chargeback_canceled DEPRECATED - See above.
canceled debit_canceled Operation canceled by merchant
^ refund_canceled ^
^ payment_demand_canceled ^
^ receipt_canceled ^
^ credit_canceled ^
Deferred Payment Statuses

Concerning entity = payment

The following statuses can occur for Deferred Charges or related Closings, in addition to the statuses above.

Status Code Reason Code Comment
charged closed A Deferred Charge that was completely closed. Closings themselves, however, will be marked as debited instead, see above.

^

closed_partial A Deferred Charge that was partially closed
preauthorized preauthorized Preauthorization successful. Amount is likely to be available for closing.
^ debited_partial A successful Deferred Charge has been partially closed.
pending preauthorization_requested Operation pending (e.g., because customer has been redirected to a PSP confirmation page or the PSP processes the request asynchronously). Wait for further notification.
^ preorder_issued ^
^ preorder_requested ^
^ cancelation_requested ^
failed preauthorization_failed Operation failed due to technical reasons
^ preorder_failed ^
declined preauthorization_declined Operation declined by institution
^ preorder_declined ^
aborted preauthorization_aborted Operation is aborted by customer
expired preauthorization_expired Preauthorization reference has expired
^ request_expired Request operation has expired (no valid response from PSP)
canceled preorder_canceled Operation canceled
^ preauthorization_canceled ^
Preset Statuses

Concerning entity = payment

The following statuses can occur for PRESET flows in Delayed Payment Submission and Express Checkout, in addition to the statuses above. Note that in Delayed Payment Submission the preset account is part of the LIST object which will not change the status. Therefore these statuses only occur on the PRESET call itself in this case, and are visible if issued from the backend.

Status Code Reason Code Comment
preset preset The Preset is complete and ready for a CHARGE.
pending preset_requested The Preset is still incomplete. In Express Checkout the user may have to select further data.
^ confirmation_requested Occurs in Express Checkout only, when the Preset needs a CONFIRM to be completed.
failed preset_failed Operation failed due to technical reasons
rejected preset_rejected Operation failed due to configuration issues.
declined preset_declined Operation declined by payment provider
expired preset_expired The completed or still incomplete Preset expired and can no longer be used for consecutive operations.
canceled preset_canceled Operation was canceled (typically by the merchant)
Customer Registration Statuses

Concerning entity = customer

The customerRegistrationPassword will be sent exactly once after an account registration with such a notification. customerRegistrationId will be returned for other notifications as well.

Status Code Reason Code Comment
registered registered Customer is registered
pending registration_requested Registration requested; wait for further notification

^

deregistration_requested Operation pending; wait for further notification

^

registration_cancelation_requested ^
failed registration_failed Operation failed due to technical reasons
declined registration_declined Operation declined by institution
aborted registration_aborted Operation is aborted by customer
expired registration_expired Registration reference has expired
canceled registration_canceled Operation canceled
Account Statuses

Concerning entity = account

Status Code Reason Code Comment
registered registered Account is registered
deregistered deregistered De-registration is done successfully
Payment Session Statuses

Concerning entity = session

Status Code Reason Code Comment Entity
expired list_expired An initiated List expired, i.e., its reference is no longer valid and no Charge can be executed through it anymore. session
listed listed The List is valid and a Charge can be executed. Only in List reply
pending charge_requested The List is in use, but the Charge state is unknown for now (i.e., because the customer is redirected to the PSP page to close the payment). session
rejected list_rejected The List could not be generated due to the current configuration (e.g., missing methods or providers for the requested country or currency). session
failed list_failed The List has failed due to a technical problem and no action is possible for this List. session
canceled list_canceled The List has been canceled (by the merchant) and no action is possible for this List. session
ended list_used The List has been used for payment and no action is possible for this List. session

^

ended The List is in the end-state and will be removed/deleted. session

 

Status Codes

Status Codes describe the current state of an operation, they provide a basic information which your server system should listen to. They are sent in LIST and CHARGE responses as well as via Status Notifications.

Please sign in to view further details of this article. Login

Web Content Display

Result Codes

Result Codes describe the outcome of an operation in detail. To simplify, the OPG performs a mapping of the Return Code to interpret the Interaction Codes, which we recommend to use in most cases.

A Result Code consists of three groups separated by dots:

  1. The first group is numeric and called Return Code (or formerly Standard Code). The Return Code 00000 means that no error occured during payment request processing.
  2. The second group contains alphanumerical characters and refers to a component that generated this return code. Standard components are described by three digits whereas custom components and server extensions are usually referred to by their code names.
  3. The third group is a qualifier that may contain additional information, as given by the provider. Usually the qualifier is encoded by three digits and default value is 000 if no additional information is available.

Component and qualifier are called Investigation Info and help to analyze error conditions. Result codes are complemented by Result Info messages, which contain original payment service provider information, when available.

For example:

Result Code: 00100.102.000
Return Code = 00100 - Invalid request
Component code = 102 - Merchant HTTP Gateway Listener
Qualifier = 000 - no additional information

Result Code: 45020.WIRECARD.51
Return Code = 45020 - Not sufficient funds / exceeds limit
Component code = WIRECARD - Wirecard PSP adapter
Qualifier = 51 - Insufficient funds or credit limit exceeded. (Wirecard error code)

Web Content Display

Return Codes

Return Codes are a unified representation of all Payment Service Providers' responses concerning a payment transaction. As such, Return Codes are low-level information that can be used for detailed analysis, especially of denied payments.

From the low-level Return Codes the higher-level Status Codes and Interaction Codes are derived, which were designed for easier handling in day-to-day use cases.

The Return Codes are represented by the following attributes, which are available in CHARGE responses and Status Notifications:
  • returnCode: numerical representation, shown as part of the Result Code.
  • returnCodeName: human readable representation, see table below.
  • returnCodeSource: indicates where in the chain the response was generated. Together with the pspCode and institutionCode this should make clear, which organization should be contacted in case of transaction specific questions. Its value can be either of:
    • GATEWAY (Payment Gateway, first level)
    • PSP (Connected payment service provider, second level)
    • INSTITUTION (The banking institution that may be behind the payment service provider)

The table below includes all Return Codes of the Payment Gateway with their numbers, names, descriptions and if they are considered recoverable in the context of Fallback Routing.

Number Code Name Recoverable Description
0 OK   Approved
1 OK_PENDING   Pending, wait for updated status
2 OK_SCHEDULED_FOR_BATCH   Pending due to transaction queuing, wait for updated status
5 OK_TEST_MODE   OK / Production level test mode
6 OK_CUSTOMER_ACTION_REQUIRED   Customer needs to take action, eg manually confirm on provider side. The merchant does not need to inform the customer, this is taken care of.
7 OK_MERCHANT_ACTION_REQUIRED   Merchant needs to take action, eg manually confirm on provider side, or inform the customer to take action.
8 OK_PROVIDER_ACTION_REQUIRED   Provider needs to take action, eg manually review and approve the transaction.
11 ABORTED_BY_CUSTOMER   Aborted, operation is aborted by customer
14 CANCELED   Canceled, operation is canceled (typically by merchant)
15 CHARGEDBACK   Charged back, charge back was received
16 IN_DISPUTE   Dispute process has been initialized
17 OPERATION_REQUEST_EXPIRED   Requested operation is expired
10050 OPERATION_NOT_SUPPORTED x Operation is not supported
10100 WORKFLOW_TEMPLATE_NOT_FOUND   No workflow for operation
10103 INVALID_TRANSACTION_STATE   Operation is invalid for current process state
10105 DUPLICATED_TRANSACTION   Same transaction has been already submitted
10520 MAX_REQUESTS_OCCURRED x Transaction is rejected because of heavy load from one host
10530 INSTITUTION_NOT_SUPPORTED x Institution is not supported
10531 INVALID_INSTITUTION x Institution is unknown
10532 CONTACT_INSTITUTION   Contact institution
11000 SERVICE_ERROR x Error occurs during request processing
11005 THIRD_PARTY_SERVICE_ERROR x Error from third party service on provider side
11010 TRANSACTION_IN_USE   Transaction is blocked by other request
11011 CURRENCY_CONVERTER_INVALID_RATE x Currency converter - invalid currency rate
11012 CURRENCY_CONVERTER_MISSING_RATE x Currency converter - missing currency rate
11013 TERMINAL_IN_USE x Terminal is locked by other request
11014 CURRENCY_CONVERTER_ERROR x Currency converter service error
11020 ADAPTER_NOT_AVAILABLE x Provider adapter is not available
11021 ADAPTER_COMMUNICATION_ERROR x Communication error with adapter
11025 ADAPTER_ERROR x An error in adapter
12000 REQUEST_ERROR x Adapter can not create a valid request for communication with target service, so no service communication took place
12010 COMMUNICATION_ERROR x Communication error with target service because of socket connect timeout, read timeout or IOException
12015 TEMPORARY_UNAVAILABLE x Payment service temporary unavailable
13000 RESPONSE_ERROR   Cannot parse or understand provided response
13010 API_VERSION_ERROR x Service API version is not compatible with version used by a service-client
13050 INVALID_REQUEST x The request has wrong or in an unexpected format, or it is not accpted by a reason like 'cannot process empty request', 'missing signature', 'no action type found in request' and so on
20100 INVALID_CONFIGURATION x Configuration is invalid, no detail information given
20150 INVALID_PROVIDER_CONTRACT x Provider configuration is invalid
20151 INVALID_PROVIDER_CREDENTIALS x Invalid provider credentials
20152 MISSING_PROVIDER_CREDENTIALS x Missing provider credentials
20160 NO_ROUTE_FOR_NETWORK x No route to provider
20161 NO_NETWORK_BY_PROVIDER x No network by provider
20162 NOT_ALLOWED x Requested action is not allowed by contract
20163 AMOUNT_NOT_ALLOWED x Requested amount is not allowed by contract
20164 COUNTRY_NOT_ALLOWED x Country is not allowed by contract
20165 CURRENCY_NOT_ALLOWED x Currency is not allowed by contract
20180 METHOD_NOT_SUPPORTED x Requested method is not supported
20200 MERCHANT_UNKNOWN   Merchant is not known on OPG side
30000 INVALID_REFERENCE x Invalid transaction- or other unspecified- reference
30001 INVALID_CUSTOMER_REGISTRATION_REFERENCE x Invalid customer registration reference
30002 INVALID_ACCOUNT_REGISTRATION_REFERENCE x Invalid payment account registration reference
30003 MISSING_REFERENCE x Missing transaction- or other unspecified- reference
30004 EXPIRED_REFERENCE x Expired transaction- or other unspecified- reference
30005 USED_REFERENCE x Used transaction- or other unspecified- reference
30006 MISSING_CUSTOMER_REGISTRATION_REFERENCE x MIssing customer registration reference
30007 MISSING_ACCOUNT_REGISTRATION_REFERENCE x Missing payment account registration reference
30008 CANCELED_REFERENCE x Canceled (voided or invalidated) transaction- or other unspecified- reference
30009 CANCELED_ACCOUNT_REGISTRATION_REFERENCE x Canceled (voided or invalidated) payment account registration reference
30010 INVALID_CUSTOMER_REGISTRATION x Invalid data in customer registration
30011 INVALID_REGISTERED_ACCOUNT x Invalid data in registered account
45000 DECLINED x Declined
45010 INVALID_ACCOUNT   Invalid card or account
45011 EXPIRED_ACCOUNT   Expired card or account
45012 RESTRICTED_ACCOUNT   Restricted card or account
45013 INCOMPLETE_ACCOUNT   Incomplete account, some attribute missing
45014 LOCKED_ACCOUNT   Account is locked
45015 TEST_ACCOUNT   Test account
45016 NOT_ACTIVATED_ACCOUNT   Not activated account
45017 LOST_OR_STOLEN_CARD   Lost or stolen card
45018 PICK_UP_CARD   The card is requested by an issuer to be retrieved
45020 NON_SUFFICIENT_FUNDS   Not sufficient funds / exceeds limit
45025 ACCOUNT_SURPASSED_LIMIT   The account exceeds limit (daily limit, weekly limit, amount of transactions count, amount of single transaction and so on)
45100 TRANSACTION_EXCEEDS_LIMIT   Transaction's amount is above limit
45300 SECURITY_VIOLATION x Security violation
45340 ALLOWABLE_VERIFICATION_TRIES_EXCEEDED   Allowable retries exceeded
45341 NOT_AUTHENTICATED_ACCOUNT   Password or pin/verification code does not match
45400 RISK_MANAGEMENT_VIOLATION x Declined by risk management system
45405 RISK_VELOCITY_CHECK x Declined by velocity check
45406 RISK_REPEATED_REVERSALS x Declined because of often payment reversals from customer side
45407 RISK_AVS_CHECK x Declined by Address Verification System
45408 RISK_SUSPECTED_FRAUD   Suspected fraud
45409 RISK_BLACKLIST   Account or customer is blacklisted
50000 VALIDATION_ERROR x Data (not necessarily account-related) does not pass the validation logic, feedback is without specific information
50005 INVALID_DATA x Invalid data not necessarily account-related
50010 INVALID_BANK_CODE   Invalid bank code
50011 INVALID_BANK_NAME   Invalid bank name
50012 INVALID_IBAN   Invalid IBAN
50013 INVALID_BIC   Invalid BIC
50015 INVALID_ACCOUNT_NUMBER   Invalid account number
50016 INVALID_HOLDER_NAME   Invalid holder name
50017 INVALID_BANK_LOCATION   Invalid bank location
50018 INVALID_BANK_LOCATION_ID   Invalid bank location ID
50030 INVALID_COUNTRY   Invalid country
50050 INVALID_EXPIRY_MONTH   Invalid expiry month
50051 INVALID_EXPIRY_YEAR   Invalid expiry year
50052 INVALID_EXPIRY_DATE   Invalid expiry date
50053 INVALID_VERIFICATION_CODE   Invalid verification code
50070 INVALID_LOGIN   Invalid login
50080 INVALID_PASSWORD   Invalid password
50081 INVALID_AUTHENTICATION_DATA   Invalid 3d secure or other authentication data
50095 INVALID_EMAIL   Invalid email
50100 INVALID_AMOUNT_FORMAT   Invalid amount format
50105 INVALID_URL_FORMAT   Invalid URL format
50120 INVALID_CURRENCY_FORMAT   Invalid currency format
50130 INVALID_REFERENCE_TEXT   Invalid reference text
50170 INVALID_BILLING_ADDRESS   Invalid billing address
50190 INVALID_SHIPPING_ADDRESS   Invalid shipping address
50300 INVALID_PRODUCT_INFO   Invalid product info
51005 MISSING_DATA x Missing data (not necessarily account-related), no details given
51009 MISSING_ACCOUNT   No account information provided
51010 MISSING_BANK_CODE   Missing bank code
51011 MISSING_BANK_NAME   Missing bank name
51012 MISSING_IBAN   Missing IBAN
51013 MISSING_BIC   Missing BIC
51015 MISSING_ACCOUNT_NUMBER   Missing account number
51016 MISSING_HOLDER_NAME   Missing holder name
51017 MISSING_BANK_LOCATION   Missing bank location
51018 MISSING_BANK_LOCATION_ID   Missing bank location ID
51030 MISSING_COUNTRY   Missing country
51050 MISSING_EXPIRY_MONTH   Missing expiry month
51051 MISSING_EXPIRY_YEAR   Missing expiry year
51052 MISSING_EXPIRY_DATE   Missing expiry date
51053 MISSING_VERIFICATION_CODE   Missing verification code
51070 MISSING_LOGIN   Missing login
51080 MISSING_PASSWORD   Missing password
51081 MISSING_AUTHENTICATION_DATA   Missing 3d secure or other authentication data
51095 MISSING_EMAIL   Missing email address
51100 MISSING_AMOUNT   Missing amount
51120 MISSING_CURRENCY   Missing currency
51130 MISSING_REFERENCE_TEXT   Missing reference text
51170 MISSING_BILLING_ADDRESS   Missing billing address
51190 MISSING_SHIPPING_ADDRESS   Missing shipping address
51300 MISSING_PRODUCT_INFO   Missing product (shopping cart) info
99999 UNKNOWN x Result code is unknown

 

Return Codes

Return Codes are a unified representation of all Payment Service Providers' responses concerning a payment transaction. As such, Return Codes are low-level information that can be used for detailed analysis, especially of denied payments.

From the low-level Return Codes the higher-level Status Codes and Interaction Codes are derived, which were designed for easier handling in day-to-day use cases.

Please sign in to view further details of this article. Login

Web Content Display

Test Accounts & Magic Numbers

Web Content Display

Test Accounts

There is a full scale testing suite provided by optile to cover edge and corner cases, triggered by payment amounts, see Magic Numbers.

Apart from that you can use these straight forward account numbers for some of your adapters in place, including the optile "dummy" adapter (not to be confused with the "Test Adapter" mentioned above).

Test Account Numbers Credit Cards
Payment Service Provider VISA MasterCard American Express Diner's Club Discover Maestro
Adyen Holder name: any
Expiry date: 06 / 2016
CVV: 737
Number: 4111 1111 1111 1111
Holder name: any
Expiry date: 06 / 2016
CVC: 737
Number: 5555 5555 5555 4444
Holder name: any
Expiry date: 06 / 2016
CID: 7373
Number: 3700 0000 0000 002
Holder name: any
Expiry date: 06 / 2016
CVV2: 737
Number: 3600 6666 3333 44
Holder name: any
Expiry date: 06 / 2016
CID: 737
Number: 6011 6011 6011 6611
Holder name: any
Expiry date: 06 / 2016
CVC: 737
Number: 6731 0123 4567 8906
Authorize.Net Holder name: any
Expiry date: any date in the future
CVV: any 3-digit number
Number: 4007000000027
  Holder name: any
Expiry date: any date in the future
CID: any valid 4-digit number
Number: 370000000000002
Holder name: any
Expiry date: any date in the future
CVV2: any valid 3-digit number
Number: 38000000000006
Holder name: any
Expiry date: any date in the future
CID: any 3-digit number
Number: 6011000000000012
 
Concardis Holder name: any
Expiry date: 12 / 18
CVV: 147
Number.: 4149 0115 0000 0147

Holder name: any
Expiry date: 12 / 18
CVV: 003
Number.:
5232 0500 0001 0003

       
eMerchantPay "holderName": any,
"number": 4111111111111111,
"expiryMonth": 1,
"expiryYear": 2017,
"verificationCode": "123"
"holderName": any,
"number": "5500000000000004",
"expiryMonth": 1,
"expiryYear": 2017,
"verificationCode": "123"
       
Ingenico Holder name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Number e.g.:
4111 1111 1111 1111
Holder name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Number e.g.:
5544444444444444
       
optile Dummy Adapter - TestPSP Holder name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Numbers e.g.:
4111 1111 1111 1111
4012 8888 8888 1881

Holder name: any, min. 3 chars
Expiry date: any date in the future
CVC: any valid 3-digit number
Numbers e.g.:
5500 0000 0000 0004
5544 4444 4444 4444
5555 5555 5555 4444

5102 8819 1749 4147 ->
generates Account Exceeds Limit (45020) RETRY

Holder name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Numbers e.g.:
3400 0000 0000 009
3700 0000 0000 002
Holder name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Number: 3000 0000 0000 04
older name: any, min. 3 chars
Expiry date: any date in the future
CVV: any 3-digit number
Number: 6011 0000 0000 0004
 
Secure Trading

Holder name: any
Expiry date: any
CVV: any
Number.: 4111110000000211
(authorization)

Number.: 4111110000000112 (decline)

Holder name: any
Expiry date: any
CVV: any
Number.: 5100000000000511
(authorization)

Number.: 5100000000000412 (decline)

       
Six Holder name: any
Expiry date: 12 2017
CVV: 596
Number: 4761739090000088
Holder name: any
Expiry date: 12 2025
CVV: 123
Number: 5413330089600010
       
Telecash/IPG Holder name: any
Expiry date: 10 2020
CVV: 123
Number: 4035874000424977
Holder name: any
Expiry date: 10 2020
CVV: 123
Number: 5426064000424979
       
Wirecard Holder name: any
Expiry date: any date in the future
CVV: any 3-digit number
Number: 4200000000000000
Holder name: any
Expiry date: any date in the future
CVC: any 3-digit number
Number: 5500000000000000
Holder name: any
Expiry date: any date in the future
CID: any valid 4-digit number
Number: 370000000000000
Holder name: any
Expiry date: any date in the future
CVV2: any valid 3-digit number
Number: 38000000000000
Holder name: any
Expiry date: any date in the future
CID: any 3-digit number
Number: 6011000000000000
Holder name: any
Expiry date: any date in the future
CVC: any 3-digit number
Number: 675940000000000002
WorldPay

Holder name: Sansa Stark,
number: 4444333322221111,
expiryMonth: 12,
expiryYear: 2020,
CVV: 555

Notice: For 3D Secure tests, use ">>>3D" as holder name.
Other CVVs trigger different behaviors.
More information

 

Holder name: Tom James,
number: 5555555555554444,
expiryMonth: 7,
expiryYear: 2019,
CVV: 555

Notice: For 3D Secure tests, use ">>>3D" as holder name.
Other CVVs trigger different behaviors.
More information

 

       
Bank Accounts
PSP Adyen Wirecard Sofortüberweisung optile dummy adapter
Bank Account Account Number: 1234567890
Bank Code: 12345678
Holder name: any
Account Number: 12345678
Bank Code: 70070010
First Name: John F
Last Name: Doe
Bank Code (BLZ): 88888888
Account Number: any number
PIN: any 4-digit number

Account Number e.g.: 1111111
Bank Code e.g.: 79050000
Holder name: any, min. 3 chars

or

IBAN: DE02120300000000202051
BIC: BYLADEM1001
Account Holder: Any

 

Web Content Display

Magic Numbers

We ask merchants to unrestrictedly go through the following testing phases before going live:

# Test Phase Test Target OPG system Adapter(s) Test Cases
1 Use Case Sandbox Tests Merchant integration with Payment Gateway Sandbox Test Adapter Supplied by optile
2 Provider Sandbox Tests Provider sandbox functionality and configuration Sandbox Real adapters Supplied by provider(s)
3 Provider Live Tests Provider live configuration Live Real adapters Basic cases (real payments)
4 Live Monitoring Real life processing Live Real adapters Real customer payment

 

Use Case Sandbox Tests (1)

The Payment Gateway enables you to test the "happy path" (a success is returned) as well as negative responses (e.g. denials) and edge cases (e.g. chargebacks) in the Sandbox environment. You configure the "Test Adapter" (TESTPSP) in the background and this way you can easily double check the integration of your system(s) with the Payment Gateway.

The Test Adapter will respond according to the given payment amount and therefore confront your system with different kinds of behavior as shown in the table below. Note that depending on the features you implemented you only need a subset of test cases. The features are identified by codes that are also used throughout the documentation.

The provided cases are primarily intended for automated testing. For 'redirect' methods such as PayPal there will be a redirect to a dummy page provided, containing buttons that simulate different behavior (successful payment or customer abort). However, they only take reliably effect if none of the following test cases are used. If one of these test cases is triggered, no button should be clicked, and the OPG will proceed with status transitions according to the test case. Clicking a button in this case would result in conflicting status notifications.

Notes:
  • "sync or async provider": The test adapter can simulate two kinds of payment providers. Therefore, most test cases exist two times, one for each provider type:
    • synchronous: There is an immediate reply from the provider. Most providers behave like this.
    • asynchronous: There is an intermediate state ("pending") as a reply and first notification. Usually some seconds later the final information will be available (asynchronous), delivered via notification. An example is the provider Adyen.
  • Interaction Codes are listed for frontend interactions, and ideally should be the only codes evaluated during a payment session. For other scenarios like ADM, Status Codes should be used.
Testcases for Frontend Checkout and Chargebacks:
Test Case # Payment Amount Feature Code Test Case Name sync or async provider Test Steps / Calls Charge statusCode (reasonCode) result(s) Charge interaction Code (Reason) result(s) Note
101 1,01 CHECKOUT Successful frontend payment sync LIST, CHARGE charged PROCEED (OK)  
102 1,02 CHECKOUT Failed frontend payment (technical reason) sync LIST, CHARGE failed ABORT (1)
103 1,03 CHECKOUT Declined frontend payment (business reason) sync LIST, CHARGE declined RETRY (1)
104 1,04 CHECKOUT Successful frontend payment async LIST, CHARGE pending, charged PROCEED (PENDING), PROCEED (OK)  
105 1,05 CHECKOUT Failed frontend payment (technical reason) async LIST, CHARGE pending, failed PROCEED (PENDING), ABORT  
106 1,06 CHECKOUT Declined frontend payment (business reason) async LIST, CHARGE pending, declined PROCEED (PENDING), RETRY  
107 1,07 CHECKOUT Payment expired due to customer inactivity (e.g., prepayment not done, actions on redirected page not completed) async LIST, CHARGE pending, aborted PROCEED (PENDING), ABORT  
108 1,08 CHARGEBACK   -

LIST, CHARGE,charged_back

CHARGE success, charged_back PROCEED (OK)  
109 1,09 CHARGEBACK   - LIST, CHARGE, information_requested, charged_back CHARGE success, information_requested, charged_back PROCEED (OK)  
110 1,10 CHARGEBACK   - LIST, CHARGE, information_requested, charged CHARGE success, information_requested, charged (debited) PROCEED (OK)  
111 1,11 REDIR Customer gets redirected for frontend charge and completes payment async LIST, CHARGE pending, charged PROCEED (PENDING), PROCEED (OK) (2)
112 1,12 REDIR Customer gets redirected for frontend charge and cancels payment async LIST, CHARGE pending, aborted PROCEED (PENDING), ABORT  
119 1,19 CHARGEBACK   - LIST, CHARGE, charged_back,
charged
CHARGE success, charged_back,
charged (debited)
PROCEED (OK)  
120 1,20 CHECKOUT Failed frontend payment (business  reason) sync LIST, CHARGE failed TRY_OTHER_NETWORK  
121 1,21 CHECKOUT   sync

LIST,

CHARGE

failed TRY_OTHER_ACCOUNT  
122 1,22 CHARGEBACK   - LIST, CHARGE, information_requested, charged_back CHARGE success,
information_requested
(notification_of_chargeback), charged_back
PROCEED (OK)  

(1) In real world the interaction code could vary
(2) Outcome depends on customer interaction, which can also be done with the provided test adapter. Redirections always mean asynchronous communication.

Testcases for Payout of Transactions (AKA "Refunds"):
Test Case # Payment Amount Feature Code Test Case Name sync or async provider Test Steps / Calls Charge statusCode result(s) Charge interaction Code (Reason) result(s) Note
201 2,01 PAYOUT-TX Successful full refund of a previous transaction sync LIST, CHARGE, PAYOUT charged, paid_out PROCEED (OK), PROCEED (OK)  
202 2,02 PAYOUT-TX Failed full refund of a previous transaction sync LIST, CHARGE, PAYOUT charged, failed

PROCEED (OK), RETRY

 
203 2,03 PAYOUT-TX Declined full refund of a previous transaction sync LIST, CHARGE, PAYOUT charged, declined PROCEED (OK), RETRY  
204 2,04 PAYOUT-TX Successful full refund of a previous transaction async LIST, CHARGE, PAYOUT pending, charged, pending, paid_out PROCEED (PENDING), PROCEED (OK), PROCEED (PENDING), PROCEED (OK)  
205 2,05 PAYOUT-TX Failed full refund of a previous transaction async LIST, CHARGE, PAYOUT pending, charged, pending, failed

PROCEED (PENDING), PROCEED (OK), PROCEED (PENDING),

ABORT

 
206 2,06 PAYOUT-TX Declined full refund of a previous transaction async LIST, CHARGE, PAYOUT pending, charged, pending, declined

PROCEED (PENDING), PROCEED (OK), PROCEED (PENDING),

RETRY

 
207 2,07 PAYOUT-PART Successful partial refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial) charged, paid_out PROCEED (OK),  
208 2,08 PAYOUT-PART Failed partial refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial) charged, failed PROCEED (OK),  
209 2,09 PAYOUT-PART Declined partial refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial) charged, declined PROCEED (OK), RETRY  
210 2,10 PAYOUT-PART Successful partial refund of a previous transaction async LIST, CHARGE, PAYOUT(partial) pending, charged, pending, paid_out PROCEED (OK),  
211 2,11 PAYOUT-PART Failed partial  refund of a previous transaction async LIST, CHARGE, PAYOUT(partial) pending, charged, pending, failed PROCEED (OK),  
212 2,12 PAYOUT-PART Declined partial refund of a previous transaction async LIST, CHARGE, PAYOUT(partial) pending, charged, pending, declined PROCEED (OK), RETRY  
213 2,13 PAYOUT-MULTI Successful multiple refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial), PAYOUT (full) charged, paid_out PROCEED (OK),  
214 2,14 PAYOUT-MULTI Failed multiple refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial), PAYOUT (full) charged, failed PROCEED (OK), ABORT  
215 2,15 PAYOUT-MULTI Declined multiple refund of a previous transaction sync LIST, CHARGE, PAYOUT(partial), PAYOUT (full) charged, declined PROCEED (OK),  RETRY  
216 2,16 PAYOUT-MULTI Successful multiple refund of a previous transaction async LIST, CHARGE, PAYOUT(partial), PAYOUT (full) pending, charged, pending, paid_out PROCEED (OK),  
217 2,17 PAYOUT-MULTI Failed multiple refund of a previous transaction async LIST, CHARGE, PAYOUT(partial), PAYOUT (full) pending, charged, pending, failed PROCEED (OK), ABORT  
218 2,18 PAYOUT-MULTI Declined multiple refund of a previous transaction async LIST, CHARGE, PAYOUT(partial), PAYOUT (full) pending, charged, pending, declined PROCEED (OK), RETRY  
Testcases for Deferred Charges:

Make sure to differentiate between the initial CHARGE and subsequent CLOSING transactions.

Test Case # Payment Amount Feature Code Test Case Name sync or async provider Test Steps / Calls CHARGE / CLOSING statusCode result(s) CHARGE / CLOSING interaction Code (Reason) reply Note
401 4,01 DEFER Successful deferred Charge sync LIST, CHARGE CHARGE: preauthorized PROCEED (OK) Credit Cards or Direct Debit
402 4,02 DEFER Failed deferred Charge sync LIST, CHARGE CHARGE: failed ABORT  
403 4,03 DEFER Declined deferred Charge sync LIST, CHARGE CHARGE: declined RETRY  
404 4,04 DEFER Successful deferred Charge async LIST, CHARGE CHARGE: pending, preauthorized PROCEED (PENDING)  
405 4,05 DEFER Failed deferred Charge async LIST, CHARGE CHARGE: pending, failed PROCEED (PENDING)  
406 4,06 DEFER Declined deferred Charge async LIST, CHARGE CHARGE: pending, declined PROCEED (PENDING)  
407 4,07 DEFER Demanded Charge (e.g., prepayment) that expired due to missing customer payment async LIST, CHARGE CHARGE: pending, request_expired PROCEED (PENDING)  
408 4,08 REDIR & DEFER Successful deferred Charge with Redirect network async LIST, CHARGE CHARGE: pending, preauthorized PROCEED (PENDING) e.g., PayPal
409 4,09 DEFER Deferred Charge that expired due to missing Closing sync LIST, CHARGE CHARGE: preauthorized, preauthorization_expired PROCEED (OK)  
410 4,10 DEFER Successful deferred Charge and full Closing sync LIST, CHARGE, CLOSING (full) CLOSING: charged PROCEED (OK)  
411 4,11 DEFER Successful deferred Charge, failed full Closing sync LIST, CHARGE, CLOSING (full) CLOSING: failed ABORT  
412 4,12 DEFER Successful deferred Charge, declined full Closing sync LIST, CHARGE, CLOSING (full) CLOSING: declined RETRY  
413 4,13 DEFER Successful deferred Charge and full Closing async LIST, CHARGE, CLOSING (full) CLOSING: pending, charged PROCEED (PENDING)  
414 4,14 DEFER Successful deferred Charge, failed full Closing async LIST, CHARGE, CLOSING (full) CLOSING: pending, failed PROCEED (PENDING)  
415 4,15 DEFER Successful deferred Charge, declined full Closing async LIST, CHARGE, CLOSING (full) CLOSING: pending, declined PROCEED (PENDING)  

(1) CANCEL is not a transaction itself, therefore the status of the corresponding CHARGE will be affected and returned.

Testcases for Recurring Charges:
Test Case # Payment Amount Feature Code Test Case Name s/a Test Steps / Calls statusCode result(s) CHARGE interaction Code (Reason) reply
701 7,01 RECUR Successful Recurring Registration sync LIST, CHARGE, CHARGE (recurring)

Init. CHARGE: charged

CUSTOMER: registered

Rec. CHARGE: charged

Init. CHARGE: PROCEED (OK)

Rec. CHARGE: PROCEED (OK)

Testcases for ADM

Please note that these cases are applicable only to recurring charges.

Test Case # Payment Amount Feature Code Test Case Name s/a Test Steps / Calls statusCode result(s) CHARGE interaction Code (Reason) reply
801 8,01 ADM-EXCEEDS_LIMIT   sync

Recurring CHARGE, (ADM - failed),  (ADM - failed), (ADM - successful)

CHARGE failed, CHARGE failed,  CHARGE success

ADM for interaction RETRY - EXCEEDS_LIMIT

802 8,02 ADM-EXCEEDS_LIMIT-FAILED   sync

Recurring CHARGE,  (ADM - failed), (ADM - failed), (ADM - failed)

CHARGE failed ADM for interaction RETRY - EXCEEDS_LIMIT
803 8,03 ADM-DECLINED   sync

Recurring CHARGE,  (ADM - failed), (ADM - failed), (ADM - successful)

CHARGE failed, CHARGE failed,  CHARGE success ADM for interaction RETRY - DECLINED
804 8,04 ADM-DECLINED-FAILED   sync

Recurring CHARGE, (ADM - failed), (ADM - failed), (ADM - failed)

CHARGE failed ADM for interaction RETRY - DECLINED
805 8,05 ADM-TEMPORARY_FAILURE   sync

Recurring CHARGE => (ADM - failed) => (ADM - failed) => (ADM - successful)

 

CHARGE failed, CHARGE failed,  CHARGE success ADM for interaction RETRY - TEMPORARY_FAILURE
806 8,06 ADM-TEMPORARY_FAILURE-FAILED   sync

Recurring. CHARGE => (ADM - failed) => (ADM - failed) => (ADM - failed)

 

CHARGE failed ADM for interaction RETRY - TEMPORARY_FAILURE

 

Magic Numbers

We ask merchants to unrestrictedly go through the following testing phases before going live:

# Test Phase Test Target OPG system Adapter(s) Test Cases
1 Use Case Sandbox Tests Merchant integration with Payment Gateway Sandbox Test Adapter Supplied by optile
2 Provider Sandbox Tests Provider sandbox functionality and configuration Sandbox Real adapters Supplied by provider(s)
3 Provider Live Tests Provider live configuration Live Real adapters Basic cases (real payments)
4 Live Monitoring Real life processing Live Real adapters Real customer payment

 

Please sign in to view further details of this article. Login

Web Content Display

SDK Resources

Web Content Display

PHP Developer Resources

Here you find a PHP SDK for the OPG server payment API available for download.

opg-payment-php-sdk-1.0.zip

This contains a simple demo shop with an API client and model implementation in PHP that covers server-to-server communication (in the folder PaymentClient). It contains all model classes and all communication methods to manage LISTs (ListApi class), CHARGEs (ChargeApi class) and PAYOUTs (PayoutApi class). Please read the included readme.md for further information.

Please note that the PHP SDK is updated on request. Please contact us if you plan to integrate it with more features than those mentioned.

PHP Developer Resources

Here you find a PHP SDK for the OPG server payment API available for download.

Please sign in to view further details of this article. Login

Web Content Display

Java Developer Resources

Here you find the Java Model Classes for the OPG server payment API available for download.

oscato-model-download-v1.20.70.zip

Please note that this contains the model for a server-to-server client. If you are looking for JavaScipt to run in a web browser for client-to-server communication, have a look at our AJAX library.

Java Developer Resources

Here you find the Java Model Classes for the OPG server payment API available for download.

Please sign in to view further details of this article. Login

Web Content Display

OpenAPI Definition

Here you find abstract definitions of the OPG payment APIs in OpenAPI ("Swagger") 2.0 format using YAML. You can use them to generate models for your API clients in a multitude of programming langues, for example Go, Java, NodeJS, Objective C, Perl, PHP, Python, Ruby, and others, using swagger-codegen.

Note there is a difference in models between the "server-to-server" communication, where your server makes requests against OPG (for example the LIST request), and the "client-to-server" communication, where a web browser or mobile app makes requests (for example the CHARGE request).

Please find available for download:

OpenAPI Definition

Here you find abstract definitions of the OPG payment APIs in OpenAPI ("Swagger") 2.0 format using YAML. You can use them to generate models for your API clients in a multitude of programming langues, for example Go, Java, NodeJS, Objective C, Perl, PHP, Python, Ruby, and others, using swagger-codegen.

Note there is a difference in models between the "server-to-server" communication, where your server makes requests against OPG (for example the LIST request), and the "client-to-server" communication, where a web browser or mobile app makes requests (for example the CHARGE request).

Please sign in to view further details of this article. Login

Web Content Display

Glossary

The following list is a compilation of terms used across this document to help you to better understand optile payment services.

  • Adapter: A software module running at optile that makes the connection to a particular Payment Provider, translates (payment) requests into their API and logic, and translates back into optile's unified API and status space.
  • CHARGE request: used to charge using a selected method during a payment session. It is also known in the payment industry as "capture".
  • LIST request: the initial request to optile payment API that starts a session. It responds with a list of applicable and registered methods (networks) used to build the payment page.
  • Method: a payment method, such as Visa, SEPA Direct Debit, PayPal, etc. Can typically be selected by a user on the Payment Page to make a payment, but potentially also for payouts (credits).
  • Network: often used as a synonym for Method in a technical context.
  • Payment Account: a customer payment account registered in OPG Secure Storage.
  • Payment Page: a page during the checkout flow of a merchant that allows users to select a (payment) Method.
  • Payment Provider: a PSP, card acquirer or wallet system that a merchant can use to execute online payments, often through various Methods.
  • Route: a combination of one Method and one Payment Provider that would be available in the context of a merchant configuration at optile.
  • Routing: the function to define which Payment Provider is used for a transaction with a selected (payment) method, depending on configurable parameters such as the country of origin, route cost and network availability.
  • TESTPSP: optile internal adapter used for testing purposes, it simulates the responses of a production adapter used with partner networks. It can be used by developers to test the integration with optile payment features.
  • Token: Secret values used for security. Tokens are needed for every merchant that wants to use optile APIs, they are unique for each merchant and differ between sandbox and live environments.

Glossary

The following list is a compilation of terms used across this document to help you to better understand optile payment services.

Please sign in to view further details of this article. Login

Web Content Display

FAQs

To check our FAQs, please refer to our Help Center.

Make sure to register or sign in to the Help Center to be able to view the protected FAQs. If you could not find an answer to your question, please do not hesitate to submit a ticket with your request.

Web Content Display

Hybrid & Migration Strategies

If you already have an existing payment provider setup which you want to keep while starting with optile in parallel, then there are multiple ways to achieve this, which we want to present here. They are separated into different aspects of payment provider integration, but we will use the following color coding.

A migration does not have to go through all stages depicted in the diagrams. Typically only one or two stages may be chosen.The stages are just ordered by the deepness of their optile integration to give conceptual orientation.

In the following description, legacy methods means those payment methods that make up your current payment page, i.e., for which you have an existing integration directly with the payment respective provider(s).

Payment Page

Static Payment Page: Most merchants have a "hard-coded" payment page, or their own selection logic which payment methods should be displayed for an individual transaction. We assume that this is typically handled on server-side. Provider routing is rarely implemented.

Use routing recommendations only: With the help of optile's Open Routing feature the legacy payment page can be used, only the decision which provider should be used for a payment request would be based on optile's LIST response. This requires all payment method forms and provider integrations to be already present on your system.

Static Redirects / Static Forms with Standalone Charge: The legacy payment page will be used, so the payment page forms and selection has to be present on your side. However, the payment request for all or some payment methods will be done through optile, using the Standalone Charge feature. This is very simple for methods that require a redirect only. For others the corresponding input forms have to be accurately modeled. In any case the configured possibilities on optile side need to always support the choices presented by the merchant's payment page. As a result there is a technical provider-independence for the optile methods, but the payment page is still limited to the methods coded in your system, so it's not "implement once".

Server-side method list merge: Here optile is configured to offer payment methods that complement the legacy ones. Therefore optile's LIST response will be read out and its methods merged with those that are still handled by your system. This requires visual merge logic and a case distinction on submit on your system, but if generically implemented this is already an "implement once" solution, meaning you could add methods and providers on runtime. Also, a step-by-step migration of legacy payment methods is easy, because you can remove your system's representation of them on the page and add them to optile instead.

Hybrid Page with AJAX library: Also in this approach there will be a mix of legacy and optile methods on the payment page. Instead of orchestrating this on your server-side, however, the optile AJAX library will inject the optile methods on client side and will also support the distinction on submit (going to legacy or optile endpoints). Therefore it requires only minimum implementation effort on your side. See the separate chapter on Hybrid AJAX page for a detailed documentation.

Own page intelligence / scoring: You are basically using optile's dynamic payment page. However, you employ your own (or third-party) customer scoring system to dynamically select the payment methods to be shown for each session. You can use this information to further limit the optile-originating set of methods via the preselection.networkCodes array in the LIST request. In theory you could also filter on your side, but for integration scenarios that have a CHARGE request directly from the client this leaves a loophole for proficient end customers to still other methods. If you also employ your own provider routing logic, you can continue doing so by using optile's Open Routing functionality and override optile's routing recommendation in the CHARGE request. In any case.

Fail-over payment page: You are using optile's full payment page (optionally with the aforementioned own intelligence or scoring), but you keep your legacy page as a fallback, which you could switch to in case optile was not reachable at some point (which you will hopefully and probably not experience).

In addition to the frontend please keep in mind that in most cases you should have a listener for Status Notifications and other backend processes in place too.

Hybrid & Migration Strategies

If you already have an existing payment provider setup which you want to keep while starting with optile in parallel, then there are multiple ways to achieve this, which we want to present here. They are separated into different aspects of payment provider integration, but we will use the following color coding.

A migration does not have to go through all stages depicted in the diagrams. Typically only one or two stages may be chosen.The stages are just ordered by the deepness of their optile integration to give conceptual orientation.

In the following description, legacy methods means those payment methods that make up your current payment page, i.e., for which you have an existing integration directly with the payment respective provider(s).

Please sign in to view further details of this article. Login

Web Content Display

Hybrid AJAX Page

We offer a simple way to use your existing payment methods (called legacy methods here) and optile powered methods together on a hybrid payment page, using the Selective Native or Display Native integration with the hybrid functionality of our AJAX library.

The idea is that you keep your existing method list, submit button, and logic. With the help of optile's AJAX library you append optile's methods to your payment method list (visually). For optile's methods you use optile's submit logic (also through the AJAX library) which is technically triggered by a separate submit button. However both, your legacy submit button and optile's submit button have exactly the same look and they get interchanged automatically and without user's notice, depending on which payment method is selected. If you prefer, you can also extend your existing submit button instead of having two that interchange. See the variation below step 4 for that option.

In any case you can keep your existing methods and logic. The addition of optile methods will only require one small change in your HTML (step 1), one server-side initialization call against OPG (step 2), and one JavaScript callback function from your side (step 3). Step 4 depends on which buttons you want to use. The rest will be taken care of by optile's AJAX library.

Step-by-Step Guide

1. Integrate optile's payment method list (through its AJAX library)

Integrate optile's AJAX library into your payment page as described in AJAX Library Integration. The placeholder for optile's methods (the paymentNetworks div) should go directly below (or above) your existing method list. Adjust the CSS in a way that the optile method list appears in the same visual style as your legacy list. Hide the radio buttons, add borders, add highlight styling for selected entries using CSS selectors, adjust sizes or whatever else is necessary. In the initialization call to the library add the deselectLegacyMethods function (see step 3.2). The payButton ID identifies the button that should be used for optile methods, not your legacy button (see step 4 how you can spare this and extend your own button instead).

2. Integrate optile's LIST request

In order to initialize optile's payment method list your system first needs to make an (authenticated) LIST request from your server-side to the OPG. This should happen when the user navigates to the payment page. As integration parameter you can use SELECTIVE_NATIVE or DISPLAY_NATIVE.

The resulting LIST ID should then be used to initialize the AJAX library on the payment page. The library will in turn fetch the payment methods available through optile's logic and the corresponding resources, and will render the list into the placeholder from step 1.

3. Combine the lists

Currently we have two lists which both can have one payment method selected. Now we need some logic that makes sure that in total only one method can be selected. This means when the user selects a method in one list, any potential selection in the other list has to be removed.

Let's look at the two cases:

3.1. If the user selects any method from the legacy list make your system call this function in optile's AJAX library: deselectDynamicMethods() - This will remove any existing selection in the optile list. Also it will hide optile's submit button, if it was given in the initialization. Make sure you show your legacy button in this case.

3.2. If the user selects any method from the optile list, the AJAX library will detect this and invoke the deselectLegacyMethods callback function that you indicated in the init call. You should implement this function in a way that is deselects all methods in your legacy list and, if applicable, hides your legacy button. optile's AJAX library will automatically show the optile button, if it was given in the init call.

4. The submit button

If you go with the two button option you have a very clear separation of the submit flows. Make sure both buttons look exactly the same and hide the correct one on page load. Detect when the user selects a legacy method, show your legacy button and invoke optile's JavaScript function from 3.1. which will also hide the optile button. Your callback function from 3.2. should in turn hide your legacy button while optile's AJAX library will show the optile button, if given in the init call.

As a result, a click on the currently visible button will either trigger your existing logic, or it will be an optile submit to OPG.

Variation: Extend your submit button

In case you already have a listener to your submit button you could also extend its logic instead of having a separate optile button.

In this variation you don't have a separate optile button on your payment page, and therefore you don't pass the payButton ID to the AJAX libraries' init call. As a consequence the JavaScript functions from 3.1. and 3.2. would still run as described, making sure only one entry in both payment method lists is selected, but now they don't show or hide submit buttons any more. Reflect this in your implementation of the callback function from 3.2.

The listener on your button, however, now needs to check before data submission, if a legacy or an optile method is selected. In case of a legacy method it can just proceed as before. In case of an optile method it should invoke the AJAX libraries' function: optilePaymentAction()

This will perform a validation first, and on success execute the transaction with OPG. If you want to skip the validation step, you can also call optileOperationAction() instead (which we don't recommend in general).

As a result, there is one button which invokes a different submission logic, depending on the selected method.

This functionality of the AJAX library will be provided within a few weeks after requested by a customer. Please contact us when interested.
AJAX library Initialization call example

$('#paymentNetworks').checkoutList({
  baseUrl: "https://api.sandbox.oscato.com/pci/v1/",
  listId: someVariable,
  deselectLegacyMethods: yourCallbackFunctionName
});

Hybrid AJAX Page

We offer a simple way to use your existing payment methods (called legacy methods here) and optile powered methods together on a hybrid payment page, using the Selective Native or Display Native integration with the hybrid functionality of our AJAX library.

Please sign in to view further details of this article. Login

Web Content Display

Methods & Providers Special Cases

Since most PSPs require hard-coding on the merchant side to integrate different payment methods, we are often asked:

"How do I integrate this method or this provider?"

The answer for optile is in general: Simply stick to the unified flow of the LIST request and CHARGE request (and others as laid out in this documentation) and let your system listen to the Notifications. optile's API unification will make it work for all methods and providers.

You do not have to, and you should not hard code methods or forms in your system (except for Half Native Integration). Instead, include them dynamically as they provided in the LIST responses during runtime. This way, you lower you implementation and maintenance effort and profit from optile's dynamic payment page functionality, which adapts to payment amounts, customers, countries, etc.

Having said that, there are cases where a method or provider requires LIST attributes that are otherwise optional, or has other specifics regarding their technical integration. We try to give you an overview here. Please note, however, that also payment provider APIs can behave differently for different setups, so thorough testing with all combinations of providers and methods is always required.

Web Content Display

3D Secure

Here we walk you through the API flow with 3D Secure enabled provider contracts, looking at optile's LIST and CHARGE Requests, and how they behave in the case of customer cards that are either enrolled or not enrolled with 3D Secure. The examples in this section are based on a test contract from the PSP Wirecard, who provides transparent testing of 3D Secure which is not available with every Payment Provider.

In the following examples we will use a Wirecard sandbox contract with 3D Secure enabled. The following accounts can be used for testing 3D Secure scenarios on Wirecard:

VISA:

Card Number: 4012000300001003
CVV: 003
Expiry Date: Any valid date
3D Secure Password: wirecard
Holder Name: Any

Mastercard:

Card Number: 5413330300001006
CVV: 006
Expiry Date: Any valid date
3D Secure Password: wirecard
Holder Name: Any

Note: The 3D Secure enrolled test accounts are PSP specific, the format and behavior differs very much. Please refer to PSP specific documentation or contact optile support (support@optile.net) to find out 3D Secure testing details with different PSPs.
Step 1: LIST Request

This example illustrates the PURE_NATIVE integration type where a CHARGE request with account information is passed from the merchant's system to the OPG. To ensure that 3D Secure processing is enabled in this example, we explicitly configured a separate division called "3Dsecure" with PSP contracts that have 3D Secure enabled on the PSP side (please contact our support to help you with contract configuration). As an alternative, passing a customerScore in the LIST with values ranging from 0 - 1000 can filter out some contracts depending on the configuration, and enable or disable the security features like 3D Secure check. Passing a low number in the customerScore field should leave only 3D Secure contracts in the routing.

Important: Many PSPs require a customer IP and a user Agent to be passed during a 3D Secure authentication request. That is why it is recommended to fill out the clientInfo object during a LIST request.
LIST Request:
 {
"transactionId": "3d-0001234",
"country": "DE",
"integration": "PURE_NATIVE",
"division": "3Dsecure",
"callback": {
  "returnUrl": "https://dev.oscato.com/demoshop/summary.html",
  "cancelUrl": "https://dev.oscato.com/demoshop/payment-failure.html",
  "notificationUrl": "https://dev.oscato.com/demoshop/optile-notifications"
  },
"customer": {
  "number": "123",
  "email": "buyer123@example.com"
  },
"customerScore": 200,
"clientInfo": {
  "ip": "83.171.174.105",
  "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Gecko/20100101 Firefox/55.0",
  "acceptHeader": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
  },
"payment": {
  "reference": "demoshop 0001234-123",
  "amount": 25.99,
  "currency": "EUR"
  }
}

Response:
 {
"links": {
  "self": "https://api.sandbox.oscato.com/api/lists/59c10807cb425c2661d45481lmn83pf5uk1775tukqc41v52j9"
  },
"timestamp": "2017-09-19T12:05:27.646+0000",
"operation": "LIST",
"resultCode": "00000.11.000",
"resultInfo": "2 applicable and 0 registered networks are found",
"returnCode": {
  "name": "OK",
  "source": "GATEWAY"
  },
"status": {
  "code": "listed",
  "reason": "listed"
  },
"interaction": {
  "code": "PROCEED",
  "reason": "OK"
  },
"identification": {
  "longId": "59c10807cb425c2661d45481lmn83pf5uk1775tukqc41v52j9",
  "shortId": "16244-09875",
  "transactionId": "3d-0001234"
  },
"networks": {
  "applicable": [{
    "code": "VISA",
    "label": "Visa",
    "method": "CREDIT_CARD",
    "grouping": "CREDIT_CARD",
    "registration": "OPTIONAL",
    "recurrence": "NONE",
    "redirect": false,
    "links": {
      "form": "https://resources.sandbox.oscato.com/resource/form/DEMOSHOP/standard.html",
      "logo": "https://resources.sandbox.oscato.com/resource/network/DEMOSHOP/de_DE/VISA/logo.png",
      "self": "https://api.sandbox.oscato.com/api/lists/59c10807cb425c2661d45481lmn83pf5uk1775tukqc41v52j9/VISA",
      "lang": "https://resources.sandbox.oscato.com/resource/lang/DEMOSHOP/de_DE/VISA.properties",
      "operation": "https://api.sandbox.oscato.com/api/lists/59c10807cb425c2661d45481lmn83pf5uk1775tukqc41v52j9/VISA/charge",
      "localizedForm": "https://resources.sandbox.oscato.com/resource/form/DEMOSHOP/DE/de_DE/VISA/standard.html",
      "validation": "https://api.sandbox.oscato.com/pci/v1/59c10807cb425c2661d45481lmn83pf5uk1775tukqc41v52j9/DEMOSHOP/de_DE/VISA/standard/validate"
      },
    "button": "button.charge.label",
    "selected": false
    },
  {
    "code": "MASTERCARD",
     ...
    }]
    },
    "operationType": "CHARGE"
}

Step 2a. CHARGE with enrolled credit card

If the request was successful (interaction.code = PROCEED) and the redirect.url contains a URL that does not lead to one of the "callback" URLs provided during the LIST, it means that the credit card supplied by a customer is 3D Secure enrolled and a PA request is generated.

At this point the merchant's system should redirect the client's browser to a URL from a "redirect" block of CHARGE response using a suggested HTTP "method" and HTTP "parameters". In the example above, these are the POST method and PaReq, TermUrl, and MD parameters. The property suppressIFrame, if set to true, indicates that a redirect cannot be performed within the IFrame: either a full page redirect should be executed or a new window/tab is opened.

This action should result in the rendering of a 3D Secure page by the customer's issuer bank system; in our case that is a Wirecard demo page for 3D Secure check, as shown in the figure below.

The customer is then asked to enter additional validation (SMS-tan, 3D Secure password, etc.) and continue with the payment or cancel the transaction.

In case of Wirecard, the test contract password is: wirecard

If everything was successful, the customer is automatically redirected to the returnUrl of a "callback" from the original LIST request with additional parameters from the OPG system, e.g.:
https://dev.oscato.com/demoshop/summary.html?shortId=10127-51825&interactionReason=OK&resultCode=00000.WIRECARD.0&longId=59c10d47cb427abc123263c9c&transactionId=3d-0001234&interactionCode=PROCEED&amount=25.99&reference=demoshop+0001234-123¤cy=EUR¬ificationId=2436093064195617&referenceId=59c10d47cbabc123be3263c9c×tamp=2017-09-19T14%3A47%3A34.156%2B02%3A00

If a payment has failed (due to 3D Secure check or during Authorization/Capture), the customer is automatically redirected to the cancelUrl of a "callback" from the original LIST request with additional parameters from the OPG system, e.g.:
https://dev.oscato.com/demoshop/payment-failure.html?shortId=08706-31667&interactionReason=INVALID_ACCOUNT&resultCode=45010.WIRECARD.525&longId=59c112b4cb4abc123c1a7a69c&transactionId=3d-0001234&interactionCode=TRY_OTHER_ACCOUNT¬ificationId=2436364692588779&referenceId=59c112b4cb42f93abc123a69c×tamp=2017-09-19T14%3A52%3A05.785%2B02%3A00

CHARGE Request:
POST to VISA operation link from previous LIST response
{
"account": {
  "holderName": "Testy Threed",
  "number": "4012000300001003",
  "expiryMonth": 1,
  "expiryYear": 2019,
  "verificationCode": "003"
  }
}

Response:
{
"links": {
  "self": "https://api.sandbox.oscato.com/api/charges/59c10d47cb427396be3263c9c"
  },
"timestamp": "2017-09-19T12:27:53.844+0000",
"operation": "CHARGE",
"resultCode": "00001.WIRECARD.0",
"resultInfo": "Pending, you have to check the status later",
"pspCode": "WIRECARD",
"returnCode": {
  "name": "OK_PENDING",
  "source": "PSP"
  },
"status": {
  "code": "pending",
  "reason": "debit_requested"
  },
"interaction": {
  "code": "PROCEED",
  "reason": "PENDING"
  },
"identification": {
  "longId": "59c10d47cb427396be3263c9c",
  "shortId": "10127-51825",
  "transactionId": "3d-0001234",
  "pspId": "C660018150582407317218"
  },
"redirect": {
  "url": "https://c3-test.wirecard.com/acssim/app/bank",
  "method": "POST",
  "parameters": [{
    "name": "PaReq",
    "value": "eJxtU9tuozAQfe9XIN6LL2CMI+Oq3ewlD9lNt6kq7RsLo4IacGpgQ/br11CybQIWSMzMGebM+Iy86cqd8wdMXegqdomHXQeqVGdF9Ry7j9sv15Hr1E1SZclOVxC7R6jdG3Ult7kBWD5A2hpQV449cg11nTyDU2Sxy4KQM1/YJ/B5QEUYEOy+4Qbs5vYnvL7bg29koSwJj0p0Ms9BazBpnlTNuXsIJenr3eq7ItQPWCjRaE5xJZjVUjGMMbEvlujNMQVWSQnqqTCQJiZzllBq5yHXe4mGwBSf6rZqzFFF1JY/GVNYa3Yqb5r9AqHD4eAdxgJeqkuJ+uB5x2i+Zblpe3c9R6QrMvV7d0/v//7arF/yFTzpbvuS3f342unt51UsUY+Y5mVJA4piwrEgwiHBgvIF8yUa/DMDL/seFWWeEPjDsZc3hqY5+5H17SlXCIkunDOTbY2xsjwqwSM72pM1BUK3tzLtfyzR/++Lec4PTn76NquptLHa4CwUViyMR4zy0KeM+5QEHPshi3qlDaBZNoWVABGYDHSKSz1I9LGqpfa+Fv29D/tklw2db9s/Ym7rMQ=="
    },
    {
    "name": "TermUrl",
    "value": "https://api.sandbox.oscato.com/decision/WIRECARD/DEMOSHOP/do.html?type=accept&requestId=59c10d4880ae1fa446fb3b6dc"
    },
    {
    "name": "MD",
    "value": ""
    }],
  "suppressIFrame": true
  },
"customer": {
  "number": "123",
  "email": "buyer123@example.com"
  }
}

Step 2b. CHARGE with not enrolled credit card

If the request was successful (interaction.code=PROCEED) and the redirect.url contains a URL that lead to one of the "callback" URLs provided during LIST, it means that the credit card supplied by a customer is not 3D Secure enrolled or cannot be validated via a 3D Secure process at the time and CHARGE was processed without a 3D Secure authentication.

The interaction code may also indicate an issue with the payment; if this is the case and if redirect is present, the redirect.url will lead to cancelUrl from "callback" provided during LIST.

At this point the merchant's system may redirect the client's browser to a URL from the redirect block of CHARGE response using a suggested HTTP "method" and HTTP "parameters" or it may follow any other logic of successful payment processing as it is done during a non-3D Secure flow.

CHARGE Request:
POST to VISA operation link from previous LIST response
{
"account": {
  "holderName": "Testy Threed",
  "number": "4111111111111111",
  "expiryMonth": 1,
  "expiryYear": 2019,
  "verificationCode": "003"
  }
}

Response:
{
"links": {
  "payout": "https://api.sandbox.oscato.com/api/charges/59c117dfcb427396be3263efc/payout",
  "self": "https://api.sandbox.oscato.com/api/charges/59c117dfcb427396be3263efc"
  },
"timestamp": "2017-09-19T13:13:04.615+0000",
"operation": "CHARGE",
"resultCode": "00000.WIRECARD.0",
"resultInfo": "AVS Unavailable.",
"pspCode": "WIRECARD",
"returnCode": {
  "name": "OK",
  "source": "PSP"
  },
"status": {
  "code": "charged",
  "reason": "debited"
  },
"interaction": {
  "code": "PROCEED",
  "reason": "OK"
  },
"clearing": {
  "amount": 25.99,
  "currency": "EUR"
  },
"identification": {
  "longId": "59c117dfcb427396be3263efc",
  "shortId": "10818-81133",
  "transactionId": "3d-0001235",
  "pspId": "C874211150582678450819"
  },
"redirect": {
  "url": "https://dev.oscato.com/demoshop/summary.html",
  "method": "GET",
  "parameters": [{
    "name": "shortId",
    "value": "10818-81133"
    },
    {
    "name": "interactionReason",
    "value": "OK"
    },
    {
    "name": "resultCode",
    "value": "00000.WIRECARD.0"
    },
    {
    "name": "longId",
    "value": "59c117dfcb427396be3263efc"
    },
    {
    "name": "transactionId",
    "value": "3d-0001235"
    },
    {
    "name": "interactionCode",
    "value": "PROCEED"
    },
    {
    "name": "amount",
    "value": "25.99"
    },
    {
    "name": "reference",
    "value": "demoshop 0001235-123"
    },
    {
    "name": "currency",
    "value": "EUR"
    }]
    },
"customer": {
  "number": "123",
  "email": "buyer123@example.com"
  }
}

3D Secure

Here we walk you through the API flow with 3D Secure enabled provider contracts, looking at optile's LIST and CHARGE Requests, and how they behave in the case of customer cards that are either enrolled or not enrolled with 3D Secure. The examples in this section are based on a test contract from the PSP Wirecard, who provides transparent testing of 3D Secure which is not available with every Payment Provider.

Please sign in to view further details of this article. Login

Web Content Display

Amazon

Amazon Pay offers an express checkout experience with specific implementation requirements described under our Express Checkout documentation. Please check this document for instructions on how to integrate this and other express checkout methods.

Other than the specific payment flow for express checkout, Amazon requests that successful or failed order attempts are delivered to the end customer by email. Upon receiving a final status notification from optile, the merchant should build the appropriate email message, which does not need to comply to Amazon design guidelines, but must deliver the success or fail message to the customer. 

Amazon

Amazon Pay offers an express checkout experience with specific implementation requirements described under our Express Checkout documentation. Please check this document for instructions on how to integrate this and other express checkout methods.

Please sign in to view further details of this article. Login

Web Content Display

Installment Payment

Paying with installments comes with special risks. One of the consequences is a two-step form for the user, see ACTIVATE Request for technical details.

IP Address Required

Most installment providers will require the current IP address of the customer, so please provide it in the LIST Request as clientInfo.ip.

Customer Name, Billing and Shipping Addresses

Typically, customer name and addresses are also required.

There are two NetworkConfiguration flags that you can set to not include the corresponding method in the LIST Response under the following circumstances:

  • Exclude for different Shipping and Billing Addresses: If set to true this method will not be displayed if the LIST Request contained both, customer.address.shipping and customer.address.billing explicitly and any of the fields are not equal by string comparison (this includes the case when a field is undefined in one address, but exists in the other).
  • Exclude for different Shipping and Billing Names: If set to true this method will not be displayed if the LIST Request contained both, customer.address.shipping.name and customer.address.billing.name explicitly and any of the fields inside the name objects are not equal by string comparison (this includes the case when a field is undefined in one name object, but exists in the other).

Note: If the Name check excludes the method, also the Address check will exclude it, but not vice versa. In that sense the Address check is more strict. The Name check would still allow a different address as long as the recipient name is equal.

To make use of this feature, be sure to provide the customer name(s) explicitly in the address objects, not in the generic customer.name object.

This configuration can be applied to any other method, too, but for installments it is especially important.

URL to Data Privacy Guideline

In the first step of the installment form the user will give their consent to data privacy guidelines that allow the provider to do checks about the customer with external parties. These guidelines are linked, and this URL needs to be configured on the OPG side. Please contact our support about the dataPrivacyConsentUrl as part of the NetworkConfiguration as long as this option is not available in the portal. We recommend that you provide generic guidelines that fit to any of your providers. If you have only one installment provider you can also use a URL provided by them.

Base URL for Contract PDF

In the second step of the installment form there is a link to a PDF, which officially summarizes the conditions for the user. This is generated by the provider, but to make it more trustworthy, it should come from your domain. Therefore we offer you to configure a Document Proxy Base URL for your Division, e.g.:

http://www.example.com/docs.

The link in the customer form will then point to that URL with a parameter bedu attached. bedu is for base64 encoded document url. This could result in:

http://www.example.com/docs?bedu=aHR0cHM6Ly9yZXNvdXJjZXMubGl2ZS5vc2NhdG8uY29tL3Jlc291cmNlL2RvYy81N2UzOWIyYjQyL2NyZWRpdC5wZGY=

When this URL is requested your server should decode the parameter value from base64, which again contains a URL, in this example:

https://resources.sandbox.oscato.com/resource/doc/57e39b2b42/credit.pdf

From this URL the PDF should be streamed to download for the customer. Note that it is an optile domain, which again acts as a proxy because some installment providers require additional authentication to retrieve the PDF.

If you do not configure your own Document Proxy Base URL, the optile proxy will be used for the link. This is not perfect, because it is an unknown domain for the user, but functionally, it will work.

The bottom line is that we recommend to build your own document proxy. All it has to do is decode the bedu parameter and stream the PDF from whatever URL is encoded there.

Installment Payment

Please sign in to view further details of this article. Login

Web Content Display

Intercard

There are some fields that are mandatory for an Intercard payment (in addition to optile's mandatory fields):

  • Customer#Name#firstName
  • Customer#Name#lastName
  • Mandate#reference
  • Mandate#MandateAuthentication#time

Intercard

Please sign in to view further details of this article. Login

Web Content Display

MuchBetter

When using MuchBetter, the customer is asked to confirm a transaction started on the merchant shop within their proprietary mobile application.

That means that a transaction on MuchBetter will stay on statusCode: pending until the customer logs in the app and approves the payment, and will change to statusCode: charged after confirmation.

By MuchBetter's own implementation guidelines, a merchant is required to include the following message after requesting for a payment:

"Please complete the payment in your MuchBetter app".

On a similar pattern, when implementing payouts a merchant is required to include the following message after request:

"Your funds will be with you shortly".

MuchBetter

When using MuchBetter, the customer is asked to confirm a transaction started on the merchant shop within their proprietary mobile application.

Please sign in to view further details of this article. Login

Web Content Display

Redirect Networks

Classic PayPal, Sofort, and many alternative payment methods are classified as Redirect Networks in the optile terminology.
  • These methods we call redirect networks because to complete the payment your customer has to be redirected to an external page of the corresponding provider.
     
  • For pure redirect methods, your system does not need extra logic to take care of this. In any case it should redirect the customer if a redirect URL is given in the CHARGE Response. This also applies to methods with in-page forms such as cards. In this case the user will be redirected to the successUrl or cancelUrl you provided in the LIST Request.
     
  • In many (but not all) cases these networks do not have an input form that can be displayed directly inside the payment page. You do not need extra logic to cover this. The form snippets provided in the LIST Response should be included as always, they will just be empty.
     

Redirect Networks

Classic PayPal, Sofort, and many alternative payment methods are classified as Redirect Networks in the optile terminology.

Please sign in to view further details of this article. Login

Web Content Display

PayPal

PayPal offers a variety of checkout scenarios that may require some specific implementation to be done by you. We list these corner cases in the examples below.
finalOperation Parameter
  • Deferred payments: A standard Deferred Payment flow comprises of an initial preauthorization step where the initial order amount is approved by the customer, and one or more capture steps up to the total preauthorized amount are issued to close the transaction. Case a merchant wants to signal that a capture is final, no matter if its cumulated value is still below the initial preauthorization, that can be done by passing the parameter finalOperation = true in the request. For example, considering a preauthorization of 20,00 Euro, if a capture of 5,00 Euro is signed with finalOperation = true, no more additional capture steps can be executed. This parameter must be passed in the CLOSING request as shown in the example on the right side. You can also find this parameter documented in our API Reference.
  • Refunds: In a similar fashion as with final capture explained above, a payout operation can also be defined as final via parameter finalOperation. This means that a refund can be marked as final, even though its value is lower than the total captured amount, and no more additional refunds will be allowed. The parameter must be passed in the PAYOUT request body.
Modern PayPal Integration
  • The modern PayPal integration requires a provider-proprietary JavaScript library called checkout.js. Other than handling the payment session, this library also delivers a PayPal-approved payment button which follows their own styling guidelines and must be used by a merchant in order to be completely certified to use PayPal services. You can read about optile's AJAX library handling provider buttons or how to integrate provider buttons natively, in any case following optile's "implement once" abstraction.
Example of marking a partial closing as final

{
"payment": {
  "reference": "order nr. 04842",
  "amount": 5.00,
  "currency": "EUR",
  "invoiceId": "O-21072017/035/0001637"
  },
"finalOperation": true
}

PayPal

PayPal offers a variety of checkout scenarios that may require some specific implementation to be done by you. We list these corner cases in the examples below.

Please sign in to view further details of this article. Login

Web Content Display

SEPA and BACS Direct Debit

SEPA (or BACS in the UK) offers a direct debit payment scheme used across Europe. When integrating this method, a merchant requests a mandate from its customer, which is used as authorization to collect payments via direct debit from the customer bank account. We give details for the integration of this method below.
  • Your system should generate and send additional information about the mandate (e.g., the proposed mandate reference) in the LIST or CHARGE Request (via the mandate parameter structure). Please note that the mandate reference should be shorter than 35 characters and alpha numeric.
  • The existing mandate information should also be sent when requesting Recurring Charges.
  • You should include in the payment.reference parameter a message in the format "Shop-URL, Shop-Hotline/Support e-mail, and transaction ID". See example in the right pane.
  • In the CHARGE Response and Status Notification your system will receive the final mandate values being used by the PSP for this transaction (because depending on your contract it may use its own values).

More information about the Mandate:

Mandate {

reference (string): 

The SEPA mandate reference (aka Mandate ID) proposed by the merchant has to be unique in the scope of the merchant's creditorId

creditorId (string, optional): 

The SEPA creditor ID of the merchant  could also be configured for some PSPs within a contract which is optional. In case when a PSP uses its own creditor ID, it will be returned in the reply and the status notification

authentication (MandateAuthentication, optional):  Required by some PSPs for SEPA transactions

Below we present a generic diagram for the payment flow:

Payment Sequence Diagram - SEPA
Example Mandate Reference

{
  "transactionId": "93acf8c4-dbb3-411c-b9fb-abc123c3f7aa",
  "country": "DE",
  "channel": null,
  "division": null,
  "callback": {
    "returnUrl": "https://dev.oscato.com/shop/success.html",
    "cancelUrl": "https://dev.oscato.com/shop/cancel.html",
    "notificationUrl":"https://dev.oscato.com/shop/notify.html",
    "summaryUrl": null
  },
  "customer": {
    "number": "123ABC",
    "email": "john.doe@example.com",
    "birthday": null,
    "name": {
      "title": null,
      "firstName": "FIRST_NAME",
      "middleName": null,
      "lastName": "SECOND_NAME",
      "maidenName": null
    },
    "addresses": null,
    "phones": null,
    "registration": null
  },
  "clientInfo": null,
  "payment": {
    "reference": "www.shop.com, contact support@shop.com - TiD 123456789",
    "amount": 89,
    "currency": "EUR",
    "invoiceId": null,
    "longReference": null
  },
  "products": null,
  "updateOnly": false,
  "presetFirst": false,
  "style": {
    "language": "en",
    "theme": null,
    "cssOverride": null,
    "client": null
  },
  "preselection": {
    "deferral": "ANY"
  },
  "extraElements": null,
  "mandate": {
    "reference": "Authorization for shop.com",
    "creditorId": null,
    "authentication": {
      "time": "543836748822",
      "city": null
    }
  },
  "installment": null
}

SEPA and BACS Direct Debit

SEPA (or BACS in the UK) offers a direct debit payment scheme used across Europe. When integrating this method, a merchant requests a mandate from its customer, which is used as authorization to collect payments via direct debit from the customer bank account. We give details for the integration of this method below.

Please sign in to view further details of this article. Login

Web Content Display

Interac2Pay

Interac2Pay is a Redirect Network with some specific features. It's important to know that the Provider requires to open their page in form of pop-up widget.

For Interac e-transfer method there are several specific mandatory parameters:

  • Customer email-address
  • Customer first name
  • Customer last name
  • Mobile phone number (for credit operation)

If you are using one of the Native Integration scenarios it's necessary to make some implementation adjustments in order to support this network.

  • Check the CHARGE response's parameter displayInPopup. If this parameter is 'true', the redirect page has to be opened in pop-up mode.
  • For the Inteac e-transfer method there is no redirection to success URLs implemented by the Provider. The customer is supposed to close the pop-up provider's page and by default they will land on the same page where the "Pay" button is placed. If there is a redirection to success page is required, you have to implement this action yourself.

According to Interac certification requirements there is a potential possibility to change the payment amount on online-banks side, so they require the Merchant to be aware of this risk and to check the payment amount received back from the online-bank.

In the status notifications there are two payment amounts passed for Interac provider:

  • Amount – original payment amount,
  • Clearing amount – payment amount received from Interac after payment was completed in online-bank

Please be informed that Clearing amount car differ from original Amount.

Example redirect block of LIST Response
{
"redirect": {
"url": "https://interac.express-connect.com/webflow?transaction=5bbf0f67b55f285...",
"method": "GET",
"displayInPopup": true
}
}

Interac2Pay

Please sign in to view further details of this article. Login

Web Content Display

Worldpay

When using Worldpay as a PSP, make sure to pass the clientinfo in the LIST Request.

Mandatory Parameter for WorldPay

  ...,
  "clientInfo": {
    "ip": "string",
    "userAgent": "string",
    "acceptHeader": "string"
  }, ...

Worldpay

Please sign in to view further details of this article. Login

Web Content Display

Compatibility

optile software for usage by clients' users, systems, or end customers is designed to support the following web browsers and technical standards.

Supported web browsers:

  • Internet Explorer: Version 9 and higher
  • Firefox, Chrome, Edge, Safari: Current and one previous version

Mobile apps for iPhone are designed to support iOS 4 and greater.

optile APIs do support TLS 1.2 or greater.

Usage of any other web browsers, mobile operating systems, or cryptographic protocols may lead to decreased or no functionality.

Compatibility is subject to change in the course of general technological progress.

Compatibility

optile software for usage by clients' users, systems, or end customers is designed to support the following web browsers and technical standards.

Please sign in to view further details of this article. Login

Web Content Display

Enterprise Features

For Enterprise merchants we offer additional functionality. Please note that access to these features requires corresponding contracts and has to be enabled explicitly by optile. Please contact us if you want to access this functionality.

Web Content Display

Open Routing

In some cases, a merchant needs to control the routing behaviour during a payment session, not relying on the OPG's calculated routing priority (as configured via the merchant portal), but being able to programatically define custom rules for routing on their side. This is possible in Pure Native integration scenarios, with or without Client Side Encryption, by passing routing information in the CHARGE request.

LIST Request

A LIST request (POST, GET or PUT) with the additional view=routes query parameter will trigger Open Routing information for each applicable or registered network in the LIST response.

For example, a LIST request (POST) could look like: https://api.sandbox.oscato.com/api/lists?view=routes

The following rules must be respected when using routes with the view parameter:

  • If routes is present, the route information is returned in the LIST response.
  • If there are conflicting or unknown arguments like view=routes,-routes or view=abc, the request will fail as invalid. Note that open routing can be combined with other features, such as JSON Forms.
  • If there is any query parameter present other than view, it will be ignored.

The LIST response orders routes by priority according to the currently configures routing strategy. This means the first route is the one that would be tried first if a normal CHARGE was executed. Every route in this context contains the data as given in the example in the right pane, namely:

  • Contract identification, including adapter and provider codes;
  • Cost information as defined via configuration in the contracts app in the merchant portal.
Example LIST Response
{
...
"networks": {
  "applicable": [{
    "code": "MASTERCARD",
    ...
    "routing": {
      "strategy": "LEAST_COST",
      "routes": [
      {
	"contract": {
	  "id": "5a55e5780d9c031b6c5c6f5a",
	  "providerCode": "EMERCHANTPAY",
	  "adapterCode": "EMERCHANTPAY"
	},
	"costs": {
	  "normalized": 0.1,
	  "original": {
	  "amount": 0.1,
	  "currency": "EUR"
	  }
        }
      }]
    }
...
}

CHARGE Request

During CHARGE a merchant can specify the routes to be used. Additionally to the usually required parameters, one or more routes found in the LIST response should be added as seen in the example in the right pane.

Since this not something to be manipulated by the end customer, a corresponding CHARGE needs to come from a merchant server system, therefore a Pure Native integration scenario (with or without Client Side Encryption) is required.

This is how the OPG will behave when using Open Routing during a CHARGE operation:

  • If no routing list is passed, or it is null, then the routing priority from OPG will be used.
  • If the list is empty, then no processing will take place, and the response Interaction Code will be: ABORT - INVALID_REQUEST
  • Only the passed routes will be considered for processing, in the order in which they were given.
  • Routes are identified by contract.id, like is shown in the example. If the contract.id doesn't exist at OPG, there will be an error with interaction codes ABORT - INVALID_REQUEST.
  • adapterCode and providerCode are optional inside the contract object. If any of them is passed, they need to match the configured contract. Otherwise there will be an error (and no route fallback) with interaction codes: ABORT - INVALID_REQUEST.
  • The costs data within a route can be optionally passed, but it will be ignored.
Example of CHARGE body:
{
"account": {
  "holderName": "John Doe",
  "number": "42551111111114444",
  "verificationCode": "123",
  "expiryMonth": "12",
  "expiryYear": "2019"
  },
"autoRegistration": true,
"routes": [{
    "contract": {
      "id": "33f4b0d039272d1825ec38a0",
      "adapterCode": "ADYEN-JSON",
      "providerCode": "ADYEN"
    },
    "costs": {
      "normalized": 0.06,
      "original": {
        "amount": 0.07,
        "curency": "GBP"
      }
    }
  },
  {
    "contract": {
      "id": "54f9b03ce4b0d039272d1825"
    }
  }
]}

Open Routing

In some cases, a merchant needs to control the routing behaviour during a payment session, not relying on the OPG's calculated routing priority (as configured via the merchant portal), but being able to programatically define custom rules for routing on their side. This is possible in Pure Native integration scenarios, with or without Client Side Encryption, by passing routing information in the CHARGE request.

Please sign in to view further details of this article. Login