Skip to content

added support for MLE #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 4, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
### **Cybersource Storefront Reference Architecture Quick Launch Cartridge** ###
### **Cybersource Storefront Reference Architecture Quick Launch Cartridge**

- **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](https://www.cybersource.com/en-gb.html)
- **Categories:** Payment Processing, Fraud Detection, Address Validation, Tax Computation
- **Version:** 25.2.0
- **Last Certification Date:** March 2025
- **Supports SFRA v7.0**
- **JavaScript Controllers Friendly:** **YES**

* **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](https://www.cybersource.com/en-gb.html)
* **Categories:** Payment Processing, Fraud Detection, Address Validation, Tax Computation
* **Version:** 25.1.0
* **Last Certification Date:** January 2025
* **Supports SFRA v7.0**
* **JavaScript Controllers Friendly:** **YES**
### Contact

### Contact ###
* <globalpartnersolutionscs@visa.com>
- <globalpartnersolutionscs@visa.com>

----
---

### Installation Guide ###
### Installation Guide

1. [Install the Cartridge and Setup Workspace](documentation/markdown/Install-catridge-WrkSpace-Setup.md)
2. [Configure the Cartridge](documentation/markdown/Configure-cartridge.md)
3. [Configure the Payment Method](documentation/markdown/Configure-payment-method.md)
4. [Configure features (OPTIONAL)](documentation/markdown/Configure-features.md)
5. [Test and go live](documentation/markdown/Test-golive.md)
6. [Release Notes](documentation/markdown/Release-notes.md)
1. [Install the Cartridge and Setup Workspace](documentation/markdown/Install-catridge-WrkSpace-Setup.md)
2. [Configure the Cartridge](documentation/markdown/Configure-cartridge.md)
3. [Configure the Payment Method](documentation/markdown/Configure-payment-method.md)
4. [Configure features (OPTIONAL)](documentation/markdown/Configure-features.md)
5. [Test and go live](documentation/markdown/Test-golive.md)
6. [Release Notes](documentation/markdown/Release-notes.md)
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
'use strict';

$(document).ready(function () {
var captureContext = $('#flexTokenResponse').val();
var captureContext = JSON.parse($('#flexTokenResponse').val()).keyId;
var flex = new Flex(captureContext); // eslint-disable-line no-undef
var customStyles = {
input: {
@@ -25,7 +25,7 @@ $(document).ready(function () {
color: '#a94442'
}
};
var microform = flex.microform("card",{
var microform = flex.microform({
styles: customStyles
});
var number = microform.createField('number');
@@ -107,7 +107,7 @@ $(document).ready(function () {
var decodedJwt = parseJwt(response);
document.getElementById('cardNumber').valid = true;
$('#flex-response').val(response);
$('#cardNumber').val(decodedJwt.content.paymentInformation.card.number.maskedValue);
$('#cardNumber').val(decodedJwt.data.number);

if ($('.submit-payment').length === 1) {
$('.submit-payment').trigger('click');
@@ -137,7 +137,7 @@ $(document).ready(function () {
case 'discover':
correctCardType = 'Discover';
break;
case 'dinersclub':
case 'diners-club':
correctCardType = 'DinersClub';
break;
case 'maestro':
@@ -146,6 +146,18 @@ $(document).ready(function () {
case 'jcb':
correctCardType = 'JCB';
break;
case "cartesbancaires":
correctCardType = "CartesBancaires";
break;
case "elo":
correctCardType = "Elo";
break;
case "cup":
correctCardType = "China UnionPay";
break;
case "jcrew":
correctCardType = "JCrew";
break;
}
$('#cardType').val(correctCardType);
}
71 changes: 39 additions & 32 deletions cartridges/int_cybs_sfra_base/cartridge/apiClient/ApiClient.js
Original file line number Diff line number Diff line change
@@ -3,40 +3,40 @@ var Bytes = require('dw/util/Bytes');
var Encoding = require('dw/crypto/Encoding');
var Mac = require('dw/crypto/Mac');
var MessageDigest = require('dw/crypto/MessageDigest');

var configObject = require('*/cartridge/configuration/index');
var MerchantConfig = require('./merchantConfig');
var Logger = require('./logger');

var _exports = function () {}

_exports.prototype.createService = function (){
var PaymentsHttpService = dw.svc.LocalServiceRegistry.createService("PaymentHttpService", {
createRequest: function (svc, url, headers, method, requestBody) {
var keys = Object.keys(headers);
var StringHeaders = "";
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
svc.addHeader(key, headers[key]);
StringHeaders += key + ":" + headers[key] + "\n";
}
svc.URL = url;
svc.setRequestMethod(method.toUpperCase());
if (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PATCH') {
if (typeof requestBody === 'string') {
return requestBody;
var _exports = function () { }

_exports.prototype.createService = function () {
var PaymentsHttpService = dw.svc.LocalServiceRegistry.createService("PaymentHttpService", {
createRequest: function (svc, url, headers, method, requestBody) {
var keys = Object.keys(headers);
var StringHeaders = "";
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
svc.addHeader(key, headers[key]);
StringHeaders += key + ":" + headers[key] + "\n";
}
svc.URL = url;
svc.setRequestMethod(method.toUpperCase());
if (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PATCH') {
if (typeof requestBody === 'string') {
return requestBody;
}
return JSON.stringify(requestBody);
}
return JSON.stringify(requestBody);
},
parseResponse: function (svc, client) {
return client.text;
},
filterLogMessage: function (msg) {
// No need to filter logs. No sensitive information.
return msg;
}
},
parseResponse: function (svc, client) {
return client.text;
},
filterLogMessage: function (msg) {
// No need to filter logs. No sensitive information.
return msg;
}
});
return PaymentsHttpService;
});
return PaymentsHttpService;
};

_exports.prototype.setConfiguration = function (configObject) {
@@ -183,7 +183,7 @@ _exports.prototype.normalizeParams = function (params) {
return newParams;
}

_exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, authNames, contentTypes, accepts, returnType, callback) {
_exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi) {
var requestHost = this.basePath.substr(
this.basePath.indexOf("//") + 2
);
@@ -219,6 +219,13 @@ _exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams
}
payload = JSON.stringify(bodyParam);

var isMLEEnabled = configObject.mleEnabled;

if (isMLEEnabled && isMLESupportedByCybsForApi == true) {
var encryptPayload = require('*/cartridge/scripts/mleEncrypt/jweEncrypt.js');
payload = encryptPayload.getJWE(payload);

}
var signature = this.getHttpSignature(resource, method, merchantKeyId, requestHost, merchantId, merchantSecretKey, payload);
var digest = this.generateDigest(payload);
digest = "SHA-256=" + digest;
@@ -247,9 +254,9 @@ _exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams

if (response.ok) {
var responseObj = response.object;
if(path === '/microform/v2/sessions'){
if (path === '/microform/v2/sessions') {
callback(responseObj, false, response);
}else{
} else {
callback(JSON.parse(responseObj), false, response);
}
} else {
Original file line number Diff line number Diff line change
@@ -93,11 +93,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = PtsV2PaymentsCapturesPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/pts/v2/payments/{id}/captures', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}
};
Original file line number Diff line number Diff line change
@@ -86,11 +86,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = RiskV1AuthenticationsPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/risk/v1/authentications', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}

@@ -131,11 +132,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = RiskV1AuthenticationSetupsPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/risk/v1/authentication-setups', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}

@@ -176,11 +178,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = RiskV1AuthenticationResultsPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/risk/v1/authentication-results', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}
};
Original file line number Diff line number Diff line change
@@ -254,4 +254,4 @@
};

return exports;
}));
}));
Original file line number Diff line number Diff line change
@@ -86,11 +86,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = PtsV2PaymentsPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/pts/v2/payments', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}

@@ -138,11 +139,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = PtsV2IncrementalAuthorizationPatch201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/pts/v2/payments/{id}', 'PATCH',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}
};
Original file line number Diff line number Diff line change
@@ -93,11 +93,12 @@
var contentTypes = ['application/json;charset=utf-8'];
var accepts = ['application/hal+json;charset=utf-8'];
var returnType = PtsV2PaymentsReversalsPost201Response;
var isMLESupportedByCybsForApi = true;

return this.apiClient.callApi(
'/pts/v2/payments/{id}/reversals', 'POST',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType, callback
authNames, contentTypes, accepts, returnType, callback, isMLESupportedByCybsForApi
);
}

Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ module.exports = {
SANDBOX_RUN_ENV: "cybersource.environment.sandbox",
PRODUCTION_RUN_ENV: "cybersource.environment.production",
APPLICATION_NAME: "Salesforce B2C(REST)",
APPLICATION_VERSION: "25.1.0",
APPLICATION_VERSION: "25.2.0",

/* Digest Constants*/
SIGNATURE_ALGORITHAM: "SHA-256=",
11 changes: 8 additions & 3 deletions cartridges/int_cybs_sfra_base/cartridge/configuration/index.js
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ var LogfileMaxSize = '5242880'; // 10 MB In Bytes
* Send this value in all requests that are sent through the partner solution. CyberSource assigns the ID to the partner.
* Note When you see a partner ID of 999 in reports, the partner ID that was submitted is incorrect.
*/
var SolutionId = 'FTN2UOLO';
var SolutionId = 'GTIWK1VH';

var CruiseDDCEndPoint = {
Stage: 'https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect',
@@ -127,10 +127,15 @@ function getConfig(config) {
googlePayEnvironment: config.googlePayEnvironment || customPreferences.GooglePay.Preferences.GooglePayEnvironment.getValue(),
enableGooglePayOnCart: config.enableGooglePayOnCart || customPreferences.GooglePay.Preferences.EnableGooglePayOnCart.getValue(),

// DecisionManager
// Click to pay
visaSRCEnabled: config.vscCheckoutEnabled || customPreferences.ClicktoPay.Preferences.ClicktoPayEnabled.getValue(),
visaSRCKey: config.visaSRCKey || customPreferences.ClicktoPay.Preferences.ClicktoPayKey.getValue(),
VisaSRCProduction: config.VisaSRCProduction || customPreferences.ClicktoPay.Preferences.ClicktoPayProduction.getValue()
VisaSRCProduction: config.VisaSRCProduction || customPreferences.ClicktoPay.Preferences.ClicktoPayProduction.getValue(),

//MLE
mleEnabled: config.mleEnabled || customPreferences.MLE.Preferences.EnableMLE.getValue(),
mleCertificateSerialNumber: config.mleCertificateSerialNumber || customPreferences.MLE.Preferences.MLECertificateSerialNumber.getValue(),
mleCertificateAlias: config.mleCertificateAlias || customPreferences.MLE.Preferences.MLECertificateAlias.getValue()
};
}
module.exports = getConfig();
Original file line number Diff line number Diff line change
@@ -602,5 +602,46 @@ module.exports = {
}
}
}
},

/* MLE Custom Preference */
MLE: {
id: 'Cybersource_MLE',
display_name: 'Message-Level Encryption Configration',
Preferences: {
/** @type {CustomPreference} */
EnableMLE: {
id: 'Cybersource_MLEEnabled',
display_name: 'Enable Message-Level Encryption',
description: 'Enable or Disable Message-Level Encryption.',
type: Types.boolean,
default: false,
flags: {
mandatory: false
}
},
/** @type {CustomPreference} */
MLECertificateSerialNumber: {
id: 'Cybersource_CertificateSerialNo',
display_name: 'Certificate Serial Number',
description: 'Serial Number of "CyberSource_SJC_US" certificate extracted from p12 file.',
type: Types.string,
default: undefined,
flags: {
mandatory: false
}
},
/** @type {CustomPreference} */
MLECertificateAlias: {
id: 'Cybersource_CertificateAlias',
display_name: 'Alias of the Certificate',
description: '',
type: Types.string,
default: undefined,
flags: {
mandatory: false
}
}
}
},
};
Loading