medusa-payment-yookassa
Version:
YooKassa payment provider for Medusa
275 lines • 22.1 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 yoo_checkout_1 = require("@a2seven/yoo-checkout");
const axios_1 = __importDefault(require("axios"));
const utils_1 = require("@medusajs/framework/utils");
class YookassaBase extends utils_1.AbstractPaymentProvider {
static validateOptions(options) {
if (!(0, utils_1.isDefined)(options.shopId)) {
throw new Error("Required option `shopId` is missing in YooKassa plugin");
}
if (!(0, utils_1.isDefined)(options.secretKey)) {
throw new Error("Required option `secretKey` is missing in YooKassa plugin");
}
}
constructor(container, options) {
// @ts-ignore
super(...arguments);
this.logger_ = container.logger;
this.options_ = options;
this.yooCheckout_ = new yoo_checkout_1.YooCheckout({
shopId: options.shopId,
secretKey: options.secretKey,
});
}
get options() {
return this.options_;
}
normalizePaymentParameters(extra) {
const res = {};
res.description =
extra?.description ??
this.options_?.paymentDescription;
res.capture =
extra?.capture ??
this.paymentOptions.capture ??
this.options_.capture;
res.payment_method_data = this.paymentOptions?.payment_method_data;
res.confirmation = extra?.confirmation;
return res;
}
/**
* Initiate a new payment.
*/
async initiatePayment({ currency_code, amount, data, context, }) {
this.logger_.debug("YookassaBase.initiatePayment:\n" + JSON.stringify({ currency_code, amount, data, context }, null, 2));
const additionalParameters = this.normalizePaymentParameters(data);
const createPayload = {
amount: {
value: amount,
currency: currency_code.toUpperCase(), // Medusa stores currency codes in lower case of ISO-4217
},
metadata: {
session_id: data?.session_id
},
...additionalParameters
};
try {
const response = await this.yooCheckout_.createPayment(createPayload, context?.idempotency_key);
const paymentId = "id" in response ? response.id : data?.session_id;
return {
id: paymentId,
data: response,
};
}
catch (e) {
throw this.buildError("An error occurred in initiatePayment", e);
}
}
/**
* Retrieve payment status and map it to Medusa status.
*/
async getPaymentStatus({ data }) {
this.logger_.debug("YookassaBase.getPaymentStatus:\n" + JSON.stringify(data, null, 2));
const id = data?.id;
if (!id) {
throw this.buildError("No payment ID provided while getting payment status", new Error("No payment ID provided"));
}
try {
const payment = await this.yooCheckout_.getPayment(id);
const paymentData = payment;
switch (payment.status) {
case yoo_checkout_1.PaymentStatuses.pending:
return { status: utils_1.PaymentSessionStatus.PENDING, data: paymentData };
case yoo_checkout_1.PaymentStatuses.canceled:
return { status: utils_1.PaymentSessionStatus.CANCELED, data: paymentData };
case yoo_checkout_1.PaymentStatuses.waiting_for_capture:
return { status: utils_1.PaymentSessionStatus.AUTHORIZED, data: paymentData };
case yoo_checkout_1.PaymentStatuses.succeeded:
return { status: utils_1.PaymentSessionStatus.CAPTURED, data: paymentData };
default:
return { status: utils_1.PaymentSessionStatus.PENDING, data: paymentData };
}
}
catch (e) {
throw this.buildError("An error occurred in getPaymentStatus", e);
}
}
/**
* Capture an existing payment.
*/
async capturePayment(input) {
this.logger_.debug("YookassaBase.capturePayment:\n" + JSON.stringify(input, null, 2));
const payment = input.data;
// Avoid autoCapture in https://github.com/medusajs/medusa/blob/ceb504db2ce44dec43dff652fb306eb4e4f6059e/packages/modules/payment/src/services/payment-module.ts#L590
if (payment.status === yoo_checkout_1.PaymentStatuses.succeeded)
return { data: input };
const payload = {
amount: payment.amount
};
const idempotencyKey = input.context?.idempotency_key;
try {
const response = await this.yooCheckout_.capturePayment(payment.id, payload, idempotencyKey);
return { data: response };
}
catch (e) {
throw this.buildError("An error occurred in capturePayment", e);
}
}
/**
* Authorize a payment by retrieving its status.
*/
async authorizePayment(input) {
this.logger_.debug("YookassaBase.authorizePayment:\n" + JSON.stringify(input, null, 2));
const statusResponse = await this.getPaymentStatus(input);
return statusResponse;
}
/**
* Cancel an existing payment.
*/
async cancelPayment(input) {
this.logger_.debug("YookassaBase.cancelPayment:\n" + JSON.stringify(input, null, 2));
const paymentId = input.data?.id;
const idempotencyKey = input.context?.idempotency_key;
try {
const response = await this.yooCheckout_.cancelPayment(paymentId, idempotencyKey);
return { data: response };
}
catch (e) {
throw this.buildError("An error occurred in cancelPayment", e);
}
}
/**
* Retrieve a payment.
*/
async retrievePayment(input) {
this.logger_.debug("YookassaBase.retrievePayment:\n" + JSON.stringify(input, null, 2));
try {
const payment = await this.yooCheckout_.getPayment(input.data?.id);
return { data: payment };
}
catch (e) {
throw this.buildError("An error occurred in retrievePayment", e);
}
}
/**
* Refund a payment.
*/
async refundPayment({ amount, data, context, }) {
this.logger_.debug("YookassaBase.refundPayment:\n" + JSON.stringify({ amount, data, context }, null, 2));
const payment = data;
const id = payment?.id;
if (!id) {
throw this.buildError("No payment ID provided while refunding payment", new Error("No payment ID provided"));
}
const payload = {
payment_id: id,
amount: {
value: new utils_1.BigNumber(amount).numeric.toString(),
currency: payment?.amount?.currency,
},
};
try {
await this.yooCheckout_.createRefund(payload, context?.idempotency_key);
return await this.retrievePayment({ data });
}
catch (e) {
throw this.buildError("An error occurred in refundPayment", e);
}
}
/**
* Delete a payment.
* Payment deletion is not supported by YooKassa.
*/
async deletePayment(input) {
this.logger_.debug("YookassaBase.deletePayment:\n" + JSON.stringify(input, null, 2));
return input;
}
/**
* Update a payment.
* Payment update is not supported by YooKassa.
*/
async updatePayment(input) {
this.logger_.debug("YookassaBase.updatePayment:\n" + JSON.stringify(input, null, 2));
return input;
}
/**
* Process webhook event and map it to Medusa action.
*/
async getWebhookActionAndData(webhookData) {
this.logger_.debug("YookassaBase.getWebhookActionAndData:\n" + JSON.stringify(webhookData, null, 2));
const isValid = await this.isWebhookEventValid(webhookData);
if (!isValid)
return {
action: utils_1.PaymentActions.NOT_SUPPORTED
};
const { event, object } = webhookData.data;
switch (event) {
case yoo_checkout_1.WebHookEvents["payment.succeeded"]:
return {
action: utils_1.PaymentActions.SUCCESSFUL,
data: {
session_id: object.metadata.session_id,
amount: object.amount.value,
}
};
case yoo_checkout_1.WebHookEvents["payment.waiting_for_capture"]:
return {
action: utils_1.PaymentActions.AUTHORIZED,
data: {
session_id: object.metadata.session_id,
amount: object.amount.value,
},
};
case yoo_checkout_1.WebHookEvents["payment.canceled"]:
return {
action: utils_1.PaymentActions.CANCELED,
data: {
session_id: object.metadata.session_id,
amount: object.amount.value,
},
};
default:
return {
action: utils_1.PaymentActions.NOT_SUPPORTED
};
}
}
/**
* Validate Webhook event
* @param {object} webhookData - the data of the webhook request: req.body
* @returns {boolean} - stutus of validation
*/
async isWebhookEventValid(webhookData) {
const [object, status] = webhookData.data.event.split('.');
try {
switch (object) {
case "payment":
const payment = await this.yooCheckout_.getPayment(webhookData.data.object.id);
return payment.status === status;
case "refund":
const refund = await this.yooCheckout_.getRefund(webhookData.data.object.id);
return refund.status === status;
default:
return false;
}
}
catch (e) {
throw this.buildError(`An error occurred in isWebhookEventValid when validating a ${object}`, e);
}
}
/**
* 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());
}
}
exports.default = YookassaBase;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieW9va2Fzc2EtYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcGF5bWVudC15b29rYXNzYS9jb3JlL3lvb2thc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx3REFVOEI7QUFDOUIsa0RBQXlDO0FBQ3pDLHFEQU9rQztBQW1DbEMsTUFBZSxZQUFhLFNBQVEsK0JBQXdDO0lBSzFFLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBd0I7UUFDN0MsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUE7UUFDM0UsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQywyREFBMkQsQ0FBQyxDQUFBO1FBQzlFLENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBc0IsU0FBK0IsRUFBRSxPQUF3QjtRQUM3RSxhQUFhO1FBQ2IsS0FBSyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUE7UUFFbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFBO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSwwQkFBVyxDQUFDO1lBQ2xDLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7U0FDN0IsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUlELElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQTtJQUN0QixDQUFDO0lBRU8sMEJBQTBCLENBQ2hDLEtBQStCO1FBRS9CLE1BQU0sR0FBRyxHQUFHLEVBQTZC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