Skip to content

Commit 2b9ddda

Browse files
Merge pull request #16 from CyberSource/release-25.1.0
Flex microform v2 upgrade
2 parents 5b4638d + 550196c commit 2b9ddda

23 files changed

+334
-87
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
* **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)
55
* **Categories:** Payment Processing, Fraud Detection, Address Validation, Tax Computation
6-
* **Version:** 24.4.0
7-
* **Last Certification Date:** September 2024
6+
* **Version:** 25.1.0
7+
* **Last Certification Date:** January 2025
88
* **Supports SFRA v7.0**
99
* **JavaScript Controllers Friendly:** **YES**
1010

cartridges/int_cybs_sfra/cartridge/client/default/custom/flexMicroform.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
'use strict';
44

55
$(document).ready(function () {
6-
var captureContext = JSON.parse($('#flexTokenResponse').val()).keyId;
6+
var captureContext = $('#flexTokenResponse').val();
77
var flex = new Flex(captureContext); // eslint-disable-line no-undef
88
var customStyles = {
99
input: {
@@ -25,7 +25,7 @@ $(document).ready(function () {
2525
color: '#a94442'
2626
}
2727
};
28-
var microform = flex.microform({
28+
var microform = flex.microform("card",{
2929
styles: customStyles
3030
});
3131
var number = microform.createField('number');
@@ -107,7 +107,7 @@ $(document).ready(function () {
107107
var decodedJwt = parseJwt(response);
108108
document.getElementById('cardNumber').valid = true;
109109
$('#flex-response').val(response);
110-
$('#cardNumber').val(decodedJwt.data.number);
110+
$('#cardNumber').val(decodedJwt.content.paymentInformation.card.number.maskedValue);
111111

112112
if ($('.submit-payment').length === 1) {
113113
$('.submit-payment').trigger('click');
@@ -137,7 +137,7 @@ $(document).ready(function () {
137137
case 'discover':
138138
correctCardType = 'Discover';
139139
break;
140-
case 'diners-club':
140+
case 'dinersclub':
141141
correctCardType = 'DinersClub';
142142
break;
143143
case 'maestro':

cartridges/int_cybs_sfra/cartridge/client/default/scss/components/_creditCardField.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
background-size: contain;
1111
}
1212

13-
&[data-type="diners-club"]::after {
13+
&[data-type="dinersclub"]::after {
1414
background-image: url('../../images/payment-types.png');
1515
background-size: auto;
1616
background-position: -230px -205px;

cartridges/int_cybs_sfra/cartridge/templates/default/secureAcceptanceFlexMicroformContent.isml

+14-19
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,32 @@
77
<div id="cardNumber-container" class="form-control"></div>
88
<div class="invalid-feedback"></div>
99
</div>
10-
<isif condition="${pdict.flexTokenResult == null}">
11-
<div class="alert alert-danger">${flexError}</div>
12-
</isif>
10+
<isif condition="${pdict.flexTokenResult == null}">
11+
<div class="alert alert-danger">${flexError}</div>
12+
</isif>
1313
</div>
1414
</div>
1515
</div>
1616

1717
<div class="row">
1818
<div class="col-12">
19-
<div class="form-group securityCode" data-cardNumber="${Resource.msg('securityCode.placeholder','cybersource',null)}">
20-
<label class="form-control-label" for="securityCode">${Resource.msg('field.credit.card.security.code','creditCard',null)}</label>
19+
<div class="form-group securityCode"data-cardNumber="${Resource.msg('securityCode.placeholder', 'cybersource', null)}">
20+
<label class="form-control-label"
21+
for="securityCode">${Resource.msg('field.credit.card.security.code', 'creditCard', null)}</label>
2122
<div class="security-code-wrapper">
2223
<div id="securityCode-container" class="form-control"></div>
2324
<div class="invalid-feedback"></div>
2425
</div>
25-
<isif condition="${pdict.flexTokenResult == null}">
26-
<div class="alert alert-danger">${flexError}</div>
27-
</isif>
26+
<isif condition="${pdict.flexTokenResult == null}">
27+
<div class="alert alert-danger">${flexError}</div>
28+
</isif>
2829
</div>
2930
</div>
3031
</div>
3132

32-
<isif condition="${pdict.flexTokenResult != null}" >
33-
<isset name="flextoken" value="${pdict.flexTokenResult}" scope="page" />
34-
<input type="hidden" value="${JSON.stringify(flextoken)}" name="flexTokenResponse" id="flexTokenResponse"/>
35-
<input type="hidden" value="${JSON.stringify(flextoken.jwk)}" name="flextokenObj" id="flextokenObj"/>
33+
<isif condition="${pdict.flexTokenResult != null}">
34+
<isset name="flextoken" value="${pdict.flexTokenResult}" scope="page" />
35+
<input type="hidden" value="${flextoken}" name="flexTokenResponse" id="flexTokenResponse" />
3636
</isif>
3737

3838
<iscomment>Secure Acceptance Flex MicroForm </iscomment>
@@ -48,10 +48,5 @@
4848
</div>
4949

5050
<iscomment>Secure Acceptance Flex Microform Scripts </iscomment>
51-
52-
<isif condition="${dw.system.System.getInstanceType()!= 2}">
53-
<script src="https://testflex.cybersource.com/cybersource/assets/microform/0.11/flex-microform.min.js"></script>
54-
<iselse>
55-
<script src="https://flex.cybersource.com/cybersource/assets/microform/0.11/flex-microform.min.js"></script>
56-
</iselse>
57-
</isif>
51+
52+
<script src = '${pdict.clientLibrary}' integrity = '${pdict.clientLibraryIntegrity}' crossorigin="anonymous"></script>

cartridges/int_cybs_sfra_base/cartridge/apiClient/ApiClient.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ _exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams
193193
var merchantKeyId = this.merchantConfig.getMerchantKeyID();
194194
var merchantSecretKey = this.merchantConfig.getMerchantsecretKey();
195195
var payload = "";
196+
var Constants = require('../apiClient/constants');
196197

197198
var url = this.buildUrl(path, pathParams, queryParams);
198199

@@ -210,7 +211,8 @@ _exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams
210211
if (!bodyParam.clientReferenceInformation) {
211212
bodyParam.clientReferenceInformation = {};
212213
}
213-
214+
bodyParam.clientReferenceInformation.applicationName = Constants.APPLICATION_NAME;
215+
bodyParam.clientReferenceInformation.applicationVersion = Constants.APPLICATION_VERSION;
214216
bodyParam.clientReferenceInformation.partner = {
215217
solutionId: this.merchantConfig.getSolutionId(),
216218
developerId: this.merchantConfig.getDeveloperId()
@@ -245,7 +247,11 @@ _exports.prototype.callApi = function (path, httpMethod, pathParams, queryParams
245247

246248
if (response.ok) {
247249
var responseObj = response.object;
248-
callback(JSON.parse(responseObj), false, response);
250+
if(path === '/microform/v2/sessions'){
251+
callback(responseObj, false, response);
252+
}else{
253+
callback(JSON.parse(responseObj), false, response);
254+
}
249255
} else {
250256
callback(response.errorMessage, response.error, response);
251257
}

cartridges/int_cybs_sfra_base/cartridge/apiClient/api/AsymmetricKeyManagementApi.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@
175175

176176
var authNames = [];
177177
var contentTypes = ['application/json;charset=utf-8'];
178-
var accepts = ['application/hal+json;charset=utf-8'];
178+
var accepts = ['application/json'];
179179
var returnType = KmsV2KeysAsymGet200Response;
180180

181181
return this.apiClient.callApi(
182-
'/kms/v2/keys-asym/{keyId}', 'GET',
182+
'/flex/v2/public-keys/{keyId}', 'GET',
183183
pathParams, queryParams, headerParams, formParams, postBody,
184184
authNames, contentTypes, accepts, returnType, callback
185185
);

cartridges/int_cybs_sfra_base/cartridge/apiClient/api/KeyGenerationApi.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
var returnType = FlexV1KeysPost200Response;
9696

9797
return this.apiClient.callApi(
98-
'/flex/v1/keys', 'POST',
98+
'/microform/v2/sessions', 'POST',
9999
pathParams, queryParams, headerParams, formParams, postBody,
100100
authNames, contentTypes, accepts, returnType, callback
101101
);

cartridges/int_cybs_sfra_base/cartridge/apiClient/constants.js

+8
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,19 @@ module.exports = {
3030
PRODUCTION_URL: "",
3131
SANDBOX_RUN_ENV: "cybersource.environment.sandbox",
3232
PRODUCTION_RUN_ENV: "cybersource.environment.production",
33+
APPLICATION_NAME: "Salesforce B2C(REST)",
34+
APPLICATION_VERSION: "25.1.0",
3335

3436
/* Digest Constants*/
3537
SIGNATURE_ALGORITHAM: "SHA-256=",
3638
HmacSHA256: "HmacSHA256",
3739

40+
/* Flex microform constants */
41+
ENCRYPTION_TYPE: "RsaOaep256",
42+
CLIENT_VERSION : "v2",
43+
44+
45+
3846
/* Logging Labels*/
3947
BEGIN_TRANSACTION: "START > =======================================",
4048
END_TRANSACTION: "END > =========================================",

cartridges/int_cybs_sfra_base/cartridge/configuration/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var LogfileMaxSize = '5242880'; // 10 MB In Bytes
2323
* Send this value in all requests that are sent through the partner solution. CyberSource assigns the ID to the partner.
2424
* Note When you see a partner ID of 999 in reports, the partner ID that was submitted is incorrect.
2525
*/
26-
var SolutionId = '6EIFFEUD';
26+
var SolutionId = 'FTN2UOLO';
2727

2828
var CruiseDDCEndPoint = {
2929
Stage: 'https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect',

cartridges/int_cybs_sfra_base/cartridge/controllers/CheckoutServices.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ server.post('handlingConsumerAuthResponse', server.middleware.https, function (r
439439
}
440440

441441
// eslint-disable-next-line
442-
else if (authenticateResponse.errorInformation.reason === 'CUSTOMER_AUTHENTICATION_REQUIRED' && session.custom.Flag3ds === false) {
442+
else if ((authenticateResponse.errorInformation ? authenticateResponse.errorInformation.reason === 'CUSTOMER_AUTHENTICATION_REQUIRED' : false) && session.custom.Flag3ds === false) {
443443
session.custom.Flag3ds = true;
444444
// eslint-disable-next-line no-shadow
445445
res.render('payerAuthentication/scaRedirect', {

cartridges/int_cybs_sfra_base/cartridge/controllers/SecureAcceptance.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ var configObject = require('../configuration/index');
66
if (configObject.cartridgeEnabled) {
77
server.get('CreateFlexToken', server.middleware.https, function (req, res, next) {
88
var Flex = require('~/cartridge/scripts/http/payments');
9-
var flexResult = Flex.createFlexKey(null);
10-
res.render('secureAcceptanceFlexMicroformContent', {
11-
flexTokenResult: flexResult
12-
});
13-
next();
9+
var flexResult = Flex.createFlexKey();
10+
var parsedPayload = Flex.jwtDecode(flexResult);
11+
if(parsedPayload != null){
12+
var clientLibrary = parsedPayload.ctx[0].data.clientLibrary;
13+
var clientLibraryIntegrity = parsedPayload.ctx[0].data.clientLibraryIntegrity;
14+
res.render('secureAcceptanceFlexMicroformContent', {
15+
flexTokenResult: flexResult,
16+
clientLibrary: clientLibrary,
17+
clientLibraryIntegrity: clientLibraryIntegrity
18+
});
19+
next();
20+
}
1421
});
1522
}
1623

cartridges/int_cybs_sfra_base/cartridge/scripts/hooks/payment/processor/payments_credit_form_processor.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function processForm(req, paymentForm, viewFormData) {
3131
case 'discover':
3232
correctCardType = 'Discover';
3333
break;
34-
case 'diners-club':
34+
case 'dinersclub':
3535
correctCardType = 'DinersClub';
3636
break;
3737
case 'maestro':

cartridges/int_cybs_sfra_base/cartridge/scripts/http/networkTokenSubscription.js

+34-4
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,41 @@ function createWebhookSubscription(callback) {
109109
);
110110
}
111111

112+
function deleteSusbscriprion(id, callback){
113+
var postBody = null;
114+
115+
var pathParams = {
116+
'webhookId' : id
117+
};
118+
var queryParams = {};
119+
var headerParams = {};
120+
var formParams = {};
121+
122+
var authNames = [];
123+
var contentTypes = ['application/json;charset=utf-8'];
124+
var accepts = ['application/json;charset=utf-8'];
125+
var returnType = {};
126+
apiClient.instance.callApi(
127+
'/notification-subscriptions/v1/webhooks/{webhookId}' , 'DELETE',
128+
pathParams, queryParams, headerParams, formParams, postBody,
129+
authNames, contentTypes, accepts, returnType, callback
130+
);
131+
}
112132
function createNetworkTokenSubscription() {
113133
retrieveAllCreatedWebhooks(function (data, error, response) {
114-
if (data.webhookId) {
115-
Logger.error('Subscription already exists');
134+
if (data[0].webhookId) {
135+
var obj = CustomObjectMgr.getCustomObject("Network Tokens Webhook", merchantId);
136+
if (obj == null) {
137+
deleteSusbscriprion(data[0].webhookId, function (data, error, responseData) {
138+
if(responseData.status === 'OK'){
139+
createNetworkTokenSubscription();
140+
}
141+
});
142+
}
116143
}
117144
if (error) {
118145
data = JSON.parse(data);
119-
if (data.statusCode === 404 && data.errorDescription === 'Record Not Found') {
146+
if (data.statusCode === 404) {
120147
var key = '';
121148
createWebhookSecurityKey(function (data, error, response) {
122149
if (!error) {
@@ -136,7 +163,10 @@ function createNetworkTokenSubscription() {
136163
}
137164
});
138165
Transaction.wrap(function () {
139-
var obj = CustomObjectMgr.createCustomObject('Network Tokens Webhook', merchantId);
166+
var obj = CustomObjectMgr.getCustomObject("Network Tokens Webhook", merchantId);
167+
if (obj == null) {
168+
obj = CustomObjectMgr.createCustomObject('Network Tokens Webhook', merchantId);
169+
}
140170
obj.custom.SecurityKey = key;
141171
obj.custom.SubscriptionId = webhookId;
142172
});

cartridges/int_cybs_sfra_base/cartridge/scripts/http/payerAuthentication.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,10 @@ function paConsumerAuthenticate(billingDetails, referenceInformationCode, total,
386386
} else {
387387
try {
388388
var parsedData = JSON.parse(data);
389-
var reasonCodeObject = parsedData.errorInformation.details.filter(function (e) { return e.field === 'reasonCode'; }).pop();
389+
var reasonCodeObject = parsedData;
390+
if(parsedData.errorInformation != null){
391+
reasonCodeObject = parsedData.errorInformation.details.filter(function (e) { return e.field === 'reasonCode'; }).pop();
392+
}
390393
result = {
391394
status: reasonCodeObject.reason
392395
};

0 commit comments

Comments
 (0)