@unchainedshop/plugins
Version:
Because of a Typescript issue with upstream "postfinancecheckout", the Postfinance plugin has been disabled from transpilation, import the source ts files from src and enable node_module tsc or copy over the src/payment/postfinance-checkout to your projec
110 lines • 5.44 kB
JavaScript
import { EnrollmentStatus } from '@unchainedshop/core-enrollments';
import { createLogger } from '@unchainedshop/logger';
import { fixPeriods } from './fix-periods.js';
const logger = createLogger('unchained:core-payment:iap');
const { APPLE_IAP_SHARED_SECRET } = process.env;
const AppleNotificationTypes = {
INITIAL_BUY: 'INITIAL_BUY',
DID_RECOVER: 'DID_RECOVER',
DID_CHANGE_RENEWAL_STATUS: 'DID_CHANGE_RENEWAL_STATUS',
DID_FAIL_TO_RENEW: 'DID_FAIL_TO_RENEW',
DID_CHANGE_RENEWAL_PREF: 'DID_CHANGE_RENEWAL_PREF',
};
export const appleIAPHandler = async (req, res) => {
if (req.method === 'POST') {
try {
const resolvedContext = req.unchainedContext;
const { modules, services } = resolvedContext;
const responseBody = req.body || {};
if (responseBody.password !== APPLE_IAP_SHARED_SECRET) {
throw new Error('shared secret not valid');
}
const transactions = responseBody?.unified_receipt?.latest_receipt_info; // eslint-disable-line
const latestTransaction = transactions[0];
if (responseBody.notification_type === AppleNotificationTypes.INITIAL_BUY) {
// Find the cart to checkout
const orderPayment = await modules.orders.payments.findOrderPaymentByContextData({
context: {
'meta.transactionIdentifier': latestTransaction.transaction_id,
},
});
if (!orderPayment)
throw new Error('Could not find any matching order payment');
const order = await services.orders.checkoutOrder(orderPayment.orderId, {
paymentContext: {
receiptData: responseBody?.unified_receipt?.latest_receipt, // eslint-disable-line
},
});
const orderId = order._id;
const enrollment = await modules.enrollments.findEnrollment({
orderId,
});
await fixPeriods({
transactionId: latestTransaction.original_transaction_id,
transactions,
enrollmentId: enrollment._id,
orderId,
}, resolvedContext);
logger.info(`Apple IAP Webhook: Confirmed checkout for order ${order.orderNumber}`, {
orderId: order._id,
});
}
else {
// Just store payment credentials, use the enrollments paymentProvider reference and
// let the job do the rest
const originalOrderPayment = await modules.orders.payments.findOrderPaymentByContextData({
context: {
'meta.transactionIdentifier': latestTransaction.original_transaction_id,
},
});
if (!originalOrderPayment)
throw new Error('Could not find any matching order payment');
const originalOrder = await modules.orders.findOrder({
orderId: originalOrderPayment.orderId,
});
const enrollment = await modules.enrollments.findEnrollment({
orderId: originalOrder._id,
});
await services.orders.registerPaymentCredentials(enrollment.payment.paymentProviderId, {
transactionContext: {
receiptData: responseBody?.unified_receipt?.latest_receipt, // eslint-disable-line
},
userId: enrollment.userId,
});
await fixPeriods({
transactionId: latestTransaction.original_transaction_id,
transactions,
enrollmentId: enrollment._id,
orderId: originalOrder._id,
}, resolvedContext);
logger.info(`Apple IAP Webhook: Processed notification for ${latestTransaction.original_transaction_id} and type ${responseBody.notification_type}`);
if (responseBody.notification_type === AppleNotificationTypes.DID_RECOVER) {
if (enrollment.status !== EnrollmentStatus.TERMINATED &&
responseBody.auto_renew_status === 'false') {
await services.enrollments.terminateEnrollment(enrollment);
}
}
if (responseBody.notification_type === AppleNotificationTypes.DID_CHANGE_RENEWAL_STATUS) {
if (enrollment.status !== EnrollmentStatus.TERMINATED &&
responseBody.auto_renew_status === 'false') {
await services.enrollments.terminateEnrollment(enrollment);
}
}
logger.info(`Apple IAP Webhook: Updated enrollment from Apple`);
}
res.writeHead(200);
res.end();
return;
}
catch (e) {
logger.warn(`Apple IAP Webhook: ${e.message}`, e);
res.writeHead(503);
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
return;
}
}
res.writeHead(404);
res.end();
};
export default appleIAPHandler;
//# sourceMappingURL=handler-express.js.map