Introduction
Mercanet is a secure multi-channel e-commerce payment solution that complies with the PCI DSS standard. It allows you to accept and manage payment transactions by taking into account business rules related to your activity (payment on dispatch, deferred payment, recurring payment, payment in instalments, …).
Document purpose
This document purpose is to explain the implementation of the Client Side Encryption solution until production starts.
Client Side Encryption functionally allows sensitive information (card number and csc code) to be encrypted and to process them throw Office (M2M).
This functionality allow you to lower PCI requirement and therefore to only be subject to SAQ A-EP type impacts (see: https://www.pcisecuritystandards.org/pci_security/completing_self_assessment)
Who does this document target?
This document is intended for the merchants who want to integrate the Mercanet solution in a quick, simple way. Client Side Encryption allows to manage payment pages having data card that doesn't transit on your server and therefore lower the PCI requirement.
For an overview of the Mercanet solution, it's recommended to consult following documentation
- Functional presentation.
- Feature configuration guide.
Prerequisites
A good knowledge of one industry standard web programming language such as Java, PHP or .Net is required.
Secret key management
Upon your subscription, BNP Paribas provides a secret key on the Mercanet Téléchargement extranet that will allow you to secure exchanges between your website and the Mercanet server.
You are responsible for looking after this key and should take all measures to:
- restrict access to the key
- safeguard it by encrypting it
- never copy it onto a non-secure disc or device
- never send it (via e-mail or regular mail) in a non-secure method
A secret key compromised (and used by a malicious third party) might disrupt the regular operation of your shop and might in particular generate unauthorised sales or cash transactions (e.g. refunds).
The very same secret key is used on the various Paypage, Office (M2M), In-App and Walletpage connectors.
keyVersion
field with the new
version, otherwise you will get an answer code 34 (suspected
fraud).CSE key managment
Mercanet Client Side Encryption require an encryption key. Like the Secret key, the CSE key is provided on the Mercanet Téléchargement extranet.
Understanding payment using Client Side Encryption
Client Side Encryption consists of Javascript library embedded on your payment page. It encrypts sensitive data before the web form is submitted to your server.
Encrypted data are then used to make a call to Office (M2M) card payment services in order to be processed
CSE functionality brings you following advantages:
- It's not mandatory to redirect customers to an external payment page
- PCI requirement is lowered since no plain sight sensitive data transits on your server.
1. The payment form included the CSE Javascript library and the public key. Card data are processed by the library and encrypt using the key.
2. You collect payment details.
3. You send the card data to Mercanet to process the transaction.
4. The Mercanet server deciphers encrypted data using the CSE private key part and process the payment.
5. The Mercanet server sends a response to allows you to display the payment result.
Implementing Client Side Encryption in 4 steps
Implementing CSE is an optional Office (M2M) (SOAP/JSON) feature.
In order to start with Office (M2M), please refer to its dedicated documentation.
The CSE feature is available for cardOrder
, cardCheckEnrollment
, addCard
functions when the panType
field is set to CSE and for
walletOrder
, walletCheckEnrollment
functions when the
cscType
field is set to
CSE
Include SDPX CSE library
In order to use CSE functionality, you should include the Mercanet encryption library in the <head> tag of your payment page.
There are two ways to proceed:
- Standard JavaScript inclusion
<script type="text/javascript" src="https://office-server.mercanet.bnpparibas.net/scripts/cse/latest/sdpx.encrypt.js"></script>
- Inclusion using the AMD module
The encryption library is compatible with AMD and can be used with any AMD module or library like RequireJS.
RequireJS recommend to include you script this way:
<script data-main="scripts/main" src="scripts/require.js"></script>
This will guaranty you a single entry point for your application since the your script data-main will be load async
Then, inside main.js, you can use the function require in order to load the encryption library.
<script> require(['https://office-server.mercanet.bnpparibas.net/scripts/cse/latest/sdpx.encrypt.js'], function(sdpx) { // ... }); </script>
In the following example, the first require function parameter is an array of dependency modules needed for your applicaiton. The module name (i.e scripts/sdpx.encrypt ) represents the JS file without the filename extension.
If wanted, you can configure RequireJS in order for it to map the path for practicalness:
<script> requirejs.config({ baseUrl: './', paths: { 'sdpx.encrypt': 'https://office-server.mercanet.bnpparibas.netscripts/cse/latest/sdpx.encrypt' } }); require(['sdpx.encrypt'], function(sdpx) { // ... }); </script>
Implement the payment HTML form
<!DOCTYPE html>
<html lang="en">
<head>
<title>Merchant payment page</title>
</head>
<body>
<form id="payment-form">
<input type="text" id="card-number" sdpx-encrypted />
<input type="text" id="card-expiry-month" />
<input type="text" id="card-expiry-year" />
<input type="text" id="card-csc-value" sdpx-encrypted />
<input type="submit" value="Checkout"/>
</form>
</body>
</html>
Currently Mercanet card payment services support card number and csc code field.
Link the payment form validation event to the CSE library
<script>
var paymentFormId = 'payment-form';
var merchantCseKeyValue = '00CE1A815AA0E970EB6E70...9434E9578F000308AD1E1B|010001';
var merchantCseKeyVersion = '2';
var paymentForm = sdpx.encrypt.onSubmitEncryptForm(paymentFormId, merchantCseKeyValue, merchantCseKeyVersion);
</script>
onSubmitEncryptForm should be called after the page loading.
This means that the above script should be inserted at the end of the <body> section or differed using, either, the onload property on the <body> element, or a listener addition in order to detect the end of the DOM loading of the page (see DOMContentLoaded and readystatechange).
document.onreadystatechange = function () {
if (document.readyState === "interactive") {
var paymentForm = sdpx.encrypt.onSubmitEncryptForm(paymentFormId, merchantCseKeyValue, merchantCseKeyVersion);
}
}
Testing on the customer's test environment
The test and integration steps can be implemented using the test environment.
The URL for the test environment is: https://office-server-mercanet.test.sips-services.com/
The following IDs must be used to carry out this test:
Merchant ID | 201040040170001 |
Secret key version | 1 |
Secret key | rxSP61eeP_oNi5TxCD7Ngy9YcwC8MLw6OlmFGGcsY54 |
CSE key version | 3 |
CSE key | 00AA519EC129B375E8E30DCA7018251433907DF339439 DF0402ABADDD20F3198AB4EC152D830E48ED9B3402660 5BB614897176ECD15DF887A6A79A7392E81BEB2C3CA8D 33FB5E9F9B31DA7809EF1D4EE0B02F3DA15F39B003548 9B53030E2D73AFF4D75433E72C7B614C8852F6E1B99A8 4B50973CD3ACAC642270E636C74739D08C75F11CB9716 8FC23EEFCEACD375BED6C2EE3B826D787F80B282DEC63 EC61FFBCBEC5426E26F423A783D6585865439153E1AF7 23F132933CA7671F8D6A9E9C3AF351081D1465EA20689 2F8D7E1ABBA53373BB4D370A7E02E374E394A8FA20481 C2A121BF7F0300007B7DAD4E69CD66CD99C344D3EC6E7 359EED51D9C6326C01D|010001 |
Advanced implementation
Fields validation activation
The SDPX CSE library can be used to validate input fields on the client side. The functionality is not activated by default, but it can be useful since encrypted data can't by validated on your server.
In order to activate client side field validation an array including fields definition to be checked can be embedded within the object returning be the function onSubmitEncryptForm. An array cell is a JSON structure with the following properties:
Property | Mandatory | Description |
---|---|---|
id | yes | Id of the HTML to be checked |
validator | yes | default validator or custom function to be used to check the field value |
onSuccess | no | callback triggered on a successful field validation |
onError | no | callback triggered on erroneous field validation |
<script>
var paymentForm = sdpx.encrypt.onSubmitEncryptForm(paymentForm, merchantCseKeyValue, merchantCseKeyVersion);
var fieldValidationDefs = [
{ id: 'card-number', validator: '@CardNumber', onSuccess: successValidationHandler, onError: errorValidationHandler },
{ id: 'card-csc-value', validator: '@CscValue', onSuccess: successValidationHandler, onError: errorValidationHandler },
{ id: 'card-expiry-month', validator: '@ExpiryMonth', onSuccess: successValidationHandler, onError: errorValidationHandler },
{ id: 'card-expiry-year', validator: '@ExpiryYear', onSuccess: successValidationHandler, onError: errorValidationHandler }
/*
// Custom validator example:
{ id: 'card-expiry', validator: customCardExpiryValidator, onSuccess: successValidationHandler, onError: errorValidationHandler }
*/
];
paymentForm.setValidations(fieldValidationDefs);
/**
* Custom validator example: check the card expiry value (format 'mm/yyyy')
*
* @param {value} the HTML input element value to validate
* @return {boolean} true if the value is valid, false otherwise
*/
function customCardExpiryValidator(val) {
// Validate the card expiry value
return /^[0-9]{2}\/[0-9]{4}$/.test(val);
}
/**
* Handle success validation
*
* @param {element} the HTML element that has been successfully validated
* @return {void}
*/
function successValidationHandler(element) {
// Do sthg if needed
}
/**
* Handle error validation
*
* @param {Error} a JSON object containing error information
* @return {void}
*/
function errorValidationHandler(error) {
// Handle error
}
</script>
Default field validator
Reference | Description | Source code |
---|---|---|
@CardNumber | Check that card number is between 6 and 19 digits | return /^[0-9]{6,19}$/.test(val); |
@CscValue | Check that csc code is between 3 and 4 digits | return /^[0-9]{3,4}$/.test(val); |
@ExpiryMonth | Check that the month is in range 1 to 12. | return /^[0-9]{2}$/.test(val) && (val > 0) && (val <= 12); |
@ExpiryYear | Check to the year is valid | return /^[0-9]{4}$/.test(val) && (val >= (new Date()).getFullYear()); |
JSON object description reminder
Reference | Description | Exemple |
---|---|---|
message | error message('is invalid!') | card-number is invalid! |
validator | validator reference or custom function name used to validation | @CardNumber, customCardExpiryValidator, ... |
element | HTML element to be checked | HTMLElement |
reason | JavaScript error object describing the validation failure | Error:* Error('Validation returns false')* Error('No validator found for element [<field-id>]') |
Error management
By default, when facing an incident linked to the library usage, a JavaScript error is intercepted and the form submission is canceled.
In order to be able to deal with it, a callback function can be attached to the object returned by onSubmitEncryptForm.
<script>
var paymentForm = sdpx.encrypt.onSubmitEncryptForm(paymentForm, merchantCseKeyValue, merchantCseKeyVersion);
paymentForm.setErrorHandler(errorHandler);
function errorHandler(error) {
// Display an error message to the end user and send information to your server
}
</script>