/**
* @copyright Transpayrent ApS 2021
* @license Common Transpayrent API license
* @version 1.0.0
*
* @class
* @classdesc The Transpayrent SDK simplifies the [strong consumer authentication (SCA)]{@link https://en.wikipedia.org/wiki/Strong_customer_authentication} and [payment authorization]{@link https://en.wikipedia.org/wiki/Authorization_hold} through the consumer's browser
* while handling [PCI DSS compliance]{@link https://www.pcisecuritystandards.org/}.
* The SDK handles the secure communication with Transpayrent's Payment Gateway and orchestrates the integration into 3 simple steps for the scenarios summarized in the table below.
* | Authorize Payment | Store Payment Card |
* | ----------------- | ------------------ |
* | The payment maybe be authorized for a payment transaction using the card details entered by the consumer in the following simple steps: <ol><li>[Create a new payment transaction]{@link Transpayrent#createTransaction}</li><li>[Authenticate the consumer using 3D Secure or equivalent]{@link Transpayrent#authenticate}</li><li>[Authorize the payment for the payment transaction]{@link Transpayrent#authorize}</li></ol> | The consumer's payment card may be securely stored in Transpayrent's Secure Vault and added to the consumer's wallet in the following simple steps: <ol><li>[Create a new payment transaction]{@link Transpayrent#createTransaction}</li><li>[Authenticate the consumer using 3D Secure or equivalent]{@link Transpayrent#authenticate}</li><li>[Save the consumer's payment card]{@link Transpayrent#save}</li></ol> |
*
* ***Please note that the SDK is intended to communicate directly with Transpayrent's Payment Gateway to handle [PCI DSS compliance]{@link https://www.pcisecuritystandards.org/} for authentication and authorization.***
*
* The SDK handles the authentication by orchestrating the calls to several methods internally and automatically performing the following actions if required:
* * [Fingerprint the consumer's brower]{@link Transpayrent#fingerprint} in an invisible iframe
* * [Display an authentication challenge]{@link Transpayrent#displayChallenge} to the consumer in an iframe
*
* The *look'n'feel* of the authentication challenge may be fully customized using [CSS]{@link https://en.wikipedia.org/wiki/CSS} simply by passing the appropriate iframe configuration when invoking the SDK's [authenticate]{@link Transpayrent#authenticate} method.
* The SDK includes methods for performing each part *(initialization, authentication and verification)* of the strong consumer authentication process but it's strongly recommended to use the [authenticate]{@link Transpayrent#authenticate} to orchestrate the process.
*
* The code sample below provides a complete illustration of how the payment page should use the SDK to create a new payment transaction, authenticate the consumer, securely store the payment card and authorize the payment using the stored card for a payment transaction.
* Please note that the sample assumes a payment session has already been created.
* <font size="-2">
* ```
* <script src="https://storage.googleapis.com/static.[ENVIRONMENT].transpayrent.cloud/v1/swagger-client.js"></script>
* <script src="https://storage.googleapis.com/static.[ENVIRONMENT].transpayrent.cloud/v1/transpayrent.js"></script>
* <script>
* var transpayrentConfig = {
* merchantId: [UNIQUE MERCHANT ID ASSIGNED BY TRANSPAYRENT],
* sessionId: [ID IN THE RESPONSE FROM "Create Payment Session"],
* accessToken: '[x-transpayrent-access-token HTTP HEADER IN THE RESPONSE FROM "Create Payment Session"]'
* };
* var url = 'https://generator.[ENVIRONMENT].transpayrent.cloud/v1/'+ transpayrentConfig.merchantId +'/system/PAYMENT_GATEWAY/sdk/CLIENT';
* var body = { correlation_id : 'TP-103645',
* amount: { currency : 208, // DKK
* value : 100 } };
* var card = { payment_method_id: 109, // VISA
* card_number: 4111111111111111, // Successful Authorization: Manual Challenge with browser fingerprint
* expiry_month: 9,
* expiry_year: 22,
* cvv: 987,
* card_holder_name: 'John Doe',
* save: true };
* var address = { street : 'Arne Jacobsens Allé 7',
* appartment : '5. sal',
* city : 'Copenhagen S',
* postal_code : '2300',
* state : 'CO',
* country: 208 }; // Denmark
* var phone = { international_dialing_code: 45, // Denmark
* phone_number: 12345678 };
* var email = 'hello@transpayrent.dk';
* var save = { card : card,
* consumer_id : '[MERCHANT'S CONSUMER ID FROM PAYMENT SESSION]',
* name : "My VISA Card" }
* var ssoToken = '[MERCHANT'S SINGLE SIGN-ON TOKEN FOR AUTHORIZING A PAYMENT WITH THE CONSUMER'S WALLET]';
*
* var sdk = new Transpayrent(url, transpayrentConfig);
*
* // Create payment transaction for securely storing the consumer's payment card and add the stored card to the consumer's wallet
* sdk.createTransaction(card.payment_method_id, { amount: { currency : 208, // DKK
* value : 0 } })
* .then(
* transaction => {
* // Creation of Payment Transaction failed - Display status message
* if (transaction.status) {
* alert('API: '+ transaction.api +' failed with HTTP Status Code: '+ transaction.status);
* return Promise.reject(null);
* }
* else {
* var body = { card : card,
* billing_address : address,
* shipping_address : address,
* contact : { mobile : phone,
* work : phone,
* home : phone,
* email : email } };
* var iframeConfig = { container : document.body,
* css: 'challenge',
* callback : function (event, iframe) {
* switch (event) {
* case 'authentication-challenge-initiated':
* // DO SOMETHING BEFORE THE AUTHENTICATION CHALLENGE IS DISPLAYED
* break;
* case 'authentication-challenge-completed':
* // DO SOMETHING AFTER THE AUTHENTICATION CHALLENGE IS COMPLETE
* break;
* }
* } };
* return sdk.authenticate(transaction.id, body, iframeConfig);
* }
* })
* .then(
* authentication => {
* // Consumer Authentication failed
* if (authentication.status) {
* // Consumer failed authentication challenge
* if (authentication.status == 511) {
* alert('Consumer failed authentication challenge for payment transaction: '+ authentication.transaction_id);
* }
* // API request failed - Display status message
* else {
* alert('API: '+ authentication.api +' failed with HTTP Status Code: '+ authentication.status);
* }
* return Promise.reject(null);
* }
* // Consumer Authentication succesfully completed
* else {
* save.card.cryptogram = authentication.cryptogram;
* return sdk.save(authentication.transaction_id, save);
* }
* })
* .then(
* save => {
* // Saving Payment Card failed - Display status message
* if (save.status) {
* alert('API: '+ save.api +' failed with HTTP Status Code: '+ save.status);
* return Promise.reject(null);
* }
* // Payment card succesfully saved and added to the consumer's wallet
* else {
* var request = { payment_method_id: 201, // Consumer Wallet
* valuable_id : save.valuable_id,
* access_token : ssoToken }
*
* // Create new transaction for authorizing a payment with the stored card
* return sdk.createTransaction(request.payment_method_id, body)
* .then(
* transaction => {
* // Creation of Payment Transaction failed - Display status message
* if (transaction.status) {
* alert('API: '+ transaction.api +' failed with HTTP Status Code: '+ transaction.status);
* return Promise.reject(null);
* }
* // Authorize the payment for the payment transaction using the consumer's stored card
* else {
* return sdk.authorize(transaction.id, request);
* }
* });
* }
* })
* .then(
* authorization => {
* // Payment Authorization failed - Display status message
* if (authorization.status) {
* alert('API: '+ authorization.api +' failed with HTTP Status Code: '+ authorization.status);
* }
* // Payment Authorization completed - Display success message
* else {
* alert('Payment transaction: '+ authorization.transaction_id +' successfully authorized');
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error(reason);
* }
* });
* </script>
* ```
* </font>
*
* @see [SwaggerClient] {@link https://github.com/swagger-api/swagger-js#swagger-client-}
*
* @constructor
* @description Creates a new instance of the Transpayrent SDK, which simplifies the strong consumer authentication (SCA) and payment authorization through the consumer's browser.
* @example <caption>Instantiate the Transpayrent SDK</caption>
* <script src="https://storage.googleapis.com/static.[ENVIRONMENT].transpayrent.cloud/v1/swagger-client.js"></script>
* <script src="https://storage.googleapis.com/static.[ENVIRONMENT].transpayrent.cloud/v1/transpayrent.js"></script>
* <script>
* var transpayrentConfig = {
* merchantId: [UNIQUE MERCHANT ID ASSIGNED BY TRANSPAYRENT],
* sessionId: [ID IN THE RESPONSE FROM "Create Payment Session"],
* accessToken: '[x-transpayrent-access-token HTTP HEADER IN THE RESPONSE FROM "Create Payment Session"]'
* };
* var url = 'https://generator.[ENVIRONMENT].transpayrent.cloud/v1/'+ transpayrentConfig.merchantId +'/system/PAYMENT_GATEWAY/sdk/CLIENT';
* var sdk = new Transpayrent(url, transpayrentConfig);
* </script>
*
* @param {String} url The URL pointing to the Payment Gateway's OpenAPI service definitions.
* @param {BaseConfig} config The base configuration for the API requests.
*/
function Transpayrent(url, config) {
/**
* Base configuration for all requests made to the Payment Gateway APIs.
*
* @typedef {Object} BaseConfig
* @property {Integer} merchantId Transpayrent's unique ID for the merchant.
* @property {Long} sessionId Transpayrent's unique ID for the payment session that was returned as the `id` property in the response from the "Create Payment Session" API.
* @property {String} accessToken The access token for the payment session that was returned in the HTTP Header: `x-transpayrent-access-token` in the response from the "Create Payment Session" API.
*/
/**
* The base configuration for the API requests.
*
* @private
*
* @type {BaseConfig}
*/
this._config = config;
this._config.url = url;
/**
* The Swagger Client that was generated from the provided URL.
* The client is used to interact with the Payment Gateway APIs defined using [Open API]{@link https://www.openapis.org}
*
* @private
*
* @type {SwaggerClient}
*/
this._client = new SwaggerClient(url, { requestInterceptor: (request) => {
if (!request.loadSpec) {
request.headers['authorization'] = 'Bearer '+ this._config.accessToken;
}
},
responseInterceptor: (response) => {
if (response.ok) {
// Update the API access token the refreshed token returned by the server
if (response.headers['x-transpayrent-access-token']) {
this._config.accessToken = response.headers['x-transpayrent-access-token'];
}
}
// API request failed
else if (this._config.url != response.url) {
var body = response.body;
if (Array.isArray(body) == false) {
body = new Array(body);
}
if (body[0].system || body[0].status_code) {
response.ok = true;
}
}
},
});
/**
* A representation of a status message returned by the Transpayrent Payment Gateway.
*
* @see [StatusMessage](/v1/model/common/status-message/status-message_v1.yaml#/StatusMessage)
* @see [SYSTEM](/v1/model/common/status-message/system_v1.yaml#/SYSTEM)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} StatusMessage
*/
/**
* A status response returned by the Payment Gateway when an API request fails.
*
* @typedef {Object} Status
* @property {String} api The Payment Gateway API that returned the message(s).
* @property {Integer} status The HTTP Status Code returned by the Payment Gateway.
* @property {Array.<StatusMessage>} messages A list of messages returned by the Payment Gateway.
*/
/**
* Normalizes the status message(s) returned by the Transpayrent Payment Gateway into an object with the following properties:
*
* @private
*
* @param {String} api
* @param {Integer} status
* @param {Any} messages
* @returns {Status} A normalized object with the status message(s) returned by the Payment Gateway
*/
Transpayrent.prototype._normalizeStatus = function (api, status, messages) {
return { api : api,
status : status,
messages : Array.isArray(messages) ? messages : new Array(messages) };
};
/**
* Constructs an iframe which sends an HTTP POST request to enable the Access Control Server (ACS) to fingerprint the consumer's browser.
*
* @public
*
* @param {String} url The URL to the Access Control Server (ACS), which will create a fingerprint of the consumer's browser as part of the 3D Secure process for strong consumer authentication.
* @param {String} data The base64 encoded request data that must be sent to the Access Control Server (ACS).
* The data will be sent to the ACS in the `threeDSMethodData` field for 3D Secure v2 and in the `pareq` field for 3D Secure v1.
* @returns {HTMLIFrameElement} The constructed iframe element
*/
Transpayrent.prototype.fingerprint = function (url, data) {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.style.visibility = 'hidden';
iframe.setAttribute('id', 'threeDSMethodIframe');
iframe.setAttribute('name', 'threeDSMethodIframe');
document.body.appendChild(iframe);
var form = document.createElement('form');
form.setAttribute('id', 'threeDSMethodForm');
form.setAttribute('name', 'threeDSMethodForm');
form.setAttribute('method', 'post');
form.setAttribute('target', 'threeDSMethodIframe');
form.setAttribute('action', url);
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('id', 'threeDSMethodData');
input.setAttribute('name', 'threeDSMethodData');
input.setAttribute('value', data);
form.appendChild(input);
document.body.appendChild(form);
form.submit();
return iframe;
};
/**
* Configuration for the constructed iframe element which will be used to display the authentication challenge.
*
* @example <caption>Example callback function</caption>
* function (event, iframe) {
* switch (event) {
* case 'authentication-challenge-initiated':
* // DO SOMETHING BEFORE THE AUTHENTICATION CHALLENGE IS DISPLAYED
* break;
* case 'authentication-challenge-completed':
* // DO SOMETHING AFTER THE AUTHENTICATION CHALLENGE IS COMPLETE
* break;
* }
*
* @typedef {Object} IFrameConfig
* @property {Element} container The container element in which the constructed iframe will be displayed. Defaults to `document.body`.
* @property {String} css Optional CSS class(es) that will be applied to the constructed iframe.
* @property {String} callback An optional callback function which will be invoked just before the authentication challenge is initiated and just after the challenge is completed.
* The callback function accepts 2 arguments:
* - event: The event that triggered the callback, will be either `authentication-challenge-initiated` or `authentication-challenge-completed`
* - iframe: The constructed iframe that is used for the authentication challenge
*/
/**
* Constructs the iframe element for displaying the authentication challenges and attaches it inside the provided container element.
*
* @public
*
* @param {String} url The URL to the Access Control Server (ACS) will use for the challenge during the strong consumer authentication (SCA) process.
* @param {String} data The base64 encoded request data that must be sent to the Access Control Server (ACS).
* The data will be sent to the ACS in the `creq` field.
* @param {IFrameConfig} config The configuration for the constructed iframe element
* @returns {HTMLIFrameElement} The constructed iframe element
*/
Transpayrent.prototype.displayChallenge = function (url, data, config) {
if (!config.container) {
config.container = document.body;
}
else {
config.container.style.visibility = 'visible';
}
var iframe = document.createElement('iframe');
if (config.css) {
iframe.className = config.css;
}
iframe.setAttribute('id', 'challengeIframe');
iframe.setAttribute('name', 'challengeIframe');
config.container.appendChild(iframe);
if (config.callback) {
config.callback('authentication-challenge-initiated', iframe);
}
var form = document.createElement('form');
form.setAttribute('id', 'challengeForm');
form.setAttribute('name', 'challengeForm');
form.setAttribute('method', 'post');
form.setAttribute('target', 'challengeIframe');
form.setAttribute('action', url);
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('id', 'creq');
input.setAttribute('name', 'creq');
input.setAttribute('value', data);
form.appendChild(input);
input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('id', 'threeDSSessionData');
input.setAttribute('name', 'threeDSSessionData');
form.appendChild(input);
document.body.appendChild(form);
form.submit();
return iframe;
};
/**
* The unique id for the payment method (AMEX, MasterCard, VISA etc.).
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [PAYMENT_METHOD_ID](/v1/model/payment-gateway/payment-method/payment-method-id_v1.yaml#/PAYMENT_METHOD_ID)
*
* @enum
* @typedef {Enum} PAYMENT_METHOD_ID
*/
/**
* A representation of the consumer's payment transaction.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [CreatePaymentTransactionRequest](/v1/model/payment-gateway/payment-transaction/payment-transaction_v1.yaml#/CreatePaymentTransactionRequest)
* @see [Amount](/v1/model/common/amount/amount_v1.yaml#/Amount)
* @see [CURRENCY](/v1/model/common/currency/currency_v1.yaml#/CURRENCY)
*
* @typedef {Object} CreatePaymentTransactionRequest
*/
/**
* A simplified representation of the created payment transaction.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [CreatePaymentTransactionResponse](v1/model/payment-gateway/payment-transaction/payment-transaction_v1.yaml#/CreatePaymentTransactionResponse)
* @see [RecordEntityId](/v1/model/common/record-entity-id/record-entity-id_v1.yaml#/RecordEntityId)
*
* @typedef {Object} CreatePaymentTransactionResponse
*/
/**
* Creates a new payment transaction through the Transpayrent Payment Gateway
* by invoking the [Create Payment Transaction API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/payment_transaction_v1/create_payment_transaction).
* This is the 1st method that should be called by the payment page.
*
* @public
* @example <caption>Create a new payment transaction using the Transpayrent SDK</caption>
* var paymentMethodId = 108; // VISA
* var body = { correlation_id : 'TP-103645',
* amount: { currency : 208, // DKK
* value : 100 } };
* sdk.createTransaction(paymentMethodId, body)
* .then(
* transaction => {
* // Creation of Payment Transaction failed - Display status message
* if (transaction.status) {
* // HANDLE FAILURE
* return Promise.reject(null);
* }
* else {
* // AUTHENTICATE CONSUMER BY INVOKING METHOD: authenticate
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error('Internal error: '+ reason);
* }
* });
*
* @param {PAYMENT_METHOD_ID} paymentMethodId The unique id of the payment method which will be used to authorize the payment for the payment transaction.
* @param {CreatePaymentTransactionRequest} body A representation of the consumer's payment transaction.
* @returns {CreatePaymentTransactionResponse|Status}
*/
Transpayrent.prototype.createTransaction = function (paymentMethodId, body) {
return this._client
.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
payment_method_id : paymentMethodId };
return client.apis.payment_transaction_v1.create_payment_transaction(parameters, { requestBody : body });
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
if (result.status == 201) {
return result.body;
}
// API request failed
else {
return this._normalizeStatus('create_payment_transaction', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'create_payment_transaction';
return Promise.reject(reason);
});
};
/**
* A representation of the payment details provided by the consumer for strong authentication of a payment transaction using 3D Secure or equivalent.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [InitializeAuthenticationRequest](/v1/model/service-bus/consumer-authentication/initialize-authentication_v1.yaml#/InitializeAuthenticationRequest)
* @see [PaymentCard](/v1/model/common/payment-details/payment-card_v1.yaml#/PaymentCard)
* @see [PaymentDetails](/v1/model/common/payment-details_v1.yaml#/PaymentDetails)
* @see [PAYMENT_METHOD_ID](#PAYMENT_METHOD_ID)
*
* @typedef {Object} InitializeAuthenticationRequest
*/
/**
* A representation of the details required to progress the 3D Secure process for strong consumer authentication.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [InitializeAuthenticationResponse](/v1/model/service-bus/consumer-authentication/initialize-authentication_v1.yaml#/InitializeAuthenticationResponse)
*
* @typedef {Object} InitializeAuthenticationResponse
*/
/**
* Initializes strong consumer authentication for the specified payment transaction through the Transpayrent Payment Gateway using 3D secure or equivalent
* by invoking the [Initialize Authentication For Transaction API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/consumer_authentication_v1/initialize_authentication_for_transaction).
* Calling this method directly is **not** recommended, instead call method: {@link Transpayrent#authenticate} to orchestrate the complete flow for strong consumer authentication (SCA).
* ***Please note that API calls made using this method falls under [PCI DSS]{@link https://www.pcisecuritystandards.org/}.***
*
* @see {@link Transpayrent#authenticate}
*
* @public
*
* @param {Long} transactionId The unique id of the payment transaction for which strong consumer authentication using 3D secure or equivalent is required
* @param {InitializeAuthenticationRequest} body A representation of the payment details provided by the consumer for strong authentication of a payment transaction using 3D Secure or equivalent.
* @returns {InitializeAuthenticationResponse|Status}
*/
Transpayrent.prototype.initializeAuthentication = function (transactionId, body) {
return this._client
.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
transaction_id : transactionId };
return client.apis.consumer_authentication_v1.initialize_authentication_for_transaction(parameters, { requestBody : body });
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
if (result.status == 200) {
return result.body;
}
// API request failed
else {
return this._normalizeStatus('initialize_authentication', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'initialize_authentication';
return Promise.reject(reason);
});
};
/**
* A representation of the entered payment details and details of the consumer's browser attributes required for strong authentication of a payment transaction using 3D Secure or equivalent.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [AuthenticateConsumerRequest](/v1/model/service-bus/consumer-authentication/consumer-authentication_v1.yaml#/AuthenticateConsumerRequest)
* @see [Browser](/v1/model/common/browser-details/browser-details_v1.yaml#/Browser)
* @see [PaymentCard](/v1/model/common/payment-details/payment-card_v1.yaml#/PaymentCard)
* @see [PaymentDetails](/v1/model/common/payment-details_v1.yaml#/PaymentDetails)
* @see [PAYMENT_METHOD_ID](#PAYMENT_METHOD_ID)
* @see [Address](/v1/model/common/address/address_v1.yaml#/Address)
* @see [ContactDetails](/v1/model/common/contact-details/contact-details_v1.yaml#/ContactDetails)
* @see [COUNTRY](/v1/model/common/country/country_v1.yaml#/COUNTRY)
* @see [PhoneNumber](/v1/model/common/phone-number/phone-number_v1.yaml#/PhoneNumber)
* @see [INTERNATIONAL_DIALING_CODE](/v1/model/common/international-dialing-code_v1.yaml#/INTERNATIONAL_DIALING_CODE)
* @see [Email](/v1/model/common/email/email_v1.yaml#/Email)
*
* @typedef {Object} AuthenticateConsumerRequest
*/
/**
* A representation of the successful authentication of the consumer for a payment transaction using 3D Secure.
* The payment for the payment transaction should be authorized upon receiving a successful authentication result.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [AuthenticationSuccessResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AuthenticationSuccessResult)
* @see [AbstractAuthenticationResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AbstractAuthenticationResult)
* @see [AUTHENTICATION_TYPE](/v1/model/service-bus/consumer-authentication/authentication-type_v1.yaml#/AUTHENTICATION_TYPE)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} AuthenticationSuccessResult
*/
/**
* A representation of an attempted authentication of the consumer for a payment transaction,
* which requires the consumer to complete an additional authentication challenge as part of the strong consumer authentication process using 3D Secure.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [AuthenticationChallengeResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AuthenticationChallengeResult)
* @see [AbstractAuthenticationResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AbstractAuthenticationResult)
* @see [AUTHENTICATION_TYPE](/v1/model/service-bus/consumer-authentication/authentication-type_v1.yaml#/AUTHENTICATION_TYPE)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} AuthenticationChallengeResult
*/
/**
* A representation of a failed authentication of the consumer for a payment transaction using 3D Secure.
* The consumer should be informed of the authentication failure and asked to enter the details of another card upon
* receiving a failure authentication result or the payment transaction should be abandoned so no authorization is attempted.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [AuthenticationFailureResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AuthenticationFailureResult)
* @see [AbstractAuthenticationResult](/v1/model/service-bus/consumer-authentication/authentication-result_v1.yaml#/AbstractAuthenticationResult)
* @see [AUTHENTICATION_TYPE](/v1/model/service-bus/consumer-authentication/authentication-type_v1.yaml#/AUTHENTICATION_TYPE)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} AuthenticationFailureResult
*/
/**
* Authenticates the consumer of the specified payment transaction through the Transpayrent Payment Gateway using 3D secure or equivalent
* by invoking the [Authenticate Consumer API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/consumer_authentication_v1/authenticate_consumer).
* Calling this method directly is **not** recommended, instead call method: {@link Transpayrent#authenticate} to orchestrate the complete flow for strong consumer authentication (SCA).
* ***Please note that API calls made using this method falls under [PCI DSS]{@link https://www.pcisecuritystandards.org/}.***
*
* @see {@link Transpayrent#authenticate}
*
* @public
*
* @param {Long} transactionId The unique id of the payment transaction for which strong consumer authentication using 3D secure or equivalent is required
* @param {AuthenticateConsumerRequest} body A representation of the entered payment details and details of the consumer's browser attributes required for strong authentication of a payment transaction using 3D Secure or equivalent.
* @returns {AuthenticationSuccessResult|AuthenticationChallengeResult|AuthenticationFailureResult|Status}
*/
Transpayrent.prototype.authenticateConsumer = function (transactionId, body) {
return this._client
.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
transaction_id : transactionId,
'user-agent' : '',
accept : '' };
return client.apis.consumer_authentication_v1.authenticate_consumer_for_transaction(parameters, { requestBody : body });
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
// Strong Consumer Authentication Success or Challenge
if (result.status == 200) {
result.body.transaction_id = transactionId;
return result.body;
}
// Strong Consumer Authentication Failure
else if (result.status == 511) {
result.body.transaction_id = transactionId;
result.body.status = result.status;
return result.body;
}
// // API request failed
else {
return this._normalizeStatus('authenticate_consumer', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'authenticate_consumer';
return Promise.reject(reason);
});
};
/**
* Retrieves the strong consumer authentication (SCA) result for the specified payment transaction through the Transpayrent Payment Gateway using 3D secure or equivalent.
* The method will invoke the [Get Authentication Result For Transaction API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/consumer_authentication_v1/get_authentication_result_for_transaction).
* Please note that calling this method directly is **not** recommended, instead call method: {@link Transpayrent#authenticate} to orchestrate the complete flow for strong consumer authentication (SCA).
*
* @see {@link Transpayrent#authenticate}
*
* @public
*
* @param {Long} transactionId The unique id of the payment transaction for which the strong consumer authentication using 3D secure or equivalent is required should be verified
* @returns {AuthenticationSuccessResult|AuthenticationFailureResult|Status}
*/
Transpayrent.prototype.getAuthenticationResult = function (transactionId) {
return this._client
.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
transaction_id : transactionId };
return client.apis.consumer_authentication_v1.get_authentication_result_for_transaction(parameters);
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
// Strong Consumer Authentication Success
if (result.status == 200) {
result.body.transaction_id = transactionId;
return result.body;
}
// Strong Consumer Authentication Failure
else if (result.status == 511) {
result.body.transaction_id = transactionId;
result.body.status = result.status;
return result.body;
}
// // API request failed
else {
return this._normalizeStatus('get_authentication_result', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'get_authentication_result';
return Promise.reject(reason);
});
};
/**
* Convenience method for authenticating the consumer of the specified payment transaction through the Transpayrent Payment Gateway using 3D secure or equivalent.
* The method orchestrates each part *(initialization, authentication and verification)* of the strong consumer authentication process
* by calling several methods internally in the SDK and automatically performs the following actions if required:
* * [Fingerprint the consumer's brower]{@link Transpayrent#fingerprint} in an invisible iframe
* * [Display an authentication challenge]{@link Transpayrent#displayChallenge} to the consumer in an iframe
*
* The *look'n'feel* of the authentication challenge may be fully customized using [CSS]{@link https://en.wikipedia.org/wiki/CSS} simply by passing the appropriate iframe configuration as the 3rd argument to this method.
* This is the 2nd method that should be called by the payment page.
* Please note that:
* * Calling [createTransaction]{@link Transpayrent#createTransaction} should be done prior to calling this method to create a new payment transaction and obtain a transaction id
* * Calling this method is the recommended way to complete the strong consumer authentication (SCA) flow
* * The method will register [event listeners]{@link https://developer.mozilla.org/en-US/docs/Web/API/EventListener} and listen for the following events:
* * 3DS-authentication-complete
* * 3DS-fingerprint-complete
* * ***API calls made using this method falls under [PCI DSS]{@link https://www.pcisecuritystandards.org/}.***
*
* @see {@link Transpayrent#initializeAuthentication}
* @see {@link Transpayrent#authenticateConsumer}
* @see {@link Transpayrent#getAuthenticationResult}
* @see {@link Transpayrent#fingerprint}
* @see {@link Transpayrent#displayChallenge}
*
* @public
*
* @example <caption>Authenticate consumer with 3D Secure or equivalent using the Transpayrent SDK</caption>
* var card = { payment_method_id: 108, // VISA
* card_number: 4111111111111111, // Successful Authorization: Manual Challenge with browser fingerprint
* expiry_month: 9,
* expiry_year: 22,
* cvv: 987,
* card_holder_name: "John Doe",
* save: true };
* var address = { street : 'Arne Jacobsens Allé 7',
* appartment : '5. sal',
* city : 'Copenhagen S',
* postal_code : '2300',
* state : 'CO',
* country: 208 }; // Denmark
* var phone = { international_dialing_code: 45, // Denmark
* phone_number: 12345678 };
* var email = 'hello@transpayrent.dk';
* var body = { card : card,
* billing_address : address,
* shipping_address : address,
* contact : { mobile : phone,
* work : phone,
* home : phone,
* email : email } };
* var iframeConfig = { container : document.body,
* css: 'challenge',
* callback : function (event, iframe) {
* switch (event) {
* case 'authentication-challenge-initiated':
* // DO SOMETHING BEFORE THE AUTHENTICATION CHALLENGE IS DISPLAYED
* break;
* case 'authentication-challenge-completed':
* // DO SOMETHING AFTER THE AUTHENTICATION CHALLENGE IS COMPLETE
* break;
* }
* } };
* sdk.authenticate(transaction.id, body, iframeConfig);
* .then(
* authentication => {
* // Consumer Authentication failed
* if (authentication.status) {
* // Consumer Authentication failure
* if (authentication.status == 511) {
* // HANDLE AUTHENTICATION FAILURE
* return Promise.reject(null);
* }
* // API request failed - Display status message
* else {
* // HANDLE COMMUNICATION ERROR
* return Promise.reject(null);
* }
* }
* // Consumer Authentication succesfully completed
* else {
* // AUTHORIZE PAYMENT BY INVOKING METHOD: authorize
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error('Internal error: '+ reason);
* }
* });
*
* @listens message:'3DS-fingerprint-complete'
* @listens message:'3DS-authentication-complete'
*
* @param {Long} transactionId The unique id of the payment transaction for which strong consumer authentication using 3D secure or equivalent is required
* @param {AuthenticateConsumerRequest} body A representation of the entered payment details required for strong authentication of a payment transaction using 3D Secure or equivalent.
* Please note that the `browser` property will be constructed automatically.
* @param {IFrameConfig} config The configuration for the iframe which will be constructed in case the consumer needs to be presented with an authentication challenge
* @returns {AuthenticationSuccessResult|AuthenticationFailureResult|Status}
*/
Transpayrent.prototype.authenticate = function (transactionId, body, config) {
body.device_channel_id = 2; // Browser based 3D Secure authentication
body.browser = { java_enabled : false,
javascript_enabled : true,
language : navigator.language,
color_depth : screen.colorDepth,
screen_height : screen.height,
screen_width : screen.width,
timezone_offset : new Date().getTimezoneOffset() };
return this.initializeAuthentication(transactionId, { card : body.card })
.then(
result => {
// Failure while initializing strong consumer authentication (SCA) using 3D Secure
if (result.status) {
return result;
}
else {
// Fingerprint browser
if (result.acs_url) {
var _handler = function (resolver, iframe, event) {
if (event.data != null && event.data.toLowerCase() == '3ds-fingerprint-complete') {
iframe.remove();
resolver();
}
}
var resolver;
var promise = new Promise( (resolve, reject) => {
resolver = resolve;
});
setTimeout( () => { iframe.remove(); resolver(); }, 10000);
var iframe = this.fingerprint(result.acs_url, result.request_data);
window.addEventListener('message', _handler.bind(null, resolver, iframe), false);
return promise.then(r => this.authenticateConsumer(transactionId, body),
e => e);
}
else {
return this.authenticateConsumer(transactionId, body);
}
}
},
// Low level error
reason => Promise.reject(reason) )
.then(
authentication => {
// Consumer Authentication requires challenge
if (authentication.result && authentication.result == "C") {
var _handler = function (resolver, iframe, event) {
if (event.data != null && event.data.toLowerCase() == '3ds-authentication-complete') {
if (config.callback) {
config.callback('authentication-challenge-completed', iframe);
}
iframe.remove();
resolver();
}
}
var resolver;
var promise = new Promise( (resolve, reject) => {
resolver = resolve;
});
var iframe = this.displayChallenge(authentication.acs_url, authentication.request_data, config);
window.addEventListener('message', _handler.bind(null, resolver, iframe), false);
return promise.then(r => this.getAuthenticationResult(transactionId),
e => e);
}
// Consumer Authentication complete
else {
return authentication;
}
},
// Low level error
reason => Promise.reject(reason) );
};
/**
* A representation of a payment made using a payment card such as a MasterCard credit card or a VISA debit card.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [PaymentCard](/v1/model/common/payment-details/payment-card_v1.yaml#/PaymentCard)
* @see [PaymentDetails](/v1/model/common/payment-details_v1.yaml#/PaymentDetails)
* @see [PAYMENT_METHOD_ID](#/PAYMENT_METHOD_ID)
*
* @typedef {Object} PaymentCard
*/
/**
* A representation of the details for the successful authorization of a payment transaction.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [AuthorizePaymentResponse](/v1/model/service-bus/payment-authorization/payment-authorization_v1.yaml#/AuthorizePaymentResponse)
* @see [RecordEntityId](/v1/model/common/record-entity-id/record-entity-id_v1.yaml#/RecordEntityId)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} AuthorizePaymentResponse
*/
/**
* Authorizes the payment for the specified payment transaction through the Transpayrent Payment Gateway using the provided payment details by
* invoking the [Authorize Payment For Transaction API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/authorize_payment_v1/authorize_payment_for_transaction).
* This is the 3rd method that should be called by the payment page when authorizing a payment without storing the consumer's payment card.
* Please note that:
* * Calling [authenticate]{@link Transpayrent#authenticate} should be done prior to calling this method to authenticate the consumer and obtain a cryptogram
* * Call [save]{@link Transpayrent#save} prior to calling this method to securely store the consumer's payment card in Transpayren's Secure Vault and add the stored payment card to the consumer's wallet
* * ***API calls made using this method falls under [PCI DSS]{@link https://www.pcisecuritystandards.org/}.***
*
* @see {@link Transpayrent#authenticate}
*
* @public
*
* @example <caption>Authorize payment with payment card details using the Transpayrent SDK</caption>
* var card = { payment_method_id: 108, // VISA
* card_number: 4111111111111111, // Successful Authorization: Manual Challenge with browser fingerprint
* expiry_month: 9,
* expiry_year: 22,
* cvv: 987,
* card_holder_name: "John Doe",
* save: true,
* cryptogram : [CRYPTOGRAM RETURNED BY STRONG CONSUMER AUTHENTICATION] };
* sdk.authorize(authentication.transaction_id, card)
* .then(
* authorization => {
* // Payment Authorization failed - Display status message
* if (authorization.status) {
* // HANDLE AUTHORIZATION FAILURE
* }
* // Payment Authorization completed - Display success message
* else {
* // HANDLE AUTHORIZATION SUCCESS
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error('Internal error: '+ reason);
* }
* });
*
* @example <caption>Authorize payment with stored payment card using the Transpayrent SDK</caption>
* var request = { payment_method_id: 201, // Consumer Wallet
* valuable_id: [VALUABLE ID RETURNED BY SDK METHOD: save] };
* sdk.authorize(save.transaction_id, request)
* .then(
* authorization => {
* // Payment Authorization failed - Display status message
* if (authorization.status) {
* // HANDLE AUTHORIZATION FAILURE
* }
* // Payment Authorization completed - Display success message
* else {
* // HANDLE AUTHORIZATION SUCCESS
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error('Internal error: '+ reason);
* }
* });
*
* @param {Long} transactionId The unique id of the payment transaction for which the payment should be authorized
* @param {PaymentCard} card A representation of a payment made using a payment card such as a MasterCard credit card or a VISA debit card
* @returns {AuthorizePaymentResponse|Status}
*/
Transpayrent.prototype.authorize = function (transactionId, card) {
return this._client.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
transaction_id : transactionId };
var body = { payment_details : card };
return client.apis.authorize_payment_v1.authorize_payment_for_transaction(parameters, { requestBody : body });
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
if (result.status == 200) {
return result.body;
}
// API request failed
else {
return this._normalizeStatus('authorize_payment', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'authorize_payment';
return Promise.reject(reason);
});
};
/**
* A representation of the payment details for the payment instrument, such as a MasterCard credit card or a VISA debit card, which will be saved.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [SaveConsumerValuableRequest](/v1/model/service-bus/consumer-valuable-storage/consumer-valuable-storage_v1.yaml#/SaveConsumerValuableRequest)
* @see [PaymentCard](/v1/model/common/payment-details/payment-card_v1.yaml#/PaymentCard)
* @see [PaymentDetails](/v1/model/common/payment-details_v1.yaml#/PaymentDetails)
* @see [PAYMENT_METHOD_ID](#/PAYMENT_METHOD_ID)
*
* @typedef {Object} SaveConsumerValuableRequest
*/
/**
* A representation of the details for successfully saving the provided payment card.
* Please refer to the [online documentation](/api-docs/index.html) for details on the object properties.
*
* @see [SaveConsumerValuableResponse](/v1/model/service-bus/consumer-valuable-storage/consumer-valuable-storage_v1.yaml#/SaveConsumerValuableResponse)
* @see [RecordEntityId](/v1/model/common/record-entity-id/record-entity-id_v1.yaml#/RecordEntityId)
* @see [STATUS_CODE](/v1/model/common/status-message/status-code_v1.yaml#/STATUS_CODE)
*
* @typedef {Object} SaveConsumerValuableResponse
*/
/**
* Securely stores the provided payment instrument for the specified payment transaction into Transpayrent's Secure Vault
* by invoking the [Save Consumer Valuable For Transaction API](/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/consumer_wallet_v1/save_consumer_valuable_for_transaction).
* The saved payment instrument is automatically added to the consumer's wallet if a consumerId is provided in the request or was specified for the Payment Session.
* This is the 3rd method that should be called by the payment page when storing the consumer's payment card.
* Please note that:
* * Calling [authenticate]{@link Transpayrent#authenticate} should be done prior to calling this method to authenticate the consumer and obtain a cryptogram
* * Merchants can only save a payment instrument for a payment transaction that is part of a payment session owned by the merchant
* * ***API calls made using this method falls under [PCI DSS]{@link https://www.pcisecuritystandards.org/}.***
*
* @see {@link Transpayrent#authenticate}
*
* @public
*
* @example <caption>Save payment instrument using the Transpayrent SDK</caption>
* var card = { payment_method_id: 108, // VISA
* card_number: 4111111111111111, // Successful Authorization: Manual Challenge with browser fingerprint
* expiry_month: 9,
* expiry_year: 22,
* cvv: 987,
* card_holder_name: "John Doe",
* cryptogram : [CRYPTOGRAM RETURNED BY STRONG CONSUMER AUTHENTICATION] };
* var body = { card : card,
* consumer_id : "CID-12345", // Defaults to the Consumer ID from the Payment Session if omitted
* name : "My VISA Card" }
* sdk.save(authentication.transaction_id, body)
* .then(
* save => {
* // Saving payment instrument failed - Display status message
* if (save.status) {
* // HANDLE SAVE FAILURE
* }
* // Payment instrument successfully saved
* else {
* // AUTHORIZE PAYMENT BY INVOKING METHOD: authorize
* }
* })
* .catch(reason => {
* // Low level error - Display error message
* if (reason) {
* console.error('Internal error: '+ reason);
* }
* });
*
* @param {Long} transactionId The unique id of the payment transaction for which the payment card was authenicated
* @param {SaveConsumerValuableRequest} body The payment details for the payment card which will be securely stored in Transpayrent's Secure Valut and added to the consumer's wallet
* @returns {SaveConsumerValuableResponse|Status}
*/
Transpayrent.prototype.save = function (transactionId, body) {
return this._client.then(
client => {
var parameters = { merchant_id : this._config.merchantId,
session_id : this._config.sessionId,
transaction_id : transactionId };
return client.apis.consumer_wallet_v1.save_consumer_valuable_for_transaction(parameters, { requestBody : body });
},
// Error: Failed to load OpenAPI specification from url
reason => {
console.error('Failed to load OpenAPI specification from url: '+ this._config.url +' due to: '+ reason);
return Promise.reject(reason);
})
.then(
result => {
if (result.status == 200) {
result.body.transaction_id = transactionId;
return result.body;
}
// API request failed
else {
return this._normalizeStatus('save_consumer_valuable', result.status, result.body);
}
},
// Low level error
reason => {
reason.api = 'save_consumer_valuable';
return Promise.reject(reason);
});
};
}