vendure-plugin-nowpayments
Version:
A cryptocurrency payment gateway plugin for Vendure that integrates with NOWPayments.io, enabling your store to accept payments in Bitcoin, Ethereum, and 100+ other cryptocurrencies.
162 lines (161 loc) • 8.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NOWPaymentsController", {
enumerable: true,
get: function() {
return NOWPaymentsController;
}
});
const _ts_decorate = require("@swc/helpers/_/_ts_decorate");
const _ts_metadata = require("@swc/helpers/_/_ts_metadata");
const _ts_param = require("@swc/helpers/_/_ts_param");
const _common = require("@nestjs/common");
const _express = require("express");
const _core = require("@vendure/core");
const _nowpaymentsservice = require("./nowpayments.service");
const _types = require("./types");
const _constants = require("./constants");
const _nowpaymentspaymenthandler = require("./nowpayments-payment.handler");
const missingSignatureErrorMessage = 'Missing x-nowpayments-sig header';
const signatureErrorMessage = 'Error verifying NOWPayments IPN signature';
const noOrderIdErrorMessage = 'No order_id in the IPN payload';
let NOWPaymentsController = class NOWPaymentsController {
async handleIpn(body, signature, request, res) {
if (!signature) {
_core.Logger.error(missingSignatureErrorMessage, _constants.loggerCtx);
res.status(_common.HttpStatus.BAD_REQUEST).send(missingSignatureErrorMessage);
return;
}
const { order_id, payment_status } = body;
if (!order_id) {
_core.Logger.error(noOrderIdErrorMessage, _constants.loggerCtx);
res.status(_common.HttpStatus.BAD_REQUEST).send(noOrderIdErrorMessage);
return;
}
if (!this.nowPaymentsService.verifySignature(body, signature)) {
_core.Logger.error(`${signatureErrorMessage} for order ${order_id}`, _constants.loggerCtx);
res.status(_common.HttpStatus.BAD_REQUEST).send(signatureErrorMessage);
return;
}
if (payment_status === 'failed' || payment_status === 'expired') {
const orderCode = order_id.replace(this.nowPaymentsService.invoicePrefix, '');
_core.Logger.warn(`Payment for order ${orderCode} ${payment_status}`, _constants.loggerCtx);
res.status(_common.HttpStatus.OK).send('Ok');
return;
}
if (payment_status !== 'finished') {
const orderCode = order_id.replace(this.nowPaymentsService.invoicePrefix, '');
_core.Logger.info(`Received ${payment_status} status update for order ${orderCode}`, _constants.loggerCtx);
res.status(_common.HttpStatus.OK).send('Ok');
return;
}
const orderCode = order_id.replace(this.nowPaymentsService.invoicePrefix, '');
const defaultChannel = await this.channelService.getDefaultChannel();
const lookupCtx = await this.requestContextService.create({
apiType: 'admin',
channelOrToken: defaultChannel.token
});
const order = await this.orderService.findOneByCode(lookupCtx, orderCode);
if (!order) {
_core.Logger.error(`Unable to find order ${orderCode}, unable to process IPN for payment ${body.payment_id}!`, _constants.loggerCtx);
res.status(_common.HttpStatus.BAD_REQUEST).send(`Order ${orderCode} not found`);
return;
}
const orderChannels = await this.orderService.getOrderChannels(lookupCtx, order);
var _orderChannels_;
const orderChannel = (_orderChannels_ = orderChannels[0]) != null ? _orderChannels_ : defaultChannel;
const channelCtx = await this.requestContextService.create({
apiType: 'admin',
channelOrToken: orderChannel.token,
languageCode: _core.LanguageCode.en,
req: request
});
try {
await this.connection.withTransaction(channelCtx, async (ctx)=>{
const orderInTx = await this.orderService.findOneByCode(ctx, orderCode);
if (!orderInTx) {
throw new Error(`Unable to find order ${orderCode}, unable to process IPN for payment ${body.payment_id}!`);
}
if (orderInTx.state !== 'ArrangingPayment' && orderInTx.state !== 'ArrangingAdditionalPayment') {
const transitionToStateResult = await this.orderService.transitionToState(ctx, orderInTx.id, 'ArrangingPayment');
if (transitionToStateResult instanceof _core.OrderStateTransitionError) {
_core.Logger.error(`Error transitioning order ${orderCode} to ArrangingPayment state: ${transitionToStateResult.message}`, _constants.loggerCtx);
throw transitionToStateResult;
}
}
const paymentMethod = await this.getPaymentMethod(ctx);
const addPaymentToOrderResult = await this.orderService.addPaymentToOrder(ctx, orderInTx.id, {
method: paymentMethod.code,
metadata: {
paymentId: body.payment_id,
invoiceId: body.invoice_id,
paymentStatus: payment_status,
actuallyPaid: body.actually_paid,
payAmount: body.pay_amount,
payCurrency: body.pay_currency,
outcomeAmount: body.outcome_amount,
outcomeCurrency: body.outcome_currency,
orderId: order_id
}
});
if (!(addPaymentToOrderResult instanceof _core.Order)) {
_core.Logger.error(`Error adding payment to order ${orderCode}: ${addPaymentToOrderResult.message}`, _constants.loggerCtx);
throw addPaymentToOrderResult;
}
_core.Logger.info(`NOWPayments payment id ${body.payment_id} added to order ${orderCode}`, _constants.loggerCtx);
});
res.status(_common.HttpStatus.OK).send('Ok');
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
_core.Logger.error(`IPN processing failed for order ${orderCode}: ${message}`, _constants.loggerCtx);
if (!res.headersSent) {
res.status(_common.HttpStatus.INTERNAL_SERVER_ERROR).send('IPN processing failed');
}
}
}
async getPaymentMethod(ctx) {
const method = (await this.paymentMethodService.findAll(ctx)).items.find((m)=>m.handler.code === _nowpaymentspaymenthandler.nowPaymentsPaymentHandler.code);
if (!method) {
throw new _core.InternalServerError(`[${_constants.loggerCtx}] Could not find NOWPayments PaymentMethod`);
}
return method;
}
constructor(nowPaymentsService, requestContextService, orderService, paymentMethodService, channelService, connection){
this.nowPaymentsService = nowPaymentsService;
this.requestContextService = requestContextService;
this.orderService = orderService;
this.paymentMethodService = paymentMethodService;
this.channelService = channelService;
this.connection = connection;
}
};
_ts_decorate._([
(0, _common.Post)('ipn'),
_ts_param._(0, (0, _common.Body)()),
_ts_param._(1, (0, _common.Headers)('x-nowpayments-sig')),
_ts_param._(2, (0, _common.Req)()),
_ts_param._(3, (0, _common.Res)()),
_ts_metadata._("design:type", Function),
_ts_metadata._("design:paramtypes", [
typeof _types.NOWPaymentsIPNData === "undefined" ? Object : _types.NOWPaymentsIPNData,
Object,
typeof Request === "undefined" ? Object : Request,
typeof _express.Response === "undefined" ? Object : _express.Response
]),
_ts_metadata._("design:returntype", Promise)
], NOWPaymentsController.prototype, "handleIpn", null);
NOWPaymentsController = _ts_decorate._([
(0, _common.Controller)('nowpayments'),
_ts_metadata._("design:type", Function),
_ts_metadata._("design:paramtypes", [
typeof _nowpaymentsservice.NOWPaymentsService === "undefined" ? Object : _nowpaymentsservice.NOWPaymentsService,
typeof _core.RequestContextService === "undefined" ? Object : _core.RequestContextService,
typeof _core.OrderService === "undefined" ? Object : _core.OrderService,
typeof _core.PaymentMethodService === "undefined" ? Object : _core.PaymentMethodService,
typeof _core.ChannelService === "undefined" ? Object : _core.ChannelService,
typeof _core.TransactionalConnection === "undefined" ? Object : _core.TransactionalConnection
])
], NOWPaymentsController);
//# sourceMappingURL=nowpayments.controller.js.map