UNPKG

@gorgo/medusa-payment-robokassa

Version:

Robokassa payment provider for Medusa

337 lines 32.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("@medusajs/framework/utils"); const types_1 = require("../types"); const axios_1 = __importDefault(require("axios")); const fast_xml_parser_1 = require("fast-xml-parser"); const utils_2 = require("../utils"); const crypto_1 = require("crypto"); const telemetry_1 = require("@gorgo/telemetry"); class RobokassaBase extends utils_1.AbstractPaymentProvider { static validateOptions(options) { RobokassaBase.telemetry_.track("plugin.started"); if (!(0, utils_1.isDefined)(options.merchantLogin)) { throw new Error("Required option `merchantLogin` is missing in Robokassa provider"); } if (!(0, utils_1.isDefined)(options.password1)) { throw new Error("Required option `password1` is missing in Robokassa provider"); } if (!(0, utils_1.isDefined)(options.password2)) { throw new Error("Required option `password2` is missing in Robokassa provider"); } if (!(0, utils_1.isDefined)(options.hashAlgorithm) || !types_1.HashAlgorithms.includes(options.hashAlgorithm)) { throw new Error("Required option `hashAlgorithm` is missing in Robokassa provider"); } if (options.useReceipt == true) { if (!(0, utils_1.isDefined)(options.taxation)) { throw new Error("Required option `taxation` is missing in Robokassa provider"); } else if (!types_1.taxations.includes(options.taxation)) { throw new Error(`Invalid option \`taxation\` provided in Robokassa provider. Valid values are: ${types_1.taxations.join(", ")}`); } if (!(0, utils_1.isDefined)(options.taxItemDefault)) { throw new Error("Required option `taxItemDefault` is missing in Robokassa provider"); } else if (!types_1.taxes.includes(options.taxItemDefault)) { throw new Error(`Invalid option \`taxItemDefault\` provided in Robokassa provider. Valid values are: ${types_1.taxes.join(", ")}`); } if (!(0, utils_1.isDefined)(options.taxShippingDefault)) { throw new Error("Required option `taxShippingDefault` is missing in Robokassa provider"); } else if (!types_1.taxes.includes(options.taxShippingDefault)) { throw new Error(`Invalid option \`taxShippingDefault\` provided in Robokassa provider. Valid values are: ${types_1.taxes.join(", ")}`); } } } constructor(container, options) { super(container, options); this.baseUrl_ = "https://auth.robokassa.ru"; this.paymentUrl_ = `${this.baseUrl_}/Merchant/Index.aspx`; this.getPaymentUrl_ = `${this.baseUrl_}/Merchant/WebService/Service.asmx/OpStateExt`; this.capturePaymentUrl_ = `${this.baseUrl_}/Merchant/Payment/Confirm`; this.options_ = options; this.logger_ = container.logger; } createSignature(signatureParams) { const concatenatedParams = signatureParams.filter(v => v).join(":"); const res = (0, crypto_1.createHash)(this.options_.hashAlgorithm).update(concatenatedParams).digest('hex'); return res; } normalizePaymentParameters(extra) { const res = {}; if (extra?.data?.SuccessUrl2) res.SuccessUrl2 = extra?.data?.SuccessUrl2; if (extra?.data?.SuccessUrl2Method) res.SuccessUrl2Method = extra?.data?.SuccessUrl2Method; if (extra?.data?.FailUrl2) res.FailUrl2 = extra?.data?.FailUrl2; if (extra?.data?.FailUrl2Method) res.FailUrl2Method = extra?.data?.FailUrl2Method; if (extra?.data?.EMail) res.EMail = extra?.data?.EMail; if (extra?.data?.Culture) res.Culture = extra?.data?.Culture; const isTest = extra?.data?.isTest ?? (this.options_.isTest ? "1" : undefined); if (isTest !== undefined) res.isTest = isTest; const stepByStep = extra?.data?.StepByStep ?? (this.options_.capture === false ? "true" : undefined); if (stepByStep !== undefined) res.StepByStep = stepByStep; return res; } /** * Initiate a new payment. */ async initiatePayment(input) { this.logger_.debug(`RobokassaBase.initiatePayment input:\n${JSON.stringify(input, null, 2)}`); const { amount, context = {} } = input; const outSum = Number(amount).toFixed(2); // TODO: can we avoide generating invoice id? const invoiceId = (0, utils_2.stringToNumberHash)(context.idempotency_key).toString(); const sessionId = input.data?.session_id; const cart = input.data?.cart; const additionalParameters = this.normalizePaymentParameters(input); let receipt = {}; if (this.options_.useReceipt && cart) { receipt = (0, utils_2.generateReceipt)(this.options_.taxation, this.options_.taxItemDefault, this.options_.taxShippingDefault, input.data?.cart); } const receiptJson = JSON.stringify(receipt); const receiptEncoded = encodeURIComponent(receiptJson); const raw = [ this.options_.merchantLogin, outSum, invoiceId, ...(this.options_.useReceipt ? [receiptJson] : []), ...(additionalParameters.StepByStep ? [additionalParameters.StepByStep] : []), additionalParameters.SuccessUrl2, additionalParameters.SuccessUrl2Method, additionalParameters.FailUrl2, additionalParameters.FailUrl2Method, this.options_.isTest ? this.options_.testPassword1 : this.options_.password1, `Shp_SessionID=${sessionId}` ]; const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm); const payment = { MerchantLogin: this.options_.merchantLogin, OutSum: outSum, ...(this.options_.useReceipt ? { Receipt: receiptEncoded } : {}), InvoiceID: invoiceId, SignatureValue: signature, Shp_SessionID: sessionId, ...additionalParameters }; const params = new URLSearchParams(payment).toString(); const paymentUrl = `${this.paymentUrl_}?${params}`; const output = { id: invoiceId, data: { paymentUrl: paymentUrl, ...payment } }; this.logger_.debug("RobokassaBase.initiatePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Capture an existing payment. */ async capturePayment(input) { this.logger_.debug(`RobokassaBase.capturePayment input:\n${JSON.stringify(input, null, 2)}`); const invoiceId = input.data?.InvoiceID; const outSum = input.data?.OutSum; const raw = [ this.options_.merchantLogin, outSum, invoiceId, this.options_.isTest ? this.options_.testPassword1 : this.options_.password1 ]; const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm); const capturePayment = { MerchantLogin: this.options_.merchantLogin, InvoiceID: invoiceId, SignatureValue: signature, OutSum: outSum }; const params = new URLSearchParams(capturePayment).toString(); const capturePaymentUrl = `${this.capturePaymentUrl_}?${params}`; try { const response = await axios_1.default.post(capturePaymentUrl); const output = { data: response.data }; this.logger_.debug("RobokassaBase.capturePayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in capturePayment", e); } } /** * Authorize a payment by retrieving its status. */ async authorizePayment(input) { this.logger_.debug(`RobokassaBase.authorizePayment input:\n${JSON.stringify(input, null, 2)}`); const output = await this.getPaymentStatus(input); this.logger_.debug("RobokassaBase.authorizePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Delete a payment. * Payment delete is not supported by Robokassa. */ async deletePayment(input) { this.logger_.debug(`RobokassaBase.deletePayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("RobokassaBase.deletePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Update a payment. * Payment update is not supported by Robokassa. */ async updatePayment(input) { this.logger_.debug(`RobokassaBase.updatePayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("RobokassaBase.updatePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Refund a payment. * Payment refund is not supported by Robokassa. */ async refundPayment(input) { this.logger_.debug(`RobokassaBase.refundPayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("RobokassaBase.refundPayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Cancel an existing payment. */ async cancelPayment(input) { this.logger_.debug(`RobokassaBase.cancelPayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("RobokassaBase.cancelPayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Retrieve a payment. */ async retrievePayment(input) { this.logger_.debug(`RobokassaBase.retrievePayment input:\n${JSON.stringify(input, null, 2)}`); const invoiceId = input.data?.InvoiceID; const raw = [ this.options_.merchantLogin, invoiceId, this.options_.isTest ? this.options_.testPassword2 : this.options_.password2 ]; const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm); const params = new URLSearchParams({ MerchantLogin: this.options_.merchantLogin, InvoiceID: invoiceId, Signature: signature, }).toString(); const url = `${this.getPaymentUrl_}?${params}`; try { const { data: xml } = await axios_1.default.post(url); const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false, attributeNamePrefix: "@_", }); const parsed = parser.parse(xml); const response = parsed['OperationStateResponse']; const output = { data: { ...input.data, response: response } }; this.logger_.debug("RobokassaBase.retrievePayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in retrievePayment", e); } } /** * Retrieve payment status and map it to Medusa status. */ async getPaymentStatus(input) { this.logger_.debug(`RobokassaBase.getPaymentStatus input:\n${JSON.stringify(input, null, 2)}`); try { const response = (await this.retrievePayment(input)).data?.response; if (!response || !response.Result || !response.State) { throw new Error("Invalid response structure from Robokassa"); } const result = response.Result; const state = response.State; const resultCode = parseInt(result.Code, 10); const resultDescription = result.Description; if (resultCode !== 0) { throw new Error(`Robokassa error ${resultCode}: ${resultDescription}`); } const paymentState = parseInt(state.Code, 10); const map = { 10: utils_1.PaymentSessionStatus.CANCELED, 60: utils_1.PaymentSessionStatus.CANCELED, 20: utils_1.PaymentSessionStatus.AUTHORIZED, 5: utils_1.PaymentSessionStatus.PENDING, 50: utils_1.PaymentSessionStatus.PENDING, 3: utils_1.PaymentSessionStatus.PENDING, 80: utils_1.PaymentSessionStatus.REQUIRES_MORE, 100: utils_1.PaymentSessionStatus.CAPTURED, }; const status = map[paymentState] ?? utils_1.PaymentSessionStatus.ERROR; const output = { status, data: { ...input.data, response } }; this.logger_.debug("RobokassaBase.getPaymentStatus output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in getPaymentStatus", e); } } async getWebhookActionAndData(payload) { this.logger_.debug(`RobokassaBase.getWebhookActionAndData payload:\n${JSON.stringify(payload, null, 2)}`); const data = payload.data; const isValid = await this.isWebhookEventValid(data); if (!isValid) return { action: utils_1.PaymentActions.NOT_SUPPORTED }; const sessionId = data.Shp_SessionID; const outSum = Number(data.OutSum); const result = { action: utils_1.PaymentActions.SUCCESSFUL, data: { session_id: sessionId, amount: outSum } }; this.logger_.debug("RobokassaBase.getWebhookActionAndData result:\n" + JSON.stringify(result, null, 2)); return result; } async isWebhookEventValid(data) { const incomingSignature = data.SignatureValue; const raw = [ data.OutSum, data.InvId, this.options_.password2, `Shp_SessionID=${data.Shp_SessionID}` ]; const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm); return signature === incomingSignature; } /** * Helper to build errors with additional context. */ buildError(message, error) { if (axios_1.default.isAxiosError(error)) { return new Error(`${message}: ${error.response?.status} ${error.response?.data?.code} - ${error.response?.data?.description}`.trim()); } return new Error(`${message}: ${error.message}`.trim()); } } RobokassaBase.identifier = "robokassa"; RobokassaBase.telemetry_ = (0, telemetry_1.createTelemetryClient)({ packageDir: __dirname }); exports.default = RobokassaBase; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9ib2thc3NhLWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheW1lbnQtcm9ib2thc3NhL2NvcmUvcm9ib2thc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFLa0M7QUFhbEMsb0NBUWlCO0FBQ2pCLGtEQUF5QztBQUN6QyxxREFBMkM7QUFDM0Msb0NBSWlCO0FBQ2pCLG1DQUFtQztBQUNuQyxnREFBd0Q7QUFFeEQsTUFBZSxhQUFjLFNBQVEsK0JBQXlDO0lBVzVFLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBeUI7UUFDOUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtRQUVoRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQTtRQUNyRixDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDhEQUE4RCxDQUFDLENBQUE7UUFDakYsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFBO1FBQ2pGLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLHNCQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFnRCxDQUFDLEVBQUUsQ0FBQztZQUM1SCxNQUFNLElBQUksS0FBSyxDQUFDLGtFQUFrRSxDQUFDLENBQUE7UUFDckYsQ0FBQztRQUNELElBQUksT0FB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