unchainedshop-bobzero-plugin
Version:
Plugin for unchained engine to support payments with the bob zero ecommerce product of bob Finance AG.
149 lines • 6.16 kB
JavaScript
import { PaymentAdapter, PaymentDirector, PaymentError } from '@unchainedshop/core-payment';
import { log } from '../log.js';
import fetch from 'node-fetch';
import { LogLevel } from '@unchainedshop/logger';
import { BobZeroStatus } from '../types.js';
const { BOB_ZERO_API_ENDPOINT, BOB_ZERO_API_KEY } = process.env;
const BOB_ZERO_API_BASE_URL = `${BOB_ZERO_API_ENDPOINT}/BobFinancingFacadeOnboarding`;
const BOB_ZERO_API_HEADERS = {
bobFinanceSuiteApiKey: `${BOB_ZERO_API_KEY}`,
};
const createFinancingSession = async (params) => {
log('Create financing', params);
const body = {
order: {
ref: params.orderReference,
gross_amount: params.amount || 0,
currency: 'CHF',
},
payment: {
type: 'financing',
duration: 0,
},
sale: {
webshop_return_url: params.redirectUrl,
},
customer: {
language: params.language,
firstname: params.order.billingAddress?.firstName || null,
lastname: params.order.billingAddress?.lastName || null,
email: params.order.contact?.emailAddress,
phone: null,
nationality: null,
addresses: params.order.billingAddress
? [
{
type: 'actual',
street: params.order.billingAddress.addressLine,
house_nr: null,
city: params.order.billingAddress.city,
zip: params.order.billingAddress.postalCode,
region: null,
country: params.order.billingAddress.countryCode,
country3: null,
},
]
: [],
},
};
const financing = (await fetch(`${BOB_ZERO_API_BASE_URL}/create_financing`, {
method: 'POST',
headers: BOB_ZERO_API_HEADERS,
body: JSON.stringify(body),
}).then((res) => res.json()));
if (financing.financing_uid) {
log('Create session', {
url: `${BOB_ZERO_API_BASE_URL}/create_session?financing_uid=${financing.financing_uid}`,
});
const financingSession = (await fetch(`${BOB_ZERO_API_BASE_URL}/create_session?financing_uid=${financing.financing_uid}`, {
method: 'GET',
headers: BOB_ZERO_API_HEADERS,
}).then((res) => res.json()));
return financingSession;
}
return null;
};
const checkIsPaid = (order, orderModule, financing) => {
const pricing = orderModule.pricingSheet(order);
const totalAmount = pricing.total({ useNetPrice: false }).amount;
return (financing.order.gross_amount && financing.order.gross_amount.toFixed(2) === totalAmount.toFixed(2));
};
export const BobZeroPlugin = {
...PaymentAdapter,
key: 'shop.unchained.payment.bob_zero',
label: 'Bob Zero',
version: '2.0.0',
typeSupported(type) {
return type === 'GENERIC';
},
actions: (params) => {
const { modules } = params.context;
const adapterActions = {
...PaymentAdapter.actions(params),
configurationError() {
if (!BOB_ZERO_API_KEY || !BOB_ZERO_API_ENDPOINT) {
return PaymentError.INCOMPLETE_CONFIGURATION;
}
return null;
},
isActive: () => {
if (adapterActions.configurationError() === null)
return true;
return false;
},
isPayLaterAllowed() {
return false;
},
sign: async (transactionContext = { language: 'de', redirectUrl: null }) => {
try {
log('Sign', transactionContext);
const { order, orderPayment } = params.paymentContext;
const pricing = modules.orders.pricingSheet(order);
const { currency, amount } = pricing.total({ useNetPrice: false });
const session = await createFinancingSession({
amount,
currency,
language: transactionContext.language,
orderReference: orderPayment._id,
order,
redirectUrl: transactionContext.redirectUrl,
});
if (!session)
throw new Error('Bob Zero Plugin: Failed to create session');
return JSON.stringify(session);
}
catch (e) {
log('Signing failed', { level: LogLevel.Warning, e });
throw new Error(e);
}
},
// Return true: order paid
// Return false: check cart remains open, no order is created yet
charge: async (transactionContext) => {
const transactionId = transactionContext?.financing_id;
const orderId = transactionContext?.order.ref;
log('Charge', { transactionId, orderId });
// --> check if session is finished (success or failure)
if (!transactionId)
return false;
// --> throw error if payment failed
if (transactionContext.status.ext_status !== BobZeroStatus.WebhookSuccessfulFinancing)
return false;
// --> get order
if (!params.paymentContext.order)
return false;
const order = params.paymentContext.order;
// --> checks if order is still valid (amount the same)
const isPaid = checkIsPaid(order, modules.orders, transactionContext);
if (!isPaid)
return false;
return {
transactionId: `${transactionId}`,
};
},
};
return adapterActions;
},
};
PaymentDirector.registerAdapter(BobZeroPlugin);
//# sourceMappingURL=bobZeroPlugin.js.map