0% found this document useful (0 votes)
28 views

CyberSource SiteGenesis Controllers LINK Cartridge 3DS2

Uploaded by

Deepa Narayan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views

CyberSource SiteGenesis Controllers LINK Cartridge 3DS2

Uploaded by

Deepa Narayan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 11

CyberSource SiteGenesis Controllers LINK

Cartridge 3DS2.X - Developer Guide

Upgrading from Version 17.2.X to Version 19.3.0

1
Table of Contents
1. CyberSource Cartridge Overview....................................................................................................................2
2. Payer Authentication.......................................................................................................................................2
Payer Authentication Service..........................................................................................................................6
3. Change Logs....................................................................................................................................................8
4. Support French Processor..............................................................................................................................11

1. CyberSource Cartridge Overview

The CyberSource package contains four cartridges. A core cartridge (int_cybersource) that contains core API
integrations, including the building and handling of API requests, and parsing responses into objects usable by
the storefront. The two legacy architecture cartridges (int_cybersource_pipelines,
int_cybersource_controllers) each contain sets of wrappers that connect the core code to their respective
SFCC platforms. Version 18.1 and higher of the CyberSource cartridge package adds a fourth cartridge
(int_cybersource_sfra/ LINK_cybersource), which combines a modified version of the core code that exists in
the int_cybersource, along with the necessary hooks, extensions, and wrappers to connect this code to the
SFRA storefront.

2. Payer Authentication
The CyberSource LINK Cartridge 19.3.0 provides support for the latest 3D Secure 2.x specification. Upgrading
your Payer Authentication integration from the legacy 3D Secure 1.0 specification to 2.x will allow for better
authentication rates from issuers and meet PSD2 regulatory requirements for Strong Customer Authentication
(SCA) in Europe.
The following is a high-level architectural diagram of how the Payer Authentication integration works:

2
Implementation of 3DS2.x

<Reference Generic section on CyberSource LINK Cartridge Version 19.3.0 integration guide document >
Template – summary.isml
Below changes are generic for Secure Accpetance/Klarna_credit/Device fingerprint

1. Set summary page tag for Secure Acceptance Iframe


<iscontent type="text/html" charset="UTF-8" compact="true"/>
<isset name="summarypage" value="${true}" scope="page"/>
<isdecorate template="checkout/pt_checkout"/>

2. Add below code above <isreportcheckout checkoutstep="${5}" checkoutname="${'OrderSummary'}"/>


<isscript>
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
</isscript>
<isset name="klarnarequired" value="${false}" scope="page"/>
<isif condition="${!empty(pdict.Basket)}">
<isset name="LineCntr" value="${pdict.Basket}" scope="page"/>
<iselseif condition="${!empty(pdict.Order)}">
<isset name="LineCntr" value="${pdict.Order}" scope="page"/>
</isif>
<isset name="summaryaction" value="${URLUtils.https('COSummary-Submit')}" scope="page" />
<script src="${URLUtils.staticURL('/lib/jquery/jquery-1.11.1.min.js')}" type="text/javascript"></script>
<isset name="paymentMethod" value="${null}" scope="page"/>
<isset name="isIFrame" value="${false}" scope="page" />
<isif condition="${!empty(LineCntr.getPaymentInstruments())}">
<isloop items="${LineCntr.getPaymentInstruments()}" var="paymentInstr" status="loopstate">
<isset name="paymentMethod" value="$
{dw.order.PaymentMgr.getPaymentMethod(paymentInstr.paymentMethod).ID}" scope="page"/>
<isif condition="$

3
{dw.order.PaymentMgr.getPaymentMethod(paymentInstr.paymentMethod).ID==CybersourceConstants.METHOD_SA_IFRAME}
">
<isset name="summaryaction" value="${URLUtils.https('COSummary-SubmitOrder')}" scope="page"
/>
<isset name="isIFrame" value="${true}" scope="page" />
<iselseif condition="$
{CybersourceConstants.KLARNA_PAYMENT_METHOD.equals(dw.order.PaymentMgr.getPaymentMethod(paymentInstr.payment
Method).ID)}" >
<isset name="klarnarequired" value="${true}" scope="page"/>
</isif>
</isloop>
</isif>
<isif condition="${!empty(LineCntr)}">
<isreportcheckout checkoutstep="${5}" checkoutname="$
{'OrderSummary'}"/>

3. Replace pdict.Basket with LineCntr at below places


