@sonatel-os/juf
Version:
The community SDK for Orange Money, SMS, Email & Sonatel APIs on the Orange Developer Platform.
1 lines • 24.1 kB
Source Map (JSON)
{"version":3,"sources":["/Users/JOHNSON028877/Documents/new-juf.js/dist/chunk-7HR2MVLX.cjs","../src/payment/payment.structure.js","../src/payment/qrCodeDecoder.js","../src/payment/paymentService.js"],"names":["logger"],"mappings":"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","file":"/Users/JOHNSON028877/Documents/new-juf.js/dist/chunk-7HR2MVLX.cjs","sourcesContent":[null,"import { define, object, string, number, optional, defaulted } from 'superstruct';\n\nconst Merchant = object({\n code: number(),\n sitename: string(),\n});\n\nconst Bill = object({\n amount: number(),\n reference: string(),\n});\n\nconst Urls = object({\n failed: optional(defaulted(string(), null)),\n cancel: optional(defaulted(string(), null)),\n success: optional(defaulted(string(), null)),\n callback: optional(defaulted(string(), null)),\n});\n\nexport const CheckoutPaymentStructure = object({\n merchant: Merchant,\n bill: Bill,\n urls: Urls,\n});\n\nconst Metadata = define('object', (value) => {\n return typeof value === 'object' && value !== null;\n});\n\nconst Validity = optional(number());\n\nexport const QRCodePaymentStructure = object({\n merchant: Merchant,\n bill: Bill,\n urls: optional(Urls),\n metadata: optional(Metadata),\n validity: Validity,\n});\n\nexport const QRCodeDecodePaymentStructure = object({\n id: string(),\n});\n","/**\n * QR Code Decoder\n * @namespace Service\\QRCodeDecoder\n * @description Standalone service for decoding QR codes.\n *\n * This is separated from the main Payment service because it uses a\n * different authentication mechanism (static SP authorization instead of OAuth2 Bearer tokens).\n * Only applications with explicit `decode_qr_sp_authorization` credentials can use this.\n */\n\nimport Requester from '../core/requester.js';\nimport { envConfig } from '../../config/index.js';\nimport { DECODE_QR_URI } from '../core/urls.js';\nimport { getApiUrl } from '../core/apiUrl.js';\nimport { QRCodeDecodePaymentStructure } from './payment.structure.js';\nimport { logger as rootLogger } from '../core/logger.js';\nimport { validate } from '../core/validation.js';\nimport { fromAxiosError } from '../core/errors.js';\n\n/**\n * @class QRCodeDecoder\n * @classdesc Decodes QR codes by their ID using static SP authorization.\n *\n * Unlike other payment operations that use OAuth2 Bearer tokens via the Authentication service,\n * QR code decoding requires a separate `decode_qr_sp_authorization` credential.\n * This is a privileged operation — only authorized applications can decode QR codes.\n *\n * @example\n * // Default usage\n * const decoder = QRCodeDecoder.init();\n * const { content } = await decoder.decode({ id: 'doyaT9sH3rGFph_ZuKIs' });\n *\n * @example\n * // With dependency injection (for testing)\n * const decoder = new QRCodeDecoder({ client: mockAxios, authorization: 'Basic test', logger: mockLogger });\n */\nclass QRCodeDecoder {\n /** @private @type {import('axios').AxiosInstance} */\n #client;\n\n /** @private @type {string} */\n #authorization;\n\n /** @private */\n #logger;\n\n /**\n * Creates a QRCodeDecoder instance with injectable dependencies.\n *\n * @param {object} deps - Dependencies.\n * @param {import('axios').AxiosInstance} deps.client - HTTP client instance.\n * @param {string} deps.authorization - Static SP authorization header value.\n * @param {object} deps.logger - Logger instance.\n */\n constructor({ client, authorization, logger }) {\n this.#client = client;\n this.#authorization = authorization;\n this.#logger = logger;\n }\n\n /**\n * Factory method to initialize QRCodeDecoder with default dependencies.\n * @returns {QRCodeDecoder} An initialized instance.\n */\n static init() {\n const apigeeConfig = envConfig.get('apigee');\n\n return new QRCodeDecoder({\n client: Requester.bootstrap({ baseURL: getApiUrl() }),\n authorization: apigeeConfig.decode_qr_sp_authorization,\n logger: rootLogger.child('qr-decoder'),\n });\n }\n\n /**\n * Decodes a QR code by its ID.\n *\n * @async\n * @param {object} qrDetails - The details required to decode the QR code.\n * @param {string} qrDetails.id - The unique identifier of the QR code.\n * @returns {Promise<{ id: string, content: { merchantCode: string, merchantName: string, amount: number, reference: string, scope: string, type: string, metadata: object } }>}\n * @throws {import('../core/errors.js').ValidationError} When input validation fails.\n * @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.\n *\n * @example\n * const { content } = await decoder.decode({ id: 'doyaT9sH3rGFph_ZuKIs' });\n * console.log(content.amount, content.reference);\n */\n async decode({ id }) {\n validate({ id }, QRCodeDecodePaymentStructure, 'decodeQrCode');\n\n try {\n const { data } = await this.#client.get(DECODE_QR_URI.replace(':id', id), {\n headers: { authorization: this.#authorization },\n });\n return data;\n } catch (error) {\n if (error.code?.startsWith('JUF_')) throw error;\n\n this.#logger.error('QR code decoding failed', { qrId: id, status: error.response?.status });\n throw fromAxiosError(error, 'Error decoding QR code.');\n }\n }\n}\n\nexport default QRCodeDecoder;\n","/**\n * Payment\n * @namespace Service\\Payment\n * @description Payment Service to handle various payment-related functionalities.\n */\n\nimport Requester from '../core/requester.js';\nimport { envConfig } from '../../config/index.js';\nimport { GENERATE_QR_URI, GENERATE_PAYMENT_LINK_URI } from '../core/urls.js';\nimport { getApiUrl } from '../core/apiUrl.js';\nimport Authentication from '../auth/authenticationService.js';\nimport QRCodeDecoder from './qrCodeDecoder.js';\nimport { CheckoutPaymentStructure, QRCodePaymentStructure } from './payment.structure.js';\nimport { logger as rootLogger } from '../core/logger.js';\nimport { validate, validateUrls } from '../core/validation.js';\nimport { fromAxiosError } from '../core/errors.js';\nimport { CURRENCY_UNIT } from '../core/constants.js';\nimport { buildAuthHeader } from '../core/authHeader.js';\n\n/**\n * @class Payment\n * @classdesc Handles payment operations including initializing payments, generating QR codes, and decoding QR codes.\n *\n * Supports dependency injection for testability — pass dependencies via constructor,\n * or use the {@link Payment.init} factory for default behavior.\n *\n * @example\n * // Default usage (backward compatible)\n * const paymentService = Payment.init();\n *\n * @example\n * // With dependency injection (for testing)\n * const paymentService = new Payment({ authService: mockAuth, client: mockAxios, config: mockConfig, logger: mockLogger });\n */\nclass Payment {\n /** @private @type {import('axios').AxiosInstance} */\n #client;\n\n /** @private @type {Authentication} */\n #authService;\n\n /** @private */\n #config;\n\n /** @private */\n #logger;\n\n /** @private @type {QRCodeDecoder} */\n #qrDecoder;\n\n /**\n * Creates a Payment instance with injectable dependencies.\n *\n * @param {object} deps - Dependencies for the payment service.\n * @param {Authentication} deps.authService - Authentication service instance.\n * @param {import('axios').AxiosInstance} deps.client - HTTP client instance.\n * @param {object} deps.config - Apigee configuration (for onProd, onPProd).\n * @param {object} deps.logger - Logger instance with error/warn/info/debug methods.\n * @param {QRCodeDecoder} [deps.qrDecoder] - Optional QR code decoder instance.\n */\n constructor({ authService, client, config, logger, qrDecoder }) {\n this.#authService = authService;\n this.#client = client;\n this.#config = config;\n this.#logger = logger;\n this.#qrDecoder = qrDecoder;\n }\n\n /**\n * Factory method to initialize Payment service with default dependencies.\n * @method init\n * @memberof Service\\Payment\n * @param {object} [deps] - Optional shared dependencies.\n * @param {Authentication} [deps.authService] - Shared auth instance (avoids duplicate token fetches).\n * @returns {Payment} An initialized instance of Payment.\n */\n static init({ authService } = {}) {\n const apigeeConfig = envConfig.get('apigee');\n\n return new Payment({\n authService: authService || Authentication.init(),\n client: Requester.bootstrap({ baseURL: getApiUrl() }),\n config: apigeeConfig,\n logger: rootLogger.child('payment'),\n qrDecoder: QRCodeDecoder.init(),\n });\n }\n\n /**\n * Retrieve Authorization headers from cached or fresh token.\n *\n * @private\n * @returns {Promise<{ Authorization: string }>} Authorization headers.\n */\n async #getAuthHeaders() {\n const { access_token, token_type } = await this.#authService.debug();\n return buildAuthHeader(access_token, token_type);\n }\n\n /**\n * Prepares a payment checkout for the OMPay payment gateway.\n *\n * @async\n * @method preparePaymentCheckout\n * @memberof Service\\Payment\n * @param {object} paymentDetails - The payment details.\n * @param {object} paymentDetails.merchant - Merchant information.\n * @param {number} paymentDetails.merchant.code - The merchant code.\n * @param {string} paymentDetails.merchant.sitename - The merchant's site name.\n * @param {object} paymentDetails.bill - Bill information.\n * @param {number} paymentDetails.bill.amount - The amount to be paid.\n * @param {string} paymentDetails.bill.reference - The reference for the transaction.\n * @param {object} paymentDetails.urls - URLs for payment status.\n * @param {string} [paymentDetails.urls.failed] - URL to redirect if payment fails.\n * @param {string} [paymentDetails.urls.cancel] - URL to redirect if payment is canceled.\n * @param {string} [paymentDetails.urls.success] - URL to redirect upon successful payment.\n * @param {string} [paymentDetails.urls.callback] - Callback URL for payment updates.\n * @returns {Promise<{link: string, secret: number}>} The checkout link and secret.\n * @throws {import('../core/errors.js').ValidationError} When input validation fails.\n * @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.\n *\n * @example\n * payment.preparePaymentCheckout({\n * merchant: { code: 123456, sitename: 'your-sitename' },\n * bill: { amount: 10, reference: '654321' },\n * urls: {\n * failed: 'https://my.site/failed',\n * cancel: 'https://my.site/canceled',\n * success: 'https://my.site/success'\n * }\n * })\n * .then(console.log)\n * .catch(console.log)\n */\n async preparePaymentCheckout({ merchant, bill, urls }) {\n validate({ merchant, bill, urls }, CheckoutPaymentStructure, 'preparePaymentCheckout');\n validateUrls(urls);\n\n const { code: merchantCode, sitename } = merchant;\n const { reference, amount } = bill;\n const { success: successUrl, cancel: cancelUrl, failed: failedUrl, callback: callbackUrl } = urls;\n\n try {\n const { Authorization } = await this.#getAuthHeaders();\n\n try {\n await this.createPaymentQRCode({ merchant, bill, urls, validity: 10 });\n } catch {\n this.#logger.warn('QR code service unavailable, proceeding with USSD only', { reference });\n }\n\n const payload = {\n merchantCode,\n sitename,\n amount,\n reference,\n onProd: Boolean(this.#config.onProd),\n onPProd: Boolean(this.#config.onPProd),\n urls: {\n ...(cancelUrl && { cancelUrl }),\n ...(failedUrl && { failedUrl }),\n ...(successUrl && { successUrl }),\n ...(callbackUrl && { callbackUrl }),\n },\n };\n\n const { data } = await this.#client.post(GENERATE_PAYMENT_LINK_URI, payload, {\n headers: { Authorization },\n });\n return data;\n } catch (error) {\n if (error.code?.startsWith('JUF_')) throw error;\n\n this.#logger.error('Payment checkout failed', { reference, status: error.response?.status });\n throw fromAxiosError(error, 'Service not available. Check your setup and try again.');\n }\n }\n\n /**\n * Creates a QR code for a payment.\n *\n * @async\n * @method createPaymentQRCode\n * @memberof Service\\Payment\n * @param {object} paymentDetails - The details for the QR code.\n * @param {object} paymentDetails.merchant - Merchant information.\n * @param {number} paymentDetails.merchant.code - The merchant code.\n * @param {string} paymentDetails.merchant.sitename - The merchant's site name.\n * @param {object} paymentDetails.bill - Bill information.\n * @param {number} paymentDetails.bill.amount - The amount to be paid.\n * @param {string} paymentDetails.bill.reference - The reference for the transaction.\n * @param {object} [paymentDetails.urls] - URLs for payment status.\n * @param {string} [paymentDetails.urls.failed] - URL to redirect if payment fails.\n * @param {string} [paymentDetails.urls.cancel] - URL to redirect if payment is canceled.\n * @param {string} [paymentDetails.urls.success] - URL to redirect upon successful payment.\n * @param {string} [paymentDetails.urls.callback] - Callback URL for payment updates.\n * @param {object} [paymentDetails.metadata] - Additional metadata for the QR code.\n * @param {number} [paymentDetails.validity] - Validity period for the QR code in seconds.\n * @returns {Promise<{ deepLink: string, deepLinks: { MAXIT: string, OM: string }, qrCode: string, validity: number, metadata: object, shortLink: string, qrId: string }>}\n * @throws {import('../core/errors.js').ValidationError} When input validation fails.\n * @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.\n *\n * @example\n * payment.createPaymentQRCode({\n * merchant: { code: 123456, sitename: 'your-sitename' },\n * bill: { amount: 10, reference: '654321' },\n * metadata: { myKey: 'value' },\n * validity: 300\n * })\n * .then(console.log)\n * .catch(console.log)\n */\n async createPaymentQRCode({ merchant, bill, urls = {}, metadata = {}, validity }) {\n validate({ merchant, bill, urls, metadata, validity }, QRCodePaymentStructure, 'createPaymentQRCode');\n validateUrls(urls);\n\n const { code: merchantCode, sitename } = merchant;\n const { reference, amount } = bill;\n const {\n success: callbackSuccessUrl,\n cancel: callbackCancelUrl,\n failed: callbackFailedUrl,\n callback: xCallbackUrl,\n } = urls;\n\n try {\n const { Authorization } = await this.#getAuthHeaders();\n\n const payload = {\n amount: { unit: CURRENCY_UNIT, value: amount },\n callbackCancelUrl: callbackCancelUrl || callbackFailedUrl,\n callbackSuccessUrl,\n reference,\n code: merchantCode,\n metadata: { ...metadata, reference },\n name: sitename,\n validity,\n };\n\n const headers = {\n Authorization,\n ...(xCallbackUrl && { 'X-Callback-Url': xCallbackUrl }),\n };\n\n const { data } = await this.#client.post(GENERATE_QR_URI, payload, { headers });\n return data;\n } catch (error) {\n if (error.code?.startsWith('JUF_')) throw error;\n\n this.#logger.error('QR code generation failed', { reference, status: error.response?.status });\n throw fromAxiosError(error, 'QR code generation failed. Please try again.');\n }\n }\n\n /**\n * Decodes a QR code by its ID.\n * Delegates to {@link QRCodeDecoder} — a separate service that uses static SP authorization\n * instead of OAuth2 tokens. Only authorized applications can decode QR codes.\n *\n * @async\n * @method decodeQrCode\n * @memberof Service\\Payment\n * @param {object} qrDetails - The details required to decode the QR code.\n * @param {string} qrDetails.id - The unique identifier of the QR code.\n * @returns {Promise<{ id: string, content: { merchantCode: string, merchantName: string, amount: number, reference: string, scope: string, type: string, metadata: object } }>}\n * @throws {import('../core/errors.js').ValidationError} When input validation fails.\n * @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.\n *\n * @example\n * payment.decodeQrCode({ id: 'doyaT9sH3rGFph_ZuKIs' })\n * .then(console.log)\n * .catch(console.log)\n */\n async decodeQrCode({ id }) {\n return this.#qrDecoder.decode({ id });\n }\n}\n\nexport default Payment;\n"]}