UNPKG

@gorgo/medusa-payment-tkassa

Version:
307 lines 29.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 crypto_1 = __importDefault(require("crypto")); const t_kassa_api_1 = require("t-kassa-api"); const types_1 = require("../types"); const utils_2 = require("../utils"); const telemetry_1 = require("@gorgo/telemetry"); class TkassaBase extends utils_1.AbstractPaymentProvider { static validateOptions(options) { TkassaBase.telemetry_.track("plugin.started"); if (!(0, utils_1.isDefined)(options.terminalKey)) { throw new Error("Required option `terminalKey` is missing in T-Kassa provider"); } if (!(0, utils_1.isDefined)(options.password)) { throw new Error("Required option `password` is missing in T-Kassa provider"); } if ((0, utils_1.isDefined)(options.useReceipt)) { if (!(0, utils_1.isDefined)(options.taxation)) { throw new Error("Required option `taxation` is missing in T-Kassa provider"); } else if (!types_1.Taxations.includes(options.taxation)) { throw new Error(`Invalid option \`taxation\` provided in T-Kassa provider. Valid values are: ${types_1.Taxations.join(", ")}`); } if (!(0, utils_1.isDefined)(options.taxItemDefault)) { throw new Error("Required option `taxItemDefault` is missing in T-Kassa provider"); } else if (!types_1.TaxItem.includes(options.taxItemDefault)) { throw new Error(`Invalid option \`taxItemDefault\` provided in T-Kassa provider. Valid values are: ${types_1.TaxItem.join(", ")}`); } if (!(0, utils_1.isDefined)(options.taxShippingDefault)) { throw new Error("Required option `taxShippingDefault` is missing in T-Kassa provider"); } else if (!types_1.TaxShipping.includes(options.taxShippingDefault)) { throw new Error(`Invalid option \`taxShippingDefault\` provided in T-Kassa provider. Valid values are: ${types_1.TaxShipping.join(", ")}`); } if (!(0, utils_1.isDefined)(options.ffdVersion)) { throw new Error("Required option `ffdVersion` is missing in T-Kassa provider"); } else if (!types_1.FfdVersions.includes(options.ffdVersion)) { throw new Error(`Invalid option \`ffdVersion\` provided in T-Kassa provider. Valid values are: ${types_1.FfdVersions.join(", ")}`); } } } constructor(container, options) { super(container, options); this.serverUrl_ = "https://securepay.tinkoff.ru"; this.options_ = options; this.logger_ = container.logger; this.client_ = new t_kassa_api_1.TKassa(options.terminalKey, options.password, { server: this.serverUrl_ }); } normalizePaymentParameters(extra) { const res = {}; if (extra?.SuccessURL) res.SuccessURL = extra?.SuccessURL; if (extra?.FailURL) res.FailURL = extra?.FailURL; if (extra?.PayType) { res.PayType = extra.PayType; } else { if (this.options_.capture !== undefined) { res.PayType = this.options_.capture ? "O" : "T"; } else { res.PayType = "O"; } } return res; } /** * Initiate a new payment. */ async initiatePayment({ currency_code, amount, data, context, }) { this.logger_.debug("TkassaBase.initiatePayment input:\n" + JSON.stringify({ currency_code, amount, data, context }, null, 2)); const additionalParameters = this.normalizePaymentParameters(data); const cart = data?.cart; let receipt = {}; try { // Get receipt data if (this.options_.useReceipt && cart) { receipt = (0, utils_2.generateReceipt)(this.options_.ffdVersion, this.options_.taxation, this.options_.taxItemDefault, this.options_.taxShippingDefault, cart); } // Init Payment const initPaymentParams = { TerminalKey: this.options_.terminalKey, Password: this.options_.password, Amount: (0, utils_2.getSmallestUnit)(amount, currency_code), OrderId: data?.session_id, ...additionalParameters, ...(this.options_.useReceipt ? { Receipt: receipt } : {}), }; this.logger_.debug("TkassaBase.initiatePayment initParams:\n" + JSON.stringify(initPaymentParams, null, 2)); const response = await this.client_.init(initPaymentParams); const paymentId = String(response.PaymentId); const output = { id: paymentId, data: { ...response, receipt } }; this.logger_.debug("TkassaBase.initiatePayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in initiatePayment", e); } } /** * Capture an existing payment. */ async capturePayment(input) { this.logger_.debug(`TkassaBase.capturePayment input:\n${JSON.stringify(input, null, 2)}`); const paymentId = input.data?.PaymentId; try { const response = await this.client_.confirm({ TerminalKey: this.options_.terminalKey, Password: this.options_.password, PaymentId: paymentId }); const output = { data: { ...response, receipt: input.data?.receipt } }; this.logger_.debug("TkassaBase.capturePayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in capturePaymentt", e); } } /** * Authorize a payment by retrieving its status. */ async authorizePayment(input) { this.logger_.debug(`TkassaBase.authorizePayment input:\n${JSON.stringify(input, null, 2)}`); const output = await this.getPaymentStatus(input); this.logger_.debug("TkassaBase.authorizePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Delete a payment. * Payment delete is not supported by T-Kassa. */ async deletePayment(input) { this.logger_.debug(`TkassaBase.deletePayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("TkassaBase.deletePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Update a payment. * Payment update is not supported by T-Kassa. */ async updatePayment(input) { this.logger_.debug(`TkassaBase.updatePayment input:\n${JSON.stringify(input, null, 2)}`); const output = input; this.logger_.debug("TkassaBase.updatePayment output:\n" + JSON.stringify(output, null, 2)); return output; } /** * Refund a payment. */ async refundPayment({ amount, data, }) { this.logger_.debug(`TkassaBase.refundPayment input:\n${JSON.stringify({ amount, data }, null, 2)}`); const paymentId = data?.PaymentId; const amountValue = typeof amount === 'object' && 'value' in amount ? amount.value : typeof amount === 'string' || typeof amount === 'number' ? amount : ""; const receipt = (0, utils_2.generateRefundReceipt)(amount, data?.OrderId, data?.receipt); try { const response = await this.client_.cancel({ TerminalKey: this.options_.terminalKey, Password: this.options_.password, PaymentId: paymentId, ...((0, utils_2.getSmallestUnit)(amount, 'RUB') !== data?.amount ? { Receipt: receipt } : {}), // TODO: to remove hardcoded currency? ...(amountValue ? { Amount: (0, utils_2.getSmallestUnit)(Number(amountValue), 'RUB') } // TODO: to remove hardcoded currency? : {}) }); const output = { data: { ...response, receipt: data?.receipt } }; this.logger_.debug("TkassaBase.refundPayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in refundPayment", e); } } /** * Cancel an existing payment. */ async cancelPayment(input) { this.logger_.debug(`TkassaBase.cancelPayment input:\n${JSON.stringify(input, null, 2)}`); const paymentId = input.data?.PaymentId; try { const response = await this.client_.cancel({ TerminalKey: this.options_.terminalKey, Password: this.options_.password, PaymentId: paymentId }); const output = { data: { ...response, receipt: input.data?.receipt } }; this.logger_.debug("TkassaBase.cancelPayment output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in cancelPayment", e); } } /** * Retrieve a payment. */ async retrievePayment(input) { this.logger_.debug(`TkassaBase.retrievePayment input:\n${JSON.stringify(input, null, 2)}`); const paymentId = input.data?.PaymentId; try { const response = await this.client_.getState({ TerminalKey: this.options_.terminalKey, Password: this.options_.password, PaymentId: paymentId }); const output = { data: { ...response, receipt: input.data?.receipt } }; this.logger_.debug("TkassaBase.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(`TkassaProvider.getPaymentStatus input:\n${JSON.stringify(input, null, 2)}`); const paymentId = input.data?.PaymentId; if (!paymentId || typeof paymentId !== 'string') { throw this.buildError("No payment ID provided while getting payment status", new Error("No payment ID provided")); } try { const response = await this.client_.getState({ TerminalKey: this.options_.terminalKey, Password: this.options_.password, PaymentId: paymentId, }); const status = response.Status; const output = { status: types_1.PaymentStatusesMap[status] ?? utils_1.PaymentSessionStatus.ERROR, data: { ...response, receipt: input.data?.receipt }, }; this.logger_.debug("TkassaBase.getPaymentStatus output:\n" + JSON.stringify(output, null, 2)); return output; } catch (e) { throw this.buildError("An error occurred in getPaymentStatus", e); } } async getWebhookActionAndData(webhookData) { this.logger_.debug(`TkassaProvider.getWebhookActionAndData payload:\n${JSON.stringify(webhookData, null, 2)}`); const isValid = await this.isWebhookEventValid(webhookData); if (!isValid) return { action: utils_1.PaymentActions.NOT_SUPPORTED }; const data = webhookData.data; const result = { action: types_1.PaymentStatusesMap[types_1.PaymentStatuses[data.Status]] ?? utils_1.PaymentSessionStatus.ERROR, data: { session_id: data.OrderId, amount: (0, utils_2.getAmountFromSmallestUnit)(data.Amount, "RUB") // TODO: to remove hardcoded currency? } }; this.logger_.debug("TkassaBase.getWebhookActionAndData result:\n" + JSON.stringify(result, null, 2)); return result; } async isWebhookEventValid(payload) { const data = payload.data; if (!data || !data.Status || !data.OrderId || !data.Amount) { return false; } const incomingToken = data.Token; const requiredKeys = [ "TerminalKey", "OrderId", "Success", "Status", "PaymentId", "ErrorCode", "Amount", "CardId", "Pan", "ExpDate" ]; const params = {}; for (const key of requiredKeys) { const value = data[key]; params[key] = String(value); } params["Password"] = this.options_.password; const sortedKeys = Object.keys(params).sort(); let concat = ""; for (const key of sortedKeys) { concat += params[key]; } const hash = crypto_1.default.createHash("sha256").update(concat).digest("hex"); const valid = incomingToken === hash; return valid; } /** * Helper to build errors with additional context. */ buildError(message, error) { const errorDetails = "raw" in error ? error.raw : error; return new Error(`${message}: ${error.message}. ${"detail" in errorDetails ? errorDetails.detail : ""}`.trim()); } } TkassaBase.identifier = "tkassa"; TkassaBase.telemetry_ = (0, telemetry_1.createTelemetryClient)({ packageDir: __dirname }); exports.default = TkassaBase; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGthc3NhLWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheW1lbnQtdGthc3NhL2NvcmUvdGthc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFLa0M7QUFhbEMsb0RBQTJCO0FBQzNCLDZDQUFvQztBQUVwQyxvQ0FVaUI7QUFDakIsb0NBS2lCO0FBQ2pCLGdEQUF3RDtBQUV4RCxNQUFlLFVBQVcsU0FBUSwrQkFBc0M7SUFTdEUsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFzQjtRQUMzQyxVQUFVLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO1FBRTdDLElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFBO1FBQ2pGLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMsMkRBQTJELENBQUMsQ0FBQTtRQUM5RSxDQUFDO1FBQ0QsSUFBSSxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxJQUFJLEtBQUssQ0FBQywyREFBMkQsQ0FBQyxDQUFBO1lBQzlFLENBQUM7aUJBQU0sSUFBSSxDQUFDLGlCQUFTLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxNQUFNLElBQUksS0FBSyxDQUFDLCtFQUErRSxpQkFBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENB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