UNPKG

@gorgo/medusa-payment-robokassa

Version:

Robokassa payment provider for Medusa

327 lines 26.7 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"); class RobokassaBase extends utils_1.AbstractPaymentProvider { static validateOptions(options) { 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"); } } 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; if (extra?.data?.isTest) res.isTest = (extra?.data?.isTest ?? this.options_.isTest) ? "1" : undefined; if (extra?.data?.StepByStep) res.StepByStep = (extra?.data?.StepByStep ?? this.options_.capture) ? undefined : "true"; 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 additionalParameters = this.normalizePaymentParameters(input); const raw = [ this.options_.merchantLogin, outSum, invoiceId, 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, InvoiceID: invoiceId, SignatureValue: signature, Shp_SessionID: sessionId, ...additionalParameters }; const params = new URLSearchParams(payment).toString(); const paymentUrl = `${this.paymentUrl_}?${params}`; return { id: invoiceId, data: { paymentUrl: paymentUrl, ...payment } }; } /** * 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); return { data: response.data }; } 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 statusResponse = await this.getPaymentStatus(input); return statusResponse; } /** * 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)}`); return input; } /** * 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)}`); return input; } /** * 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)}`); return input; } /** * Cancel an existing payment. */ async cancelPayment(input) { this.logger_.debug(`RobokassaBase.cancelPayment input:\n${JSON.stringify(input, null, 2)}`); return input; } /** * 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']; return { data: { ...input.data, response: response } }; } 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); switch (paymentState) { case 10: // 10 is canceled case 60: // 60 is refunded return { status: utils_1.PaymentSessionStatus.CANCELED, // TODO: why we need input.data here? data: { ...input.data, response: response } }; case 20: // 20 is on hold (capture not done yet) return { status: utils_1.PaymentSessionStatus.AUTHORIZED, data: { ...input.data, response: response } }; case 5: // 5 is initiated case 50: // 50 is payed, but still processing return { status: utils_1.PaymentSessionStatus.PENDING, data: { ...input.data, response: response } }; case 80: // 80 is paused return { status: utils_1.PaymentSessionStatus.REQUIRES_MORE, data: { ...input.data, response: response } }; case 100: // is successfully captured return { status: utils_1.PaymentSessionStatus.CAPTURED, data: { ...input.data, response: response } }; default: return { status: utils_1.PaymentSessionStatus.ERROR, data: { ...input.data, response: response } }; } } 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); return { action: utils_1.PaymentActions.SUCCESSFUL, data: { session_id: sessionId, amount: outSum } }; } 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"; exports.default = RobokassaBase; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9ib2thc3NhLWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheW1lbnQtcm9ib2thc3NhL2NvcmUvcm9ib2thc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFLa0M7QUFhbEMsb0NBS2lCO0FBQ2pCLGtEQUF5QztBQUN6QyxxREFBMkM7QUFDM0Msb0NBR2lCO0FBQ2pCLG1DQUFtQztBQUVuQyxNQUFlLGFBQWMsU0FBUSwrQkFBeUM7SUFTNUUsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUF5QjtRQUM5QyxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQTtRQUNyRixDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDhEQUE4RCxDQUFDLENBQUE7UUFDakYsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFBO1FBQ2pGLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLHNCQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFnRCxDQUFDLEVBQUUsQ0FBQztZQUM1SCxNQUFNLElBQUksS0FBSyxDQUFDLGtFQUFrRSxDQUFDLENBQUE7UUFDckYsQ0FBQztJQUNILENBQUM7SUFFRCxZQUFZLFNBQTZCLEVBQUUsT0FBeUI7UUFDbEUsS0FBSyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQTtR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