In order for your storefront to use 3D-Secure, you need to write a custom widget and use it to replace the CyberSource Payment Authorization Widget on the Payer Authentication Layout. The custom widget must manage various communications between the storefront, the Commerce Cloud server, and the credit card issuer.
The widget.json
file should be similar to the following:
{ "name": "Generic Card 3DS Widget", "javascript": "genericCard3DS", "jsEditable": true, "global": false, "i18nresources": "genericCard3DS", "imports": [ "payment", "paymentauthorization", "order", "site" ], "pageTypes": ["payment"] }
Write the widget JavaScript
The widget’s JavaScript code should implement the following logic:
Listen for the
ORDER_AUTHORIZE_PAYMENT
event and initiate payer authentication.Populate the authentication form and submit it to the issuer’s URL.
Publish a
PAYMENT_GET_AUTH_RESPONSE
event to trigger polling the Commerce Cloud server to detect when it receives the authorization response from the merchant.Handle timeout and error cases.
This section includes examples of code that implements these operations.
Listening for the ORDER_AUTHORIZE_PAYMENT
event and initiating payer authentication:
$.Topic(pubsub.topicNames.ORDER_AUTHORIZE_PAYMENT).subscribe(function(obj) { if (obj[0].details) { widget.authDetails = obj[0].details; widget.createSignatureIfIframeIsLoaded(widget.authDetails, 0); } });
Populating the authentication form and submitting it to the issuer’s URL:
widget.injectFormValuesForPayerAuth( uiIntervenedPaymentGroup.customPaymentProperties); widget.injectActionURL( uiIntervenedPaymentGroup.customPaymentProperties.payerAuthEnrollReply_acsURL); widget.postForm();
Publishing a PAYMENT_GET_AUTH_RESPONSE
event to trigger polling the Commerce Cloud server to detect when it receives the authorization response from the merchant:
var messageDetails = [{message: "success", orderid: authDetails.orderDetails.id, orderuuid: authDetails.orderDetails.uuid, paymentGroupId: uiIntervenedPaymentGroup.paymentGroupId, numOfRetries: uiIntervenedPaymentGroup.customPaymentProperties.maxRetryCount, delay: uiIntervenedPaymentGroup.customPaymentProperties.delayInMillis }]; $.Topic(pubsub.topicNames.PAYMENT_GET_AUTH_RESPONSE).publish(messageDetails);
Handling the error cases, such as being unable to access the issuer URL, or receiving an authentication error from the issuer. For example:
widget.handleErrors = function() { try { $.Topic(pubsub.topicNames.ORDER_SUBMISSION_FAIL).publish([{message: "fail"}]); } catch(e) { log.error('Error Handling Order Fail'); log.error(e); } try { widget.handleTimeout(); } catch(e) { log.error('Error Handling Timeout'); log.error(e); } };