<isif condition="${!pdict.CurrentForms.multishipping.entered.value}">
<ischeckoutprogressindicator step="3" multishipping="false" rendershipping="$
{LineCntr.productLineItems.size() == 0 ? 'false' : 'true'}"/>
<iselse/>
<ischeckoutprogressindicator step="4" multishipping="true" rendershipping="$
{LineCntr.productLineItems.size() == 0 ? 'false' : 'true'}"/>
</isif>
4. Add condition for secure acceptance error by replacing place order error with below code
<div id="errordiv">
<isif condition="${pdict.CurrentHttpParameterMap.SecureAcceptanceError != null && !
empty(pdict.CurrentHttpParameterMap.SecureAcceptanceError.stringValue)}">
<div class="error-form">${Resource.msg('confirm.error.technical','checkout',null)}</div>
<iselseif condition="${pdict.PlaceOrderError != null}">
<div class="error-form">${Resource.msg(pdict.PlaceOrderError.code,'checkout',null)}</div>
</isif>
</div>
</isif>

5. Replace pdict.Basket with LineCntr at below places


<iscomment>render each shipment</iscomment>
<isset name="shipmentCount" value="${0}" scope="page"/>

<isloop items="${LineCntr.shipments}" var="shipment" status="shipmentloopstate">

<isif condition="${shipment.productLineItems.size() > 0 ||


shipment.giftCertificateLineItems.size() > 0}">

<isset name="shipmentCount" value="${shipmentCount+1}" scope="page"/>


<isif condition="$
{LineCntr.shipments.size() > 1}">

.....
. . . <existing code>. . .
....
<iscomment>RENDER COUPON/ORDER DISCOUNTS</iscomment>
<isloop items="${LineCntr.couponLineItems}"
var="couponLineItem" status="cliloopstate">

4
....
. . <existing code>. .
....
<td class="item-total">
<isif condition="$
{couponLineItem.applied}">
<span class="coupon-applied">$
{Resource.msg('summary.applied','checkout',null)}</span>
<iselse/>
<span class="coupon-not-applied">$
{Resource.msg('summary.notapplied','checkout',null)}</span>
</isif>
</td>

</tr>
</isif>

</isloop>

<isloop items="${LineCntr.priceAdjustments}"
var="priceAdjustment" status="cliloopstate">

6.Update with below section for Klarna/Secure acceptance Iframe and device fingerprint and cardinal script related
changes
<div class="order-summary-footer">

<div class="place-order-totals">
<isordertotals p_lineitemctnr="${LineCntr}" p_showshipmentinfo="${false}"
p_shipmenteditable="${false}" p_totallabel="${Resource.msg('summary.ordertotal','checkout',null)}"/>
</div>
<isif condition="${!empty(klarnarequired) && klarnarequired}" >
<div id="klarna_container"></div>
<div id="auth_button"></div>
<input type="hidden" id="processorToken" name="processorToken" value=$
{session.privacy.processorToken}/>
</isif>
<isif condition="${!empty(pdict.Basket)}">
<form action="${summaryaction}" method="post" class="submit-order"
name="submitOrder">
<fieldset>
<div class="form-row">
<a class="back-to-cart <isif condition="${!
empty(klarnarequired) && klarnarequired}"> hide</isif>" href="${URLUtils.url('Cart-Show')}">
<isprint value="$
{Resource.msg('summary.editcart','checkout',null)}" encoding="off" />
</a>
<isif condition="${!empty(klarnarequired) &&
klarnarequired}" >

5
<input type="hidden" id="klarnaAuthToken"
name="klarnaAuthToken"/>
</isif>
<button class="button-fancy-large <isif condition="${!
empty(klarnarequired) && klarnarequired}"> hide</isif>" type="submit" name="submit" value="$
{Resource.msg('global.submitorder','locale',null)}">
$
{Resource.msg('global.submitorder','locale',null)}
</button>
</div>
<input type="hidden" name="$
{dw.web.CSRFProtection.getTokenName()}" value="${dw.web.CSRFProtection.generateToken()}"/>
<input type="hidden" id="DFReferenceId" name="DFReferenceId" />
</fieldset>
</form>
</isif>
</div>
<isif condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('CsDeviceFingerprintEnabled')}">
<isinclude url="${URLUtils.url('CYBCredit-IncludeDigitalFingerprint')}"/>
</isif>
<isif condition="${isIFrame}">
<isinclude template="secureacceptance/secureAcceptanceIframeSummmary"/>
</isif>
<isif condition="${pdict.iscardinal }">
<isinclude template="cardinal/songbird"/>
</isif>
</isdecorate>

Payer Authentication Service


