UNPKG

@unchainedshop/plugins

Version:

Official plugin collection for the Unchained Engine with payment, delivery, and pricing adapters

88 lines (87 loc) 3.63 kB
import { OrderPricingSheet, PaymentAdapter, PaymentDirector, PaymentError, } from '@unchainedshop/core'; import { createLogger } from '@unchainedshop/logger'; const logger = createLogger('unchained:paypal-checkout'); let checkoutNodeJssdk; try { checkoutNodeJssdk = await import('@paypal/checkout-server-sdk'); } catch { logger.warn("npm dependency '@paypal/checkout-server-sdk' is not installed, paypal adapter will not work"); } const { PAYPAL_CLIENT_ID, PAYPAL_SECRET, PAYPAL_ENVIRONMENT = 'sandbox' } = process.env; const environment = () => { const clientId = PAYPAL_CLIENT_ID; const clientSecret = PAYPAL_SECRET; return PAYPAL_ENVIRONMENT !== 'live' ? new checkoutNodeJssdk.core.SandboxEnvironment(clientId, clientSecret) : new checkoutNodeJssdk.core.LiveEnvironment(clientId, clientSecret); }; const roundToDecimals = (number, decimals) => { const num = Math.pow(10, decimals); return Math.round(number * num) / num; }; const PaypalCheckout = { ...PaymentAdapter, key: 'shop.unchained.payment.paypal', label: 'Paypal', version: '1.0.1', initialConfiguration: [], typeSupported: (type) => { return type === 'GENERIC'; }, actions: (config, context) => { const adapter = { ...PaymentAdapter.actions(config, context), configurationError: () => { const publicCredentialsValid = PAYPAL_CLIENT_ID && PAYPAL_SECRET; if (!publicCredentialsValid) { return PaymentError.WRONG_CREDENTIALS; } return null; }, isActive: () => { if (adapter.configurationError() === null) return true; return false; }, isPayLaterAllowed: () => { return false; }, sign: async () => { return PAYPAL_CLIENT_ID || null; }, charge: async ({ orderID }) => { const { order } = context; if (!order) throw new Error('Order missing in payment context'); if (!orderID) { throw new Error('You have to provide orderID in paymentContext'); } try { const request = new checkoutNodeJssdk.orders.OrdersGetRequest(orderID); const client = new checkoutNodeJssdk.core.PayPalHttpClient(environment()); const paypalOrder = await client.execute(request); const pricing = OrderPricingSheet({ calculation: order.calculation, currencyCode: order.currencyCode, }); const ourTotal = roundToDecimals(pricing.total({ useNetPrice: false }).amount / 100, 2); const paypalTotal = roundToDecimals(paypalOrder.result.purchase_units[0].amount.value, 2); if (ourTotal === paypalTotal) { return order; } logger.warn('Missmatch PAYPAL ORDER', JSON.stringify(paypalOrder.result, null, 2)); logger.debug('OUR ORDER', order); logger.debug('OUR PRICE', pricing); throw new Error(`Payment mismatch`); } catch (e) { logger.warn(e); throw new Error(e.message, { cause: e }); } }, }; return adapter; }, }; PaymentDirector.registerAdapter(PaypalCheckout);