Cybersource Cartridge Controllers Integration Guide
Cybersource Cartridge Controllers Integration Guide
Copyright
© 07/24/2020 Cybersource Corporation. All rights reserved. Cybersource Corporation (“Cybersource”) furnishes this document and
the software described in this document under the applicable agreement between the reader of this document (“You”) and
Cybersource (“Agreement"“. You may use this document and/or software only in accordance with the terms of the Agreement.
Except as expressly set forth in the Agreement, the information contained in this document is subject to change without notice and
therefore should not be interpreted in any way as a guarantee or warranty by Cybersource. Cybersource assumes no responsibility
or liability for any errors that may appear in this document. The copyrighted software that accompanies this document is licensed to
You for use only in strict accordance with the Agreement. You should read the Agreement carefully before using the software.
Except as permitted by the Agreement, You may not reproduce any part of this document, store this document in a retrieval system,
or transmit this document, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior wr itten
consent of Cybersource.
By accepting this document, you acknowledge and accept that you are responsible for and assume liability for the functionality,
maintenance and availability of your software and network. At all times, it is your responsibility to ensure the accuracy, technical
sufficiency and functionality of your software, network, plug-ins, configurations, applications, code, application program interfaces
(APIs), software development kits and all other technology (“Your Network”). You are responsible for Your Network’s ability to use
and/or access the Cybersource network, any Cybersource API and receive the benefit of Cybersource’s services. You are
responsible for all costs, fees, expenses and liabilities associated with Your Network’s ability to access and interface with the
Cybersource network and receive the benefit of Cybersource’s services. Cybersource will not be responsible or liable for loss or
costs associated with or that results from Your Network’s inability to connect to or process transactions on the Cybersource network.
Trademarks
Authorize.Net, eCheck.Net, and The Power of Payment are registered trademarks of Cybersource Corporation. Cybersource,
Cybersource Payment Manager, Cybersource Risk Manager, Cybersource Decision Manager, and Cybersource Connect are
trademarks and/or service marks of Cybersource Corporation. Visa, Visa International, Cybersource, the Visa logo, and the
Cybersource logo are the registered trademarks of Visa International in the United States and other countries. Bank America and
the Bank America logo are the registered trademarks of Bank of America in the United States and other countries. All other
trademarks, service marks, registered marks, or registered service marks are the property of their respective owners.
Confidentiality Notice
This document is furnished to you solely in your capacity as a client of Cybersource and as a participant in the Visa payments
system.
By accepting this document, you acknowledge that the information contained herein (the “Information”) is confidential and subject to
the confidentiality restrictions contained in Visa's operating regulations and/or other confidentiality agreements, which limit your use
of the Information. You agree to keep the Information confidential and not to use the Information for any purpose other than its
intended purpose and in your capacity as a customer of Cybersource or as a participant in the Visa payments system. The
Information may only be disseminated within your organization on a need-to-know basis to enable your participation in the Visa
payments system. Please be advised that the Information may constitute material non-public information under U.S. federal
securities laws and that purchasing or selling securities of Visa Inc. while being aware of material non-public information would
constitute a violation of applicable U.S. federal securities laws.
2 Visa Confidential
Release: April 2023
Version: 23.1.0
Visa Confidential 3
Table of Contents
1. Introduction .................................................................................................................... 5
Contact .................................................................................................................................................................. 5
4 Visa Confidential
Retail POS .......................................................................................................................................................... 107
Batch Jobs .......................................................................................................................................................... 116
7. Subscription Token Creation ......................................................................................................................... 122
Unit Test Services ....................................................................................................................... 122
Authorize Credit Card ........................................................................................................................................ 124
12. Failover/Recovery Process .......................................................................................................................... 136
13. Supported Locales ....................................................................................................................................... 137
1. Introduction
• Description: Cybersource, a Visa solution, is the only global, modular payment
management platform built on secure Visa infrastructure with the payment reach and fraud
insights of a massive $500B+ global processing network. You can find out more about what
Cybersource does here.
• Categories: Payment Processing, Fraud Detection, Address Validation, Tax Computation
• Version: 23.1.0
• Compatibility: This version of the Cybersource cartridge is not compatible with the latest
versions of SG. This version is compatible with Salesforce B2C Commerce 21.2 release.
Contact
• Global Partner Solutions - CS: [email protected]
Visa Confidential 5
2. CyberSource SG Cartridge Architecture
NOTE: If you are using different IDE, refer respective developer guide to setup the workspace.
6 Visa Confidential
Step 3: Build and Upload the code
Prerequisite: Install node under "Cybersource" folder.
• npm install:
This assumes that you already have npm installed on your command line. If not,
please install node first. If you encounter an error, please try and address that first, either
by Googling or contacting us.
Gulp
Grunt
SCSS
Visa Confidential 7
4. Configure the Cartridge
Prerequisite
If you are new to Cybersource, and would like to start using Cybersource Cartridge quickly,
begin by signing up for a Sandbox Account.
You will also need to create an API Key and API Shared Secret Key that you can use to
authenticate requests to our sandbox server. Follow same steps to generate Production key
and shared secret.
• Service (cybersource.conversiondetailreport,
cybersource.soap.transactionprocessor.generic, cybersource.http.flextoken)
8 Visa Confidential
• Payment Method
Field Description
Enable Cybersource Enable or disable Cybersource Cartridge. If disabled none of the
Cartridge Cybersource services are invoked
Cybersource Merchant Cybersource Merchant ID
ID
CyberSource Cybersource SOAP Key. Follow the link for directions.
Merchant Key
CyberSource Endpoint Select Test(Test) or Production(Production)
CyberSource Unique identifier generated by Cybersource for System Integrator
Developer ID
Services (Required)
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import “metadata/site_genesis_meta /meta/Payment-Services.xml” in Business
Manager (Administration > Operations > Import & Export).
Step 2: Go to Administration > Operations > Services
Step 3: Make sure service with name cybersource.soap.transactionprocessor.generic exist.
Visa Confidential 9
5. Configure the Payment method
Payment Methods
1. Credit Card Authorization
1.1. Secure Acceptance Hosted Checkout – iFrame
1.2. Secure Acceptance Redirect
1.3. Secure Acceptance Checkout API
1.4. Secure Acceptance Flex MicroForm
1.5. Direct Cybersource SOAP API
2. Apple Pay
3. PayPal
4. Google Pay
5. Visa SRC
6. Bank Transfer
7. Alipay
8. Klarna
9. WeChat Pay
Custom Code
Pre-Requisite: Make sure the controller cartridges of site site-genesis is (say, e.g.
app_storefront_controllers and “int_cybersource, int_cybersource_controllers” are specified in Site
Settings path under Manage Sites > Merchant Site as per current site
Modify the references of actual storefront cartridges in CyberSource cartridges under
CybersourceConstants.ds during CyberSource integration. Cybersource cartridge is developed assuming
storefront cartridge naming conventions as:
• app_storefront_core
• app_storefront_controllers
Generic Section
Controller - COPlaceOrder.js
Update “handlePayments” Function
1. This function use for invoke payment processor Authorize function and check the result
2. Check for the result of authorization as failed
3. Return authorization result rather than empty when there is no error occurred
function handlePayments(order) {
var authorizationResult ={};
10 Visa Confidential
if (order.getTotalNetPrice() !== 0.00) {
if (paymentInstruments.length === 0) {
return {
missingPaymentInfo: true
};
}
/**
*SetsthetransactionIDforthepaymentinstrument.
*/
var handlePaymentTransaction = function () {
paymentInstrument.getPaymentTransaction().setTransactionID(order.getOrderNo());
};
if
(PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()).getPaymentProcesso
r() === null) {
Transaction.wrap(handlePaymentTransaction);
} else {
}
}
}
return authorizationResult;
}
Visa Confidential 11
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.technical')
};
});
}else if(handlePaymentsResult.returnToPage){
app.getView({
Order : handlePaymentsResult.order
}).render('checkout/summary/summary');
return {};
}else if(handlePaymentsResult.redirection){
response.redirect(handlePaymentsResult.redirectionURL);
return {};
}else if(handlePaymentsResult.carterror){
app.getController('Cart').Show();
return {};
}else if(handlePaymentsResult.intermediate){
app.getView({
alipayReturnUrl : handlePaymentsResult.alipayReturnUrl
}).render(handlePaymentsResult.renderViewPath);
return {};
} else if(handlePaymentsResult.intermediateSA){
app.getView({
Data:handlePaymentsResult.data, FormAction:handlePaymentsResult.formAction
}).render(handlePaymentsResult.renderViewPath);
return {};
}else if (handlePaymentsResult.missingPaymentInfo) {
session.custom.SkipTaxCalculation=false;
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.technical')
};
});
}else if (handlePaymentsResult.declined) {
session.custom.SkipTaxCalculation=false;
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined')
};
});
} else if (handlePaymentsResult.process3DRedirection) {
return handlePaymentsResult;
} else if (handlePaymentsResult.review) {
ReviewOrder({Order:order});
return {};
} else if (handlePaymentsResult.pending) {
ReviewOrder({Order:order});
return {};
}
12 Visa Confidential
var orderPlacementStatus = Order.submit(order);
if (!orderPlacementStatus.error) {
clearForms();
}
return orderPlacementStatus;
}
Visa Confidential 13
// Clears all forms used in the checkout process.
clearForms();
app.getController('COSummary').ShowConfirmation(order);
return;
}
Add “submitOrder” function
Add the submit order function with the code snippet below
/**
*Submittheorderandsendorderconfirmationemail
*@paramargs
*/
function SubmitOrder(args) {
var orderPlacementStatus = Order.submit(args.Order);
if (!orderPlacementStatus.error) {
clearForms();
app.getController('COSummary').ShowConfirmation(args.Order);
return;
}
app.getController('COSummary').Start();
}
Update “submit” function
Replace the submit function with the code snippet below
/*
* Asynchronous Callbacks for SiteGenesis.
* Identifies if an order exists, submits the order, and shows a confirmation message.
*/
function submit(args) {
var Provider = require('int_cybersource_controllers/cartridge/scripts/Provider');
var providerParam = request.httpParameterMap.provider.stringValue;
if(!empty(providerParam)) {
var providerResult = Provider.Check(args);
if(!empty(providerResult)){
if(providerResult.pending){
ReviewOrder({Order:providerResult.Order});
return;
}else if(providerResult.load3DRequest){
app.getView().render('cart/payerauthenticationredirect');
return;
} else if(providerResult.submit){
SubmitOrder({Order:providerResult.Order});
return;
} else if(providerResult.error){
fail({Order:providerResult.Order});
return;
} else if(providerResult.cancelfail){
app.getController('COSummary').Start({PlaceOrderError:providerResult.PlaceOrderError});
return;
} else if(providerResult.carterror){
app.getController('Cart').Show();
return;
} else if(providerResult.redirect){
app.getView({Location : providerResult.location}).render(providerResult.render);
return;
14 Visa Confidential
}
} else {
return;
}
}
app.getController('Cart').Show();
return;
}
Update Export functions
exports.Fail = guard.ensure(['https'], fail);
exports.ReviewOrder = ReviewOrder;
exports.SubmitOrder = SubmitOrder;
exports.FailWeChatOrder = guard.ensure(['https'], failWeChatOrder);
Controller - COBilling.js
Update Export Function
exports.ReturnToForm = guard.ensure(['https'], returnToForm);
Visa Confidential 15
if (null != cart && !empty(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID)) {
var Cybersource = require('int_cybersource_controllers/cartridge/scripts/Cybersource');
Cybersource.ResetPaymentForms({Basket:cart.object, PaymentType:
app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value});
}
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
var status = Transaction.wrap(function () {
if
(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(CybersourceC
onstants.METHOD_PAYPAL)) {
app.getForm('billing').object.paymentMethods.creditCard.clearFormElement();
cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_CREDIT
_CARD));
} else if
(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(PaymentInstru
ment.METHOD_CREDIT_CARD)) {
cart.removePaymentInstruments(cart.getPaymentInstruments(CybersourceConstants.METHOD_PAYP
AL));
} else if
(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(PaymentInstru
ment.METHOD_BML)) {
app.getForm('billing').object.paymentMethods.creditCard.clearFormElement();
if (!app.getForm('billing').object.paymentMethods.bml.ssn.valid) {
return false;
}
cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_CREDIT
_CARD));
}
return true;
});
return status;
}
if (!empty(request.httpParameterMap.noPaymentNeeded.value)) {
return true;
}
if (!empty(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value)
&&
16 Visa Confidential
app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(PaymentInstru
ment.METHOD_CREDIT_CARD)
&& empty(app.getForm('billing').object.paymentMethods.creditCard.selectedCardID.value)) {
if (!app.getForm('billing').object.valid) {
return false;
}
}
return true;
}
Visa Confidential 17
var Cybersource = require('int_cybersource_controllers/cartridge/scripts/Cybersource');
return Cybersource.SaveCreditCard();
Add below code snippet inside the condition for selectedCreditCard to update selectedcarduuid
in Credit card
if (selectedCreditCard) {
app.getForm('billing').object.paymentMethods.creditCard.number.value =
selectedCreditCard.getCreditCardNumber();
app.getForm('billing').object.paymentMethods.creditCard.selectedCardID.value =
selectedCreditCard.UUID;
Add new parameter “selectedPaymentMethod” and add Switch condition to handle different
APM’s as below:
[Note: All app.js changes are similar to billing.js, please refer the below section for billing.js
changes, below method contains generic code used for different payment methods as given
below]
function populateCreditCardForm(cardID,selectedPaymentMethod) {
// load card details
var url = util.appendParamToURL(Urls.billingSelectCC, 'creditCardUUID', cardID);
ajax.getJson({
url: url,
callback: function (data) {
if (!data) {
window.alert(Resources.CC_LOAD_ERROR);
returnfalse;
}
switch (selectedPaymentMethod) {
case "SA_REDIRECT":
$('.payment-method-expanded .saCCToken .field-wrapper').val(data.selectedCardID);
$("#dwfrm_billing_paymentMethods_creditCard_selectedCardID").val(data.selectedCardID);
break;
case "SA_IFRAME":
18 Visa Confidential
$('.payment-method-expanded .saIframeCCToken .field-
wrapper').val(data.selectedCardID);
$("#dwfrm_billing_paymentMethods_creditCard_selectedCardID").val(data.selectedCardID);
break;
case "CREDIT_CARD":
setCCFields(data);
break;
default:
setCCFields(data);
}
}
});
});
Visa Confidential 19
}
$creditCard.find('input[name$="_cvn"]').val('').trigger('change');
$creditCard.find('[name$="creditCard_selectedCardID"]').val(data.selectedCardID).trigger('change')
;
$creditCard.find("input[name$='_cvn']").val('');
}
[Note: This method contains generic code for different payment methods as given below]
function updatePaymentMethod(paymentMethodID) {
var $paymentMethods = $('.payment-method');
$paymentMethods.removeClass('payment-method-expanded');
var dataMethod = paymentMethodID;
if (paymentMethodID=='SA_SILENTPOST') {
dataMethod = 'CREDIT_CARD';
}
var $selectedPaymentMethod = $paymentMethods.filter('[data-method="' + dataMethod + '"]');
if ($selectedPaymentMethod.length === 0) {
$selectedPaymentMethod = $('[data-method="Custom"]');
}
if (paymentMethodID=="VISA_CHECKOUT") {
$(".continue-place-order").hide();
$(".visacheckoutbutton").show();
}
else if (paymentMethodID=="PAYPAL" || paymentMethodID=="PAYPAL_CREDIT") {
$("#billingAgreementCheckbox").attr('checked',false);
$(".continue-place-order").hide();
}
else {
$(".continue-place-order").show();
$(".visacheckoutbutton").hide();
}
if (paymentMethodID=="CREDIT_CARD" || paymentMethodID=="SA_SILENTPOST") {
$(".spsavecard").show();
} else if ((paymentMethodID=="SA_REDIRECT" || paymentMethodID=="SA_IFRAME") &&
SitePreferences.TOKENIZATION_ENABLED) {
$(".spsavecard").show();
}
else {
$(".spsavecard").hide();
}
$selectedPaymentMethod.addClass('payment-method-expanded');
20 Visa Confidential
$('input[name$="_selectedPaymentMethodID"]').removeAttr('checked');
$('input[value=' + paymentMethodID + ']').prop('checked', 'checked');
formPrepare.validateForm();
• Add below code snippetafter formPrepare.init to handle card details on billing page based
on APM selected
formPrepare.init({
formSelector: 'form[id$="billing"]',
continueSelector: '[name$="billing_save"]'
});
$ccContainer.find('input[name*="_number"]').on('change',function(e){
$($checkoutForm).find('input[name$="_selectedCardID"]').val('');
});
$ccContainer.find('input[name$="_owner"]').on('change',function(e){
$($checkoutForm).find('input[name$="_selectedCardID"]').val('');
});
$ccContainer.find('select[name$="creditCard_type"]').on('change',function(e){
$($checkoutForm).find('input[name$="_selectedCardID"]').val('');
});
$ccContainer.find('select[name*="expiration"]').on('change',function(e){
$($checkoutForm).find('input[name$="_selectedCardID"]').val('');
var selectedPaymentMethodID =
$('input[name$="_selectedPaymentMethodID"]:checked').val();
var cardNumber = $($checkoutForm).find('input[name*="_number"]').val();
if(cardNumber.indexOf('****') != -1 && selectedPaymentMethodID == 'SA_SILENTPOST'){
$($checkoutForm).find('input[name*="_number"]').val('');
}
});
Visa Confidential 21
updatePaymentMethod($(this).val());
});
// select credit card from list
$('#creditCardList').on('change', function () {
$selectedPaymentMethod.addClass('payment-method-expanded');
Form - customeraddress.xml
Include the following code just above the action events
<field formid="phone" label="profile.phone" description="address.phone.example" type="string"
mandatory="true" binding="phone" max-length="20"/>
<group formid="email">
<field formid="emailAddress" label="profile.email" type="string" mandatory="true"
regexp="^[\w.%+-]+@[\w.-]+\.[\w]{2,6}$" binding="email" max-length="50" missing-
error="forms.address.email.invalid" range-error="forms.address.email.invalid" parse-
error="forms.address.email.invalid" value-error="forms.address.email.invalid"/>
</group>
22 Visa Confidential
Form - paymentinstruments.xml
Include address fromId just below new credit card formId
Form – creditcard.xml
• Set the default value of formid="saveCard" to false
Visa Confidential 23
Template - paymentmethods.isml
1. Add code to declare CyberSource constant file
Line 4 to Line 6
<iscomment> TEMPLATENAME: paymentmethods.isml </iscomment>
<isinclude template="util/modules"/>
<isscript>
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
</isscript>
<isif condition="${pdict.OrderTotal > 0}">
2. Add conditional statement to show declined message for PayPal, visa checkout and
secure acceptance
Line 14 to Line 16
<legend>
${Resource.msg('billing.paymentheader','checkout',null)}
<div class="dialog-required"> <span class="required-indicator">•
<em>${Resource.msg('global.requiredfield','locale',null)}</em></span></div>
</legend>
<isif condition="${pdict.PaypalSetServiceError != null || pdict.VisaCheckoutError != null
|| pdict.SecureAcceptanceError != null}">
<div class="error-
form">${Resource.msg('confirm.error.declined','checkout',null)}</div>
</isif>
24 Visa Confidential
<isloop
items="${pdict.CurrentForms.billing.paymentMethods.selectedPaymentMethodID.options}"
var="paymentMethodType">
3. Remove red highlighted code and replace with a condition to display bank transfer
payment methods
Line 28
<isset name="radioID" value="${paymentMethodType.value}" scope="page"/>
<div class="field-wrapper">
<input id="is-${radioID}" type="radio" class="input-radio <isif
condition="${paymentMethodType.object.paymentProcessor.ID.equalsIgnoreCase("bank_transfer"
) == true }">bank-transfer</isif>"
name="${pdict.CurrentForms.billing.paymentMethods.selectedPaymentMethodID.htmlName}"
value="${paymentMethodType.htmlValue}" <isif condition="${paymentMethodType.value ==
pdict.CurrentForms.billing.paymentMethods.selectedPaymentMethodID.htmlValue}">checked="ch
ecked"</isif> />
4. Remove Credit card and bml payment method section as highlighted below
Remove code from line 44 to 94
<iscomment>
Credit card block
--------------------------------------------------------------
</iscomment>
Visa Confidential 25
</label>
Line 88
<isscript>
var currentCountry = require('~/cartridge/scripts/util/Countries').getCurrent(pdict);
</isscript>
Line 46 to Line 90
<isdynamicform
formobject="${pdict.CurrentForms.billing.paymentMethods.creditCard.expiration}"
formdata="${currentCountry.dynamicForms.expirationInfo}"/>
</div>
<isscript>
var help = {
26 Visa Confidential
7. Add below code for PayPal changes
<isinclude template="common/paymentmethods"/>
<iscomment>
Custom processor
--------------------------------------------------------------
</iscomment>
</div>
8. Take the value of selected payment method PayPal from constant file
Line 147
Visa Confidential 27
<div class="payment-method <isif condition="${!empty(pdict.selectedPaymentID) &&
pdict.selectedPaymentID==CybersourceConstants.METHOD_PAYPAL}">payment-method-
expanded</isif>" data-method="Custom">
<!-- Your custom payment method implementation goes here. -->
${Resource.msg('billing.custompaymentmethod','checkout',null)}
</div>
Template – summary.isml
Below changes are generic for Secure Accpetance/Klarna_credit/Device fingerprint
<isdecorate template="checkout/pt_checkout"/>
28 Visa Confidential
scope="page" />
<isset name="isIFrame" value="${true}" scope="page" />
<iselseif
condition="${CybersourceConstants.KLARNA_PAYMENT_METHOD.equals(dw.order.PaymentMgr.get
PaymentMethod(paymentInstr.paymentMethod).ID)}" >
<isset name="klarnarequired" value="${true}" scope="page"/>
</isif>
</isloop>
</isif>
<isif condition="${!empty(LineCntr)}">
</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"/>
Visa Confidential 29
.....
. . . <existing code>. . .
....
<iscomment>RENDER COUPON/ORDER DISCOUNTS</iscomment>
</tr>
</isif>
</isloop>
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"
30 Visa Confidential
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}" >
<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>
<isif condition="${klarnarequired}">
<script src="${URLUtils.staticURL('/js/cybersource-custom.js')}"></script>
</isif>
</isdecorate>
Template - cart.isml
1. Add if condition to handle PlaceOrder error on cart page inside cart-banner
<isslot id="cart-banner"description="Banner for Cart page" context="global"/>
<isif condition="${pdict.PlaceOrderError != null}">
<div class="error-
form">${Resource.msg(pdict.PlaceOrderError.code,'checkout',null)}</div>
</isif>
2. Update below code to apply coupon on cart page inside <div class="cart-footer">
<iselseif condition="${pdict.CouponStatus != null && pdict.CouponStatus.error}">
Visa Confidential 31
<div class="error">
${Resource.msgf("cart.APPLIED", "checkout", "",
pdict.CurrentForms.cart.couponCode.htmlValue)}
</div>
</isif>
</div>
Resources – form.properties
• Add year values above year year.2022=2022
year.2037=2037
year.2036=2036
year.2035=2035
year.2034=2034
year.2033=2033
year.2032=2032
year.2031=2031
year.2030=2030
year.2029=2029
year.2028=2028
year.2027=2027
year.2026=2026
year.2025=2025
year.2024=2024
year.2023=2023
year.2022=2022
Controller- common.js
Update validatePaymentInstruments function
Update below ifcondition so that expired card is not shown in saved credit card list during
checkout.
// In case of method CREDIT_CARD, check payment cards
if (PaymentInstrument.METHOD_CREDIT_CARD.equals(paymentInstrument.paymentMethod)) {
// Gets payment card.
var card = PaymentMgr.getPaymentCard(paymentInstrument.creditCardType);
32 Visa Confidential
if (card && cards.contains(card) && !paymentInstrument.isCreditCardExpired()) {
continue;
}
}
Overview
The CC Auth service is integrated via the SG OOTB dynamically generated
app.payment.processor.cybersource_credit hook. The cybersource_credit hook is registered in
the hooks.json file with script
./cartridge/scripts/hooks/payment/processor/cybersource_credit. This script acts as a wrapper
to the core CyberSource Authorization code. Behind this wrapper, an API request is
constructed, sent to CS, and the response parsed. In the case of a successful authorization
(response code 100), the hook returns a JSON object without an error. All other response codes
received result in an error being present in the return object, triggering the storefront to display
an error message, and not create the order. Actions taken when making the Authorization call
are as follows:
1. Creates CyberSource authorization request using ship-to, bill-to, credit card data, and
purchase total data from the current basket.
2. If authorize Payer is configured, then make the authorize payer request. If not, ignore
and continue with the authorization request.
3. Create a credit card authorization request.
4. If DAV is enabled, set up DAV business rules, as needed.
5. Set up AVS if enabled.
6. Make the service call to CyberSource via the SOAP API.
7. If Delivery Address Verification is enabled, then: a. Capture pertinent DAV result
information & DAV Reason Code. Update shipping address if a suggestion was returned
and the ‘CS DAV Update Shipping Address With DAV Suggestion’ site preference is
enabled. b. If DAV fails and DAV On Failure is set to ‘REJECT’, then exit immediately with
rejection response
8. If DAV On Failure is set to ‘APPROVE’ and the DAV Reason Code is a fail code (not 100),
then: a. Exit immediately with declined or review response, as merchant defines
9. Capture pertinent AVS information.
10. Capture Fraud response in a session variable to be handled later.
11. Validate authorization reason code and set corresponding values, based on Auth
response code.
Visa Confidential 33
Implementation
Cybersource Cartridge supports the following ways of processing Credit Card a. Secure
Acceptance Hosted Checkout – iFrame b. Secure Acceptance Redirect c. Secure Acceptance
Checkout API d. Secure Acceptance Flex MicroForm e. Direct Cybersource Payment API
Prerequsite
In the Business Manager, go to Merchant Tools > Ordering > Payment Methods and
select CREDIT_CARD. And in CREDIT_CARD details, double check if Payment
Processor = "CYBERSOURCE_CREDIT"
Form - creditcard.xml
1. Include the following form field after saveCard field in the form:
<!-- field for credit card subscription -->
2. Remove max-length="16" from credit card number field to allow cards numbers of
varied length.
Template - creditcardjson.isml
Update code to mask ccNumber inside if condition, also retrieve subscription token of saved
card to be used further:
<isscript>
var ccNumber;
if('maskedFourDigit' in pdict.SelectedCreditCard.custom &&
!empty(pdict.SelectedCreditCard.custom.maskedFourDigit)){
ccNumber = pdict.SelectedCreditCard.custom.maskedFourDigit;
} else {
ccNumber = pdict.SelectedCreditCard.maskedCreditCardNumber;
}
var cc = {
maskedNumber:ccNumber,
holder:pdict.SelectedCreditCard.creditCardHolder,
type:pdict.SelectedCreditCard.creditCardType,
expirationMonth:pdict.SelectedCreditCard.creditCardExpirationMonth,
expirationYear:pdict.SelectedCreditCard.creditCardExpirationYear,
selectedCardID:pdict.SelectedCreditCard.UUID
}
var json = JSON.stringify(cc);
</isscript>
34 Visa Confidential
Template - minicreditcard.isml
Add condition to map credit card number with four digit mask card number
<isscript>
var ccType, ccNumber, ccMonth, ccYear, ccOwner;
if (pdict.card) {
ccType = pdict.card.creditCardType;
if('maskedFourDigit' in pdict.card.custom && !empty(pdict.card.custom.maskedFourDigit)){
ccNumber = pdict.card.custom.maskedFourDigit;
} else {
ccNumber = pdict.card.maskedCreditCardNumber;
}
ccMonth = pdict.card.creditCardExpirationMonth;
ccYear = pdict.card.creditCardExpirationYear;
ccOwner = pdict.card.creditCardHolder;
}
</isscript>
Script - Resource.ds
Update ResourceHelper.getPreferences
COOKIE_HINT: (cookieHintAsset && cookieHintAsset.online) || false,
CHECK_TLS: Site.getCurrent().getCustomPreferenceValue('checkTLS'),
TOKENIZATION_ENABLED: (Site.getCurrent().getCustomPreferenceValue('CsTokenizationEnable')
== 'YES')? true : false
Controller–COBilling.js
Update initCreditCardList function
Update function to migrate old card based on current paymentIntstrument inside customer
authenticated if condition
if (customer.authenticated) {
var profile = app.getModel('Profile').get();
if (profile) {
applicableCreditCards = profile.validateWalletPaymentInstruments(countryCode,
paymentAmount.getValue()).ValidPaymentInstruments;
}
Controller - Hooks.json
Replace hook entry for CYBERSOURCE_CREDIT
[Note: Please delete CYBERSOURCE_CREDIT.js from <storefront controller
cartridge>/cartridge/script/payment/processor to process the file present in CyberSource
cartridge]
{
"name": "app.payment.processor.CYBERSOURCE_CREDIT",
"script":
Visa Confidential 35
"./../../../int_cybersource_controllers/cartridge/scripts/payment/processor/CYBERSO
URCE_CREDIT"
},
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_SecureAcceptance and set values for the parameter:
[Note: Below changes are covered in custom code > Generic section > COPlaceOrder.js, defined
here for reference only]
36 Visa Confidential
if (handlePaymentsResult.error) {
session.custom.SkipTaxCalculation=false;
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined')
};
});
}else if(handlePaymentsResult.returnToPage){
app.getView({
Order : handlePaymentsResult.order
}).render('checkout/summary/summary');
return {};
}else if(handlePaymentsResult.intermediateSA){
app.getView({
Data:handlePaymentsResult.data, FormAction:handlePaymentsResult.formAction
}).render(handlePaymentsResult.renderViewPath);
return {};
}else if (handlePaymentsResult.missingPaymentInfo) {
Controller - COSummary.js
Create new “SubmitOrder” function
Add a new function as below and add the export of the function at the end of file
function submitOrder() {
var cart = Cart.get();
if (cart) {
submit();
return;
} else if (!empty(session.privacy.order_id)) {
response.addHttpHeader("X-FRAME-OPTIONS","SAMEORIGIN");
var Order = app.getModel('Order');
app.getView({
Order : Order.get(session.privacy.order_id).object
}).render('checkout/summary/summary');
return;
} else {
app.getController('Cart').Show();
return {};
}
}
Visa Confidential 37
Template changes
Update “summary.isml”
Secure acceptance Iframe related changes are done in summary.isml
Please refer to the changes mentioned under custom code – generic section- >
summary.isml
Update “miniBillingInfo.isml”
Replace the line
<isset name="billingAddress" value="${pdict.Basket.billingAddress}" scope="page"/>
<isset name="paymentInstruments" value="${pdict.Basket.paymentInstruments}" scope="page"/> with the
code below
<isif condition="${!empty(pdict.Basket)}">
<isset name="lineCtnr" value="${pdict.Basket}" scope="page"/>
<isset name="billingAddress" value="${lineCtnr.billingAddress}" scope="page"/>
<isset name="paymentInstruments" value="${lineCtnr.paymentInstruments}" scope="page"/>
<iselseif condition="${!empty(pdict.Order)}">
<isset name="lineCtnr" value="${pdict.Order}" scope="page"/>
<isset name="billingAddress" value="${pdict.Order.billingAddress}" scope="page"/>
<isset name="paymentInstruments" value="${pdict.Order.paymentInstruments}" scope="page"/>
</isif>
<isif condition="${!empty(billingAddress)}">
<h3 class="section-header">
<isif condition="${!empty(pdict.Basket)}"><a href="${URLUtils.https('COBilling-Start')}"
class="section-header-note">${Resource.msg('global.edit','locale',null)}</a></isif>
${Resource.msg('minibillinginfo.billingaddress','checkout',null)}
</h3>
<div class="details">
<isminicheckout_address p_address="${billingAddress}"/>
</div>
38 Visa Confidential
</div>
Update “miniSummary.isml”
• Add below code snippet just above this line <isif
condition="${!empty(pdict.checkoutstep)}">
<isif condition="${!empty(pdict.Basket)}">
<isset name="lineCtnr" value="${pdict.Basket}" scope="page"/>
<iselseif condition="${!empty(pdict.Order)}">
<isset name="lineCtnr" value="${pdict.Order}" scope="page"/>
</isif>
<isif condition="${!empty(pdict.checkoutstep)}">
• Replace the line with below line <isif condition="${checkoutstep <= 5}">
<isif condition="${lineCtnr.productLineItems.size() == 0
&&lineCtnr.giftCertificateLineItems.size() == 1}">
<isset name="editUrl" value="${URLUtils.url('GiftCert-Edit','GiftCertificateLineItemID',
lineCtnr.giftCertificateLineItems[0].UUID)}" scope="page"/>
</isif>
Visa Confidential 39
• Replace the line with below ${Resource.msg('summary.title','checkout',null)} <a
class="section-header-note"
href="${editUrl}">${Resource.msg('global.edit','locale',null)}</a>
${Resource.msg('summary.title','checkout',null)} <isif
condition="${!empty(pdict.Basket)}"><a class="section-header-note"
href="${editUrl}">${Resource.msg('global.edit','locale',null)}</a></isif>
<div class="checkout-mini-cart">
<isif condition="${checkoutstep != 5 && checkoutstep != 6}">
<isminilineitems p_lineitemctnr="${lineCtnr}"/>
</isif>
</div>
Update “minshipments.isml”
• Replace this line <isset name="Shipments" value="${pdict.Basket.shipments}"
40 Visa Confidential
scope="page"/> with below code snippet
<isif condition="${!empty(pdict.Basket)}">
<isset name="lineCtnr" value="${pdict.Basket}" scope="page"/>
<isset name="Shipments" value="${lineCtnr.shipments}" scope="page"/>
<iselseif condition="${!empty(pdict.Order)}">
<isset name="lineCtnr" value="${pdict.Order}" scope="page"/>
<isset name="Shipments" value="${pdict.Order.shipments}" scope="page"/>
</isif>
Visa Confidential 41
<iselseif condition="${shipment.shippingAddress != null &&lineCtnr.productLineItems.size() >
0}">
Update “ReportCheckout.isml”
• Add a condition after this <isset name="checkoutname" value="${pdict.checkoutname}"
scope="page"/> with below code snippet
• Replace pdict.Basket with LineCntr twice in file along with null check
.SecureAcceptance_IFRAMEiframe{
height:600px !important;
}
42 Visa Confidential
1.2. To Setup Secure Acceptance Redirect
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or
import "metadata/site_genesis_meta/meta/Cybersource_SecureAcceptance.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_SecureAcceptance and set values for the parameter:
[Note: Below changes are covered in custom code > Generic section > COPlaceOrder.js, defined
here for reference only]
Visa Confidential 43
var handlePaymentsResult = handlePayments(order);
if (handlePaymentsResult.error) {
session.custom.SkipTaxCalculation=false;
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined')
};
});
}else if(handlePaymentsResult.intermediateSA){
app.getView({
Data:handlePaymentsResult.data, FormAction:handlePaymentsResult.formAction
}).render(handlePaymentsResult.renderViewPath);
return {};
} else if (handlePaymentsResult.missingPaymentInfo) {
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_SecureAcceptance and set values for the parameter:
44 Visa Confidential
SA_Silent_SecretKey Secure Acceptance Silent Post Secret
Key. Follow this link.
Secure_Acceptance_Token_Create_E Secure_Acceptance_Token_Create_E
ndpoint ndpoint.
Secure_Acceptance_Token_Update_ Secure_Acceptance_Token_Update_E
Endpoint ndpoint.
Core – Resource.ds
• Add two new Resource in ResourceHelper.getResources
Visa Confidential 45
TLS_WARNING : Resource.msg('global.browsertoolscheck.tls', 'locale', null),
INVALID_SERVICE : Resource.msg('checkout.getsignature.service.problem',
'cybersource', null),
INVALID_CREDITCARD : Resource.msg('checkout.invalid.credit.card.info',
'cybersource', null),
Create a new secure acceptance silent post function to handle credit card information using
Ajax call above this function $couponCode.on('keydown', function (e) {
$('.secureacceptance').on('click', function (e) {
var $selectPaymentMethod = $('.payment-method-options');
var selectedPaymentMethod = $selectPaymentMethod.find(':checked').val();
if ('SA_SILENTPOST' == selectedPaymentMethod) {
var $checkoutForm = $('.checkout-billing');
var ccnumber = $($checkoutForm).find('input[name$="_creditCard_number"]').val();
var cvn = $($checkoutForm).find('input[name$="_creditCard_cvn"]').val();
var month = $('.payment-method-expanded .month select').val();
var expyear = $('.payment-method-expanded .year select').val();
var dwcctype = $('.payment-method-expanded .cctype select').val();
var savecc =
$($checkoutForm).find('input[name$="_creditCard_saveCard"]').is(':checked');
var customerEmail = $("#dwfrm_billing_billingAddress_email_emailAddress").val();
var cardmap= {'Visa': '001','Amex': '003','MasterCard': '002','Discover':
'004','Maestro':'042'};
if(month.length == 1) {
month = "0"+month;
}
var cctype = cardmap[dwcctype];
var firstname =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_firstName"]').val());
var lastname =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_lastName"]').val());
var address1 =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_address1"]').val());
var address2 =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_address2"]').val());
var city =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_city"]').val());
var zipcode =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_postal"]').val());
var country =
46 Visa Confidential
encodeRequestFieldValue($($checkoutForm).find('select[name$="_addressFields_country"]').val());
var state = $($checkoutForm).find('select[name$="_addressFields_states_state"]').val();
if (state===undefined) {
state = $($checkoutForm).find('input[name$="_addressFields_states_state"]').val();
}
state = encodeRequestFieldValue(state);
var phoneno =
encodeRequestFieldValue($($checkoutForm).find('input[name$="_addressFields_phone"]').val());
var cctoken = encodeRequestFieldValue($('[data-
method="CREDIT_CARD"]').find('[name$="creditCard_selectedCardID"]').val());
if(cctoken) {
validCardNumber = true;
}
$($checkoutForm).find('input[name$="_creditCard_number"]').val("");
$($checkoutForm).find('input[name$="_creditCard_cvn"]').val("");
$($checkoutForm).find('input[name$="_creditCard_expiration_month"]').val("");
$($checkoutForm).find('input[name$="_creditCard_expiration_year"]').val("");
$($checkoutForm).find('input[name$="_creditCard_type"]').val("");
if(xhr) {
if(xhr.error == true) {
$("#saspCardError").html(xhr.errorMsg);
$("#saspCardError").addClass('error');
}
else {
$("#secureAcceptancePost").html(xhr);
$("#card_expiry_date").val(month +'-'+expyear);
Visa Confidential 47
$("#card_type").val(cctype);
$("#card_cvn").val(cvn);
if(cctoken == null || cctoken == '') {
$('#silentPostFetchToken').append('<input
type="hidden" id="card_number" name="card_number" />');
$("#card_number").val(ccnumber);
}
$("#silentPostFetchToken").submit();
}
}
else {
$("#saspCardError").html(Resources.INVALID_SERVICE);
$("#saspCardError").addClass('error');
}
},
error: function () {
$("#saspCardError").html(Resources.INVALID_SERVICE).addClass('error');
}
});
}
else{
$("#saspCardError").html(Resources.INVALID_CREDITCARD);
$("#saspCardError").addClass('error');
returnfalse;
}
}
else{
$('.secureacceptance').prop("type", "submit").submit();
returntrue;
}
});
48 Visa Confidential
var $paymentMethods = $('.payment-method');
$paymentMethods.removeClass('payment-method-expanded');
var dataMethod = paymentMethodID;
if (paymentMethodID=='SA_SILENTPOST') {
dataMethod = 'CREDIT_CARD';
}
var $selectedPaymentMethod = $paymentMethods.filter('[data-method="' + dataMethod + '"]');
if ($selectedPaymentMethod.length === 0) {
$selectedPaymentMethod = $('[data-method="Custom"]');
}
if (paymentMethodID=="VISA_CHECKOUT") {
$(".continue-place-order").hide();
$(".visacheckoutbutton").show();
}
else if (paymentMethodID=="PAYPAL" || paymentMethodID=="PAYPAL_CREDIT") {
$("#billingAgreementCheckbox").attr('checked',false);
$(".continue-place-order").hide();
}
else {
$(".continue-place-order").show();
$(".visacheckoutbutton").hide();
}
if (paymentMethodID=="CREDIT_CARD" || paymentMethodID=="SA_SILENTPOST") {
$(".spsavecard").show();
} else if ((paymentMethodID=="SA_REDIRECT" || paymentMethodID=="SA_IFRAME") &&
SitePreferences.TOKENIZATION_ENABLED) {
$(".spsavecard").show();
}
else {
$(".spsavecard").hide();
}
$selectedPaymentMethod.addClass('payment-method-expanded');
formPrepare.validateForm();
Step 1: In Business Manager, go to Administration > Customization > Services and click on the
‘cybersourceflextoken’ Credentials. Ensure the appropriate URL is set for the environment you
Visa Confidential 49
are configuring. - Test: https://apitest.cybersource.com/flex/v1/keys -
Production: https://api.cybersource.com/flex/v1/keys
Step 2: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/ site_genesis_meta
/meta/Cybersource_SecureAcceptance.xml" in Business Manager (Administration > Site
Development > Import & Export)
Step 3: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource-
FlexMicroform and set values for the parameter:
Step 4: Navigate to ‘Administration > Global Preferences > Locales’ and ensure the local
‘en_US’ is present. If not present, create a new local with the following information:
• Language Code: en
• Country Code: US
• XML Code: en-US
• ISO-3 Language: eng
• ISO-3 Country: USA
• Fallback Locale: English(en)
Once present, select the ‘en_US’ local, and navigate to the ‘Regional Settings’ tab. In the ‘Long
Date Pattern’ field, enter the sting: EEE, dd MMM yyyy HH:mm:ss z
Controller - COBilling.js
50 Visa Confidential
function validateBilling() {
if (!app.getForm('billing').object.billingAddress.valid) {
return false;
}
if (!empty(request.httpParameterMap.noPaymentNeeded.value)) {
return true;
}
if
(!empty(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value)
&&
app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(Pay
mentInstrument.METHOD_CREDIT_CARD)
&&
empty(app.getForm('billing').object.paymentMethods.creditCard.selectedCardID.value))
{
if (!app.getForm('billing').object.valid &&
empty(app.getForm('billing').object.paymentMethods.creditCard.flexresponse.value)) {
return false;
}
}
return true;
XML - creditcard.xml
Script - Resource.ds
Update ResourceHelper.getUrls
orderreview : URLUtils.https('COSummary-Start').toString(),
orderSubmit : URLUtils.https('COSummary-Submit').toString(),
WeChatCheckStatus : URLUtils.https('CYBWeChat-CheckStatusService').toString(),
failWechatOrder : URLUtils.https('COPlaceOrder-FailWeChatOrder').toString()
Visa Confidential 51
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_SecureAcceptance and set values for the parameter:
Prerequisite
• Please contact your Cybersource Representative to sign up and receive your Payer
Authentication credentials.
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/PayerAuthentication.xml" in
Business Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_PayerAuthentication and set values for the following parameters:
Field Description
CruiseApiKey A shared secret value between the merchant and Cardinal. This
value should never be exposed to the public.
52 Visa Confidential
CardinalCruiseApiPath Songbird.js script API path. Refer the section CDN in this link to get
API path.
Step 3: Go to Merchant Tools > Ordering > Payment Methods, select 'Credit/Debit cards' and
check the payer authentication checkbox on any credit card types you want to support Payer
Authentication.
Strong customer authentication (SCA) is defined as “an authentication based on the use of two
or more elements categorised as knowledge (something only the user
knows), possession (something only the user possesses) and inherence (something the user
is). These must be independent from one another, in that the breach of one does not
compromise the reliability of the others, and is designed in such a way as to protect the
confidentiality of the authentication data.”
If response code 478 is received, the issuer is declining the authorisation request but advising
that if the card holder gets SCA’d, the issuer will approve the authorisation.
Proposed Approach
Automatically retry the transaction adding Payer Auth Mandate Challenge (code 04) to force
cardholder SCA challenge. This flow should appear seamless to the card holder
Site Preferences:
Visa Confidential 53
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/sfra_meta/meta/PayerAuthentication.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_PayerAuthentication and set values for the following parameters:
Field Description
Set the value for IsSCAEnabled to yes to use Strong Customer Authentiaction feature.
Upgrade to 3DS2.0
If you are currently using CYBS cartridge and would like to upgrade to 3DS2.0, please refer doc
CyberSource Storefront Reference Architecture LINK Cartridge 3DS2.docx under cartridge
documentation folder.
Controller - COSummary.js
Update submit Function
Updte 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 creditCardForm = app.getForm('billing.paymentMethods.creditCard');
var OrderObject = cardinalUtil.getOrderObject(cart,creditCardForm);
var orderdetailsObject =
cardinalUtil.getOrderDetailsObject(placeOrderResult.Order,placeOrderResult.authenticationTransactio
nID);
OrderObject.setOrderDetails(orderdetailsObject);
var jwtToken = jwtUtil.generateTokenWithKey(OrderObject);
54 Visa Confidential
app.getView({Order: placeOrderResult.Order,
AcsURL:placeOrderResult.AcsURL,
PAReq:placeOrderResult.PAReq,
PAXID: placeOrderResult.PAXID,
authenticationTransactionID : placeOrderResult.authenticationTransactionID,
jwtToken:jwtToken,
orderstring :orderstring
}).render('cart/cardinalpayerauthentication');
}
}
Visa Confidential 55
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 creditCardForm = app.getForm('billing.paymentMethods.creditCard');
var OrderObject = cardinalUtil.getOrderObject(cart,creditCardForm);
order = JSON.stringify(OrderObject);
iscardinal = true;
}
56 Visa Confidential
app_storefront_core/cartridge/js/pages/checkout/billing.js
cctoken : cctoken,
ccnumber : ccnumber,
cvn : cvn,
month : month,
expyear : expyear,
cctype : cctype,
format : 'ajax'
Upgrade to 3DS2.0
If you are currently using CYBS cartridge and would like to upgrade to 3DS2.0, please refer
below doc. If you are not able to download find the doc under cartridge documentation folder.
2. Apple Pay
A merchant identifier uniquely identifies you to Apple Pay as a merchant who is able to accept
payments. You can use the same merchant identifier for multiple native and web apps. It never
expires.
Visa Confidential 57
1. Go to Apple portal: https://help.apple.com/developer-
account/#/devb2e62b839?sub=dev103e030bb
2. In Certificates, Identifiers & Profiles, select Identifiers from the sidebar, then click the
Add button (+) in the upper-left corner.
3. Select Merchant IDs, then click Continue.
4. Enter the merchant description and identifier name, then click Continue.
5. Review the settings, then click Register.
58 Visa Confidential
1. Go to: “Merchant Tools > Site Preferences > Apple pay
2. Check “Apple Pay Enabled?”
3. Fill in the “Onboarding” form:
• Ensure “Apple Merchant ID” and “Apple Merchant Name” match settings in your
Apple account
• Ensure all other fields match your supported Cybersource settings
4. Fill in the “Storefront Injection” form:
• Selects where Apple Pay buttons should be displayed on your site.
5. Fill in “Payment Integration” form:
• Leave all form fields blank
• Ensure “Use Basic Authorization” is checked
6. Click "Submit"
1. In the Business Manager, go to Merchant Tools > Ordering > Payment Methods and
select DW_APPLE_PAY. And in DW_APPLE_PAY details, double check if Payment
Processor = "CYBERSOURCE_CREDIT"
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/ApplePay.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Apple Pay and set
values for the following parameters:
Field Description
Visa Confidential 59
3. PayPal
Implementation
Cybersource Cartridge supports the following for PayPal: a. PayPal Express b. PayPal Credit c.
PayPal Billing Agreement
Prerequisite
Prior to development phase, there are a generic set of configurations that a development team
needs to account for. These configurations include:
2. PayPal sandbox account Screenshot of the detailed set of configurations for #1 & #2.
3. Linking developer and sandbox account. On creating a PayPal developer account, get in
touch with the CyberSource team, share the developer account details and get the
developers’ details configured on CyberSource (BackOffice Configuration tool). Share
the following keys with Cybersource:
60 Visa Confidential
• ClientID (paypalgateway_client_key) - Follow this link to generate.
• Secret (paypalgateway_secret_phrase) - Follow this link to generate.
• Merchant Account ID (paypalgateway_mid) – Follow this link to generate.
• Merchant email (paypalgateway_merchant_email) - Follow this link to generate.
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_Paypal.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource_Paypal
and set values for the parameter:
Field Description
Paypal Order Type The type of authorization to follow for PayPal orders. Select
STANDARD for Authorize & Capture or select CUSTOM for just
Authorize
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_Paypal.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource_Paypal
and set values for the parameter:
Field Description
Paypal Order The type of authorization to follow for PayPal orders. Select STANDARD for
Type Authorize & Capture or select CUSTOM for just Authorize
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_Paypal.xml" in
Business Manager (Administration > Site Development > Import & Export).
Visa Confidential 61
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource_Paypal
and set values for the parameter:
Field Description
Paypal Order The type of authorization to follow for PayPal orders. Select STANDARD for
Type Authorize & Capture or select CUSTOM for just Authorize
footer_ui.isml
Place below lines of code in footer_ui.isml at end of file
<isscript>
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
</isscript>
<isif
condition="${dw.order.PaymentMgr.getPaymentMethod(CybersourceConstants.METHOD_PAYPAL).is
Active() && dw.system.Site.current.getCustomPreferenceValue('CsEnableExpressPaypal')==true}">
<scriptsrc="https://www.paypalobjects.com/api/checkout.js"></script>
</isif>
<scriptsrc="${URLUtils.staticURL('/js/cybersource-custom.js')}"></script>
Minicart.isml
Include script module after util/module
<isincludetemplate="util/modules"/>
<isscript>
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
62 Visa Confidential
</isscript>
</form>
Cart.isml
Add cubersource constants after API include section
<isincludetemplate="util/reporting/ReportBasket.isml"/>
<isscript>
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
</isscript>
Add below lines of inside <div class="cart-actions > and <div class="cart-actions cart-actions-
top">
<div class="cart-actions cart-actions-top">
<iscomment>continue shop url is a non-secure but checkout needs a secure and that is
why separate forms!</iscomment>
Visa Confidential 63
<form class="cart-action-
checkout"action="${URLUtils.continueURL()}"method="post"name="${pdict.CurrentForms.cart.dynamic
HtmlName}"id="checkout-form">
<fieldset>
<isif condition="${enableCheckout}">
<button class="button-fancy-large" type="submit"
value="${Resource.msg('global.checkout','locale',null)}"
name="${pdict.CurrentForms.cart.checkoutCart.htmlName}">
${Resource.msg('global.checkout','locale',null)}
</button>
<isif
condition="${dw.order.PaymentMgr.getPaymentMethod(CybersourceConstants.METHOD_PAYPAL).is
Active() && dw.system.Site.current.getCustomPreferenceValue('CsEnableExpressPaypal')==true}">
<isif
condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('payPalBillingAgreements') &&
!empty(pdict.CurrentCustomer.profile) &&
!empty(pdict.CurrentCustomer.profile.custom.billingAgreementID)}">
<input type="image"
src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" alt="Paypal Express"
class="billingAgreementExpressCheckout"/>
<iselse>
<div class="paypal-button-container-cart2"></div>
</isif>
</isif>
<div class="cart-actions">
<iscomment>continue shop url is a non-secure but checkout needs a secure and that is
why separate forms!</iscomment>
<form class="cart-action-checkout" action="${URLUtils.continueURL()}" method="post"
name="${pdict.CurrentForms.cart.dynamicHtmlName}" id="checkout-form">
<fieldset>
<isif condition="${enableCheckout}">
<button class="button-fancy-large" type="submit"
value="${Resource.msg('global.checkout','locale',null)}"
name="${pdict.CurrentForms.cart.checkoutCart.htmlName}">
${Resource.msg('global.checkout','locale',null)}
</button>
<isif
condition="${dw.order.PaymentMgr.getPaymentMethod(CybersourceConstants.METHOD_PAYPAL).is
Active() && dw.system.Site.current.getCustomPreferenceValue('CsEnableExpressPaypal')==true}">
<isif
condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('payPalBillingAgreements') &&
!empty(pdict.CurrentCustomer.profile) &&
!empty(pdict.CurrentCustomer.profile.custom.billingAgreementID)}">
<input type="image"
src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" alt="Paypal Express"
class="billingAgreementExpressCheckout"/>
<iselse>
<div class="paypal-button-container-cart1"></div>
64 Visa Confidential
</isif>
</isif>
Resources.ds
Add below urls in urls json object under ResourceHelper.getUrls method.
,
paypalinitsession : URLUtils.url('CYBPaypal-InitiatePaypalExpress').toString(),
paypalcallback : URLUtils.https('CYBPaypal-SessionCallback').toString(),
billingagreement : URLUtils.https('CYBPaypal-BillingAgreement').toString(),
orderreview : URLUtils.https('COSummary-Start').toString()
,
ISPAYPALENABLED : (dw.order.PaymentMgr.getPaymentMethod('PAYPAL').isActive()
&&Site.getCurrent().getCustomPreferenceValue('CsEnableExpressPaypal')?true:false)
Checkout.properties
Add billingagreement message for PayPal.
billing.selectcreditcard=SelectCreditCard
billing.billingagreement=CreateBillingAgreement
Paymentmethods.isml
Include cubersource constant at API include section
Changes are aleady covered under custom code > generic section-> paymentmethods.isml
PAYPAL_EXPRESS.js
Include Cybersource constants at API include section
Visa Confidential 65
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
var CommonHelper =
require(CybersourceConstants.CS_CORE_SCRIPT+'helper/CommonHelper');
Transaction.wrap(function () {
CommonHelper.removeExistingPaymentInstruments(cart);
var paymentInstrument =
cart.createPaymentInstrument(CybersourceConstants.METHOD_PAYPAL,
cart.getNonGiftCertificateAmount());
});
if(paymentResponse.authorized)
{
return {authorized: true};
}else if(paymentResponse.pending){
return {review: true};
}
else{
return {error: true};
}}
66 Visa Confidential
ValidatePaymentInstruments.ds
Add import
importPackage( dw.web );
if(PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(pi.paymentMethod) ||
Resource.msg("paymentmethodname.paypal", "cybersource", null).equals(pi.paymentMethod))
{
continue;
PayPal Credit
Controller – PAYPAL_CREDIT.js
Include API at the top of file as below:
/* API Includes */
var Cart = require('~/cartridge/scripts/models/CartModel');
var PaymentMgr = require('dw/order/PaymentMgr');
var Transaction = require('dw/system/Transaction');
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
var CommonHelper =
require(CybersourceConstants.CS_CORE_SCRIPT+'helper/CommonHelper');
function Handle(args) {
var cart = Cart.get(args.Basket);
Transaction.wrap(function () {
CommonHelper.removeExistingPaymentInstruments(cart);
var paymentInstrument =
cart.createPaymentInstrument(CybersourceConstants.METHOD_PAYPAL_CREDIT,
cart.getNonGiftCertificateAmount());
});
Visa Confidential 67
Update authorize function for PayPal credit payment instrument
function Authorize(args) {
var paymentInstrument = args.PaymentInstrument;
var paymentProcessor =
PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()).getPaymentProcessor();
var adapter = require(CybersourceConstants.PAYPAL_ADAPTOR);
//Logic to determine if this is standard/custom Paypal order
Transaction.wrap(function () {
paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor;
});
var paymentResponse = adapter.PaymentService(args.Order,paymentInstrument);
if(paymentResponse.authorized)
{
return {authorized: true};
}else if(paymentResponse.pending){
return {review: true};
}
else{
return {error: true};
}
}
Paymentmethods.isml
Above mentioned steps for PayPal Express is also required for PayPal credit except minicart.isml
and cart.isml. Only additional div for payment-method need to add in paymentmethods.isml
Changes are aleady covered under custom code > generic section-> paymentmethods.isml
68 Visa Confidential
3. The above response must be available in script file defined in hook (say: hook script)
where OCAPI hook function to be developed
Interface AS Service
a. Using “Interface AS Service” has limitation that merchant site MUST disable “Limit
Storefront Order” setting
b. Register interface in service initialization script file say “SoapServiceInit.ds”
c. Define above service end point as merchant site URL for “CYBAndroidPay -Authorize” in
BM service configurations
d. Define user/password to be picked from site preferences “cybAndroidPayInterfaceUser”,
“cybAndroidPayInterfacePassword” in service initialization script file say
“SoapServiceInit.ds”
e. The Hook script file having OCAPI hook defined invoke service endpoint by passing
required JSON input. (The JSON Input format defined in appropriate REST Interface
section above in the document.)
f. Interpret the response received and display thank you page on success and order failure
page on failure
Parameter Type
lineItemCtnr dw.order.LineItemCtnr
orderNo String
IPAddress String
Cryptogram String
networkToken String
tokenExpirationMonth String
Visa Confidential 69
tokenExpirationYear String
cardType String
e. This function called to update the payment instrument with the service response
PaymentInstrumentUtils.UpdatePaymentTransactionCardAuthorize(paymentInstrument,
ServiceResponseObject: Object)
Parameter Type
paymentInstrument dw.order.PaymentInstrument
ServiceResponseObje Object
ct
f. Interpret the response received and display thank you page on success and order failure
page on failure
70 Visa Confidential
Cryptogram String
networkToken String
tokenExpiration String
Month
tokenExpiration String
Year
cardType String
f. This function called to update the payment instrument with the service response
PaymentInstrumentUtils.UpdatePaymentTransactionCardAuthorize(paymentInstru
ment, ServiceResponseObject: Object)
Parameter Type
paymentInstru dw.order.PaymentInstrument
ment
ServiceRespon Object
seObject
g. Interpret the response received and display thank you page on success and order failure
page on failure
4. Visa Checkout
Prerequisite:
1. To complete the checkout process successfully create Visa Checkout profile (link) on
CyberSource business center console under 'Account Management > Digital Payment
Solutions > Profiles > Enable Visa Checkout'.
2. Click profile tab and add profile, configure all the mandatory settings, also use API Key
from Setting Tab.
3. Create Secret key from ‘Account Management > Client Integration Management >
Payment Configuration > Key Management’. Click Generate key and select shared
secret.
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_VisaCheckout.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_VisaCheckout and set values for the parameter:
FIeld Description
Visa Confidential 71
widget/resources/js/integration/v1/sdk.js
LIVE: https://assets.secure.checkout.visa.com/checkout-
widget/resources/js/integration/v1/sdk.js
72 Visa Confidential
Visa Checkout
billing.js
Add a condition just afte selectedPaymentMethod condition to display or hide visa checkout
button on selected payment methods as ‘VISA_CHECKOUT’.
Sample code:
[Note: Below changes are covered in custom code > Generic section > billing.js, defined here for
reference only]
if (paymentMethodID=="VISA_CHECKOUT") {
$(".continue-place-order").hide();
$(".visacheckoutbutton").show();
}
else {
$(".continue-place-order").show();
$(".visacheckoutbutton").hide();
}
[note: this section updated in custom code section as to reduce redundancy]
Visa Confidential 73
paymentmethods.isml
1.) Add ondition for Visa Checkout error handling just after closing of </legend> block.
[Note: Below snippet is for reference purpose only, changes are aleady covered under
custom code > generic section ->COPlaceOrder.js]
billing.isml
• Add class on “continue to place order” button that would be used in billing.js to hide or
show button based on payment method selection below isbonusdiscountlineitem tag and
set type as button
<div class="form-row form-row-button">
<button class="button-fancy-large secureacceptance continue-place-
order"type="button"name="${pdict.CurrentForms.billing.save.htmlName}"
value="${Resource.msg('global.continueplaceorder','locale',null)}"><span>${Resourc
e.msg('global.continueplaceorder','locale',null)}</span></button>
</div>
</div>
cart.isml
1.) Include Visa checkout button:
Add following lines above cart-recommendations div
<!-- BEGIN Visa Checkout code -->
<isif
condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('cybVisaButtonOnCart')}">
<isif condition="${pdict.CurrentHttpParameterMap.visacheckout.value}">
<isinclude url="${URLUtils.url('CYBVisaCheckout-
74 Visa Confidential
Button','visacheckout','pdict.CurrentHttpParameterMap.visacheckout.value')}"/>
<iselse>
<isinclude url="${URLUtils.url('CYBVisaCheckout-Button')}"/>
</isif>
</isif>
<!-- END Visa Checkout code -->
minicart.isml
2.) Add following line in after </isapplepay> tag anddiv having id <div class="mini-cart-
totals"> before checkout button
<!-- BEGIN Visa Checkout code -->
<isif
condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('cybVisaButtonOnCart')}">
<isif condition="${empty(pdict.CurrentHttpParameterMap.visacheckout.value) ||
!pdict.CurrentHttpParameterMap.visacheckout.value}">
<isinclude url="${URLUtils.url('CYBVisaCheckout-
Button','buttonsource','minicart')}"/>
<iselse>
<isinclude url="${URLUtils.url('CYBVisaCheckout-Button')}"/>
</isif>
</isif>
<!-- END Visa Checkout code -->
footer_UI.isml
1.) Include the template visacheckout/launch.isml at the end of the file.
<iscomment>Visa Checkout launch</iscomment>
<isincludetemplate="visacheckout/launch.isml"/>
header.isml
1.) In the header section replace mini-cart section with below snippet
<iscomment>INCLUDE: Mini-cart, do not cache</iscomment>
<div id="mini-cart">
<isif condition="${!empty(pdict.CurrentHttpParameterMap.visacheckout.value) &&
pdict.CurrentHttpParameterMap.visacheckout.value}">
<isinclude url="${URLUtils.url('Cart-
MiniCart','visacheckout',pdict.CurrentHttpParameterMap.visacheckout.value)}"/>
<iselse>
<isinclude url="${URLUtils.url('Cart-MiniCart')}"/></isif>
</div>
htmlhead.isml
1.) Add following line to prevent visa checkout clickjacking in the end
<iscomment>Visa Checkout clickjacking prevention</iscomment>
<isinclude template="visacheckout/clickjackingPrevent.isml"/>
Visa Confidential 75
Controller - Cart.js
Update the Show() method with Visa checkout changes.
1.) Add following hightlighted line of code to show() function as shown in the snippet:
function show() {
var cartForm = app.getForm('cart');
app.getForm('login').invalidate();
cartForm.get('shipments').invalidate();
var VisaCheckout =
require('int_cybersource/cartridge/scripts/visacheckout/helper/VisaCheckoutHelper');
var VInitFormattedString='';
var signature='';
var result = VisaCheckout.Initialize();
if (result.success) {
VInitFormattedString = result.VInitFormattedString;
signature= result.signature;
}
// TO handle the visa checkout click even on cart and billing page from mini cart
session.custom.cyb_CurrentPage = "CybCart";
app.getView('Cart', {
cart: app.getModel('Cart').get(),
RegistrationStatus: false,
VInitFormattedString:VInitFormattedString,
Signature:signature
}).render('checkout/cart/cart');
Controller - COBilling.js
Update start function to make Visa checkout button non clickable on billing and cart page
/**
*Updatescartcalculationandpageinformationandrendersthebillingpage.
*@transactional
*@param{module:models/CartModel~CartModel}cart-ACartModelwrappingthecurrentBasket.
*@param{object}params-
(optional)ifpassed,addedtoviewpropertiessotheycanbeaccessedinthetemplate.
*/
function start(cart, params) {
app.getController('COShipping').PrepareShipments();
// TO handle the visa checkout click even on cart and billing page from mini cart
session.custom.cyb_CurrentPage = "CybBilling";
Transaction.wrap(function () {
cart.calculate();
});
76 Visa Confidential
var pageMeta = require('~/cartridge/scripts/meta');
pageMeta.update({
pageTitle: Resource.msg('billing.meta.pagetitle', 'checkout', 'SiteGenesis Checkout')
});
returnToForm(cart, params);
}
// if the payment method is set to gift certificate get the gift certificate code from the form
if (!empty(cart.getPaymentInstrument()) && cart.getPaymentInstrument().getPaymentMethod() ===
PaymentInstrument.METHOD_GIFT_CERTIFICATE) {
app.getForm('billing').copyFrom({
giftCertCode: cart.getPaymentInstrument().getGiftCertificateCode()
});
}
var VisaCheckout =
require('int_cybersource/cartridge/scripts/visacheckout/helper/VisaCheckoutHelper');
var VInitFormattedString='',signature='';
var result = VisaCheckout.Initialize(false);//no delivery address in lightbox
if (result.success) {
VInitFormattedString = result.VInitFormattedString;
signature = result.signature;
}
pageMeta.update({
pageTitle: Resource.msg('billing.meta.pagetitle', 'checkout', 'SiteGenesis Checkout')
});
if (params) {
app.getView(require('~/cartridge/scripts/object').extend(params, {
VInitFormattedString:VInitFormattedString,
Basket: cart.object,
Signature:signature,
ContinueURL: URLUtils.https('COBilling-Billing')
})).render('checkout/billing/billing');
} else {
app.getView({
Basket: cart.object,
VInitFormattedString:VInitFormattedString,
Signature:signature,
ContinueURL: URLUtils.https('COBilling-Billing')
}).render('checkout/billing/billing');
}
}
5. Bank Transfer
Visa Confidential 77
Bank Transfer supports 5 types of Payment methods –
• SOFORT
• BANCONTACT
• IDEAL
Bank Transfer functionality is specific to PMs with sale and check status service.
SG makes the call to CyberSource Sale service to authorize the purchase amount. A secondary
call is made to check a Status service to determine result of the authorization, and the
subsequent Order creation or failure.
78 Visa Confidential
Implementation
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_BankTransfer.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_BankTransfer and set values for the parameter:
Field Description
Step 3: Go to Merchant Tools > Ordering > Payments Methods > Bank_Transfer and set values
for the parameter:
FIeld Description
isBicEnabled Attribute to check if BIC field is required for EPS and GIROPAY
to display on billing page
Refer to this link if you want to setup Decision Manager feature for Bank Trasfer transactions.
Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource: Decision
Manager Configuration and set values for the parameter:
Visa Confidential 79
Field Description
Decision Manager Enable for Bank Enable or disable Decision Manager for Bank Transfer
Transfer transactions.
Bank Transfer
Controller - hooks.json
• Add a hook for payment processor as KLARNA_CREDIT at the end of hooks.json in cartridge
app_storefront_controllers
,
{
"name": "app.payment.processor.BANK_TRANSFER",
"script":
"./../../../int_cybersource_controllers/cartridge/scripts/payment/processor/BANK_TRANSFER"
}
billing.xml
• Add form fields for BIC and Bank List
<group formid="paymentMethods">
<!--
the selected payment method, e.g. "CREDIT_CARD" or "PayPal", this field is
used to transport the payment method selection; validations then can be
made on the proper form group which defines the actual payment method attributes
-->
</list>
80 Visa Confidential
<!-- fields for CreditCard selection -->
<include formid="creditCard" name="creditcard"/>
</group>
paymentmethods.isml
• Add condition to handle bank transfer payment method on billing page present at checkout\billing\
path
Changes are aleady covered under custom code > generic section-> paymentmethods.isml
forms.properties
• Add resource bundle value
payment.bankselection=Select Bank
payment.bankselectionerorr=Please Select Bank
payment.bicnumber=BIC Number
payment.bicnumbererror=Please Enter BIC number
6. Alipay
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_Alipay.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource_Alipay
and set values for the parameter:
Field Description
Step 3: Under 'Merchant Tools > Ordering > Payment Methods' Make sure the ‘ALIPAY’
payment method is enabled and configured to use the ‘CYBERSOURCE_ALIPAY’ payment
processor.
Visa Confidential 81
Alipay Authorization
ValidatePaymentInstruments.ds
• Replace the GIFT_CERTIFICATE payment instrument check
Add import
importPackage( dw.web );
Controller – Hooks.json
• Add a hook for payment processor as CYBERSOURCE_ALIPAY at the end of hooks.json in
cartridge app_storefront_controllers
,
{
"name": "app.payment.processor.CYBERSOURCE_ALIPAY",
"script":
"./../../../int_cybersource_controllers/cartridge/scripts/payment/processor/CYBERSOURCE
_ALIPAY"
COPlaceOrder.js
• [Note: Below snipped is for reference purpose only, changes are aleady covered under custom code
> generic section ->COPlaceOrder.js].
• Note : If Alipay payment fails due to one of the fields(alipayReturnUrl) in the authorization request is
invalid, then one should check should check for length of the alipayReturnUrl field . It should not be
more than 200 characters. To maintain url length less than 200, site url excluding controller name
and method should be less than 120 characters.
var handlePaymentsResult = handlePayments(order);
if (handlePaymentsResult.error) {
session.custom.SkipTaxCalculation=false;
return Transaction.wrap(function () {
OrderMgr.failOrder(order);
return {
error: true,
PlaceOrderError: new Status(Status.ERROR, 'confirm.error.technical')
};
});
82 Visa Confidential
}else if(handlePaymentsResult.redirection){
response.redirect(handlePaymentsResult.redirectionURL);
return {};
}
else if(handlePaymentsResult.intermediate){
app.getView({
alipayReturnUrl : handlePaymentsResult.alipayReturnUrl
}).render(handlePaymentsResult.renderViewPath);
return {};
}
7. Klarna
Different countries and specific currencies could be configured to run Klarna with different
Merchant Id/Key specific to different sites. Functional flows would be similar on different sites.
Step 1: Merchant Id/Key could be configured at Merchant Tools -> Ordering -> Payment
Methods -> Klarna. In this release, Klarna has been supported for US, UK and Germany with
different sites and corresponding Merchant Ids/Key.
Step 2: On the Payment Methods page, Select the locale (language) you want to set up, then
select the Klarna payment method.
Step 3: Enter the merchantID and merchantKey field in CyberSource Credentials section of
payment method. If you leave these empty, the service will fall back to the values you entered
in the CS core site preferences.
Step 4: Select the appropriate bill-to language setting under the ‘Klarna’ custom attribute
group.
Step 5: Upload Cybersource metadata in Business Manager. If not follow "Step 6: Upload
metadata" or import "metadata/site_genesis_meta/meta/Cybersource_Klarna.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource_Klarna
and set values for the parameter:
Field Description
Visa Confidential 83
Klarna
Controller - hooks.json
• Add a hook for payment processor as KLARNA_CREDIT at the end of hooks.json in cartridge
app_storefront_controllers
,
{
"name": "app.payment.processor.KLARNA_CREDIT",
"script":
"./../../../int_cybersource_controllers/cartridge/scripts/payment/processor/KLARNA_CREDIT"
}
COBilling.js
• Update save function inside billing function to handle the error returned by Klarna session service.
save: function () {
var cart = app.getModel('Cart').get();
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
if (!resetPaymentForms() || !validateBilling() || !handleBillingAddress(cart) || // Performs validation
steps, based upon the entered billing address
// and address options.
handlePaymentSelection(cart).error) {// Performs payment method specific checks, such as credit card
verification.
if(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(Cybersource
Constants.KLARNA_PAYMENT_METHOD)){
returnToForm(cart,{KlarnaSessionError: handlePaymentSelection(cart).KlarnaSessionError});
} else {
returnToForm(cart);
}
} else {
app.getModel('Profile').get(customer.profile).addAddressToAddressBook(cart.getBillingAddress());
}
billing.isml
• Add a condition to handle error returned by session service
<iscomment>
This template visualizes the billing step of both checkout scenarios.
It provides selecting a payment method, entering gift certificates and
84 Visa Confidential
specifying a separate billing address.
Depending on the checkout scenario (single or multi shipping) it is
either the second or third checkout step.
</iscomment>
<isif condition="${!empty(pdict.KlarnaSessionError)}">
<div class="error-form">${Resource.msg(pdict.KlarnaSessionError.code,'checkout',null)}</div>
</isif>
<iscomment>Report this checkout step</iscomment>
<isreportcheckoutcheckoutstep="4"checkoutname="${'Billing'}"/>
htmlhead.isml
• Add a place holder to load Klarna JS
Line 9 - Line 20
<iscomment>See https://github.com/h5bp/html5-boilerplate/blob/5.2.0/dist/doc/html.md#x-ua-
compatible</iscomment>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<iscomment>See https://github.com/h5bp/html5-boilerplate/blob/5.2.0/dist/doc/html.md#mobile-
viewport</iscomment>
<meta name="viewport" content="width=device-width, initial-scale=1">
<isscript>
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
</isscript>
<script type="text/javascript">
WebFontConfig = {
google: { families: [ 'Lato:100,300,700,100italic,300italic:latin', 'Crete+Round:400,400italic:latin' ] }
};
(function() {
Line 78 – Line 83
summary.isml
• Changes have been made in this file to load Klarna widget on summary page and other conditions to
display Place Order and Edit button for other payment methods except Klarna.
Please refer to the changes mentioned under custom code – generic section- > summary.isml
Resource.ds
Include the following coloured line changes in the file.
Visa Confidential 85
rateLimiterReset : URLUtils.url('RateLimiter-HideCaptcha').toString(),
csrffailed : URLUtils.url('CSRF-Failed').toString(),
silentpost : URLUtils.https('CYBSecureAcceptance-
GetRequestDataForSilentPost').toString(),
klarnaupdate : URLUtils.https('CYBKlarna-UpdateSession').toString()
8. WeChat Pay
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource_WeChat.xml" in
Business Manager (Administration > Site Development > Import & Export).
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_WeChat and set values for the parameter:
FIeld Description
Test Reconciliation ID for WeChat Sets the status of the AP SALE such as settled, pending,
Pay abandoned, or failed
WeChat Pay
COBilling.js
• Update save function inside billing function to handle the Wechat Pay session.
save: function () {
var cart = app.getModel('Cart').get();
var CybersourceConstants = require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
var
CybersourceHelper=require('int_cybersource/cartridge/scripts/cybersource/libCybersource').getCybers
ourceHelper();
86 Visa Confidential
card verification.
if(app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(Cybersource
Constants.KLARNA_PAYMENT_METHOD)){
returnToForm(cart,{KlarnaSessionError: handlePaymentSelectionResult.KlarnaSessionError});
} else {
returnToForm(cart);
}
} else {
app.getModel('Profile').get(customer.profile).addAddressToAddressBook(cart.getBillingAddress());
}
Controller – hooks.json
• Add a hook for payment processor as CYBERSOURCE_WECHAT at the end of hooks.json in
cartridge app_storefront_controllers
{
"name": "app.payment.processor.CYBERSOURCE_WECHAT",
"script":
"./../../../int_cybersource_controllers/cartridge/scripts/payment/processor/CYBERSOURCE_WECHAT"
}
Visa Confidential 87
6. Configure Features (OPTIONAL)
1. Tax Calculation
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload metadata” or
import "metadata/site_genesis_meta/meta/Cybersource.xml" in Business Manager (Administration >
Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_TaxConfiguration and set values for the parameter:
Field Description
CS Tax Calculation No Nexus States List List of States to not charge tax in
CS Tax Calculation Default Product Tax Code Default tax code used when tax code is not set on
a product
CS Tax Calculation Purchase Order Acceptance City Purchase order acceptance state code
CS Tax Calculation Purchase Order Acceptance Zip Purchase order acceptance zip code
Code
CS Tax Calculation Purchase Order Acceptance Purchase order acceptance country code
Country Code
CS Tax Calculation Purchase Order Origin City Purchase order origin city
CS Tax Calculation Purchase Order Origin Purchase order origin state code
StateCode
CS Tax Calculation Purchase Order Origin ZipCode Purchase order origin zip code
88 Visa Confidential
CS Tax Calculation Purchase Order Origin Country Purchase order origin country code
Code
Tax Service
Script - calculate.js
Call calculateTaxes function of cybersource by adding below line after basket.updateTotals()
calculateProductPrices(basket);
// ===================================================
// ===== CALCULATE TAX =====
// ===================================================
if (dw.order.TaxMgr.taxationPolicy == dw.order.TaxMgr.TAX_POLICY_NET
&& dw.system.Site.getCurrent().getCustomPreferenceValue('CsEnableTaxation'))
{
require('int_cybersource/cartridge/scripts/tax/adaptor/TaxAdaptor').CalculateTa
xes(basket);
basket.updateTotals();
}else{
calculateTax(basket);
basket.updateTotals();
}
// ===================================================
// ===== DONE =====
// ===================================================
Visa Confidential 89
if (placeOrderStatus === Status.ERROR) {
session.custom.SkipTaxCalculation=false;
OrderMgr.failOrder(order);
throw new Error('Failed to place order.');
}
order.setConfirmationStatus(Order.CONFIRMATION_STATUS_CONFIRMED);
order.setExportStatus(Order.EXPORT_STATUS_READY);
Controller -Cart.js
Update submitForm function
return {
cart: cart
};
},
Controller – COShipping.js
Update “updateShippingMethodList“function
1. Set session variable session.custom.SkipTaxCalculation=true; inside for loop and
before cart.Calculate()
applicableShippingMethods = cart.getApplicableShippingMethods(address);
shippingCosts = new HashMap();
currentShippingMethod = cart.getDefaultShipment().getShippingMethod() ||
ShippingMgr.getDefaultShippingMethod();
// Transaction controls are for fine tuning the performance of the data base interactions when
calculating shipping methods
Transaction.begin();
cart.updateShipmentShippingMethod(cart.getDefaultShipment().getID(), method.getID(),
method, applicableShippingMethods);
session.custom.SkipTaxCalculation=true;
cart.calculate();
shippingCosts.put(method.getID(), cart.preCalculateShipping(method));
90 Visa Confidential
}
Controller – COPlaceOrder.js
Update “clearforms” function
Add below snippet at end of function
session.custom.cartStateString=null;
Update “start” function
1. Set session variable SkipTaxCalculation set as false in payment ERROR scenarios
session.custom.SkipTaxCalculation=false;
Visa Confidential 91
92 Visa Confidential
2. Delivery Address Verification
Step 1: To enable this service, Go to Merchant Tools > Site Preferences > Custom Preferences >
CyberSource: Core and set the ‘CS DAV Delivery Address Verification Enabled’ preference to ‘Yes’.
Step 2: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 3: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_DeliveryAddressVerification and set values for the parameter:
Field Description
CS DAV Delivery Address Verification Enabled Enable or disable the DAV service.
CS DAV Update Shipping Address With DAV Update the shipping address with the CS suggestion, if
Suggestion found.
Assuming you have implemented the Credit Card Authorization service, you are ready to use the AVS
service.
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta /meta/Cybersource.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences >
Cybersource_DeliveryAddressVerification and set values for the parameter:
FIeld Description
CS AVS Decline Leave empty to follow CS default decline flag strategy Enter flags separated by
Visa Confidential 93
Flags commas to overwrite the default flag rules
4. Device FingerPrint
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload metadata” or
import "metadata/site_genesis_meta/meta/Cybersource.xml" in Business Manager (Administration >
Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource and set
values for the parameter:
Field Description
CS Device Fingerprint URL pointing to JS that generates and retrieves the fingerprint
ThreatMetrix URL
CS Device Fingerprint Time To Time, in milliseconds between generating a new fingerprint for any
Live given customer session
Device Fingerprint
Setup:
(Prerequisites: CyberSource cartridge is already installed).
1. Enable the device fingerprint at the Site Preferences of CyberSource and set the
Organization ID (provided by CyberSource). The Merchant ID should be set already,
anyway.
94 Visa Confidential
2. Include following snippet i.e. at the billing.isml and summary.isml page
(Recommended: at bottom of page to have no visual impacts)
[Note: summary .isml device fingerprint changes are covered in custom code-generic
section- summary.isml]
<script>window.Countries = <isprint value="${json}" encoding="off"/></script>
<isif
condition="${dw.system.Site.getCurrent().getCustomPreferenceValue('CsDeviceFingerprintEnabled')}
">
<isinclude url="${URLUtils.url('CYBCredit-IncludeDigitalFingerprint')}"/>
</isif>
</isdecorate>
Do a checkout with Credit Card payment. After this checkout, at the CyberSource Business Manager you
will see (at the Transaction Manager):
Device Fingerprint: submitted
Visa Confidential 95
Example for a matching mapping rule for the device fingerprint redirection
Make an Alias entry in Business manager to execute Device finger print with “ Dynamic” redirection
Type
Go to Site > Site URLs > Aliases and add an Alias for your domain like below:
96 Visa Confidential
Visa Confidential 97
5. Decision Manager
Refer to this link to learn about Cybersource's Decision Manager.
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload metadata” or
import "metadata/site_genesis_meta/meta/Cybersource.xml" in Business Manager (Administration >
Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource and set
values for the parameter:
Field Description
Step 3: SG version lower contain a hook that interfere with this service. While the hook
manager has been updated in later versions of SG to prevent this, the CS cartridge is not yet
compatible with those storefront versions. As suggested by SFCC, manual removal of the
following hook from SG is required for this integration to function properly.
Remove
{
"name": "app.fraud.detection",
"script": "./cartridge/scripts/hooks/fraudDetection"
}
From app_storefront_base/hooks.json
Step 4: To enable Decision Manager Order Update Job: Decision Manager Order Update Job
uses a REST API to retrieve order decisions from Cybersource and update the order confirmation
status in SFCC.
To Integrate this job into your site, follow the below steps:
Step 4.1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import “metadata/site_genesis_meta/jobs.xml” in Business Manager
(Administration > Operations > Import & Export)
Step 4.2: Navigate to ‘Administration > Operations > Job’. Select the Job ‘CyberSource:
Decision Manager Order Update’.
Step 4.3: Select the “Job Steps” tab. Select the Sites you want the Job to run on, from the
‘Scope’ button.
Step 4.4: Select “UpdateOrderStatus” and update the following “custom parameters”.
Field Description
98 Visa Confidential
MerchantId CS Merchant ID for the account to get Decisions from
SAFlexKeyID Key ID. Work with CS to generate this value or Follow link to generate keys.
SAFlexSharedSecret Shared secret. Work with CS to generate this value or Follow link to generate
secret.
Step 4.5: Navigate to the ‘Schedule and History’ tab and configure the frequency you would like
the job to run.
Step 4.7: Go to Merchant Tools > Site Preferences > Custom Preferences set values for the
parameter:
CS Decision Manager Cybersource: Core Number of hours the job will look back for new
OrderUpdate Lookback decisions. CS does not support lookbacks over 24
time hours. Do not set above 24
Secure Acceptance Flex Cybersource: Host Name. CS can provide this value
Host Name Secure Acceptance
Step 4.8: When moving to a production environment, the URL for the API call needs to be
updated. This can be done in:
Administration > Operations > Services > Service Credentials > ConversionDetailReport –
Details
6. Payment Tokenization
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource and set
values for the parameter:
Visa Confidential 99
Field Description
SavedCardLimitTimeFrame Provide the number of hours that saved card attempts are
counted
</isif>
3. Include the below code right after <isdynamicform> form object to add Billing
Address Fields
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.firstname}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.lastname}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.address1}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.address2}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.country}" type="select"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.states.state}" type="select"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.city}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.postal}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.phone}" type="input"/>
<isinputfield
formfield="${pdict.CurrentForms.paymentinstruments.creditcards.address.email.emailAddress}"
xhtmlclass="email" type="input"/>
</isif>
paymentForm.clear();
paymentForm.get('creditcards.storedcards').copyFrom(paymentInstruments);
pageMeta.update(dw.content.ContentMgr.getContent('myaccount-paymentsettings'));
if (('SubscriptionError' in session.custom) && !empty(session.custom.SubscriptionError)) {
SubscriptionError = session.custom.SubscriptionError;
session.custom.SubscriptionError = null;
}
app.getView({
PaymentInstruments: paymentInstruments,
SubscriptionError : SubscriptionError
}).render('account/payment/paymentinstrumentlist');
return;
}
.getPaymentMethod(dw.order.PaymentInstrument.METHOD_CREDIT_CARD).activePaymentCards.ite
rator());
app.getView({
ContinueURL: URLUtils.https('PaymentInstruments-PaymentForm'),
SubscriptionError: subscriptionError
}).render('account/payment/paymentinstrumentdetails');
}
try {
save({
PaymentInstrument: paymentInstrument,
CreditCardFormFields: newCreditCardForm.object
});
} catch (err) {
Transaction.rollback();
return {
error: true,
SubscriptionError: SubscriptionError
};
}
if (!empty(subscriptionID)) {
paymentInstrument.setCreditCardToken(subscriptionID);
}
if (isDuplicateCard) {
wallet.removePaymentInstrument(oldCard);
}
Transaction.commit();
paymentForm.clear();
return {
success: true
};
}
},
error: function () {
// @TODO When could this happen
}
});
if (empty(SubscriptionError)) {
response.redirect(URLUtils.https('PaymentInstruments-List'));
}
}
function handlePaymentForm() {
var paymentForm = app.getForm('paymentinstruments');
var profile = customer.getProfile();
var currentTime= new Date();
paymentForm.handleAction({
create: function () {
var Site = require('dw/system/Site');
var Logger = require('dw/system/Logger');
var cyberSourceHelper =
if (!LimitSavedCardRateEnabled) {
cardCreate();
} else {
try{
var SavedCardLimitTimeFrame = !empty(cyberSourceHelper.getSavedCardLimitTimeFrame())?
cyberSourceHelper.getSavedCardLimitTimeFrame() : 0;
var SavedCardLimitCount = !empty(cyberSourceHelper.getSavedCardLimitFrame())?
cyberSourceHelper.getSavedCardLimitFrame() : 0;
} else {
cardCreate();
resetLookBackDateandCount(profile);
}
} else {
cardCreate();
resetLookBackDateandCount(profile);
function cardCreate() {
var createResult = create();
if (createResult.error) {
add(false, createResult.SubscriptionError);
return;
} else {
response.redirect(URLUtils.https('PaymentInstruments-List'));
}
}
Retail POS
This integration requires only one sub-controller to be integrated to your project. The CYBPos
.js controller screenshot is shown below which needs to be called in your project as required:
To make call for POS authentication, InitiatePOSAuthRequest method is defined where POS
related data are being passed as input parameters..
The args contains variables based on POS terminal entry mode. Below are the use and
description of variables. Assuming that args object contains the required values as follows:
• args.cardPresent
• args.entryMode
• args.catLevel
• args.terminalID
• args.amount
• args.currency
• args.storeLocation
• pos_ordernumber
If “keyed entry” mode is used on the POS terminal device.Below Input variable need to set:
• args.accountNumber
• args.cardType
• args.cvnNumber
• args.expiryMonth
• args.expiryYear
If “swiped entry” mode is used on the POS terminal device.Below Input variable need to set:
• args.trackData:
5 terminalID Identifier for the terminal at your retail location. You Optional.
can define this value yourself, but consult with the
processor for requirements. Terminal ID(s) are
configurable in a custom object named
‘POS_TerminalMapping’ (Refer custom object definition
XML to be imported). Here terminal device’s serial
number will be mapped to a Terminal ID. This variable
should be assigned device’s serial number. Code will
pick configured Terminal ID if found and passed to
CyberSource API in request.
Batch Jobs
Cybersource cartridge has 4 batch jobs created for different functional items and are placed
under int_cybersource cartridge:
To import the following Job Schedule configuration Go Adminsistration > Operations > Import &
Export-> upload the below mentioned file and import the configuration.
Verify the newly added batch jobs for Conversion detail report service.
Go to Administration - > Operations -> Job Schedules
After import above file ensure to update credentials as per cybersource merchant account
appropriately in BM.
Secure Acceptance profile settings are configured on CyberSource business center console;
along with other settings below are key settings which must be configured in cybersource
profiles in order to complete the checkout process successfully.
SA SilentPost N/A
Only five types of Card are supported in Demanware, so the cards configured in cybersource
payment settings should be in sync with Demandware supported cards
Verify the newly added batch jobs for Ideal Bank Option service.
Go to Administration - > Operations -> Job Schedules
Step 1: Upload Cybersource metadata in Business Manager. If not follow “Step 2: Upload
metadata” or import "metadata/site_genesis_meta/meta/Cybersource.xml" in Business
Manager (Administration > Site Development > Import & Export)
Step 2: Go to Merchant Tools > Site Preferences > Custom Preferences > Cybersource and set
values for the parameter:
Field Description
CS Subscription Tokens Enabled Enable or Disable the option to generate subscription tokens
[Note: Modify exports of Test Services in CYBServicesTesting.js with https guard before
executing the test cases. This activity is common for all test interfaces.]
Example: exports.StartServices=guard.ensure(['https'], StartServices);
Refer the screen shot below:
Rate Limiting can be added to the My Accounts page, so a merchant can determine the number
of cards that can be edited or added.
Device Fingerprint
Call the controller CYBServicesTesting-TestFingerprint to test the device Fingerprint Service. A
CreditCard Authorization is done and a device fingerprint will be additionally submitted.
https:// <Sandbox Name>/on/demandware.store/Sites-SiteGenesis-
Site/default/CYBServicesTesting- TestFingerprint
Payer Authentication
Call the controller CYBServicesTesting-TestPA to test the Payer Authentication Service.
https:// <Sandbox Name>/on/demandware.store/Sites-SiteGenesis-
Site/default/CYBServicesTesting- TestPA
Retail POS Authorization Request
Call the controller CYBServicesTesting-StartPOS to test the retail POS Service. This renders a
template with a form containing various request fields to enter/select values. The service
response is shown after the submit button is clicked. The field’s label turns to red colored font
if the field was mandatory.
https:// <Sandbox Name>/on/demandware.store/Sites-SiteGenesis-
Site/default/CYBServicesTesting- StartPOS
Alipay Initiate Request
Call the controller CYBServicesTesting-TestAlipayInitiateService to test Alipay Initiate request.
Use and modify the mentioned scripts to test initiate request. The end view of the unit test
controller is a template which displays all relevant request/response information in an easy to
digest manner. User can change static purchase object data and payment type to observe
various responses.
https:// <Sandbox Name>/on/demandware.store/Sites-SiteGenesis-
Site/default/CYBServicesTesting-TestAlipayInitiatesService
Create Subscription Request
Call the controllerCYBServicesTesting-CreateSubscription to test Create Subscription request.
The end node of the unit test controlleris a template which displays all relevant
request/response information.User will be presented with a form and needs to enter the
Script – applepay.js
hooks.json
Add hook for applepay at the end of file present at <core SG cartridge>/cartridge/script
{
"name": "dw.extensions.applepay.paymentAuthorized.authorizeOrderPayment",
"script": "./checkout/applepay.js"
},
Controller – BASIC_CREDIT.js
Update Handle() function with the code below
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
/**
*Verifiesacreditcardagainstavalidcardnumberandexpirationdateandpossiblyinvalidatesinvalid
formfields.
*Iftheverificationwassuccessfulacreditcardpaymentinstrumentiscreated.
*/
function Handle(args) {
var cart = Cart.get(args.Basket);
var creditCardForm = app.getForm('billing.paymentMethods.creditCard');
var PaymentMgr = require('dw/order/PaymentMgr');
Transaction.wrap(function () {
paymentInstrument.paymentTransaction.transactionID = orderNo;
paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor;
});
if
(session.forms.billing.paymentMethods.selectedPaymentMethodID.value.equals('DW_APPLE
_PAY')) {
return {review:true};
}
return {authorized: true};
}
The Interface can be tested via any REST client like SOAPUI etc. Below are the steps to test the
REST service
Install the REST client on machine or browser
Hit the secure End Point URL as POST request having merchant site URL for
“Cybersource_ApplePay-Authorize” [example: https://<merchant
sandbox>/on/demandware.store/Sites-<merchant site>-Site/default/Cybersource_ApplePay-
Authorize]
Add key-value pairs in header for credentials
HEADER KEY HEADER VALUE
Android Pay
How to test on Demandware Storefront
To test AndoridPay on Demandware site, following files need to be updated:
Controller – BASIC_CREDIT.js
Include CybersourceConstants in API include section
/* Script Modules */
var app = require('~/cartridge/scripts/app');
var CybersourceConstants =
require('int_cybersource/cartridge/scripts/utils/CybersourceConstants');
Transaction.wrap(function () {
paymentInstrument.paymentTransaction.transactionID = orderNo;
paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor;
});
if
(session.forms.billing.paymentMethods.selectedPaymentMethodID.value.equals('DW_METH
OD_AndroidPay')) {
return {review:true};
}
return {authorized: true};
}
The Interface can be tested via any REST client like SOAPUI etc. Below are the steps to test the
REST service
Install the REST client on machine or browser
Hit the secure End Point URL as POST request having merchant site URL for
“Cybersource_ApplePay-Authorize” [example: https://<merchant
sandbox>/on/demandware.store/Sites-<merchant site>-Site/default/Cybersource_ApplePay-
Authorize]
Add key-value pairs in header for credentials
HEADER KEY HEADER VALUE
dw_androidpay_us User is configured by merchant in demandware platform under
er site preferences
dw_androidpay_pa Password is configured by merchant in demandware platform
ssword under site preferences.
Content-Type application/json
Pass below JSON when Payload test data available
JSON KEY JSON VALUE
orderID The order ID of AndroidPay order object created during checkout
journey of ApplePay
encryptedPayment Encrypted AndroidPay blob data returned by ApplePay for PSP to
Blob place the order. This contains billing/shipping/card details in
encrypted form.
Pass below JSON when Network Token test data available
JSON KEY JSON VALUE
orderID The order ID of AndroidPay order object created during
checkout journey of ApplePay
Visa has dedicated data centers in Virginia and Colorado. There are no single points of failure.
Visa Data Centers implement redundant, dual-powered equipment, multiple data and power
15. http://apps.cybersource.com/library/documentation/dev_guides/Secure_Acceptance_WM/Secure_Acceptance_WM.pdf
16. http://apps.cybersource.com/library/documentation/dev_guides/Secure_Acceptance_SOP/Secure_Acceptance_SOP.pdf
17. http://apps.cybersource.com/library/documentation/dev_guides/VCO_SO_API/Visa_Checkout_SO_API.pdf
18. http://apps.cybersource.com/library/documentation/dev_guides/apple_payments/getting_started/Getting_Started.pdf
19. http://apps.cybersource.com/library/documentation/dev_guides/tokenization_SO_API/Tokenization_SO_API.pdf
20. http://apps.cybersource.com/library/documentation/dev_guides/OnlineBankTransfers_SO_API/OnlineBankTransfers_SO_API.pdf
21. http://www.cybersource.com/support_center/support_documentation
22. https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/
23. https://developer.paypal.com/demo/checkout/#/pattern/client
24. https://www.cybersource.com/products/payment_processing/android_pay/
25. https://www.cybersource.com/developers/integration_methods/apple_pay/
Upgrade Steps
Please follow the below steps to upgrade your cartridge version from 22.1.3 to 23.1.0.
Release History
1.1.0 02/06/2013 Incorporated New changes as per new Site Genesis code
2.1.2 04/25/2014 RSA key removed from the cartridge.Bug fixed related to
promotional discount.
• BML
Added :
• Visa Checkout
• Klarna
• Bank Transfer
• PayPal Credit
• PayPal Express
• PayPal Credit
• Android Pay