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.
    For example, apply discounts or loyalty gifts on the spot, or send your shopper an electronic receipt by email.

  • Tokenization for recurring 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:

  2. Consider how you will handle the privacy implications.
  3. For active shopper recognition, set up a Customer Relationship Management System (CRM) or other database for storing customer profiles.

Managing customer data and privacy

Before storing any customer data, you should consult the local laws and regulations in the countries where you operate. 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 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:

    • Recurring details
    • Recurring contract type
    • issuerCountry
    • Funding source

    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.

How it works

When the shopper makes a purchase in your store:

  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. Optionally also tokenize the card details for recurring payments.
    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
                }
            }
        }
    }
    {
        "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": {...}
        }
    }
    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.
  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. For active shopper recognition: Depending on your business logic, ask if the shopper wants to enroll in your loyalty program, collect their email address, and so on.
    You could make input requests to collet 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 for active shopper recognition and tokenization.

    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.
    • recurringContract: ONECLICK,RECURRING. Include this if you want to create a token for online recurring payments and the customer agrees to tokenize their payment details.

    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
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TimeStamp": "2020-01-17T14:14:48.000Z",
                        "TransactionID": "8ha5001579009268002"
                    }
                }
            }
        }
    }
    {
        "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": "...recurring.recurringDetailReference=8415790083332048...&recurring.shopperReference=YOUR_UNIQUE_SHOPPER_ID...&shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40gmail.com...&adjustAuthorisationData=BQABAQBoaOt7n1q1Ons6Ec..."
                }
            },
            "MessageHeader": {...}
        }
    }
    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 string first):

    • PaymentToken.TokenValue: The card alias.
    • The shopper identifiers in the Response.AdditionalResponse:

      • alias: The card alias.
      • recurringDetailReference: A token representing the shopper's payment method, for use in online recurring payments. You receive this if you included the recurringContract parameter in the request.
      • 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.

    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. For active shopper recognition: 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"
                    }
                }
            }
        }
    }
    {
        "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": "...recurring.recurringDetailReference=8415790083332048...&recurring.shopperReference=YOUR_UNIQUE_SHOPPER_ID...&shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40gmail.com...&adjustAuthorisationData=BQABAQBoaOt7n1q1Ons6Ec..."
                }
            },
            "MessageHeader": {...}
        }
    }
    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 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.
  4. In your system, store the transaction data with the shopper's customer profile.

See also