Ordering End-to-End projects allow configuring the Sandbox Payment Mode when using either the Quick Test or the Sandbox environment. While you test your data feed, you can switch between Sandbox and Production Payment Modes. In order to test payments for your Ordering End-to-End project without charging the cards, use Sandbox as your Payment Mode. The production environment does not support the Sandbox Payment Mode.
Configuration
To enable the Sandbox Payment Mode in the Sandbox environment, follow these steps:
- On the Actions Center, navigate to Configuration > Features.
- On the Account features card, find the Payment Mode radio button.
- Select the Sandbox option and click Save changes.
To enable the Sandbox Payment Mode in the Quick Test environment, follow these steps:
- On the Actions Center, navigate to Feeds > Quick Test.
- Select the Use sandbox for GPay radio button.
When the Sandbox Payment Mode is selected:
- Ordering End-to-End configures Google Pay to return instrument tokens that contain test card data instead of the actual card details.
- The
isInSandbox
field is set totrue
in the CheckoutRequestMessage and SubmitOrderRequestMessage.
The different combinations of Environment, Payment Mode and isInSandbox are as follows:
Environment | Payment Mode | isInSandbox |
---|---|---|
Quick Test | Sandbox | true |
Quick Test | Production | false |
Sandbox | Sandbox | true |
Sandbox | Production | false |
Production | Production | false |
Checkout Response Message
The CheckoutResponseMessage
sent by your Food Ordering web service contains
PaymentOptions
. When you
set up your checkout,
you provide a placeholder payment options using an example payment gateway.
- Be sure to update the
CheckoutResponseMessage
sent by your web service with the appropriate tokenization configuration.
Payment option examples
The following are example JSON PaymentOptions
objects from a
CheckoutResponseMessage
for various payment gateways using sandbox keys:
JSON
"paymentOptions": { "googleProvidedOptions": { "facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"USD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"31.85\"}} " } }
JSON
"paymentOptions": { "googleProvidedOptions": { "facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gateway\":\"braintree\",\"braintree:apiVersion\":\"v1\",\"braintree:sdkVersion\":\"1.4.0\",\"braintree:merchantId\":\"YOUR_MERCHANT_ID\",\"braintree:clientKey\":\"YOUR_BRAINTREE_SANDVOX_OR_PRODUCTION_KEY\"}}}],\"transactionInfo\":{\"currencyCode\":\"USD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"31.85\"}} " } }
JSON
"paymentOptions": { "googleProvidedOptions": { "facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gateway\":\"stripe\",\"stripe:version\":\"2018-10-31\",\"stripe:publishableKey\":\"YOUR_PRODUCTION_OR_SANDBOX_STRIPE_KEY\"}}}],\"transactionInfo\":{\"currencyCode\":\"USD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"31.85\"}} " } }
JSON
"paymentOptions": { "googleProvidedOptions": { "facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gateway\":\"stripev2\",\"gatewayMerchantId\":\"YOUR_PRODUCTION_OR_SANDBOX_STRIPE_KEY\"}}}],\"transactionInfo\":{\"currencyCode\":\"USD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"31.85\"}} " } }
Flag sandbox transactions
When the Sandbox Payment Mode is enabled, the isInSandbox
field is
included in the request and set to true
for incoming requests to your web
service endpoint (CheckoutRequestMessage
and SubmitOrderRequestMessage
).
Do the following when the isInSandbox
field is set to true
:
- Use sandbox keys instead of production keys in the tokenization configuration for your payment gateway. Most payment processors provide API keys for both sandbox and production.
- Don't trigger any communication with the web service provider, usually a restaurant, as they don't have to be informed of any sandbox transactions.
Test credit cards aren't supported, even when the transaction sandbox is enabled. You must use a real credit card when you make a transaction. However, sandbox instrument tokens contain test card details that are not chargeable.
Process payments
When a customer submits their order, Ordering End-to-End sends the
SubmitOrderRequestMessage
to your web service endpoint. The Google Pay
token
is included as a base-64 encoded string in the SubmitOrderRequestMessage
instrumentToken
field. To process the customer's payment, do one of the following depending on
your payment gateway:
Payment gateway | |
---|---|
Stripe or Braintree | Decode the base-64 encoded token string and send the appropriate data contained in the decoded token payload to your payment gateway to process the payment. |
All other payment gateways (including stripev2) | Send the complete base-64 encoded token string to your payment gateway api to process the payment. The Google Pay payment method token structure contains encrypted fields that your payment gateway can decrypt to process the payment. |
Decoded payload example
The following examples show decoded payloads returned in the instrumentToken
field for various payment gateways:
JSON
This JSON example represents a decoded payment token when using
Braintree. Extract the value of the nonce
field
and send the value to Braintree to process the payment.
{ "androidPayCards": [{ "type": "AndroidPayCard", "nonce": "aeeb8297-4242...", "description": "AndroidPay", "consumed": false, "details": { "cardType": "Visa", "lastTwo": "29" } }] }
If Google Pay is not enabled in the Braintree control panel, the
instrumentToken
field decodes to the following error:
{ "error": { "message": "Record not found" }, "fieldErrors": [] }
JSON
This JSON example represents a decoded payment token when using Stripe.
Extract the value of the id
field and send it to Stripe to
process the payment.
{ "id": "tok_abcdefg1234...", "object": "token", "card": { "id": "card_abcde...", "object": "card", "address_city": null, "address_country": null, "address_line1": null, "address_line1_check": null, "address_line2": null, "address_state": null, "address_zip": null, "address_zip_check": null, "brand": "Visa", "country": "US", "cvc_check": null, "dynamic_last4": "1234", "exp_month": 1, "exp_year": 2019, "funding": "credit", "last4": "1234", "metadata": {}, "name": null, "tokenization_method": "android_pay" }, "client_ip": "74.125.177.36", "created": 1500483670, "livemode": false, "type": "card", "used": false }
JSON
This JSON example represents a decoded payment token when using stripev2.
{ "protocolVersion":"ECv2", "signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d", "intermediateSigningKey":{ "signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}", "signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"] }, "signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}" }
JSON
This JSON example represents a decoded payment token when using Square.
{ "signature": "MEYCIQCMAsWCrY2GfHM/gMAKiK3QCKJJOIkjZeTQGzcdWgvrhwIhAJ3mXwe+wmU9z+Apv1rTDsCVQBzayvWzT4ywxytrSPla", "protocolVersion": "ECv1", "signedMessage": "{\"encryptedMessage\":\"WkYz21EYxojwTqWh6A3oYXtmctu1PlqF+tNYPA4cq017nqj16Ge7kaVR7MI1XG1OrCmcMwP20u5Zb5E28XYan8UI8M4L120orvE9XU1ivZuO4Myq2O3ue8v0lY1MDx8Mnk+5mkAv1kLmzJc91gEQ2leIwrPuMDYqsQUHzTR3Jikh5/v+iWRkyQPKKxgj5c6Erdu/pkg1xV6fQJcHNdq9Jw11zl95x6eQurxw2Uy8v811azGr+noKJbw0uye72MkhmzMS5QKOzwGT9nBfO+zPLYSEewsdOcPbNZF94zk/KU9nxom/gQ+eYEMIZvOj9lO4gQqDqR6DyWyStk7MjeXQTvXWZBI1JpqvOrlTHL0Ct18RpbfOio7hAtafzb0NnqEKlsun+SSpJmvI7U6n6Cnu1JUMUGfT/Jsi6RJ3N6pRw2BubeR1925Xl3jXQnlz5io6X1YRlAcnshZyf6CjBpKES32aTf1m1IHRhZ2Jj6i/g7Y\\u003d\",\"ephemeralPublicKey\":\"BDQA0Cf//BHPcnB0R/GRrWa2g7T1QF97eOhAYy7l45M+kJnsoeL9OaUQV/KIMLvcgbmKkZIm2FQeL7ftd6S4q4c\\u003d\",\"tag\":\"DHtVyXNo+PDr7Thi/EjBBbsr2k7y1SwGIn0D9mmPTJc\\u003d\"}" }
To process the payment using the token, return the base-64 encoded token string with your request to Square's payment api in the source_id
field prefixed by gpay:
{ "idempotency_key": "ID", "source_id": "gpay:GOOGLE_PAY_BASE64_ENCODED_TOKEN", "amount_money": { "amount": 50, "currency": "USD" }, "location_id": "LOCATION_ID", "billing_address": { "postal_code": "11111" } }
The following is a Node.js example that decodes the base-64 encoded
instrumentToken
from Braintree:
Node.js
function decodeToken(instrumentToken) { let decodedString = new Buffer(instrumentToken, 'base64').toString('ascii') if (decodedString.androidPayCards) { return decodedString.androidPayCards[0].nonce; } }