Search

Are you looking for test card numbers?

Would you like to contact support?

Point-of-sale icon

Shopper recognition and tokenization

Link transaction details to a shopper for insights, shopper engagement, and tokenization.

Connecting shopper identifiers with transaction details enables:

  • Passive shopper recognition: Gain insights to grow your business.
    For example, shopper origin data can help you to decide if you should accept new payment methods, offer currency conversion on your terminals, add signage in other languages in your shop, and so on.

  • Active shopper recognition: Engage recognized shoppers by personalizing their shopping experience.
    You can apply this after a payment, for example to add points to the shopper's loyalty account. Or you can apply this before a payment, for example to award a discount or a loyalty gift on the spot.

  • Tokenization for recurring online payments.
    You could use this when cross-selling products that require regular payments, such as an insurance policy for a product that the shopper bought in your store.

All this is especially powerful across channels. See our Unified commerce documentation for more information and use cases.

Shopper identifiers and customer profiles

Card acquisition and payment requests can return several shopper identifiers that you can use for passive and active shopper recognition and tokenization:

  • Card alias: A value that uniquely represents the shopper's card number (PAN), for example A37317672402294. With this, you can recognize the cards that are used for purchases made in your store.
  • Issuer country: Country code of the country where the card was issued. This is usually a good indicator of the shopper's nationality.
  • Funding source: Funding source of the card, for example debit or credit. For all possible values, refer to Funding source.
  • Shopper reference: A unique reference defined by you. This allows you to identify the shopper when they make a purchase. If you also collect the shopper's email address, you can link multiple card aliases to the same shopper through their email address.
  • Recurring detail reference: The token for recurring payments. For these payments, the shopper doesn't need to be present but the card alias must be linked to the shopper's email address. For more information, see our Tokenization documentation.

It is up to you which of these identifiers you want to use. For example, for passive shopper recognition you may want to run analyses on card alias and issuer country data. For active shopper recognition, you will want to create a customer profile for each shopper with their identifiers and transaction details. In this way you'll be able to tie a new payment with earlier payments made with the same card or by the same shopper, and offer loyalty rewards.

Before you begin

Before you start linking card details to shoppers:

  1. Make sure that you have built an integration that can make a payment.
  2. Consider how you will handle the privacy implications of storing customer data.
  3. Set up a Customer Relationship Management System (CRM) or other database for storing customer data.

Managing customer data and privacy

Before storing any customer data, including their tokenized payment method, you should consult the local laws and regulations in countries that you operate in. You should also ask for your customer's explicit permission to store this data, and be clear about what you intend to use it for.
If the customer asks to remove their information, you can use our Data Protection API to remove any customer-related data that you have stored with Adyen. The API also enables you to comply with the General Data Protection Regulation (GDPR) right to erasure mandate.

Enable receiving shopper identifiers

  1. In your Customer Area, go to Account > API URLs and on the Additional data settings tab select these options depending on what you want to achieve:

    Purpose Recurring details Recurring contract type issuerCountry Funding source
    Passive shopper recognition -white_check_mark- -white_check_mark-
    Active shopper recognition -white_check_mark- -white_check_mark- -white_check_mark- -white_check_mark-
    Tokenization -white_check_mark- -white_check_mark- -white_check_mark- -white_check_mark-

    Terminal API returns these data in the AdditionalResponse.

  2. Optionally receive shopper identifiers in notification webhooks as well:

    1. Set up notification webhooks.
    2. Contact our POS Support Team and ask them to ensure the card alias is included in the notification.

Passive shopper recognition

With passive shopper recognition, the payment responses and optionally the notification webhooks return the card alias, issuer country, and funding source related to a payment. You can then use these data to gain insights. For example, insights in the number of return shoppers, or where your customer base comes from.

