@gorgo/medusa-payment-tkassa
Version:
TKassa payment provider for Medusa
239 lines • 19.4 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 get_smallest_unit_1 = require("../utils/get-smallest-unit");
class TkassaBase extends utils_1.AbstractPaymentProvider {
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:\n" + JSON.stringify({ currency_code, amount, data, context }, null, 2));
const additionalParameters = this.normalizePaymentParameters(data);
try {
const response = await this.client_.init({
TerminalKey: this.options_.terminalKey,
Password: this.options_.password,
Amount: (0, get_smallest_unit_1.getSmallestUnit)(amount, currency_code),
OrderId: data?.session_id,
...additionalParameters
});
const paymentId = String(response.PaymentId);
return { id: paymentId, data: response };
}
catch (e) {
throw this.buildError("An error occurred in initiatePayment", e);
}
}
/**
* Capture an existing payment.
*/
async capturePayment(input) {
this.logger_.debug(`TkassaBase.capturePayment:\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
});
return { data: response };
}
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:\n${JSON.stringify(input, null, 2)}`);
const statusResponse = await this.getPaymentStatus(input);
return statusResponse;
}
/**
* Delete a payment.
* Payment delete is not supported by T-Kassa.
*/
async deletePayment(input) {
this.logger_.debug(`TkassaBase.deletePayment:\n${JSON.stringify(input, null, 2)}`);
return input;
}
/**
* Update a payment.
* Payment update is not supported by T-Kassa.
*/
async updatePayment(input) {
this.logger_.debug(`TkassaBase.updatePayment:\n${JSON.stringify(input, null, 2)}`);
return input;
}
/**
* Refund a payment.
*/
async refundPayment({ amount, data, }) {
this.logger_.debug(`TkassaBase.refundPayment:\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
: "";
try {
const response = await this.client_.cancel({
TerminalKey: this.options_.terminalKey,
Password: this.options_.password,
PaymentId: paymentId,
...(amountValue
? { Amount: (0, get_smallest_unit_1.getSmallestUnit)(Number(amountValue), 'RUB') }
: {})
});
return { data: response };
}
catch (e) {
throw this.buildError("An error occurred in refundPayment", e);
}
}
/**
* Cancel an existing payment.
*/
async cancelPayment(input) {
this.logger_.debug(`TkassaBase.cancelPayment:\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
});
return { data: response };
}
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
});
return { data: 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(`TkassaProvider.getPaymentStatus:\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;
return {
status: types_1.PaymentStatusesMap[status] ?? utils_1.PaymentSessionStatus.ERROR,
data: response
};
}
catch (e) {
throw this.buildError("An error occurred in getPaymentStatus", e);
}
}
async getWebhookActionAndData(webhookData) {
this.logger_.debug(`TkassaProvider.getWebhookActionAndData:\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;
return {
action: types_1.PaymentStatusesMap[types_1.PaymentStatuses[data.Status]] ?? utils_1.PaymentSessionStatus.ERROR,
data: {
session_id: data.OrderId,
amount: data.Amount
}
};
}
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";
exports.default = TkassaBase;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGthc3NhLWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheW1lbnQtdGthc3NhL2NvcmUvdGthc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFJa0M7QUFhbEMsb0RBQTJCO0FBQzNCLDZDQUFvQztBQUNwQyxvQ0FNaUI7QUFFakIsa0VBRW1DO0FBRW5DLE1BQWUsVUFBVyxTQUFRLCtCQUE4QztJQU85RSxZQUFZLFNBQTZCLEVBQUUsT0FBOEI7UUFDdkUsS0FBSyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQU5qQixlQUFVLEdBQUcsOEJBQThCLENBQUE7UUFPbkQsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUE7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFBO1FBQy9CLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxvQkFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtJQUMvRixDQUFDO0lBRU8sMEJBQTBCLENBQ2hDLEtBQStCO1FBRS9CLE1BQU0sR0FBRyxHQUFHLEVBQXNCLENBQUE7UUFFbEMsSUFBSSxLQUFLLEVBQUUsVUFBVTtZQUNuQixHQUFHLENBQUMsVUFBVSxHQUFHLEtBQUssRUFBRSxVQUFtQyxDQUFBO1FBRTdELElBQUksS0FBSyxFQUFFLE9BQU87WUFDaEIsR0FBRyxDQUFDLE9BQU8sR0FBRyxLQUFLLEVBQUUsT0FBNkIsQ0FBQTtRQUVwRCxJQUFJLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQztZQUNuQixHQUFHLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUE2QixDQUFBO1FBQ25ELENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxJQUFJLENBQUMsUUFB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