This section describes the data sent between Commerce Cloud, the merchant, and the card issuer in a 3D-Secure implementation.
Send the webhook response
If 3D-Secure is required for a transaction, the merchant returns a responseCode
value of 10000 (PAYER_AUTH_REQUIRED)
when it sends the Generic Payment webhook response to the Commerce Cloud server. The payment group is not updated.
The merchant uses the additionalProperties
map in the webhook response to supply data needed for invoking the 3D-Secure authentication page on the card issuer’s web site. This data typically includes values such as acsURL (the issuer’s URL to direct the shopper to for authentication), paReq (the payer authentication request), MD (merchant data), and TermURL (the URL to return the shopper to after authentication). The exact set of properties, and the names for these properties, may differ depending on the card issuer. The merchant can also include maxRetryCount
and delayInMillis
properties as part of the additionalProperties
map to configure the storefront’s polling behavior.
The webhook also returns a customPaymentProperties
array that specifies a list of the properties from the additionalProperties
map that should be returned to the storefront. For example:
{ "transactionType": "0100", "orderId": "o140451", "channel": "preview", "locale": "en", "currencyCode": "USD", "authorizationResponse": { "additionalProperties": { "delayInMillis": "10000", "payerAuthEnrollReply_proxyPAN": "1078787", "amount": "000000003499", "orderId": "o140451", "channel": "storefront", "maxRetryCount": "5", "locale": "en", "transactionId": "o140451-pg140415-1480662437847", "transactionTimestamp": "2016-12-02T07:07:17+0000", "transactionType": "0100", "payerAuthEnrollReply_paReq": "eNpVkctuNBgiESLAKGWnXGsJiUPcByU/n3thQd", "paymentId": "pg140415", "payerAuthEnrollReply_acsURL": "http://www.example.com/ccstoreui/v1/genericCardAuth3DS", "paymentMethod": "card", "displayMessage": "Please wait .....", "payerAuthEnrollReply_xid": "Skh0MTRsZGsxYXZPbEd4a2I1VjA=", "TermUrl": "http://www.example.com/ccstoreui/v1/payment/genericCardResponses", "currencyCode": "USD", "gatewayId": "gateway3DS" }, "customPaymentProperties": ["delayInMillis", "payerAuthEnrollReply_proxyPAN", "amount", "decision", "orderId", "channel", "maxRetryCount", "locale", "transactionId", "transactionTimestamp", "transactionType", "payerAuthEnrollReply_paReq", "paymentId", "payerAuthEnrollReply_acsURL", "paymentMethod", "displayMessage", "reasonCode", "payerAuthEnrollReply_xid", "TermUrl", "currencyCode", "gatewayId"], "responseCode": "10000" } }
Authorize the payment
The Commerce Cloud server sends the data from the webhook response, including the 3D-Secure data, to the storefront in the createOrder
endpoint response. The storefront then posts a payer authentication request to the card issuer’s website using data received from the merchant. The issuer displays an authentication page in an inline frame on the Commerce Cloud storefront. (See Create a custom payment authorization widget for information about how to customize the storefront to do this.)
After the shopper fills out the authentication form and submits it, the card issuer and the merchant communicate to determine if the shopper authenticated successfully, and if so, whether to authorize the transaction. The merchant then sends an authorization response to the Commerce Cloud server, using the POST /ccstore/v1/payment/genericCardResponses
endpoint.
The data in the POST should be in the following format:
<input id="transactionType" name="transactionType" type="hidden" value="transaction
_t
ype
"/> <input id="currencyCode" name="currencyCode" type="hidden" value="currency
_c
ode
"/> <input id="locale" name="locale" type="hidden" value="locale
"/> <input id="channel" name="channel" type="hidden" value="channel
"/> <input id="orderId" name="orderId" type="hidden" value="order
_i
d
"/> <input id="signedKeys" name="signedKeys" type="hidden" value="signed_keys
"/> <input id="signature" name="signature" type="hidden" value="signature
"/> <input id="authorizationResponse" name="authorizationResponse" type="hidden" value="authorization
_r
esponse
_
JSON
"/>
The transactionType
, currencyCode
, locale
, channel
, and orderId
properties should take their values from the equivalent properties in the Generic Payment webhook request.
The authorizationResponse
value is a JSON object. The following table lists the top-level properties of the object:
Property | Description |
---|---|
transactionType | Match value from webhook request. |
currencyCode | Match value from webhook request. |
locale | Match value from webhook request. |
channel | Match value from webhook request. |
orderId | Match value from webhook request. |
signedKeys | A comma-separated list of the properties that are used to generate the signature. See Generate the signature. |
signature | The Base64 signature returned by the merchant. See Generate the signature. |
authorizationResponse | A map of key/value pairs containing authorization data. |
The following table lists the properties of the authorizationResponse
map. All properties are required unless specified otherwise:
Property | Description |
---|---|
paymentId | Match value from webhook request. |
transactionId | Match value from webhook request. |
transactionTimestamp | Match value from webhook request. |
paymentMethod | Match value from webhook request. |
gatewayId | Match value from webhook request. |
amount | The amount authorized. The value of this property is a positive, 12-digit number that is expressed in base currency. For example, $125.75 is represented as |
merchantTransactionId | The transaction reference ID from the merchant. |
merchantTransactionTimestamp | The timestamp of the transaction from the merchant, in milliseconds. |
hostTransactionId | The transaction reference ID from the payment gateway (optional). |
hostTransactionTimestamp | The timestamp of the transaction from the gateway, in milliseconds (optional). |
responseCode | The authorization decision from the payment provider as interpreted by the merchant. Must be one of the following values:
|
responseReason | Information about why the authorization succeeded or failed. |
responseDescription | Information from the payment gateway about the response. |
authCode | The authorization code for the transaction. |
token | The payment token used by the payment provider (optional). |
additionalProperties | Key/value pairs for additional properties sent by the merchant (optional). |
customPaymentProperties | A list of the properties in the additionalProperties object that should be returned to the storefront (optional). |
The following is an example of the authorizationResponse
JSON data:
{ "transactionType":"0100", "currencyCode":"USD", "locale":"en", "channel":"preview", "orderId":"o120419", "signedKeys":"transactionType,currencyCode,locale,channel,orderId,paymentId, transactionId,paymentMethod,gatewayId,amount,merchantTransactionId,authCode", "signature":"5ad0f437X6af6X4d4eXb08cX729a310843ce", "authorizationResponse": { "paymentId":"pg130411", "transactionId":"o120419-pg130411-1478862352044", "transactionTimestamp":"2016-08-05T12:24:54+0000", "paymentMethod":"card", "gatewayId":"gateway3DS", "amount":"000000009349", "merchantTransactionId":"mID1470399894815", "merchantTransactionTimestamp":"1470399894815", "hostTransactionId":"hID1470399894715", "hostTransactionTimestamp":"1470399894715", "responseCode":"1000", "responseReason":"AuthResponseReason", "responseDescription":"AuthResponseDescription", "authCode":"AUTH-ACCEPT", "token":"token-success", "additionalProperties": { "sample-addnl-property-key1":"sample-payment-property-value1", "sample-addnl-property-key2":"sample-payment-property-value2" }, "customPaymentProperties":["sample-addnl-property-key2"] }, }
Generate the signature
The merchant uses the shared secret key to generate a signature that it supplies when it sends the authorization response using the POST /ccstore/v1/payment/genericCardResponses
endpoint. When the Commerce Cloud server receives authorization response, it applies the same logic that the merchant uses to calculate the signature, and accepts the authorization only if both signatures match.
The signature is generated on the merchant server by performing an HmacSHA256 hash of the signedKeys
properties using the shared secret key. The minimum recommended set of properties to include in signedKeys
is:
signedKeys=transactionType,currencyCode,locale,channel,orderId,paymentId, transactionId,paymentMethod,gatewayId,amount,merchantTransactionId,authCode
Using the properties listed in signedKeys
, construct a comma-separated list of key/value pairs. For example, using the signedKeys
value from the authorizationResponse
data in the example above, the list would be:
transactionType=0100,currencyCode=USD,locale=en,channel=preview,orderId=o120419, paymentId=pg130411,transactionId=o120419-pg130411-1478862352044, paymentMethod=card,gatewayId=gateway3DS,amount=000000009349, merchantTransactionId=mID1470399894815,authCode=AUTH-ACCEPT
Note: Do not include any URL-encoded characters in the list.
Using the list of key/value pairs and the shared secret key, perform the hash to generate the signature. For example:
... // secretKey - shared secret Key provided by merchant in the gateway extension // dataToSign - comma separated key/value string SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(secretKeySpec); byte[] rawHmac = mac.doFinal(dataToSign.getBytes("UTF-8")); return Base64.encodeToString(rawHmac).replace("\n", "");
Retrieve the authorization response
After posting the payment request to the issuer’s website, the storefront begins polling the Commerce Cloud server using the getPaymentGroup
endpoint to determine if the server has received the authorization response from the merchant. When the Commerce Cloud server receives the authorization response, it includes the data from the merchant in the getPaymentGroup
endpoint response it sends to the storefront.