After you have enabled receiving the issuer country and funding source in the payment response:

  1. Make a PaymentRequest with:

    Parameter Required Description
    SaleData.TokenRequestedType Customer. This returns the card alias in the TokenValue field of the response. If you do not include the TokenRequestedType field, the card alias is returned only in the AdditionalResponse.
    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"01142",
                "POIID":"V400m-346403161"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"12420",
                        "TimeStamp":"2020-01-07T14:15:25.114Z"
                    },
                    "TokenRequestedType":"Customer"
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":24.98
                    }
                }
            }
        }
    }
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
        String saleID = "YOUR_CASH_REGISTER_ID";
        String POIID = "YOUR_TERMINAL_ID";
        String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
        SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
        MessageHeader messageHeader = new MessageHeader();
        messageHeader.setProtocolVersion("3.0");
        messageHeader.setMessageClass( MessageClassType.SERVICE );
        messageHeader.setMessageCategory( MessageCategoryType.PAYMENT );
        messageHeader.setMessageType( MessageType.REQUEST );
        messageHeader.setServiceID(serviceID);
        messageHeader.setSaleID(saleID);
        messageHeader.setPOIID(POIID);
        saleToPOIRequest.setMessageHeader(messageHeader);
    
        PaymentRequest paymentRequest = new PaymentRequest();
        SaleData saleData = new SaleData();
        saleData.setTokenRequestedType( TokenRequestedType.CUSTOMER );
        TransactionIdentification saleTransactionID = new TransactionIdentification();
        saleTransactionID.setTransactionID(transactionID);
        saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
        saleData.setSaleTransactionID(saleTransactionID);
        paymentRequest.setSaleData(saleData);
    
        PaymentTransaction paymentTransaction = new PaymentTransaction();
        AmountsReq amountsReq = new AmountsReq();
        amountsReq.setCurrency("EUR");
        amountsReq.setRequestedAmount( BigDecimal.valueOf(24.98) );
        paymentTransaction.setAmountsReq(amountsReq);
        paymentRequest.setPaymentTransaction(paymentTransaction);
    
        saleToPOIRequest.setPaymentRequest(paymentRequest);
        terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    In the payment response, note the following (you may need to Base64-decode the AdditionalResponse string first):

    • PaymentToken.TokenValue: The card alias.
    • PaymentInstrumentData.CardCountryCode: The ISO numeric country code for the card issuer.
    • Response.AdditionalResponse: The card alias, funding source, and ISO numeric and alpha country code for the card issuer.
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {...},
                "SaleData": {
                    "SaleTransactionID": {
                        "TimeStamp": "2020-11-05T09:48:14.889Z",
                        "TransactionID": "916"
                    }
                },
                "PaymentReceipt": [...],
                "PaymentResult": {...},
                    "PaymentInstrumentData": {
                        "CardData": {
                            "EntryMode": [
                                "Contactless"
                            ],
                            "PaymentToken": {
                                "TokenRequestedType": "Customer",
                                "TokenValue": "M469509594859802"
                            },
                            "PaymentBrand": "mc",
                            "MaskedPan": "541333 **** 9999",
                            "CardCountryCode": "826",
                            "SensitiveCardData": {
                                "CardSeqNumb": "33",
                                "ExpiryDate": "0228"
                            }
                        },
                        "PaymentInstrumentType": "Card"
                    },
                    "AmountsResp": {
                        "AuthorizedAmount": 24.98,
                        "Currency": "EUR"
                    }
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "...alias=M469509594859802...&cardIssuerCountryId=826...&fundingSource=CREDIT&issuerCountry=GB..."
                }
            },
            "MessageHeader": {...}
        }
    }
  2. In your system, store the transaction data for analysis.

Active shopper recognition

Making a card acquisition request before making a payment request allows you to actively engage the shopper both on the spot and after the transaction. For example, if you recognize the shopper from the card acquisition, you can apply a discount, offer a gift, add points to the shopper's loyalty account, or ask the shopper whether they want to redeem loyalty points.

After you have enabled receiving shopper identifiers:

  1. You make a card acquisition request to check whether the shopper is recognized.
  2. If the card acquisition response indicates the shopper isn't known yet, you create a new customer profile and make a payment with a shopper reference of your choice.
    From now on, you can recognize the shopper by the shopper reference returned in Terminal API responses.
  3. If the card acquisition response indicates the shopper is already known, you make a payment for a recognized shopper.

