Search

Are you looking for test card numbers?

Would you like to contact support?

Point-of-sale icon

NFC-enabled passes

Learn how to process transactions with NFC-enabled passes.

Shoppers can link their credit and debit cards to a mobile wallet app and then make in-store payments with the mobile wallet using a service like Apple Pay. The payment terminal interfaces with the mobile wallet through near field communication (NFC) between the terminal and the shopper's phone or smartwatch.

Apart from credit and debit cards, shoppers can also keep other passes in their mobile wallet, such as loyalty cards, vouchers, gift cards, boarding passes, and tickets. With these NFC-enabled passes, they can for example redeem a voucher or collect points on a loyalty card.

As a merchant, you can create your own NFC-enabled passes, and tie them in with your loyalty program. With a Terminal API integration you are then able to check if the shopper has your pass in their mobile wallet, and use the pass for their transaction.

At the moment, we support this for:

  • Apple Wallet passes

How it works

There are various ways to implement NFC-enabled passes with a payment, depending on what makes sense for your pass and loyalty program:

  • Payment flow: You check for the passes after the payment, and update the shopper's account later.
  • Redeem flow: You check for the passes before the payment through a card acquisition request. If there are discounts or other advantages related to the pass, you can apply these to the payment beforehand.

    There are two variations of the redeem flow: single-tap redeem flow and double-tap redeem flow. Apart from a configuration setting, the implementation is the same. The difference is that in the double-tap flow the terminal asks the shopper a second time to present their card. This allows the shopper to redeem the NFC pass the first time that the terminal asks for their card, and then switch to another payment method the second time that the terminal asks for their card.

Select the tabs below to learn more. Before you configure your NFC pass in the Customer Area, you need to understand how these flows work and which flow you want to implement.

You make a payment request. If the shopper pays with an NFC-enabled mobile wallet, you are informed in the payment response whether the shopper has your pass in their mobile wallet. If they do, the payment response includes the unique ID of the shopper's pass so that you can update the shopper's account.

You first make a card acquisition request with an amount. The terminal asks the shopper to present their card. When the shopper taps their NFC-enabled mobile device to the payment terminal, the terminal polls the mobile wallet on the device for:

  • Your passes.
  • The details of the payment method (the credit or debit card that is linked to the wallet).

If the shopper has your pass, the card acquisition response includes the unique ID of the shopper's pass so that you can look up the shopper's account. You can then for example:

  • Make an input request to ask the shopper whether they want to redeem loyalty points.
  • Add or recalculate loyalty points.
  • Apply a discount.

Then you make a payment request for the final amount. This must be equal to or lower than the card acquisition amount.

In this flow, the shopper taps their mobile device to the terminal only once, because the card acquisition polls for the pass details and the payment method details at the same time.

You first make a card acquisition request with or without an amount. The terminal asks the shopper to present their card. When the shopper taps their NFC-enabled mobile device to the payment terminal, the terminal polls the mobile wallet on the device for your passes. If the shopper has your pass, the card acquisition response includes the unique ID of the shopper's pass so that you can look up the shopper's account. You can then for example:

  • Make an input request to ask the shopper whether they want to redeem loyalty points.
  • Add or recalculate loyalty points.
  • Apply a discount.

Then you make a payment request for the final amount. The terminal asks shopper again to present their card. The shopper can then choose to pay with their mobile wallet and tap their mobile device to the terminal a second time, or use a different payment method.

Shopper enrollment

To let shoppers enroll with the loyalty program tied to your NFC-enabled pass, and add the pass to their mobile wallet, you can inform them through email, social media, your web site, and so on.

We can also help your shoppers enroll: When they make an NFC wallet payment but don't have your pass in their mobile wallet yet, we send an NFC signal so that the shoppers receive a message with the URL where they can enroll. To make this possible, you need to provide that URL in your Customer Area configuration.

Before you begin

  1. Set up a server for your NFC-enabled passes. On this pass server, you need to make a URL available where shoppers can enroll with the loyalty program tied to your NFC-enabled pass and add the pass to their mobile wallet.

    You need to specify this URL when you configure the pass in your Customer Area.

  2. Create one or more NFC-enabled passes. See for example the Wallet Developer Guide, which explains how to create an Apple Wallet pass for your loyalty program.

    While creating your pass, a pass type ID and private key are generated. You will need these later, when you configure the pass in your Customer Area.

  3. Make sure that you have built a Terminal API integration that can make a payment.
  4. Tie in your loyalty program with your NFC-enabled passes. To learn more about how to link a customer in your loyalty program to a transaction, refer to Shopper recognition and tokenization.

Configure NFC-enabled passes in your Customer Area

