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 solution 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.
  • Shopper reference: A unique value of your choice to identify the shopper by. If you also collect the shopper's email address, you can link multiple card aliases to the same shopper through their email address.
  • 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, such as debit, credit, or prepaid.
  • 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. In your customer database, you need to create a customer profile for each shopper to store their identifiers, as well as the 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.

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.

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 request your customer's explicit permission to store this data, and be clear about what you intend to use it for.

We offer a Data Protection API. You can use this to remove any customer data that you have stored at Adyen, in order to meet 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 you have no record of the shopper, you create a new customer profile and make a payment. Optionally also tokenize the card details for recurring payments.
    From now on, the shopper is recognized based on the shopper reference you create with this payment request.
  3. If the card acquisition response indicates you already have the shopper on record, 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 have the shopper on record. This is also referred to as 'pre-transaction recognition'.

  1. Make a card acquisition request.

    {
        "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);
  2. 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. This field is included if you specified a TokenRequestedType of Customer in your request. The alias is also included in the Response.AdditionalResponse.
  3. 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 and also creates shopper identifiers.

  1. For active shopper recognition: Depending on your business logic, first collect the shopper's email address, ask if they want to enroll in your loyalty program, and so on.
    You could make input requests to collect this information, or let your staff enter the information in your cash register software.
  2. Make a payment request specifying a PaymentRequest.SaleData object that additionally includes:

    • 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. For passive shopper recognition this is enough and you don't need to specify more shopper identifiers.
    • SaleToAcquirerData: Data to create shopper identifiers for active shopper recognition and tokenization:

      • shopperEmail: The shopper's email address, if tyou 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.

      Pass these data in one of the following formats:

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

      The format you use here, determines the format of the AdditionalResponse that you'll receive.

    • PaymentData.CardAcquisitionReference: The Timestamp and TransactionID of the card acquisition request. You received this data in the POIData.POITransactionID object of the CardAcquisitionResponse.

    {
        "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@gmail.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@gmail.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);
  3. In the payment response, note the following (you may need to Base64-decode the string first):

    • PaymentToken.TokenValue: The card alias. This is included if you specified a TokenRequestedType of Customer in your request.
    • 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.

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

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. Match the shopperReference you received in the card acquisition response against a shopperReference stored 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 amount due accordingly.
  3. Make a payment request specifying a PaymentRequest.PaymentData object that additionally includes:

    • 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.
    • CardAcquisitionReference: The Timestamp and TransactionID of the card acquisition request. You received this data in the POIData.POITransactionID object of the CardAcquisitionResponse.

    {
        "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);
  4. In the payment response, note the following (you may need to Base64-decode the string first):

    • PaymentToken.TokenValue: The card alias. This is included if you specified a TokenRequestedType of Customer in your request.
    • 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.
      • shopperReference: Your unique reference for this shopper.
      • shopperEmail: The shopper's email address.

      You may not receive all of these, depending on the parameters you included when you created a new customer profile.

  5. In your system, store the transaction data with the shopper's customer profile.

See also