Check whether the shopper is recognized

When the shopper makes a purchase, first check if you already know the shopper.

  1. Make a CardAcquisitionRequest with:

    Parameter Required Description
    TokenRequestType Customer This returns the card alias in the TokenValue field of the response. If you do not include the TokenRequestedType, the card alias is returned only in the AdditionalResponse.
    CardAcquisitionTransaction -white_check_mark- This object is empty, or contains:
    • TotalAmount: The transaction amount.
    If you expect the amount to change in most cases, you can choose to omit TotalAmount.
    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"CardAcquisition",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"1020711110",
                "POIID":"V400m-346403161"
            },
            "CardAcquisitionRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"02072",
                        "TimeStamp":"2020-01-07T14:14:04+00:00"
                    },
                    "TokenRequestedType":"Customer"
                },
                "CardAcquisitionTransaction":{
                    "TotalAmount":24.98
                }
            }
        }
    }
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
    String saleID = "YOUR_CASH_REGISTER_ID";
    String POIID = "YOUR_TERMINAL_ID";
    String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
    SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
    MessageHeader messageHeader = new MessageHeader();
    messageHeader.setProtocolVersion("3.0");
    messageHeader.setMessageClass( MessageClassType.SERVICE );
    messageHeader.setMessageCategory( MessageCategoryType.CARD_ACQUISITION );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setServiceID(serviceID);
    messageHeader.setSaleID(saleID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    CardAcquisitionRequest cardAcquisitionRequest = new CardAcquisitionRequest();
    SaleData saleData = new SaleData();
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTransactionID(transactionID);
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleData.setSaleTransactionID(saleTransactionID);
    saleData.setTokenRequestedType( TokenRequestedType.CUSTOMER );
    cardAcquisitionRequest.setSaleData(saleData);
    
    CardAcquisitionTransaction cardAcquisitionTransaction = new CardAcquisitionTransaction();
    cardAcquisitionTransaction.setTotalAmount( BigDecimal.valueOf(24.98) );
    cardAcquisitionRequest.setCardAcquisitionTransaction(cardAcquisitionTransaction);
    saleToPOIRequest.setCardAcquisitionRequest(cardAcquisitionRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    In the CardAcquisitionResponse, note the following:

    • POIData.POITransactionID: The TimeStamp and TransactionID of this card acquisition request. You will need these data later when you continue with the payment.
    • PaymentInstrumentData.CardData.PaymentToken.TokenValue: The card alias. The alias is also included in the Response.AdditionalResponse.
    Card acquisition response
    {
        "SaleToPOIResponse": {
            "CardAcquisitionResponse": {
                "POIData": {
                    "POITransactionID": {
                        "TimeStamp": "2020-01-17T14:14:48.000Z",
                        "TransactionID": "8ha5001579009268002"
                    },
                    "SaleData": {...}
                },
                "PaymentInstrumentData": {
                    "CardData": {
                        "PaymentToken": {
                            "TokenRequestedType": "Customer",
                            "TokenValue": "M469509594859802"
                        },
                        ...
    "PaymentBrand": "mc",
                        "MaskedPan": "541333 **** 9999",
                        "SensitiveCardData": {
                            "ExpiryDate": "0228"
                        }
                    },
                    "PaymentInstrumentType": "Card"
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "tid=46403161&transactionType=GOODS_SERVICES&backendGiftcardIndicator=false&posadditionalamounts.originalAmountValue=2370&expiryYear=2028&alias=M469509594859802&posAmountGratuityValue=0&giftcardIndicator=false&paymentMethodVariant=mc&txtime=17%3a34%3a33&iso8601TxDate=2020-01-08T16%3a34%3a33.0000000%2b0000&cardType=mc&posOriginalAmountValue=2370&aliasType=Default&txdate=08-01-2020&paymentMethod=mc&merchantReference=02076&expiryMonth=02&cardSummary=9999&posadditionalamounts.originalAmountCurrency=EUR&posAuthAmountCurrency=EUR&posAmountCashbackValue=0&posEntryMode=CLESS_CHIP&fundingSource=CREDIT&cardScheme=mc&cardBin=541333&posAuthAmountValue=2370"
                }
            },
            "MessageHeader": {...}
        }
    }
  2. Check whether the AdditionalResponse string from the card acquisition response contains a shopperReference.

Create a new customer profile and make a payment

When the card acquisition response shows the shopper isn't known yet, you continue with a payment request that refers to the card acquisition request and also creates shopper identifiers.

  1. Depending on your business logic, ask if the shopper wants to enroll in your loyalty program, collect their email address, and so on. Make sure you also collect your shopper's consent to store their data.
    You could make input requests to collect this information from the shopper on the terminal, or let your staff enter the information in your cash register software.

  2. Make a PaymentRequest with:

    Parameter Required Description
    SaleData.SaleToAcquirerData Data to create shopper identifiers.

    See the instructions below.

    SaleData.TokenRequestedType Customer. This returns the card alias in the TokenValue field of the response. If you do not include the TokenRequestedType, the card alias is returned only in the AdditionalResponse.
    PaymentData.CardAcquisitionReference -white_check_mark- An object referencing the card acquisition:
    • TimeStamp: The timestamp returned in the POIData.POITransactionID of the card acquisition response.
    • TransactionID: The transaction ID returned in the POIData.POITransactionID of the card acquisition response.

    In SaleData.SaleToAcquirerData you can include:

    • shopperEmail: The shopper's email address, if you collected that in the first step.
    • shopperReference: Your unique reference for this shopper.

      At this point, you could additionally tokenize the payment.

    Pass the SaleToAcquirerData value in one of the following formats:

    • Option 1: A JSON object converted to a Base64 encoded string. Refer to Add information to a payment.
    • Option 2: Form-encoded key-value pairs (using & as a separator). For example:
      shopperEmail=S.Hopper@example.com&shopperReference=12345

    The format that you use here, will also be the format of the AdditionalResponse that you receive.

    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"01142",
                "POIID":"V400m-346403161"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"12420",
                        "TimeStamp":"2020-01-07T14:15:25.114Z"
                    },
                    "SaleToAcquirerData":"shopperEmail=S.Hopper@example.com&shopperReference=YOUR_UNIQUE_SHOPPER_ID",
                    "TokenRequestedType":"Customer"
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":24.98
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TimeStamp": "2020-01-17T14:14:48.000Z",
                        "TransactionID": "8ha5001579009268002"
                    }
                }
            }
        }
    }
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
    String saleID = "YOUR_CASH_REGISTER_ID";
    String POIID = "YOUR_TERMINAL_ID";
    String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
    SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
    MessageHeader messageHeader = new MessageHeader();
    messageHeader.setProtocolVersion("3.0");
    messageHeader.setMessageClass( MessageClassType.SERVICE );
    messageHeader.setMessageCategory( MessageCategoryType.PAYMENT );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setServiceID(serviceID);
    messageHeader.setSaleID(saleID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    PaymentRequest paymentRequest = new PaymentRequest();
    SaleData saleData = new SaleData();
    saleData.setSaleToAcquirerData("shopperEmail=s.hopper@example.com&shopperReference=YOUR_UNIQUE_SHOPPER_ID_IOfW3k9G2PvXFu2j");
    saleData.setTokenRequestedType( TokenRequestedType.CUSTOMER );
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTransactionID(transactionID);
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleData.setSaleTransactionID(saleTransactionID);
    paymentRequest.setSaleData(saleData);
    
    PaymentTransaction paymentTransaction = new PaymentTransaction();
    AmountsReq amountsReq = new AmountsReq();
    amountsReq.setCurrency("EUR");
    amountsReq.setRequestedAmount( BigDecimal.valueOf(24.98) );
    paymentTransaction.setAmountsReq(amountsReq);
    paymentRequest.setPaymentTransaction(paymentTransaction);
    
    PaymentData paymentData = new PaymentData();
    TransactionIdentification cardAcquisitionReference = new TransactionIdentification();
    cardAcquisitionReference.setTransactionID(transactionID);
    cardAcquisitionReference.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    paymentData.setCardAcquisitionReference(cardAcquisitionReference);
    paymentRequest.setPaymentData(paymentData);
    saleToPOIRequest.setPaymentRequest(paymentRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    In the PaymentResponse, note the following (you may need to Base64-decode the AdditionalResponse string first):

    • PaymentToken.TokenValue: The card alias.
    • The shopper identifiers in the Response.AdditionalResponse:
      • alias: The card alias.
      • shopperReference: Your unique reference for this shopper that you specified in the request.
      • shopperEmail: The shopper's email address that you specified in the request.
    Response showing the shopperReference you created
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {...},
                "SaleData": {...}
                "PaymentReceipt": [...],
                "PaymentResult": {
                    ...
                    "PaymentInstrumentData": {
                        "CardData": {
                            "EntryMode": [
                                "Contactless"
                            ],
                        "PaymentToken": {
                            "TokenRequestedType": "Customer",
                            "TokenValue": "M469509594859802"
                        },
                        "PaymentBrand": "mc",
                        "MaskedPan": "541333 **** 9999",
                        "SensitiveCardData": {
                            "CardSeqNumb": "83",
                            "ExpiryDate": "0228"
                        }
                    },
                    "PaymentInstrumentType": "Card"
                },
                "AmountsResp": {
                    "AuthorizedAmount": 24.98,
                    "Currency": "EUR"
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "...&alias=M469509594859802...&shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40gmail.com..."
                }
            },
            "MessageHeader": {...}
        }
    }

    The shopper identifiers for this shopper are now stored on the Adyen payments platform.

  3. In your system, create a customer profile for the shopper and store the shopper identifiers that you received in the payment response.
  4. Also store the transaction data with the shopper's customer profile, to start building a transaction history for the shopper.