To enable us to get the unique ID of the shopper's pass, you need to inform us about your NFC-enabled pass and the flow you want to use:

  1. Log in to your Customer Area and select the account level where you want to use your NFC-enabled pass.
  2. Go to Point of sale > Terminal settings > Payment features.
  3. Select View decrypted and go to Mobile wallet NFC pass services.
  4. At Card acquisition VAS mode, select an option for the flow you want to use. This setting determines what the terminal tries to do when you make a card acquisition request and the shopper taps a device with an NFC wallet to the payment terminal.

    • For the payment flow and the single-tap redeem flow, select VAS and payment. This gets both the NFC pass details and the NFC payment method details.
    • For the double-tap redeem flow, select VAS only. This gets the NFC pass details when you make a card acquisition request.

    • There are two more options that we list here for completeness:

      • If you don't want to collect the NFC pass details when you make a card acquisition request, select Payment only.
      • To leave it up to the shopper whether the NFC pass details are collected with your card acquisition request, select VAS or payment.

  5. Enter the Name of your pass.
  6. At Merchant pass type identifier enter the pass type ID that was generated when you created your NFC pass.
    We use this to poll only for your pass and not for passes from other organizations that the shopper may have in their mobile wallet. For an Apple Wallet pass, this has the format pass.com.company.pass-name.
  7. At Vendor type select the company responsible for the protocol that your NFC pass is based on. For example, Apple.
  8. Enter the URL where people can add the pass to their mobile wallet.
    We use this when the shopper doesn't have your pass in their wallet yet, to send an NFC signal so that the shopper receives a message with the URL where they can enroll.
  9. In the Private key slot box, select the slot where you will provide your private key. For example, Private key 1.
  10. Under Private key slots, go to the slot that you selected in the previous step and enter the private key for your NFC pass.
    This key was generated when you created the pass. We will protect and encrypt it in our back end. The terminal uses this key to decrypt the NFC message and return the unique ID of the shopper's pass in the response.
  11. To add more NFC-enabled passes, select Add wallet and repeat the steps to complete the settings.
  12. Select Save.

After you have finished the configuration, you are ready to accept your NFC-enabled pass with a payment, using either the payment flow or the redeem flow.

Use the payment flow

To make a payment request and afterwards update the shopper's NFC pass account:

  1. Make a PaymentRequest with:

    Parameter 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.
    {
        "SaleToPOIRequest": {
            "MessageHeader": {
                "ProtocolVersion": "3.0",
                "MessageClass": "Service",
                "MessageCategory": "Payment",
                "MessageType": "Request",
                "ServiceID": "s9wrxa",
                "SaleID": "POSSystemID12345",
                "POIID": "V400m-324689265"
            },
            "PaymentRequest": {
                "SaleData": {
                    "SaleTransactionID": {
                        "TransactionID": "a1b2c3",
                        "TimeStamp": "2020-06-16T16:13:16"
                    },
                    "TokenRequestedType": "Customer"
                },
                "PaymentTransaction": {
                    "AmountsReq": {
                        "Currency": "EUR",
                        "RequestedAmount": 10.99
                    }
                }
            }
        }
    }
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {
                    "POITransactionID": {
                        "TimeStamp": "2020-06-15T16:13:16.000Z",
                        "TransactionID": "fanx001580400796015.8535804008080700"
                    },
                    "POIReconciliationID": "1000"
                },
                "SaleData": {
                    "SaleTransactionID": {
                        "TimeStamp": "2020-06-15T16:13:16.000Z",
                        "TransactionID": "a1b2c3"
                    }
                },
                "PaymentReceipt": [...],
                "PaymentResult": {
                    "AuthenticationMethod": [
                        "SecuredChannel"
                    ],
                    "OnlineFlag": true,
                    "PaymentAcquirerData": {...},
                        "MerchantID": "YOUR_MERCHANT_ACCOUNT"
                    },
                    "PaymentInstrumentData": {
                        "CardData": {
                            "EntryMode": [
                                "Contactless"
                            ],
                            "PaymentToken": {
                                "TokenRequestedType": "Customer",
                                "TokenValue": "G526627978654924"
                            },
                            "PaymentBrand": "visa",
                            "MaskedPan": "481749 **** 1108",
                            "CardCountryCode": "076",
                            "SensitiveCardData": {
                                "CardSeqNumb": "00",
                                "ExpiryDate": "1223"
                            }
                        },
                        "PaymentInstrumentType": "Card"
                    },
                    "AmountsResp": {
                        "AuthorizedAmount": 10.99,
                        "Currency": "EUR"
                    }
                },
                "LoyaltyResult": [
                    {
                        "LoyaltyAccount": {
                            "LoyaltyAccountID": {
                                "IdentificationType": "AccountNumber",
                                "EntryMode": [
                                    "Contactless"
                                ],
                                "LoyaltyID": "rEqQFLnckxJ3jCvmQoLmBh"
                            },
                            "LoyaltyBrand": "AppleVAS"
                        }
                    }
                ],
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "..."
                }
            },
            "MessageHeader": {...}
        }
    }

    In the PaymentResponse, note the following:

    • LoyaltyResult: An array with your NFC enabled passes that are in the shopper's digital wallet. For each pass, there is a LoyaltyAccount object with:
      Property Description
      LoyaltyAccountID.IdentificationType AccountNumber. The type of ID of the shopper's pass.
      LoyaltyAccountID.EntryMode Contactless. Indicates how the NFC pass details were obtained.
      LoyaltyAccountID.LoyaltyID The unique ID of the shopper's pass.
      LoyaltyBrand The vendor protocol that the NFC pass is based on.

    If the response doesn't include a LoyaltyResult, the shopper hasn't yet added your NFC-enabled pass to their mobile wallet.

  2. Using the LoyaltyID and card alias returned in the response, look up the shopper in your pass server and loyalty program, and update the shopper's data. For example, the loyalty points accrued.

