UNPKG

@nicogorga/medusa-payment-mercadopago

Version:

Mercado Pago payment provider plugin for MedusaJS

403 lines 33.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("@medusajs/framework/utils"); const mercadopago_1 = __importStar(require("mercadopago")); const crypto_1 = require("crypto"); class MercadopagoProviderService extends utils_1.AbstractPaymentProvider { constructor(container, options) { super(container, options); this.options_ = options; this.client_ = new mercadopago_1.default({ accessToken: options.accessToken, }); this.logger_ = container.logger; } static validateOptions(options) { if (!options.accessToken || !(0, utils_1.isString)(options.accessToken)) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "Mercado pago 'accessToken' needs to be a non empty string"); } } async initiatePayment(input) { return { id: "", data: { session_id: input.data?.session_id, amount: input.amount, }, }; } async deletePayment(input) { const paymentId = input.data?.id; if (paymentId) { const payment = new mercadopago_1.Payment(this.client_); await payment.cancel({ id: paymentId }); } return {}; } async authorizePayment(input) { const paymentSessionId = input.data?.session_id; let data = input.data ?? {}; if (!paymentSessionId) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "No payment session id found in data"); } const payment = new mercadopago_1.Payment(this.client_); const results = ((await payment.search({ options: { external_reference: paymentSessionId, sort: 'date_approved', criteria: 'desc' }, }) // Ideally, this would be done in the call to Mercado Pago, but they don't expose an option // to filter based on status )?.results ?? []).filter(payment => payment.status === 'approved'); if (!results.length) { this.logger_.warn(`No payment found in Mercado Pago for payment session: ${paymentSessionId}\n This could be caused by lag in Mercado Pago's system and doesn't mean the payment was not created`); } data = results[0] ?? data; // Returning PaymentSessionStatus.CAPTURED for auto capture, since for UY card method they are captured automatically // TODO: Should make it conditionally in cases where a method could be not auto captured (maybe cash or another country) return { data: data, status: utils_1.PaymentSessionStatus.CAPTURED, }; } async capturePayment(input) { // For now, we assume auto capture, so no need to do anything else with Mercado Pago return { data: input.data }; } async cancelPayment({ data, context }) { try { const id = data?.id; if (!id) { return { data: data }; } const { status } = await this.getPaymentStatus({ data: data }); switch (status) { case 'authorized': const paymentClient = new mercadopago_1.Payment(this.client_); const paymentResponse = await paymentClient.cancel({ id, requestOptions: { idempotencyKey: context?.idempotency_key } }); return { data: paymentResponse }; case 'captured': const refundClient = new mercadopago_1.PaymentRefund(this.client_); const refundResponse = await refundClient.total({ payment_id: id, requestOptions: { idempotencyKey: context?.idempotency_key } }); return { data: refundResponse }; default: return { data }; } } catch (error) { throw new Error(`An error occurred in cancelPayment: ${error}`); } } async getPaymentStatus(input) { const paymentId = input.data?.id; const payment = new mercadopago_1.Payment(this.client_); const paymentData = await payment.get({ id: paymentId }); switch (paymentData.status) { case "authorized": return { status: "authorized", data: paymentData }; case "approved": return { status: "captured", data: paymentData }; case "cancelled": case "refunded": return { status: "canceled", data: paymentData }; case "rejected": return { status: "error", data: { ...paymentData, error_message: this.sanitizeErrorMessage(paymentData) } }; default: return { status: "pending", data: paymentData }; } } async refundPayment(input) { const paymentId = this.getIdOrThrow(input.data); const payment = new mercadopago_1.Payment(this.client_); const paymentData = await payment.get({ id: paymentId }); const refundAmount = Number(input.amount); const isPartial = (paymentData.transaction_amount ?? refundAmount) > refundAmount; const refund = new mercadopago_1.PaymentRefund(this.client_); const refundData = await refund.create({ payment_id: paymentId, body: { amount: isPartial ? refundAmount : undefined, }, }); return { data: refundData }; } async retrievePayment(input) { const paymentId = this.getIdOrThrow(input.data); const payment = new mercadopago_1.Payment(this.client_); const paymentData = await payment.get({ id: paymentId }); return { data: paymentData }; } updatePayment(input) { // TODO: Until working with preferences, we won't have a need for this method. After including preferences, it should update preference items and total amount // when items are added / removed from cart return Promise.resolve({ data: input.data }); } async getWebhookActionAndData(payload) { this.validateWebhookSignature(payload); const mercadopagoData = payload.data; const eventType = mercadopagoData.action; try { switch (eventType) { case "payment.created": case "payment.updated": const payment = new mercadopago_1.Payment(this.client_); const paymentData = await payment.get({ id: mercadopagoData.data.id, }); const paymentSessionId = paymentData.external_reference; if (!paymentSessionId) { throw new Error("No external_reference found in mercadopago payload, unable to match against Medusa payment session"); } if (["authorized", "approved"].includes(paymentData.status ?? "")) { return { action: paymentData.status === "approved" ? utils_1.PaymentActions.SUCCESSFUL : utils_1.PaymentActions.AUTHORIZED, data: { session_id: paymentSessionId, amount: paymentData.transaction_amount, }, }; } default: return { action: "not_supported" }; } } catch (error) { return { action: "failed" }; } } async createAccountHolder({ context }) { const { account_holder, customer, idempotency_key } = context; const id = account_holder?.data.id; if (id) { return { id }; } if (!customer) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "No customer provided while creating account holder"); } const customerClient = new mercadopago_1.Customer(this.client_); let mercadopagoCustomer; try { const body = { email: customer.email, first_name: customer.first_name || undefined, last_name: customer.last_name || undefined, date_registered: new Date().toISOString(), }; mercadopagoCustomer = await customerClient.create({ body: body, requestOptions: { idempotencyKey: idempotency_key, }, }); } catch (e) { const error = e; if (!!error.cause?.find(c => c.code === '101')) { const { results } = await customerClient.search({ options: { email: customer.email } }); mercadopagoCustomer = results[0]; } else { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.UNEXPECTED_STATE, "An error occurred while trying to create a Mercado Pago customer"); } } return { id: mercadopagoCustomer.id, data: mercadopagoCustomer }; } async updateAccountHolder({ context, }) { const { account_holder, customer, idempotency_key } = context; const accountHolderId = account_holder.data?.id; if (!accountHolderId) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "No account holder provided while updating account holder"); } // No customer, nothing to upodate with third party if (!customer) { return {}; } try { const customerClient = new mercadopago_1.Customer(this.client_); const body = { first_name: customer.first_name ?? undefined, last_name: customer.last_name ?? undefined, phone: { number: customer.phone ?? undefined }, identification: account_holder.data.identification ?? undefined, }; if (!account_holder.data.email) { body.email = customer.email; } const payload = { customerId: accountHolderId, body: body, requestOptions: { idempotencyKey: idempotency_key, } }; const updatedCustomer = await customerClient.update(payload); return { data: updatedCustomer, }; } catch (e) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.UNEXPECTED_STATE, "An error occurred in updateAccountHolder when updating a Stripe customer"); } } async savePaymentMethod({ context, data, }) { const accountHolderId = context?.account_holder?.data?.id; if (!accountHolderId) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "Account holder not set while saving a payment method"); } const paymentMethodData = data; const card = new mercadopago_1.CustomerCard(this.client_); // I opened a support ticket with Mercado Pago, as this call randomly fails or succeeds // for now, the step that calls this method has a try / catch, to allow the Payment to cotinue even if this fails const created = await card.create({ customerId: accountHolderId, body: { token: paymentMethodData.token, }, requestOptions: { idempotencyKey: context?.idempotency_key } }); return { id: created.id, data: created }; } async listPaymentMethods({ context, }) { const accountHolderId = context?.account_holder?.data?.id; if (!accountHolderId) { return []; } const cardClient = new mercadopago_1.CustomerCard(this.client_); const paymentMethods = await cardClient.list({ customerId: accountHolderId }); return paymentMethods.map((method) => ({ id: method.id, data: method, })); } async createPayment({ paymentSessionId, payload, }) { const payment = new mercadopago_1.Payment(this.client_); const paymentResponse = await payment.create({ body: { ...payload, external_reference: paymentSessionId, }, }); const errorMessage = this.sanitizeErrorMessage(paymentResponse); paymentResponse["error_message"] = errorMessage; return paymentResponse; } sanitizeErrorMessage(payment) { const status = payment.status; const statusDetail = payment.status_detail; if (status !== "rejected" || !statusDetail) { return null; } switch (statusDetail) { case "cc_rejected_bad_filled_card_number": return "Numero de tarjeta incorrecto."; case "cc_rejected_bad_filled_date": return "Numero de expiracion incorrecto."; case "cc_rejected_bad_filled_security_code": return "Numero de seguridad incorrecto."; case "cc_rejected_insufficient_amount": case "insufficient_amount": return "Saldo insuficiente."; case "cc_rejected_max_attempts": return "Has superado el maximo de intentos, prueba otra tarjeta."; case "rejected_by_bank": return "Tu banco ha rechazado el pago."; default: return "No hemos podido procesar el pago, intenta nuevamente o prueba otra tarjeta."; } } validateWebhookSignature(data) { const secret = this.options_.webhookSecret; // If no webhookSecret is set, the assumption is this protection is not required if (!secret) { return; } const headers = data.headers; const xSignature = (headers["x-signature"] ?? "noop"); const xRequestId = (headers["x-request-id"] ?? "noop"); const body = data?.data; const dataId = (body.data?.id ?? "noop"); const parts = xSignature.split(","); let timestamp; let hash; parts.forEach((part) => { const [key, val] = part.split("="); if (key && val) { const [trimmedKey, trimmedVal] = [key.trim(), val.trim()]; if (trimmedKey === "ts") { timestamp = trimmedVal; } else if (trimmedKey === "v1") { hash = trimmedVal; } } }); const manifest = `id:${dataId};request-id:${xRequestId};ts:${timestamp};`; const hmac = (0, crypto_1.createHmac)("sha256", secret); hmac.update(manifest); const sha = hmac.digest("hex"); if (sha !== hash) { this.logger_ .warn(`Unable to verify Mercado Pago authenticity of request with headers:\n ${headers} `); throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "Invalid signature"); } } getIdOrThrow(data) { const id = String(data?.id); if (!id) { throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "No valid string stored against 'id' key of data object"); } return id; } } MercadopagoProviderService.identifier = "mercadopago"; exports.default = MercadopagoProviderService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvbWVyY2Fkby1wYWdvL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFPbUM7QUFnQ25DLDJEQUFnRztBQUloRyxtQ0FBb0M7QUFXcEMsTUFBTSwwQkFBMkIsU0FBUSwrQkFBMkM7SUFNbEYsWUFBWSxTQUErQixFQUFFLE9BQTJCO1FBQ3RFLEtBQUssQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHFCQUFpQixDQUFDO1lBQ25DLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztTQUNqQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7SUFDbEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBeUI7UUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxJQUFBLGdCQUFRLEVBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDM0QsTUFBTSxJQUFJLG1CQUFXLENBQ25CLHdCQUFnQixDQUFDLFlBQVksRUFDN0IsMkRBQTJELENBQzVELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQ25CLEtBQTJCO1FBRTNCLE9BQU87WUFDTCxFQUFFLEVBQUUsRUFBRTtZQUNOLElBQUksRUFBRTtnQkFDSixVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxVQUFVO2dCQUNsQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07YUFDckI7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENB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