UNPKG

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
"use strict"; 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