Controller - COSummary.js
Update submit Function
Update function to handle Payer auth redirection
function submit() {
// Calls the COPlaceOrder controller that does the place order action and any payment authorization.
// COPlaceOrder returns a JSON object with an order_created key and a boolean value if the order was created
successfully.
// If the order creation failed, it returns a JSON object with an error key and a boolean value.
var cart = Cart.get();
var DFReferenceID = request.httpParameterMap.DFReferenceId.stringValue;
session.privacy.DFReferenceID = DFReferenceID;
var placeOrderResult = app.getController('COPlaceOrder').Start();
if (placeOrderResult.error) {
start({
PlaceOrderError: placeOrderResult.PlaceOrderError
});
} else if (placeOrderResult.order_created) {
showConfirmation(placeOrderResult.Order);
}else if(placeOrderResult.process3DRedirection){
var jwtUtil = require('int_cybersource/cartridge/scripts/cardinal/JWTBuilder');
var cardinalUtil = require('int_cybersource/cartridge/scripts/cardinal/CardinalUtils');
var OrderObject = cardinalUtil.getOrderObject(cart);
var orderdetailsObject =
cardinalUtil.getOrderDetailsObject(placeOrderResult.Order,placeOrderResult.authenticationTransactionID);
OrderObject.setOrderDetails(orderdetailsObject);
var jwtToken = jwtUtil.generateTokenWithKey(OrderObject);

var orderstring = JSON.stringify(OrderObject);

6
app.getView({Order: placeOrderResult.Order,
AcsURL:placeOrderResult.AcsURL,
PAReq:placeOrderResult.PAReq,
PAXID: placeOrderResult.PAXID,
authenticationTransactionID : placeOrderResult.authenticationTransactionID,
jwtToken:jwtToken,
orderstring :orderstring
}).render('cart/cardinalpayerauthentication');
}
}

Update start Function


Update start function to send jwt and order object
function start(context) {
var cart = Cart.get();
// Checks whether all payment methods are still applicable. Recalculates all existing non-gift certificate payment
// instrument totals according to redeemed gift certificates or additional discounts granted through coupon
// redemptions on this page.
var COBilling = app.getController('COBilling');
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
if (!COBilling.ValidatePayment(cart)) {
COBilling.Start();
return;
} else {
Transaction.wrap(function () {
cart.calculate();
});
Transaction.wrap(function () {
if (!cart.calculatePaymentTransactionTotal()) {
COBilling.Start();
}
});

7
COBilling.Start();
}
});
var order = "";
var jwtToken ="";
var iscardinal = false;
var selectedPaymentMethod = cart.getPaymentInstruments()[0].paymentMethod;
if(selectedPaymentMethod.equals(CybersourceConstants.METHOD_CREDIT_CARD) ||
selectedPaymentMethod.equals(CybersourceConstants.METHOD_SA_SILENTPOST)
|| selectedPaymentMethod.equals(CybersourceConstants.METHOD_VISA_CHECKOUT))
{
var jwtUtil = require('int_cybersource/cartridge/scripts/cardinal/JWTBuilder');
var cardinalUtil = require('int_cybersource/cartridge/scripts/cardinal/CardinalUtils');
jwtToken = jwtUtil.generateTokenWithKey();
var OrderObject = cardinalUtil.getOrderObject(cart);
order = JSON.stringify(OrderObject);
iscardinal = true;
}

var pageMeta = require('~/cartridge/scripts/meta');


var viewContext = require('app_storefront_core/cartridge/scripts/common/extend').immutable(context, {
Basket: cart.object,
jwtToken: jwtToken,
order : order,
iscardinal : iscardinal
});
pageMeta.update({pageTitle: Resource.msg('summary.meta.pagetitle', 'checkout', 'SiteGenesis Checkout')});
app.getView(viewContext).render('checkout/summary/summary');}}

3. Change Logs

Ac File Name Description


tio
n
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
8
AccountObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
Billing_Shipping_AddressObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ contains functions which are used to create order
CardinalUtils.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
CartItemObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
ConsumerObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ contains functions which create JWT Tokens
JWTBuilder.ds required for cardinal script initialization
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
OrderDetailsObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
OrderObject.ds Object which is passed to cardinal script
A int_cybersource/cartridge/scripts/cardinal/ prototype object which is useful for creating order
TokenObject.ds Object which is passed to cardinal script
M int_cybersource/cartridge/scripts/cybersource/ 1. getPartnerSolutionID changed to return new one
libCybersource.ds 2. methods added to get custompreference values
required for creating JWT Token
3. addPayerAuthEnrollInfo method modified to add
extra payerAuthEnrollService input parameters
referenceID,mobilePhone,transactionMode.
4. addPayerAuthValidateInfo method modified to
add extra payerAuthValidateService input
parameter authenticationTransactionID.
5. addPayerAuthReplyInfo method modified to add
paSpecificationVersion ,
directoryServerTransactionID input parameters to
ccAuthService request.
6. getTransactionMode method added to return
transactionmode value based on device type.
M int_cybersource/cartridge/scripts/façade/ 1. CCAuthRequest method modified to pass missing
CardFacade.ds parameters required for ccAuthService to
addPayerAuthReplyInfo method.
2. PayerAuthEnrollCheck modified to pass phone
number required for payerauthenrollservice to
addPayerAuthEnrollInfo method and new output
parameters from payerAuthEnrollReply
(authenticationTransactionID,specificationVersion,d
irectoryServerTransactionID,CAVV,UCAFAuthentica
tionData) response are set to responseObject.
3. In PayerAuthValidation method, null check is
added for PaRes value and processorTransactionId
is passed to addPayerAuthValidateInfo method and
new output parameters from

