@nackamoto/medusa-paypal-payment
Version:
Paypal payment provider for Medusa
279 lines • 23.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@medusajs/framework/utils");
const utils_2 = require("@medusajs/utils");
const paypal_server_sdk_1 = require("@paypal/paypal-server-sdk");
const formatters_1 = require("./formatters");
class PaypalPaymentProviderService extends utils_1.AbstractPaymentProvider {
constructor(container, options) {
super(container, options);
this.logger_ = container.logger;
this.options_ = options;
this.eventBusService_ = container.event_bus;
if (this.options_.oAuthClientId &&
this.options_.oAuthClientSecret &&
this.options_.environment) {
this.paypal_ = new paypal_server_sdk_1.Client({
clientCredentialsAuthCredentials: {
oAuthClientId: this.options_.oAuthClientId,
oAuthClientSecret: this.options_.oAuthClientSecret,
},
timeout: 0,
environment: this.options_.environment === "sandbox"
? paypal_server_sdk_1.Environment.Sandbox
: paypal_server_sdk_1.Environment.Production,
logging: {
logLevel: paypal_server_sdk_1.LogLevel.Info,
logRequest: {
logBody: true,
},
logResponse: {
logHeaders: true,
},
},
});
}
else {
throw new utils_2.MedusaError(utils_2.MedusaError.Types.INVALID_DATA, "oAuthClientId, oAuthClientSecret and environment are required in the provider's options.");
}
}
static validateOptions(options) {
if (!options.oAuthClientId) {
throw new utils_2.MedusaError(utils_2.MedusaError.Types.INVALID_DATA, "oAuthClientId is required in the provider's options.");
}
if (!options.oAuthClientSecret) {
throw new utils_2.MedusaError(utils_2.MedusaError.Types.INVALID_DATA, "oAuthClientSecret is required in the provider's options.");
}
if (options.environment !== "production" &&
options.environment !== "sandbox") {
throw new utils_2.MedusaError(utils_2.MedusaError.Types.INVALID_DATA, "environment needs to be either production or sandbox");
}
}
async capturePayment(paymentData) {
const paypalOrder = paymentData.data.paypalOrder;
if (paypalOrder.purchaseUnits?.length &&
paypalOrder.purchaseUnits[0].payments &&
paypalOrder.purchaseUnits[0].payments.authorizations?.length) {
const id = paypalOrder.purchaseUnits[0].payments.authorizations[0]
.id;
try {
const paymentsController = new paypal_server_sdk_1.PaymentsController(this.paypal_);
await paymentsController.captureAuthorizedPayment({
authorizationId: id,
});
return await this.retrievePayment(paymentData);
}
catch (error) {
this.logger_.error(error);
throw new Error("An error occurred in capturePayment");
}
}
throw new Error("An error occurred in capturePayment");
}
async authorizePayment(paymentData) {
try {
const status = (await this.getPaymentStatus(paymentData)).status;
const retrievedPayment = await this.retrievePayment(paymentData);
return {
data: {
...paymentData,
paypalOrder: retrievedPayment.data.paypalOrder,
paypalOrderId: retrievedPayment.data.paypalOrder
.id,
},
status: status,
};
}
catch (error) {
throw new Error("Authorize payment failed");
}
}
async cancelPayment(paymentData) {
const paypalOrder = paymentData.data.paypalOrder;
if (paypalOrder.purchaseUnits?.length &&
paypalOrder.purchaseUnits[0].payments) {
const isAlreadyCanceled = paypalOrder.status === paypal_server_sdk_1.OrderStatus.Voided;
const isCanceledAndFullyRefund = paypalOrder.status === paypal_server_sdk_1.OrderStatus.Completed &&
!!paypalOrder.purchaseUnits[0].invoiceId;
if (isAlreadyCanceled || isCanceledAndFullyRefund) {
return await this.retrievePayment(paymentData);
}
const paymentsController = new paypal_server_sdk_1.PaymentsController(this.paypal_);
try {
const isAlreadyCaptured = paypalOrder.purchaseUnits.some((pu) => pu.payments?.captures?.length);
if (isAlreadyCaptured) {
const payments = paypalOrder.purchaseUnits[0].payments;
const capturesId = payments.captures[0].id;
await paymentsController.refundCapturedPayment({
captureId: capturesId,
});
}
else {
const id = paypalOrder.purchaseUnits[0].payments.authorizations[0]
.id;
await paymentsController.voidPayment({
authorizationId: id,
});
}
return await this.retrievePayment(paymentData);
}
catch (error) {
throw new Error("An error occurred in cancelPayment");
}
}
throw new Error("An error occurred in cancelPayment");
}
async initiatePayment(paymentData) {
const ordersController = new paypal_server_sdk_1.OrdersController(this.paypal_);
const { currency_code, amount } = paymentData;
try {
const { result, ...httpResponse } = await ordersController.createOrder({
body: {
intent: paypal_server_sdk_1.CheckoutPaymentIntent.Authorize,
purchaseUnits: [
{
amount: (0, formatters_1.convertAmount)(amount, currency_code),
},
],
},
});
if (result.id) {
return {
id: result.id,
data: {
...paymentData,
paypalOrderId: result.id,
paypalOrder: result,
},
};
}
}
catch (error) {
if (error instanceof paypal_server_sdk_1.ApiError) {
const { statusCode, headers } = error;
this.logger_.error(`Status code ${statusCode.toString()}`);
this.logger_.error(JSON.stringify(headers));
}
}
throw new Error("Initialize payment failed");
}
async deletePayment(paymentSessionData) {
return paymentSessionData;
}
async getPaymentStatus(paymentData) {
const retrievedPayment = await this.retrievePayment(paymentData);
const paypalOrder = retrievedPayment.data.paypalOrder;
switch (paypalOrder.status) {
case paypal_server_sdk_1.OrderStatus.Created:
return {
status: "pending",
};
case paypal_server_sdk_1.OrderStatus.Saved:
case paypal_server_sdk_1.OrderStatus.Approved:
case paypal_server_sdk_1.OrderStatus.PayerActionRequired:
return {
status: "requires_more",
};
case paypal_server_sdk_1.OrderStatus.Voided:
return {
status: "canceled",
};
case paypal_server_sdk_1.OrderStatus.Completed:
return {
status: "authorized",
};
default:
return {
status: "pending",
};
}
}
async refundPayment(paymentData) {
const paypalOrder = paymentData.data.paypalOrder;
if (paypalOrder.purchaseUnits?.length &&
paypalOrder.purchaseUnits[0].payments) {
const purchaseUnit = paypalOrder.purchaseUnits[0];
const isAlreadyCaptured = paypalOrder.purchaseUnits.some((pu) => pu.payments?.captures?.length);
if (!isAlreadyCaptured) {
throw new Error("Cannot refund an uncaptured payment");
}
const paymentId = purchaseUnit.payments?.captures[0].id;
const currencyCode = purchaseUnit.amount?.currencyCode;
const amount = paymentData.amount;
const paymentsController = new paypal_server_sdk_1.PaymentsController(this.paypal_);
try {
await paymentsController.refundCapturedPayment({
captureId: paymentId,
body: {
amount: (0, formatters_1.convertAmount)(amount, currencyCode),
},
});
return await this.retrievePayment(paymentData);
}
catch (error) {
this.logger_.error(error);
throw new Error("An error occurred in refundPayment");
}
}
throw new Error("An error occurred in refundPayment");
}
async retrievePayment(paymentSessionData) {
const ordersController = new paypal_server_sdk_1.OrdersController(this.paypal_);
try {
const paypalOrderId = paymentSessionData.data.paypalOrder.id;
const { result, ...httpResponse } = await ordersController.getOrder({
id: paypalOrderId,
});
if (result.id) {
return {
data: {
...paymentSessionData,
paypalOrderId: result.id,
paypalOrder: result,
},
};
}
}
catch (error) {
if (error instanceof paypal_server_sdk_1.ApiError) {
const { statusCode, headers } = error;
this.logger_.error(`Status code ${statusCode.toString()}`);
this.logger_.error(JSON.stringify(headers));
throw new Error("Initialize payment failed");
}
}
throw new Error("Initialize payment failed.");
}
async updatePayment(context) {
const ordersController = new paypal_server_sdk_1.OrdersController(this.paypal_);
const { amount, currency_code } = context;
try {
const paypalOrderId = context.data.paypalOrder
.id;
await ordersController.patchOrder({
id: paypalOrderId,
body: [
{
op: paypal_server_sdk_1.PatchOp.Replace,
value: {
amount: (0, formatters_1.convertAmount)(amount, currency_code),
},
},
],
});
return await this.retrievePayment(context);
}
catch (error) {
this.logger_.error(error);
throw new Error("An error occurred in updatePayment");
}
}
async getWebhookActionAndData(data) {
return {
action: utils_1.PaymentActions.NOT_SUPPORTED,
};
}
}
PaypalPaymentProviderService.identifier = "paypal-payment";
exports.default = PaypalPaymentProviderService;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcGF5cGFsLXBheW1lbnQvc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUdtQztBQTBCbkMsMkNBQTZFO0FBQzdFLGlFQVltQztBQUNuQyw2Q0FBNkM7QUFhN0MsTUFBTSw0QkFBNkIsU0FBUSwrQkFBZ0M7SUFPekUsWUFBWSxTQUErQixFQUFFLE9BQWdCO1FBQzNELEtBQUssQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDO1FBRTVDLElBQ0UsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhO1lBQzNCLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCO1lBQy9CLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUN6QixDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLDBCQUFZLENBQUM7Z0JBQzlCLGdDQUFnQyxFQUFFO29CQUNoQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhO29CQUMxQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtpQkFDbkQ7Z0JBQ0QsT0FBTyxFQUFFLENBQUM7Z0JBQ1YsV0FBVyxFQUNULElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxLQUFLLFNBQVM7b0JBQ3JDLENBQUMsQ0FBQywrQkFBVyxDQUFDLE9BQU87b0JBQ3JCLENBQUMsQ0FBQywrQkFBVyxDQUFDLFVBQVU7Z0JBQzVCLE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsNEJBQVEsQ0FBQyxJQUFJO29CQUN2QixVQUFVLEVBQUU7d0JBQ1Ys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