Pesquisar

Are you looking for test card numbers?

Would you like to contact support?

Atenção, esta página não se encontra disponível em Português
Point-of-sale icon

Shopper loyalty

Use shopper recognition for loyalty purposes.

To engage shoppers and promote shopper loyalty, you can set up a system where you use payment data to identify a shopper, and then offer tailored benefits. For example:

  • Card-linked loyalty, where shoppers no longer need to have a physical loyalty card. Instead, the loyalty program is tied to identifiers that you receive in Terminal API responses. Using these identifiers, you look up the shopper in your loyalty program and decide on the discount or loyalty reward to offer.

  • Product recommendations based on the purchase history of the shopper. Here too, your back end system uses identifiers from the Terminal API response to look up the shopper's past purchases.

You can use the card alias to recognize the shopper's card, but you can also go one step further and create your own identifiers to be returned in card acquisition and payment responses. That enables you to identify an individual, not just their payment card, and make the shopping experience even more personal.

You also need a back end system to store customer profiles of your shoppers, containing card and shopper identifiers together with any other details that your use case requires, such as purchase data.

Card and shopper identifiers

To be able to personalize the shopper experience, save the following identifiers:

  • Card alias (alias): A value that uniquely represents the shopper's card number (PAN), for example A37317672402294. With this, you can recognize the card that a shopper is using. You can't use the card alias for making payments. You receive the card alias in the AdditionalResponse.
  • Shopper reference (shopperReference): This is your reference to identify the shopper. You submit it with a payment, and receive it back in the AdditionalResponse for that payment and also for any later card acquisition and payment responses.

    To get the shopper reference, you need to enable receiving this identifier.

  • Shopper email (shopperEmail): You collect the shopper's email address in some way, and submit it with a payment. You receive it back in the AdditionalResponse for that payment and also for any later card acquisition and payment responses.

Synchronous flow

The synchronous flow allows you to actively engage the shopper on the spot. For example, if you recognize the shopper from a card acquisition, you can apply a discount or ask the shopper whether they want to redeem loyalty points before you initiate the payment.

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. To gather the data for the customer profile, you can make input requests.
  3. If the card acquisition response indicates the shopper is already known, you optionally make input request to communicate with the shopper, and then 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 card acquisition request 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 either empty, or contains:
    • TotalAmount: The transaction amount.
    You can omit TotalAmount when you don't know the amount yet. Or you can also change the transaction amount later, in the payment 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
                }
            }
        }
    }
    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. When you receive the CardAcquisitionResponse, keep the TimeStamp and TransactionID from the POIData.POITransactionID. You need these details later in your payment request.

    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": {...}
        }
    }
  3. To verify whether you already know the shopper, check the AdditionalResponse (you may need to Base64-decode the string first):

    • If the AdditionalResponse contains a shopperReference and/or a shopperEmail, you already created a customer profile for the shopper. This means the shopper is known.

    • Alternatively, check the alias in the AdditionalResponse against the card aliases stored in your system.
      If you specified a TokenRequestedType of Customer in the request, the card alias is also returned in PaymentToken.TokenValue.
      If the shopper used an NFC wallet, there is no card alias. In that case, use the PaymentAccountReference instead.
  4. Take the next step:

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 to store in your back end system.

  1. Collect details from the shopper (depending on your use case), and ask the shopper's consent to store their details.
    You can let your staff enter the information in your cash register software, but you can also make input requests to collect the information on the terminal. For example:

  2. 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, 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.
    SaleData.SaleToAcquirerData Data to create shopper identifiers.

    See the instructions below.

    In SaleData.SaleToAcquirerData you can include:

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

    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:
      shopperReference=12345&shopperEmail=S.Hopper@example.com

    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);
  3. When you receive the response, keep the following identifiers from the AdditionalResponse (you may need to Base64-decode the string first):

    • alias: The card alias.
      If you specified a TokenRequestedType of Customer in the request, the card alias is also returned in PaymentToken.TokenValue.
    • PaymentAccountReference: Value that represents the shopper's payment account that their card and/or NFC wallet is linked to. For NFC wallet transactions, a PAN is not available and thus there's no 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 identifiers for this shopper are now stored on the plataforma de pagamentos da Adyen.

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

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 or other identifiers 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. For example,

  3. If necessary, update the final transaction amount. For example, if you applied a discount.
  4. 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);
  5. When you receive the response, keep the following identifiers from the AdditionalResponse (you may need to Base64-decode the string first):

    • alias: The card alias.
      If you specified a TokenRequestedType of Customer in the request, the card alias is also returned in PaymentToken.TokenValue.
    • PaymentAccountReference: Value that represents the shopper's payment account that their card and/or NFC wallet is linked to.
    • shopperReference: Your unique reference for this shopper, if you specified that when you created the customer profile.
    • shopperEmail: The shopper's email address, if you specified that 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": {...}
        }
    }
  6. In your system, store the transaction data with the shopper's customer profile.

Asynchronous flow

The asynchronous flow is a simpler implementation of shopper loyalty, where you rely on webhook notifications to make loyalty adjustments in your system after the payment. In this flow, you can't apply discounts or other loyalty benefits on the spot before the payment.

  1. Make sure you have set up receiving standard notifications.
  2. Create a customer profile for the shopper in your loyalty system.
  3. Make a payment.
  4. Wait for the AUTHORISATION notification.
  5. Based on the identifiers in the AUTHORISATION notification, update the shopper's customer profile in your loyalty system. For example, add loyalty points.
  6. Inform the shopper of the update in your loyalty system.

For more information about this flow, refer to our Unified Commerce documentation.

See also