Use the redeem flow

Here we describe how you can first check whether the shopper has your NFC-enabled pass in their wallet app before you initiate payment. This allows you to apply a discount or other advantages related to the pass.
Whether the shopper needs to tap their phone or smartwatch a second time to complete the payment, depends on the Customer Area configuration of your pass.

Step 1: Get the shopper's pass details

  1. Make a CardAcquisitionRequest with:

    Parameter 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.
    CardAcquisitionTransaction In the single-tap redeem flow, this object must contain:
    • TotalAmount: The transaction amount.

    In the double-tap redeem flow, you can leave this object empty if you expect the amount to change in most cases, for example if you do a card acquisition as soon as the first item is scanned.

    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"CardAcquisition",
                "MessageType":"Request",
                "ServiceID":"0305Acq",
                "SaleID":"POSSystemID12345",
                "POIID":"V400m-346403161"
            },
            "CardAcquisitionRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"0422024",
                        "TimeStamp":"2020-06-19T12:18:04"
                    },
                    "TokenRequestedType":"Customer"
                },
                "CardAcquisitionTransaction":{
                    "TotalAmount": 14.98
                }
            }
        }
    }
    {
        "SaleToPOIResponse": {
            "CardAcquisitionResponse": {
                "POIData": {
                    "POITransactionID": {
                        "TimeStamp": "2020-06-19T10:18:48.000Z",
                        "TransactionID": "8ha5001592561928000"
                    },
                    "POIReconciliationID": "1000"
                },
                "SaleData": {
                    "SaleTransactionID": {
                        "TimeStamp": "2020-06-19T12:18:04.000Z",
                        "TransactionID": "0422024"
                    }
                },
                "PaymentInstrumentData": {
                    "CardData": {
                        "PaymentToken": {
                            "TokenRequestedType": "Customer",
                            "TokenValue": "M469509594859802"
                        },
                        "PaymentBrand": "mc",
                        "MaskedPan": "541333 **** 9999",
                        "CardCountryCode": "528",
                        "SensitiveCardData": {
                            "ExpiryDate": "0228"
                        }
                    },
                    "PaymentInstrumentType": "Card"
                },
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "..."
                },
                "LoyaltyAccount": [
                    {
                        "LoyaltyAccountID": {
                            "IdentificationType": "AccountNumber",
                            "EntryMode": [
                                "Contactless"
                            ],
                            "LoyaltyID": "rEqQFLnckxJ3jCvmQoLmBh"
                        },
                        "LoyaltyBrand": "AppleVAS"
                    }
                ]
            },
            "MessageHeader": {...}
        }
    }
  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.
    • AdditionalResponse: If you already have the shopper on record, this contains a shopperReference.
    • LoyaltyResult: An array with your NFC enabled passes that are in the shopper's digital wallet. For each pass, there is a LoyaltyAccount object with:
      Property Description
      LoyaltyAccountID.IdentificationType AccountNumber. The type of ID of the shopper's pass.
      LoyaltyAccountID.EntryMode Contactless. Indicates how the NFC pass details were obtained.
      LoyaltyAccountID.LoyaltyID The unique ID of the shopper's pass.
      LoyaltyBrand The vendor protocol that the NFC pass is based on.

    If the response doesn't include a LoyaltyResult, the shopper hasn't yet added your NFC enabled pass to their mobile wallet.

  3. Using the LoyaltyID and shopperReference returned in the response, look up the shopper in your pass server and loyalty program, and apply your business logic.
    For example:

    • Make a confirmation input request to ask the shopper whether they want to redeem loyalty points.
    • Add or recalculate loyalty points.
    • Apply a discount.
    • Recalculate the transaction amount.

    Or if you don't have the shopper on record yet, you may want to:

    • Ask the shopper whether they want to enroll in your loyalty program and add your pass to their mobile wallet. If they do, you'll need to collect shopper details like their email address. You can use input requests to gather this information, or let your staff enter the information in your cash register software.
    • Create a customer profile for the shopper in your loyalty program and pass server with the information you collected.

