diff --git a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/schema.yaml b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/schema.yaml index e69de29..7a5ed6b 100644 --- a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/schema.yaml +++ b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/schema.yaml @@ -0,0 +1,68 @@ +schema.yaml: +openapi: 3.0.0 +info: + version: 1.0.1 + title: Get Session and Token API +components: + securitySchemes: + ShopperToken: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: https://my-shortcode.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/my-org-id/oauth2/authorize + tokenUrl: https://my-shortcode.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/my-org-id/oauth2/token + scopes: + c_checkoutsession_rw: Create and return session and token + clientCredentials: + tokenUrl: https://my-shortcode.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/my-org-id/oauth2/token + scopes: + c_checkoutsession_rw: Create and return session and token +paths: + /checkoutsession: + post: + summary: Create the Auth Token and Session ID + operationId: createCheckoutSession + parameters: + - in: query + name: siteId + required: true + schema: + type: string + minLength: 1 + - in: query + name: locale + required: false + schema: + type: string + minLength: 1 + responses: + "200": + description: Returns created Auth Token and Session ID + content: + application/json: + schema: + type: object + properties: + length: + type: number + results: + type: array + items: + type: object + properties: + token: + type: string + sessionId: + type: string + "404": + description: Returns general errors + content: + application/json: + examples: + not_found: + value: + { + "type": "page not found", + } +security: + - AmOAuth2: ["c_checkoutsession_rw"] diff --git a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/script.js b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/script.js index 552d615..696193d 100644 --- a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/script.js +++ b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/rest-apis/marketpay/script.js @@ -1,6 +1,17 @@ const RESTResponseMgr = require('dw/system/RESTResponseMgr'); +const marketPay = require('*/cartridge/scripts/services/marketPay') exports.createCheckoutSession = function () { + const result = marketPay.getTokenAndSessionId(); + try { + RESTResponseMgr + .createSuccess(result) + .render(); + } catch (error) { + RESTResponseMgr + .createError(404, 'Session-error', 'Not created', 'please reach out the SFCC developers.') + .render(); + } }; exports.getNextOrderId = function () { diff --git a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/helpers/site.js b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/helpers/site.js new file mode 100644 index 0000000..52bf9ae --- /dev/null +++ b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/helpers/site.js @@ -0,0 +1,21 @@ +'use strict'; + +const Site = require('dw/system/Site'); + +/** + * Retrieves a site custom preference value by ID. + * + * @param {string} preferenceID - The ID of the site custom preference. + * @returns {*} The preference value, or null if the ID is empty. + */ +function getCustomPreference(preferenceID) { + if (empty(preferenceID)) { + return null; + } + + return Site.getCurrent().getCustomPreferenceValue(preferenceID); +} + +module.exports = { + getCustomPreference +}; diff --git a/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/services/marketPay.js b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/services/marketPay.js new file mode 100644 index 0000000..1d3dc7f --- /dev/null +++ b/cartridges/int_marketpay_headless/cartridges/int_marketpay_headless/cartridge/scripts/services/marketPay.js @@ -0,0 +1,174 @@ +'use strict'; + +const LocalServiceRegistry = require('dw/svc/LocalServiceRegistry'); +const Encoding = require('dw/crypto/Encoding'); +const Bytes = require('dw/util/Bytes'); +const Logger = require('dw/system/Logger'); + +/** + * Creates and returns a LocalServiceRegistry service for authenticating with MarketPay. + * + * The service: + * - Sends a POST request with JSON credentials (username & password). + * - Uses HTTP Basic Authentication with Base64-encoded credentials. + * - Parses the JSON authentication response. + * - Provides a mock response for testing. + * + * @function + * @returns {dw.svc.HTTPService} + * A configured MarketPay authentication service instance. + */ +function getMarketPayAuthenticateService() { + let authString; + let encodedAuthString; + + return LocalServiceRegistry.createService('int.marketpay.auth', { + createRequest: function (svc, payload) { + svc.setRequestMethod('POST'); + svc.addHeader('Content-Type', 'application/json'); + + authString = payload.username + ':' + payload.password; + encodedAuthString = Encoding.toBase64(new Bytes(authString)); + svc.addHeader('Authorization', 'Basic ' + encodedAuthString); + + return JSON.stringify(payload); + }, + + parseResponse: function (svc, client) { + try { + return JSON.parse(client.text); + } catch (e) { + throw new Error('Failed to parse authentication response: ' + e.message); + } + }, + + filterLogMessage: function (msg) { + return msg; // Mask if needed + }, + + mockCall: function () { + return { + status: 'SUCCESS', + token: 'mock-auth-token' + }; + } + }); +} + +/** + * Creates and returns a LocalServiceRegistry service for creating a MarketPay session. + * + * The service: + * - Sends a POST request to the MarketPay session endpoint. + * - Uses Bearer token authentication. + * - Parses the JSON session response. + * - Provides a mock response for testing. + * + * @function + * @returns {dw.svc.HTTPService} + * A configured MarketPay session service instance. + */ +function getMarketPaySessionService() { + return LocalServiceRegistry.createService('int.marketpay.session', { + createRequest: function (svc, payload) { + svc.setRequestMethod('POST'); + svc.addHeader('Content-Type', 'application/json'); + svc.addHeader('Authorization', 'Bearer ' + payload.token); + + return JSON.stringify({}); + }, + + parseResponse: function (svc, client) { + try { + return JSON.parse(client.text); + } catch (e) { + throw new Error('Failed to parse session response: ' + e.message); + } + }, + + filterLogMessage: function (msg) { + return msg; // Mask if needed + }, + + mockCall: function () { + return { + status: 'SUCCESS', + sessionId: 'mock-session-id' + }; + } + }); +} + +/** + * Retrieves an authentication token from the MarketPay API. + * + * Calls the MarketPay authentication service using credentials configured + * as custom site preferences and returns the issued token. + * + * @function getAuthToken + * + * @throws {Error} + * Thrown when the authentication service call fails or does not return a valid token. + * + * @returns {string} + * The MarketPay authentication token. + */ +function getAuthToken() { + const site = require('*/cartridge/scripts/helpers/site.js'); + const authService = getMarketPayAuthenticateService(); + const payload = { + username: site.getCustomPreference('marketpayUsername'), + password: site.getCustomPreference('marketpayPassword') + }; + + const result = authService.call(payload); + + if (!result.ok || !result.object || !result.object.token) { + Logger.error('MarketPay Authenticate API error'); + throw new Error('Failed to retrieve MarketPay authentication token'); + } + + return result.object.token; +} + +/** + * Retrieves a MarketPay authentication token and creates a MarketPay session. + * + * This function: + * - Obtains an authentication token via {@link getAuthToken}. + * - Calls the MarketPay session service using the token. + * - Returns both the token and the created session ID. + * + * @function getTokenAndSessionId + * + * @throws {Error} + * Thrown when the authentication token cannot be retrieved. + * + * @throws {Error} + * Thrown when the session service call fails or does not return a session ID. + * + * @returns {{ token: string, sessionId: string }} + * An object containing: + * - token: The MarketPay authentication token + * - sessionId: The created MarketPay session ID + */ +function getTokenAndSessionId() { + const token = getAuthToken(); + + const sessionService = getMarketPaySessionService(); + const result = sessionService.call({ token: token }); + + if (!result.ok || !result.object || !result.object.sessionId) { + Logger.error('MarketPay Session API error', result.errorMessage); + throw new Error('Failed to retrieve MarketPay session ID'); + } + + return { + token: token, + sessionId: result.object.sessionId + }; +} + +module.exports = { + getTokenAndSessionId: getTokenAndSessionId +};