@unchainedshop/plugins
Version:
Official plugin collection for the Unchained Engine with payment, delivery, and pricing adapters
139 lines (138 loc) • 5.43 kB
JavaScript
import { createLogger } from '@unchainedshop/logger';
import { PaymentAdapter, PaymentDirector, PaymentError, OrderPricingSheet, } from '@unchainedshop/core';
const logger = createLogger('unchained:braintree');
const { BRAINTREE_SANDBOX_TOKEN, BRAINTREE_PRIVATE_KEY } = process.env;
let braintree;
try {
const braintreePackage = await import('braintree');
braintree = braintreePackage.default;
}
catch {
logger.warn("npm dependency 'braintree' is not installed, paypal adapter will not work");
}
const BraintreeDirect = {
...PaymentAdapter,
key: 'shop.unchained.braintree-direct',
label: 'Braintree Direct',
version: '1.0.0',
initialConfiguration: [
{
key: 'publicKey',
value: null,
},
{
key: 'merchantId',
value: null,
},
],
typeSupported: (type) => {
return type === 'GENERIC';
},
actions: (config, context) => {
const getPublicKey = () => {
return config.reduce((current, item) => {
if (item.key === 'publicKey')
return item.value;
return current;
}, null);
};
const getMerchantId = () => {
return config.reduce((current, item) => {
if (item.key === 'merchantId')
return item.value;
return current;
}, null);
};
const getAccessToken = () => {
return BRAINTREE_SANDBOX_TOKEN;
};
const getPrivateKey = () => {
return BRAINTREE_PRIVATE_KEY;
};
const getGateway = (braintree) => {
const accessToken = getAccessToken();
if (accessToken) {
return braintree.connect({
accessToken,
});
}
return braintree.connect({
environment: braintree.Environment.Production,
merchantId: getMerchantId(),
publicKey: getPublicKey(),
privateKey: getPrivateKey(),
});
};
const adapter = {
...PaymentAdapter.actions(config, context),
configurationError: () => {
const publicCredentialsValid = getAccessToken() || (getMerchantId() && getPublicKey() && getPrivateKey());
if (!publicCredentialsValid) {
return PaymentError.WRONG_CREDENTIALS;
}
return null;
},
isActive: () => {
if (adapter.configurationError() === null)
return true;
return false;
},
isPayLaterAllowed: () => {
return false;
},
sign: async () => {
const gateway = getGateway(braintree);
const result = await gateway.clientToken.generate({});
if (result.success) {
return result.clientToken;
}
throw new Error('Could not retrieve the client token');
},
charge: async ({ paypalPaymentMethodNonce }) => {
const { order } = context;
if (!order)
throw new Error('Order is missing in payment context');
if (!paypalPaymentMethodNonce)
throw new Error('You have to provide paypalPaymentMethodNonce in paymentContext');
const gateway = getGateway(braintree);
const address = order.billingAddress;
const pricing = OrderPricingSheet({
calculation: order.calculation,
currencyCode: order.currencyCode,
});
const rounded = Math.round(pricing.total({ useNetPrice: false }).amount / 10 || 0) * 10;
const saleRequest = {
amount: rounded / 100,
merchantAccountId: order.currencyCode,
paymentMethodNonce: paypalPaymentMethodNonce,
orderId: order.orderNumber || order._id,
shipping: address
? {
firstName: address.firstName,
lastName: address.lastName,
company: address.company,
streetAddress: address.addressLine,
extendedAddress: address.addressLine2,
locality: address.city,
region: address.regionCode,
postalCode: address.postalCode,
countryCodeAlpha2: address.countryCode,
}
: undefined,
options: {
submitForSettlement: true,
},
};
const result = await gateway.transaction.sale(saleRequest);
if (result.success) {
logger.info(`Braintree Plugin: ${result.message}`, saleRequest);
return result;
}
logger.warn(`Braintree Plugin: ${result.message}`, saleRequest);
throw new Error(result.message);
},
};
return adapter;
},
};
PaymentDirector.registerAdapter(BraintreeDirect);