Step 2: Continue with the payment

  1. Make a PaymentRequest with:

    Parameter Description
    SaleData.TokenRequestedType Customer. This returns the card alias in the TokenValue field of the response. Refer to Shopper recognition and tokenization.
    SaleData.SaleToAcquirerData If you didn't have the shopper on record yet, use this parameter to create shopper identifiers on our platform so that next time the shopper will be recognized.

    See the instructions below.

    PaymentTransaction.AmountsReq An object with:
    • Currency: The transaction currency.
    • RequestedAmount: The final transaction amount.
    PaymentData.CardAcquisitionReference 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.

    For an unrecognized shopper, you can include the following in SaleData.SaleToAcquirerData:

    • shopperEmail: The shopper's email address, if you collected that.
    • shopperReference: Your unique reference for this shopper.
    • recurringContract: ONECLICK,RECURRING.

    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&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",
                "ServiceID":"0305p",
                "SaleID":"POSSystemID12345",
                "POIID":"V400m-346403161"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TimeStamp": "2020-06-19T12:23:04.000Z",
                        "TransactionID": "042208"
                    },
                    "SaleToAcquirerData":"shopperEmail=S.Hopper@example.com&shopperReference=YOUR_UNIQUE_SHOPPER_ID&recurringContract=ONECLICK,RECURRING&tenderOption=ReceiptHandler",
                    "TokenRequestedType":"Customer"
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":14.48
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TimeStamp": "2020-06-19T10:21:27.000Z",
                        "TransactionID": "8ha5001592562087001"
                    }
                }
            }
        }
    }
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {
                    "POITransactionID": {
                        "TimeStamp": "2020-06-19T10:24:03.000Z",
                        "TransactionID": "8ha5001592562087001.8825925622358203"
                    },
                    "POIReconciliationID": "1000"
                },
                "SaleData": {
                    "SaleTransactionID": {
                        "TimeStamp": "2020-06-19T12:23:04.000Z",
                        "TransactionID": "042208"
                    }
                },
                "PaymentReceipt": [...],
                "PaymentResult": {
                    "OnlineFlag": true,
                    "PaymentAcquirerData": {...},
                        "MerchantID": "YOUR_MERCHANT_ACCOUNT"
                    },
                    "PaymentInstrumentData": {
                        "CardData": {
                            "EntryMode": [
                                "Contactless"
                            ],
                            "PaymentToken": {
                                "TokenRequestedType": "Customer",
                                "TokenValue": "M469509594859802"
                            },
                            "PaymentBrand": "mc",
                            "MaskedPan": "541333 **** 9999",
                            "CardCountryCode": "056",
                            "SensitiveCardData": {
                                "CardSeqNumb": "83",
                                "ExpiryDate": "0228"
                            }
                        },
                        "PaymentInstrumentType": "Card"
                    },
                    "AmountsResp": {
                        "AuthorizedAmount": 14.48,
                        "Currency": "EUR"
                    },
                },
                "LoyaltyResult": [
                    {
                        "LoyaltyAccount": {
                            "LoyaltyAccountID": {
                                "IdentificationType": "AccountNumber",
                                "EntryMode": [
                                    "Contactless"
                                ],
                                "LoyaltyID": "rEqQFLnckxJ3jCvmQoLmBh"
                            },
                            "LoyaltyBrand": "AppleVAS"
                        }
                    }
                ],
                "Response": {
                    "Result": "Success",
                    "AdditionalResponse": "...&alias=M469509594859802&...&recurring.recurringDetailReference=8415834992725957&...recurring.shopperReference=YOUR_UNIQUE_SHOPPER_ID&...shopperReference=YOUR_UNIQUE_SHOPPER_ID&shopperEmail=S.Hopper%40example.com&..."
                }
            },
            "MessageHeader": {...}
        }
    }

    In the PaymentResponse, note that you receive the same LoyaltyResult as in the CardAcquisitionResponse.

See also