API Reference

Payments (CNP) Adyen

Card-Not-Present payments done manually either from the POS or eCommerce checkout using Adyen as the processor.

Overview

We currently do not have our own JavaScript library that will abstract functionality for each processor, so you will need to implement client side JS functionality using the processors web components. This section is for card-not-present (CNP) / eCommerce payment processing. These elements do not require you to be PCI compliant and do not require any handling of credit card data on your part. You can find the documentation here: https://docs.adyen.com/payment-methods/cards/custom-card-integration

Basic Example using their Custom Card Integration

Here is a very simple example of the flow for a customer checking out from a web page or hand keying the information from your POS system.

Whitelist Domains

Adyen requires us to whitelist every domain that will be using their web components. This can be done using the following API endpoint. Localhost is not allowed and the page must have SSL.
https://quilt-payment-api.readme.io/reference/approvedomain-1
For every domain that you would like to work with the web component (this would probably be your eCommerce checkout page and your POS manual card entry) you'll need to add via this call.

Initialize the Adyen Component

Make sure to include Adyens JavaScript library and CSS. The links are below.

<script src="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.29.0/adyen.js"
     integrity="sha384-V7uOD/4bQuWLJRCDSfc60tVzD6rYW5BkkY3GYnaFjgg/guMih1Kx6N5Vo9dBtN3y"
     crossorigin="anonymous"></script>

<link rel="stylesheet"
     href="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.29.0/adyen.css"
     integrity="sha384-jAG16Mh+vYdXeyWKqPqL7chbdFT1aS5qjt/8jGJz5vBrI1RJ3m6/uFfMZt8li/rT"
     crossorigin="anonymous">
<script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/5.29.0/adyen.js"
     integrity="sha384-V7uOD/4bQuWLJRCDSfc60tVzD6rYW5BkkY3GYnaFjgg/guMih1Kx6N5Vo9dBtN3y"
     crossorigin="anonymous"></script>

<link rel="stylesheet"
     href="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/5.29.0/adyen.css"
     integrity="sha384-jAG16Mh+vYdXeyWKqPqL7chbdFT1aS5qjt/8jGJz5vBrI1RJ3m6/uFfMZt8li/rT"
     crossorigin="anonymous">

You will need to create a DIV with a few key HTML elements to hold the place holders for the Adyen components.

<div id="adyen-container">
    <label>
        <span>Card number:</span>
        <span data-cse="encryptedCardNumber"></span>
    </label>
    <label>
        <span>Expiry date:</span>
        <span data-cse="encryptedExpiryDate"></span>
    </label>
    <label>
        <span>CVV/CVC:</span>
        <span data-cse="encryptedSecurityCode"></span>
    </label>
</div>

You'll then need to initialize the component. The following JavaScript is a basic example of how to initialize the Adyen component. For more information refer to their documentation. You can find your clientKey in the payment portal under the Developers menu, Developer Info. Note, if you do not specify the brands below, the default is ['mc', 'visa', 'amex']

const configuration = {
    environment: 'test', // Change to 'live' for the live environment.
    clientKey: 'test_key_contact_us_for_you_key',
    locale: 'en_US',
    onChange: (state) => {
        console.info(state);
    },
    onError: (error, component) => {
        console.error(error.name, error.message, error.stack, component);
    },
};

AdyenCheckout(configuration).then(checkout => {
    this.checkout = checkout.create('securedfields', {
        // Optional configuration
        type: 'card',
        brands: ['mc', 'visa', 'amex', 'discover'],
        styles: {
            error: {
                color: 'red'
            },
            validated: {
                color: 'green'
            }
        },
        onBrand: data => {
            this.cardBrand = data.brand !== 'card' ? data.brand : '';
            this.cardImage = data.brandImageUrl;
        },
        onError: data => {
            console.log('error');
            console.log(data);
        },
    }).mount('#adyen-container');
});

Get Payment Intent

You will need to create a payment intent either server side or client-side by calling the Payment CREATE API endpoint. https://quilt-payment-api.readme.io/reference/createpaymentintent-1

// POST /v1/payment/intent
{
    "external_account_id": "account_123456",
    "amount": 12.99,
    "payment_method_types": "card",
    "capture_method": "automatic",
    "external_transaction_id": "transaction_123456"
}

This will return a result that has a payment_id and you'll need this id to authorize the payment.

Collect Payment

In order to authorize the payment, you will need to check the value of the web component to see if it has a valid card number, expiration and CVV. This data is updated with the onChange event. When the card information is valid, you will need to make a request to the Payment AUTH endpoint to complete the payment.
https://quilt-payment-api.readme.io/reference/authpayment-1

// POST /v1/payment/auth
{
    "external_account_id": "account_123456",
    "payment_id": "pi_12345",
    "amount", "24.99",  
    "external_payment_id", "your_id_for_the_transaction",  
    "card_number": "this.checkout.data.paymentMethod.encryptedCardNumber",
    "card_month_exp": "this.checkout.data.paymentMethod.encryptedExpiryMonth",
    "card_year_exp": "this.checkout.data.paymentMethod.encryptedExpiryYear",
    "card_cvv": "this.checkout.data.paymentMethod.encryptedSecurityCode"
}

If this call completes successfully, then the payment is authorized. If the capture_method on the payment intent was "automatic" then this payment will be automatically captured. If it was "manual", then the payment will need to be captured either through the portal or through the capture API.

Please note - this is a very basic example. Many more advanced scenarios are supported. Please refer to the Adyen documentation for more details.

Testing

There are test card numbers from Adyen CNP: https://docs.adyen.com/development-resources/testing/test-card-numbers/#test-address-verification-system-avs

Addresses

Submit all the information you have on a customer. More information can reduce the costs associated with a payment and reduce the risk of chargebacks from fraud.

When submitting address data with a CNP transaction there is a level of validation done to see if the address "looks" valid before sending it to the processor. If you submit an address with a US country, the address fields need to resemble an actual US address. The best way to avoid getting stopped by these checks is to use a valid US address.

Troubleshooting

I don't see the web components on my page
Make sure you have the correct HTML elements an that the ID in the .mount method is correct.

I'm getting CORS errors when loading the JS and CSS files from Adyen
Make sure you are running on a web server (Apache, Tomcat, IIS, etc) and not just in a local editor or from the file system.

I'm getting "Invalid Origin" on my web components
There are several reasons for this error. Ensure that 1) The page has SSL. 2) The domain must be on the approved list. 3) The domain isn't valid. It can't be used on localhost.

My transaction is refused because "Expiry Incorrect"
This Adyen component only accepts tests cards with an expiration of 2030 or later. One card that works is 411111111111 with the date 03/30 and three digit code: 737.