Make a payment for a recognized shopper

When the card acquisition response shows the shopper is known already, you follow up with a payment request that refers to the card acquisition.

  1. Using the shopperReference you received in the card acquisition response, find the shopper in your system.
  2. Depending on your business logic, decide if you want to apply a discount, offer a gift, and so on. If necessary, update the final transaction amount accordingly.
  3. Make a PaymentRequest with:

    Parameter Required Description
    SaleData.TokenRequestedType Customer. This returns the card alias in the TokenValue field of the response. If you do not include the TokenRequestedType field, the card alias is returned only in the AdditionalResponse.
    PaymentTransaction.AmountsReq -white_check_mark- An object with:
    • Currency: The transaction currency.
    • RequestedAmount: The final transaction amount.
    PaymentData.CardAcquisitionReference -white_check_mark- An object containing data from the card acquisition:
    • TimeStamp: The timestamp returned in the POIData.POITransactionID of the card acquisition response.
    • TransactionID: The transaction ID returned in the POIData.POITransactionID of the card acquisition response.
    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"01142",
                "POIID":"V400m-346403161"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"12420",
                        "TimeStamp":"2020-01-07T14:15:25.114Z"
                    },
                    "TokenRequestedType":"Customer"
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":24.98
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TimeStamp": "2020-01-17T14:14:48.000Z",
                        "TransactionID": "8ha5001579009268002"
                    }
                }
            }
        }
    }
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
    String saleID = "YOUR_CASH_REGISTER_ID";
    String POIID = "YOUR_TERMINAL_ID";
    String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
    SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
    MessageHeader messageHeader = new MessageHeader();
    messageHeader.setProtocolVersion("3.0");
    messageHeader.setMessageClass( MessageClassType.SERVICE );
    messageHeader.setMessageCategory( MessageCategoryType.PAYMENT );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setServiceID(serviceID);
    messageHeader.setSaleID(saleID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    PaymentRequest paymentRequest = new PaymentRequest();
    SaleData saleData = new SaleData();
    saleData.setTokenRequestedType( TokenRequestedType.CUSTOMER );
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTransactionID(transactionID);
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleData.setSaleTransactionID(saleTransactionID);
    paymentRequest.setSaleData(saleData);
    
    PaymentTransaction paymentTransaction = new PaymentTransaction();
    AmountsReq amountsReq = new AmountsReq();
    amountsReq.setCurrency("EUR");
    amountsReq.setRequestedAmount( BigDecimal.valueOf(24.98) );
    paymentTransaction.setAmountsReq(amountsReq);
    paymentRequest.setPaymentTransaction(paymentTransaction);
    
    PaymentData paymentData = new PaymentData();
    TransactionIdentification cardAcquisitionReference = new TransactionIdentification();
    cardAcquisitionReference.setTransactionID(transactionID);
    cardAcquisitionReference.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    paymentData.setCardAcquisitionReference(cardAcquisitionReference);
    paymentRequest.setPaymentData(paymentData);
    saleToPOIRequest.setPaymentRequest(paymentRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    In the payment response, note the following (you may need to Base64-decode the AdditionalResponse string first):

    • PaymentToken.TokenValue: The card alias.
    • Response.AdditionalResponse: Includes the shopper identifiers, depending on the parameters you specified when you created the customer profile.
    Payment response for a recognized shopper
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {...},
                "PaymentReceipt": [...],
                "PaymentResult": {
                    ...,
                    "PaymentInstrumentData": {
                        "CardData": {
                            ...,
                            "PaymentToken": {
                                "TokenRequestedType": "Customer",
                                "TokenValue": "M469509594859802"
                            },
                            "PaymentBrand": "mc",
                            "MaskedPan": "541333 **** 9999",
                            "SensitiveCardData": {
                                "CardSeqNumb": "83",
                                "ExpiryDate": "0228"
                            }
                        },
                        "PaymentInstrumentType": "Card"
                    },
                    "AmountsResp": {
                        "AuthorizedAmount": 24.98,
                        "Currency": "EUR"
                    }
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "...&alias=M469509594859802...&shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40gmail.com..."
                }
            },
            "MessageHeader": {...}
        }
    }
  4. In your system, store the transaction data with the shopper's customer profile.