9
payerAuthValidateReply response
(specificationVersion,directoryServerTransactionID)
are set to responseObject.
M int_cybersource/cartridge/scripts/ 1.CreateRequestData method modified for proper
secureacceptance/helper/ functioning of secure acceptance payment.
SecureAcceptanceHelper.js 2. In AuthorizeCreditCard method,
authenticationTransactionID from payer enroll
service session.privacy.process3DRequestParent
set to true are forwarded for 3DS 2.0 Redirection .
M int_cybersource/cartridge/scripts/ 1. In PayerAuthEnrollCCAuthRequest method
visacheckout/façade/VisaCheckoutFacade.js authenticationTransactionID from
payerAuthEnrollReply response is set to
responseObject required for cardinal script continue
function. 2.
processorTransactionId from payments.validated
event in cardinal script is passed to
payerauthvalidation service and null check for
PaRes value in PayerAuthValidationCCAuthRequest
method.
M int_cybersource/cartridge/scripts/ processorTransactionId from payments.validated
visacheckout/helper/VisaCheckoutHelper.js event in cardinal script is passed to
PayerAuthValidationCCAuthRequest method in
payerAuthValidation method.
A int_cybersource/cartridge/templates/default/ This isml contains script and required html dom
cardinal/songbird.isml elements and cardinal events configured for
initialising the cardinal script.
A int_cybersource/cartridge/templates/default/ This isml contains script and required html dom
cart/cardinalpayerauthentication.isml elements and cardinal events configured for
initialising the cardinal script and cardinal continue
function to start a transaction.
M int_cybersource/cartridge/templates/default/ cybersource-custom.js script file is added which
secureacceptance/ opens an SA-Iframe in the summary page.
secureAcceptanceIframeSummary.isml
M int_cybersource/cartridge/webreferences/ wsdl properties modified for updating the
CyberSourceTransaction.wsdl cybersource endpoint.
A int_cybersource/cartridge/webreferences/ new XSD file for updated cybersource endpoint
CyberSourceTransaction_1.155.xsd
M int_cybersource_controllers/cartridge/scripts/ In Process3DRequestParent method,
Cybersource.js processorTransactionId returned by cardinal
commerce script is fetched from
httpParameterMap in the request received and an
empty check is added for it and it is passed to
payerauthvalidation services based on the
paymentinstrument.
A configuration/PayerAuth-Meta.xml

10
4. Support French Processor

To support French Processor, follow one of the below steps:


I. Install the latest Cybersource cartridge from Salesforce Marketplace – This is recommended
approach (OR)
II. Manually add below changes (SFCC’s GitHub commit) into your workspace code. It is always
recommended to test (both 3ds2 and 3ds1 test cards) the changes in your lower box before
promoting to Production org.

https://github.com/SalesforceCommerceCloud/link_cybersource/commit/
6f0b66980ce7e60ffb135b65b94d173fe6027c64
https://github.com/SalesforceCommerceCloud/link_cybersource/commit/
97d2fc51084bb9a88b66101e75b5bbc91329ba14
https://github.com/SalesforceCommerceCloud/link_cybersource/commit/
dc7dc3ef176673b1247b49d2f0e54fbe90d2be8b

And update base cartridge with below code.

Update the base cartridge file name app_storefront_core/cartridge/js/pages/checkout/billing.js


cctoken : cctoken,
ccnumber : ccnumber,
cvn : cvn,
month : month,
expyear : expyear,
cctype : cctype,
format : 'ajax'

Update the base cartridge file name: app_storefront_core/cartridge/static/default/js/app.js


cctoken : cctoken,
ccnumber : ccnumber,
cvn : cvn,
month : month,
expyear : expyear,
cctype : cctype,
format : 'ajax'

Update base cartridge file


app_storefront_core/cartridge/templates/default/account/payment/paymentinstrumentdetails.isml
<isinputfield formfield="$
{pdict.CurrentForms.paymentinstruments.creditcards.newcreditcard.number}"
dynamicname="true" type="input" attributes="${numberAttributes}"/>
<isinputfield formfield="$
{pdict.CurrentForms.paymentinstruments.creditcards.newcreditcard.cvn}"
dynamicname="true" type="input" attributes="${cvnAttributes}"/>

11

You might also like