API Reference

Save COF - CNP - Adyen

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

Overview

COF is very similar to other CNP requests. Two additional parameters are required when the payment is crated and the token will be returned with the Auth call in the payment_method_id field.

A normal CNP will not allow an amount < $0.50, but when saving a card on file, CNP will allow the amount to be zero.

If you've already successfully implemented CNP, you can skip to step 3 where the two additional parameters: external_customer_id and allow_saving_card.

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.

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.

Step 1: 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.
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.

Step 2: 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 will need to contact us to get a clientKey.

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');
});

Step 3: 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",
    "external_customer_id": "cust_12345",
    "allow_saving_card": true
}

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

Step 4: 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",
    "billing_address": {
      "zip": "59085"
    }
}

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.

The token for Card on File will be returned in the payment_method_id field.

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
This means your website is not on the whitelist. We'll need to add the domain to the whitelist.

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.