Integrating CC Avenue with Salesforce Commerce Cloud
CC Avenue Integration with SFCC
Integrating CC Avenue with Salesforce Commerce Cloud (SFCC) involves several steps. CC Avenue, a popular payment gateway, seamlessly processes online payments when integrated with SFCC. Here is a comprehensive guide on how to integrate CC Avenue with SFCC1. Obtain CC Avenue Credentials:
Before initiating the integration, sign up with CC Avenue and acquire essential credentials such as Merchant ID, Access Code, and Encryption Key (Working Key).2. Configure CC Avenue in Business Manager:
- Log in to your SFCC Business Manager.
- Navigate to "Merchant Tools" > "Site Preferences" > "Payment Methods."
- Add a new payment method for CC Avenue.
- Enter relevant information, including Merchant ID, Access Code, and Encryption Key from CC Avenue.
- Configure other settings like payment flow, methods, and currencies as needed.
3. Set Up Payment Processing:
Configure the payment processing pipeline to include CC Avenue by setting up the appropriate payment processor and linking it to the CC Avenue payment method.4. Code Changes:
Now, let's delve into the coding part. In this session, we will use the Non-seamless process, utilizing the Billing page provided by CC Avenue.- Call the Handle hook to create a payment instrument in the basket.
- Create the order using COHelpers.createOrder(currentBasket).
- Submit the order data to CC Avenue from the front end; build the payload as per CC Avenue documentation.
API(transactionURL): https://test.ccavenue.com/transaction/transaction.do?command=initiateTransaction
a) EncRequest before encryption'use strict'; function PaymentRequest(order, merchantId, language, options) { const { /** @type {dw.web.URLUtils} */ URLUtils } = dw.web; const safeOptions = options || {}; this.merchant_id = merchantId; this.order_id = order.orderNo; this.currency = order.currencyCode; this.amount = order.totalGrossPrice.value; this.customer_identifier = customer.ID; this.billing_email = order.customerEmail; const { billingAddress } = order; this.billing_name = billingAddress.fullName; this.billing_address = billingAddress.address1; this.billing_city = billingAddress.city; this.billing_state = billingAddress.stateCode; this.billing_zip = billingAddress.postalCode; this.billing_country = billingAddress.countryCode && billingAddress.countryCode.value === 'US' ? 'United States' : 'India'; this.billing_tel = billingAddress.phone; const { shippingAddress } = order.defaultShipment; this.delivery_name = shippingAddress.fullName; this.delivery_address = shippingAddress.address1; this.delivery_city = shippingAddress.city; this.delivery_state = shippingAddress.stateCode; this.delivery_zip = shippingAddress.postalCode; this.delivery_country = shippingAddress.countryCode && shippingAddress.countryCode.value === 'US' ? 'United States' : 'India'; this.delivery_tel = shippingAddress.phone; this.language = language; this.redirect_url = safeOptions.redirectURL ? URLUtils.abs(safeOptions.redirectURL).toString() : URLUtils.abs('CheckoutServices-PlaceOrder').toString(); this.cancel_url = safeOptions.cancelURL ? URLUtils.abs(safeOptions.cancelURL).toString() : URLUtils.abs('CheckoutServices-PlaceOrder').toString(); this.toRequestString = () => { let string = ''; Object.keys(this).forEach(key => { if (this[key] && typeof this[key] !== 'function') { string += key + '=' + encodeURIComponent(this[key]).replace('%20', '+') + '&'; } }); return string.substr(0, string.lastIndexOf('&')); }; }; module.exports = PaymentRequest;
b) Encrypt the above request data"use strict"; const encryptionUtils = {}; var { Cipher, Encoding } = dw.crypto; var preferences = require("*/cartridge/config/preferences"); /** * Function to get the key from the hex encoded working key using MD5 hash * @param {string} workingKey - The working key to be converted * @returns {string} The key */ const getKey = (workingKey) => { const { /** @type {dw.crypto.Encoding} */ Encoding, /** @type {dw.crypto.WeakMessageDigest} */ WeakMessageDigest, } = dw.crypto; const { /** @type {dw.util.Bytes} */ Bytes } = dw.util; return Encoding.toBase64( new WeakMessageDigest("MD5").digestBytes(new Bytes(workingKey)) ); }; /** * Function to encrypt the provided plain text using the provided algorithm or AES algorithm in CBC mode * with PKCS5Padding by default and return the encrypted value in hex encoding. * @param {string} plainText - The text that has to be encrypted * @param {Object|null} options - The object containing overrides for default option. * @returns {string|null} - The hex encoded encrypted text or null in case of any errors. */ encryptionUtils.encrypt = (plainText, options) => { const workingKey = preferences.ccavenueWorkingKey; var iv = dw.crypto.Encoding.toBase64( new dw.util.Bytes( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" ) ); const cipher = new Cipher(); var enKey = getKey(workingKey); return Encoding.toHex( Encoding.fromBase64( cipher.encrypt( plainText, enKey, "AES/CBC/PKCS5Padding", iv, Number(10) ) ) ); }; /** * Function to decrypt the provided encrypted text using the provided algorithm or AES algorithm in CBC mode * with PKCS5Padding by default and return the decrypted value. * @param {string} encryptedText - The text that has to be decrypted in hex encoding * @param {Object|null} options - The object containing overrides for default option. * @returns {string|null} - The UTF-8 encoded plain text or null in case of any errors. */ encryptionUtils.decrypt = (encryptedText) => { const cipher = new Cipher(); const workingKey = preferences.ccavenueWorkingKey; const key = getKey(workingKey); var iv = dw.crypto.Encoding.toBase64( new dw.util.Bytes( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" ) ); return cipher.decrypt( Encoding.toBase64(Encoding.fromHex(encryptedText)), key, "AES/CBC/PKCS5Padding", iv, Number(10) ); }; module.exports = encryptionUtils;
c) Payload//create payment details like encryption object req for cc avenue function getPaymentFormDetails(order, currentLanguage) { const encryptionUtils = require("*/cartridge/scripts/util/encryptionUtils"); const PaymentRequestModel = require("*/cartridge/models/paymentRequest"); var merchantID = preferences.ccAvenueMerchantID; const paymentRequest = new PaymentRequestModel( order, merchantID, currentLanguage ); var paymentRequestStr = paymentRequest.toRequestString(); const encryptedText = encryptionUtils.encrypt(paymentRequestStr, null); if (encryptedText) { session.privacy.orderToken = order.orderToken; session.privacy.orderNo = order.orderNo; return { paymentRequest: paymentRequest, encryptedText: encryptedText, accessCode: preferences.ccavenueAccessKey, transactionURL: preferences.ccAvenueTransactionURL, }; } return null; }
d) Submit form from client sidevar transactionURL = data.ccAvenueRes.transactionURL; var encryptedText = data.ccAvenueRes.encryptedText; var accessCode = data.ccAvenueRes.accessCode; function submitForm(transactionURL, encryptedText, accessCode) { // Create a new form element var form = document.createElement("form"); form.method = "post"; form.action = transactionURL; // Create and append hidden input fields to the form var encRequestInput = document.createElement("input"); encRequestInput.type = "hidden"; encRequestInput.name = "encRequest"; encRequestInput.value = encryptedText; form.appendChild(encRequestInput); var accessCodeInput = document.createElement("input"); accessCodeInput.type = "hidden"; accessCodeInput.name = "access_code"; accessCodeInput.value = accessCode; form.appendChild(accessCodeInput); // Append the form to the document and submit it document.body.appendChild(form); form.submit(); } submitForm(transactionURL, encryptedText, accessCode);
- After submitting the data as a payload, a new tab opens for billing information.
- Users provide billing details, make the payment, and are redirected to the specified redirect_url to load the billing form. The redirect_url can be any controller (e.g., place-order controller) to process the payment response.
- In this controller, decrypt the response and read the payment status using the decryption logic provided in the code snippet.
- If the payment status is OK, call the Authorize Hook, where the transaction ID and payment processor are set in the payment instrument. After executing the code, place the order.
- And the page will redirect to a confirmation page
Comments
Post a Comment