Tokenization

With Adyen, you can securely store the shopper's payment details from an in-store payment, and then use the stored payment details to make online recurring payments or "subscription payments". We refer to these saved payment details as tokens and storing a shopper's payment details as tokenization.

Create a token

To create a token from an in-store transaction, you make a PaymentRequest with some additional parameters. You may want to fit this into your active shopper recognition flow, when after a card acquisition request you make a payment request for a new shopper. But it is not required to do a card acquisition before creating a token.

After you have enabled receiving shopper identifiers, proceed as follows:

  1. Collect the shopper's consent to save their payment details for future online subscription payments, and collect their email address.
    You could make input requests to collect this information from the shopper on the terminal, or let your staff enter the information in your cash register software.

  2. Make a PaymentRequest with:

    Parameter Required Description
    SaleData.SaleToAcquirerData Data to create the token and shopper identifiers.

    See the instructions below.

    In SaleData.SaleToAcquirerData you can include:

    • shopperEmail: The shopper's email address, if you collected that in the first step.
    • shopperReference: Your unique reference for this shopper (minimum length three characters).
    • recurringContract: ONECLICK,RECURRING. This creates a token for online subscription payments.

    Pass the SaleToAcquirerData value in one of the following formats:

    • Option 1: A JSON object converted to a Base64 encoded string. Refer to Add information to a payment.
    • Option 2: Form-encoded key-value pairs (using & as a separator). For example:
      shopperEmail=S.Hopper@example.com&shopperReference=12345&recurringContract=ONECLICK,RECURRING

    The format that you use here, will also be the format of the AdditionalResponse that you receive.

    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"01142",
                "POIID":"V400m-346403161"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"12420",
                        "TimeStamp":"2020-01-07T14:15:25.114Z"
                    },
                    "SaleToAcquirerData":"shopperEmail=S.Hopper@example.com&shopperReference=YOUR_UNIQUE_SHOPPER_ID&recurringContract=ONECLICK,RECURRING",
                    "TokenRequestedType":"Customer"
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":24.98
                    }
                }
            }
        }
    }
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
    String saleID = "YOUR_CASH_REGISTER_ID";
    String POIID = "YOUR_TERMINAL_ID";
    String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
    SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
    MessageHeader messageHeader = new MessageHeader();
    messageHeader.setProtocolVersion("3.0");
    messageHeader.setMessageClass( MessageClassType.SERVICE );
    messageHeader.setMessageCategory( MessageCategoryType.PAYMENT );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setServiceID(serviceID);
    messageHeader.setSaleID(saleID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    PaymentRequest paymentRequest = new PaymentRequest();
    SaleData saleData = new SaleData();
    saleData.setSaleToAcquirerData("shopperEmail=s.hopper@example.com&shopperReference=YOUR_UNIQUE_SHOPPER_ID_IOfW3k9G2PvXFu2j&recurringContract=RECURRING");
    saleData.setTokenRequestedType( TokenRequestedType.CUSTOMER );
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTransactionID(transactionID);
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleData.setSaleTransactionID(saleTransactionID);
    paymentRequest.setSaleData(saleData);
    
    PaymentTransaction paymentTransaction = new PaymentTransaction();
    AmountsReq amountsReq = new AmountsReq();
    amountsReq.setCurrency("EUR");
    amountsReq.setRequestedAmount( BigDecimal.valueOf(24.98) );
    paymentTransaction.setAmountsReq(amountsReq);
    paymentRequest.setPaymentTransaction(paymentTransaction);
    
    PaymentData paymentData = new PaymentData();
    TransactionIdentification cardAcquisitionReference = new TransactionIdentification();
    cardAcquisitionReference.setTransactionID(transactionID);
    cardAcquisitionReference.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    paymentData.setCardAcquisitionReference(cardAcquisitionReference);
    paymentRequest.setPaymentData(paymentData);
    saleToPOIRequest.setPaymentRequest(paymentRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    In the PaymentResponse, note the following (you may need to Base64-decode the AdditionalResponse string first):

    • The shopper identifiers in the Response.AdditionalResponse:
      • recurring.recurringDetailReference: A token representing the shopper's payment method, for use in online recurring payments.
      • recurring.shopperReference: Your unique reference for this shopper that you specified in the request.
      • shopperEmail: The shopper's email address that you specified in the request.
      • alias: The card alias.
    "Response
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {...},
                "SaleData": {...}
                "PaymentReceipt": [...],
                "PaymentResult": {
                    ...
                    "PaymentInstrumentData": {
                        "CardData": {
                            "EntryMode": [
                                "Contactless"
                            ],
                        "PaymentToken": {
                            "TokenRequestedType": "Customer",
                            "TokenValue": "M469509594859802"
                        },
                        "PaymentBrand": "mc",
                        "MaskedPan": "541333 **** 9999",
                        "SensitiveCardData": {
                            "CardSeqNumb": "83",
                            "ExpiryDate": "0228"
                        }
                    },
                    "PaymentInstrumentType": "Card"
                },
                "AmountsResp": {
                    "AuthorizedAmount": 24.98,
                    "Currency": "EUR"
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "...&alias=M469509594859802...recurring.recurringDetailReference=9914828517650010&recurring.shopperReference=YOUR_UNIQUE_SHOPPER_ID...&shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40gmail.com..."
                }
            },
            "MessageHeader": {...}
        }
    }

    The token and the shopper identifiers for this shopper are now stored on the Adyen payments platform.

  3. In your system, create a customer profile for the shopper and store the recurring.recurringDetailReference and the recurring.shopperReference (as well as any other shopper identifiers) that you received in the payment response.

Use a token

To make an online subscription payment using a token you created with an in-store payment, you provide the recurring.recurringDetailReference and the recurring.shopperReference returned in the response to the payment request that created the token.

For instructions, refer to Make a subscription payment.

See also