@gorgo/medusa-payment-tkassa
Version:
T-Kassa payment provider for Medusa
307 lines • 29.7 kB
JavaScript
"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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