@unchainedshop/plugins 4.8.26 → 4.8.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/delivery/post/adapter.d.ts +2 -0
- package/lib/delivery/post/adapter.js +22 -0
- package/lib/delivery/post/index.d.ts +4 -0
- package/lib/delivery/post/index.js +10 -0
- package/lib/delivery/send-message/adapter.d.ts +2 -0
- package/lib/delivery/send-message/adapter.js +39 -0
- package/lib/delivery/send-message/index.d.ts +4 -0
- package/lib/delivery/send-message/index.js +10 -0
- package/lib/delivery/stores/adapter.d.ts +2 -0
- package/lib/delivery/stores/adapter.js +42 -0
- package/lib/delivery/stores/index.d.ts +4 -0
- package/lib/delivery/stores/index.js +10 -0
- package/lib/enrollments/licensed/adapter.d.ts +6 -0
- package/lib/enrollments/licensed/adapter.js +51 -0
- package/lib/enrollments/licensed/index.d.ts +4 -0
- package/lib/enrollments/licensed/index.js +10 -0
- package/lib/files/gridfs/api.d.ts +7 -0
- package/lib/files/gridfs/api.js +163 -0
- package/lib/files/minio/adapter.d.ts +4 -0
- package/lib/files/minio/adapter.js +160 -0
- package/lib/files/minio/api.d.ts +2 -0
- package/lib/files/minio/api.js +40 -0
- package/lib/files/temp-upload/api.d.ts +8 -0
- package/lib/files/temp-upload/api.js +48 -0
- package/lib/files/temp-upload/index.d.ts +3 -0
- package/lib/files/temp-upload/index.js +15 -0
- package/lib/filters/local-search/adapter.d.ts +2 -0
- package/lib/filters/local-search/adapter.js +56 -0
- package/lib/filters/local-search/index.d.ts +4 -0
- package/lib/filters/local-search/index.js +10 -0
- package/lib/filters/strict-equal/adapter.d.ts +2 -0
- package/lib/filters/strict-equal/adapter.js +23 -0
- package/lib/filters/strict-equal/index.d.ts +4 -0
- package/lib/filters/strict-equal/index.js +10 -0
- package/lib/payment/apple-iap/api.d.ts +2 -0
- package/lib/payment/apple-iap/api.js +119 -0
- package/lib/payment/cryptopay/adapter.d.ts +2 -0
- package/lib/payment/cryptopay/adapter.js +157 -0
- package/lib/payment/cryptopay/api.d.ts +2 -0
- package/lib/payment/cryptopay/api.js +23 -0
- package/lib/payment/datatrans-v2/adapter.d.ts +2 -0
- package/lib/payment/datatrans-v2/adapter.js +417 -0
- package/lib/payment/datatrans-v2/api.d.ts +2 -0
- package/lib/payment/datatrans-v2/api.js +108 -0
- package/lib/payment/invoice/adapter.d.ts +2 -0
- package/lib/payment/invoice/adapter.js +26 -0
- package/lib/payment/invoice/index.d.ts +4 -0
- package/lib/payment/invoice/index.js +10 -0
- package/lib/payment/invoice-prepaid/adapter.d.ts +2 -0
- package/lib/payment/invoice-prepaid/adapter.js +29 -0
- package/lib/payment/invoice-prepaid/index.d.ts +4 -0
- package/lib/payment/invoice-prepaid/index.js +10 -0
- package/lib/payment/payrexx/adapter.d.ts +2 -0
- package/lib/payment/payrexx/adapter.js +161 -0
- package/lib/payment/payrexx/api.d.ts +2 -0
- package/lib/payment/payrexx/api.js +97 -0
- package/lib/payment/postfinance-checkout/adapter.d.ts +2 -0
- package/lib/payment/postfinance-checkout/adapter.js +189 -0
- package/lib/payment/postfinance-checkout/webhook.d.ts +2 -0
- package/lib/payment/postfinance-checkout/webhook.js +48 -0
- package/lib/payment/saferpay/webhook.d.ts +2 -0
- package/lib/payment/saferpay/webhook.js +64 -0
- package/lib/payment/stripe/adapter.d.ts +2 -0
- package/lib/payment/stripe/adapter.js +121 -0
- package/lib/payment/stripe/api.d.ts +6 -0
- package/lib/payment/stripe/api.js +165 -0
- package/lib/pricing/delivery-eu-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-eu-tax/adapter.js +55 -0
- package/lib/pricing/delivery-eu-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-eu-tax/index.js +10 -0
- package/lib/pricing/delivery-swiss-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-swiss-tax/adapter.js +43 -0
- package/lib/pricing/delivery-swiss-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-swiss-tax/index.js +10 -0
- package/lib/pricing/delivery-uk-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-uk-tax/adapter.js +43 -0
- package/lib/pricing/delivery-uk-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-uk-tax/index.js +10 -0
- package/lib/pricing/delivery-us-sales-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-us-sales-tax/adapter.js +58 -0
- package/lib/pricing/delivery-us-sales-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-us-sales-tax/index.js +10 -0
- package/lib/pricing/discount-100-off/adapter.d.ts +3 -0
- package/lib/pricing/discount-100-off/adapter.js +30 -0
- package/lib/pricing/discount-100-off/index.d.ts +4 -0
- package/lib/pricing/discount-100-off/index.js +10 -0
- package/lib/pricing/discount-half-price-manual/adapter.d.ts +3 -0
- package/lib/pricing/discount-half-price-manual/adapter.js +30 -0
- package/lib/pricing/discount-half-price-manual/index.d.ts +4 -0
- package/lib/pricing/discount-half-price-manual/index.js +10 -0
- package/lib/pricing/free-delivery/adapter.d.ts +3 -0
- package/lib/pricing/free-delivery/adapter.js +27 -0
- package/lib/pricing/free-delivery/index.d.ts +4 -0
- package/lib/pricing/free-delivery/index.js +10 -0
- package/lib/pricing/free-payment/adapter.d.ts +3 -0
- package/lib/pricing/free-payment/adapter.js +27 -0
- package/lib/pricing/free-payment/index.d.ts +4 -0
- package/lib/pricing/free-payment/index.js +10 -0
- package/lib/pricing/order-delivery/adapter.d.ts +3 -0
- package/lib/pricing/order-delivery/adapter.js +33 -0
- package/lib/pricing/order-delivery/index.d.ts +4 -0
- package/lib/pricing/order-delivery/index.js +10 -0
- package/lib/pricing/order-discount/adapter.d.ts +3 -0
- package/lib/pricing/order-discount/adapter.js +74 -0
- package/lib/pricing/order-discount/index.d.ts +4 -0
- package/lib/pricing/order-discount/index.js +10 -0
- package/lib/pricing/order-items/adapter.d.ts +3 -0
- package/lib/pricing/order-items/adapter.js +43 -0
- package/lib/pricing/order-items/index.d.ts +4 -0
- package/lib/pricing/order-items/index.js +10 -0
- package/lib/pricing/order-payment/adapter.d.ts +3 -0
- package/lib/pricing/order-payment/adapter.js +33 -0
- package/lib/pricing/order-payment/index.d.ts +4 -0
- package/lib/pricing/order-payment/index.js +10 -0
- package/lib/pricing/product-catalog-price/adapter.d.ts +3 -0
- package/lib/pricing/product-catalog-price/adapter.js +60 -0
- package/lib/pricing/product-catalog-price/index.d.ts +4 -0
- package/lib/pricing/product-catalog-price/index.js +10 -0
- package/lib/pricing/product-discount/adapter.d.ts +3 -0
- package/lib/pricing/product-discount/adapter.js +69 -0
- package/lib/pricing/product-discount/index.d.ts +4 -0
- package/lib/pricing/product-discount/index.js +10 -0
- package/lib/pricing/product-eu-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-eu-tax/adapter.js +56 -0
- package/lib/pricing/product-eu-tax/index.d.ts +4 -0
- package/lib/pricing/product-eu-tax/index.js +10 -0
- package/lib/pricing/product-price-rateconversion/adapter.d.ts +3 -0
- package/lib/pricing/product-price-rateconversion/adapter.js +53 -0
- package/lib/pricing/product-price-rateconversion/index.d.ts +4 -0
- package/lib/pricing/product-price-rateconversion/index.js +10 -0
- package/lib/pricing/product-quotation-price.d.ts +2 -0
- package/lib/pricing/product-quotation-price.js +40 -0
- package/lib/pricing/product-swiss-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-swiss-tax/adapter.js +57 -0
- package/lib/pricing/product-swiss-tax/index.d.ts +4 -0
- package/lib/pricing/product-swiss-tax/index.js +10 -0
- package/lib/pricing/product-uk-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-uk-tax/adapter.js +57 -0
- package/lib/pricing/product-uk-tax/index.d.ts +4 -0
- package/lib/pricing/product-uk-tax/index.js +10 -0
- package/lib/pricing/product-us-sales-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-us-sales-tax/adapter.js +52 -0
- package/lib/pricing/product-us-sales-tax/index.d.ts +4 -0
- package/lib/pricing/product-us-sales-tax/index.js +10 -0
- package/lib/quotations/manual/adapter.d.ts +2 -0
- package/lib/quotations/manual/adapter.js +24 -0
- package/lib/quotations/manual/index.d.ts +4 -0
- package/lib/quotations/manual/index.js +10 -0
- package/lib/warehousing/erc-metadata/api.d.ts +12 -0
- package/lib/warehousing/erc-metadata/api.js +43 -0
- package/lib/warehousing/erc-metadata/index.d.ts +3 -0
- package/lib/warehousing/erc-metadata/index.js +15 -0
- package/lib/warehousing/eth-minter/adapter.d.ts +2 -0
- package/lib/warehousing/eth-minter/adapter.js +119 -0
- package/lib/warehousing/eth-minter/index.d.ts +4 -0
- package/lib/warehousing/eth-minter/index.js +10 -0
- package/lib/warehousing/store/adapter.d.ts +2 -0
- package/lib/warehousing/store/adapter.js +33 -0
- package/lib/warehousing/store/index.d.ts +4 -0
- package/lib/warehousing/store/index.js +10 -0
- package/lib/worker/budgetsms/adapter.d.ts +22 -0
- package/lib/worker/budgetsms/adapter.js +169 -0
- package/lib/worker/budgetsms/index.d.ts +4 -0
- package/lib/worker/budgetsms/index.js +10 -0
- package/lib/worker/bulk-export/adapter.d.ts +3 -0
- package/lib/worker/bulk-export/adapter.js +64 -0
- package/lib/worker/bulk-export/index.d.ts +4 -0
- package/lib/worker/bulk-export/index.js +10 -0
- package/lib/worker/bulk-import/adapter.d.ts +3 -0
- package/lib/worker/bulk-import/adapter.js +65 -0
- package/lib/worker/bulk-import/api.d.ts +9 -0
- package/lib/worker/bulk-import/api.js +52 -0
- package/lib/worker/bulk-import/index.d.ts +4 -0
- package/lib/worker/bulk-import/index.js +18 -0
- package/lib/worker/bulkgate/adapter.d.ts +12 -0
- package/lib/worker/bulkgate/adapter.js +91 -0
- package/lib/worker/bulkgate/index.d.ts +4 -0
- package/lib/worker/bulkgate/index.js +10 -0
- package/lib/worker/email/adapter.d.ts +9 -0
- package/lib/worker/email/adapter.js +150 -0
- package/lib/worker/email/index.d.ts +4 -0
- package/lib/worker/email/index.js +10 -0
- package/lib/worker/enrollment-order-generator/adapter.d.ts +4 -0
- package/lib/worker/enrollment-order-generator/adapter.js +77 -0
- package/lib/worker/enrollment-order-generator/index.d.ts +4 -0
- package/lib/worker/enrollment-order-generator/index.js +13 -0
- package/lib/worker/error-notifications/adapter.d.ts +10 -0
- package/lib/worker/error-notifications/adapter.js +62 -0
- package/lib/worker/error-notifications/index.d.ts +4 -0
- package/lib/worker/error-notifications/index.js +13 -0
- package/lib/worker/export-token/adapter.d.ts +4 -0
- package/lib/worker/export-token/adapter.js +25 -0
- package/lib/worker/export-token/index.d.ts +4 -0
- package/lib/worker/export-token/index.js +13 -0
- package/lib/worker/external/adapter.d.ts +3 -0
- package/lib/worker/external/adapter.js +13 -0
- package/lib/worker/external/index.d.ts +4 -0
- package/lib/worker/external/index.js +10 -0
- package/lib/worker/gc-guests/adapter.d.ts +9 -0
- package/lib/worker/gc-guests/adapter.js +56 -0
- package/lib/worker/gc-guests/index.d.ts +4 -0
- package/lib/worker/gc-guests/index.js +13 -0
- package/lib/worker/heartbeat/adapter.d.ts +8 -0
- package/lib/worker/heartbeat/adapter.js +26 -0
- package/lib/worker/heartbeat/index.d.ts +4 -0
- package/lib/worker/heartbeat/index.js +10 -0
- package/lib/worker/http-request/adapter.d.ts +8 -0
- package/lib/worker/http-request/adapter.js +55 -0
- package/lib/worker/http-request/index.d.ts +4 -0
- package/lib/worker/http-request/index.js +10 -0
- package/lib/worker/invalidate-carts/adapter.d.ts +9 -0
- package/lib/worker/invalidate-carts/adapter.js +52 -0
- package/lib/worker/invalidate-carts/index.d.ts +4 -0
- package/lib/worker/invalidate-carts/index.js +13 -0
- package/lib/worker/message/adapter.d.ts +11 -0
- package/lib/worker/message/adapter.js +42 -0
- package/lib/worker/message/index.d.ts +4 -0
- package/lib/worker/message/index.js +10 -0
- package/lib/worker/push-notification/adapter.d.ts +9 -0
- package/lib/worker/push-notification/adapter.js +87 -0
- package/lib/worker/push-notification/index.d.ts +4 -0
- package/lib/worker/push-notification/index.js +10 -0
- package/lib/worker/twilio/adapter.d.ts +8 -0
- package/lib/worker/twilio/adapter.js +59 -0
- package/lib/worker/twilio/index.d.ts +4 -0
- package/lib/worker/twilio/index.js +10 -0
- package/lib/worker/update-coinbase-rates/adapter.d.ts +4 -0
- package/lib/worker/update-coinbase-rates/adapter.js +59 -0
- package/lib/worker/update-coinbase-rates/index.d.ts +4 -0
- package/lib/worker/update-coinbase-rates/index.js +13 -0
- package/lib/worker/update-ecb-rates/adapter.d.ts +4 -0
- package/lib/worker/update-ecb-rates/adapter.js +94 -0
- package/lib/worker/update-ecb-rates/index.d.ts +4 -0
- package/lib/worker/update-ecb-rates/index.js +13 -0
- package/lib/worker/update-token-ownership/adapter.d.ts +5 -0
- package/lib/worker/update-token-ownership/adapter.js +58 -0
- package/lib/worker/update-token-ownership/index.d.ts +4 -0
- package/lib/worker/update-token-ownership/index.js +13 -0
- package/lib/worker/zombie-killer/adapter.d.ts +15 -0
- package/lib/worker/zombie-killer/adapter.js +113 -0
- package/lib/worker/zombie-killer/index.d.ts +4 -0
- package/lib/worker/zombie-killer/index.js +13 -0
- package/package.json +19 -19
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
2
|
+
import { stripe, createOrderPaymentIntent, createRegistrationIntent } from "./stripe.js";
|
|
3
|
+
import { OrderPricingSheet, PaymentAdapter, PaymentError, } from '@unchainedshop/core';
|
|
4
|
+
const logger = createLogger('unchained:stripe');
|
|
5
|
+
export const Stripe = {
|
|
6
|
+
...PaymentAdapter,
|
|
7
|
+
key: 'shop.unchained.payment.stripe',
|
|
8
|
+
label: 'Stripe',
|
|
9
|
+
version: '2.0.0',
|
|
10
|
+
typeSupported(type) {
|
|
11
|
+
return type === 'GENERIC';
|
|
12
|
+
},
|
|
13
|
+
actions: (config, context) => {
|
|
14
|
+
const { modules } = context;
|
|
15
|
+
const descriptorPrefix = config.find(({ key }) => key === 'descriptorPrefix')?.value || '';
|
|
16
|
+
const assertUserData = async (forcedUserId) => {
|
|
17
|
+
const userId = forcedUserId || context?.userId;
|
|
18
|
+
const user = await modules.users.findUserById(userId);
|
|
19
|
+
if (!user)
|
|
20
|
+
throw new Error('User not found');
|
|
21
|
+
const email = modules.users.primaryEmail(user)?.address;
|
|
22
|
+
const name = user.profile?.displayName || user.username || email;
|
|
23
|
+
return {
|
|
24
|
+
email,
|
|
25
|
+
name,
|
|
26
|
+
userId,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
const adapterActions = {
|
|
30
|
+
...PaymentAdapter.actions(config, context),
|
|
31
|
+
configurationError() {
|
|
32
|
+
if (!stripe)
|
|
33
|
+
return PaymentError.INCOMPLETE_CONFIGURATION;
|
|
34
|
+
return null;
|
|
35
|
+
},
|
|
36
|
+
isActive: () => {
|
|
37
|
+
if (adapterActions.configurationError() === null)
|
|
38
|
+
return true;
|
|
39
|
+
return false;
|
|
40
|
+
},
|
|
41
|
+
isPayLaterAllowed() {
|
|
42
|
+
return false;
|
|
43
|
+
},
|
|
44
|
+
validate: async ({ token }) => {
|
|
45
|
+
const paymentMethod = await stripe.paymentMethods.retrieve(token);
|
|
46
|
+
return !!paymentMethod;
|
|
47
|
+
},
|
|
48
|
+
register: async ({ setupIntentId }) => {
|
|
49
|
+
if (!setupIntentId) {
|
|
50
|
+
throw new Error('You have to provide a setupIntentId');
|
|
51
|
+
}
|
|
52
|
+
const setupIntent = await stripe.setupIntents.retrieve(setupIntentId);
|
|
53
|
+
if (setupIntent.status === 'succeeded') {
|
|
54
|
+
return {
|
|
55
|
+
token: setupIntent.payment_method,
|
|
56
|
+
customer: setupIntent.customer,
|
|
57
|
+
payment_method_types: setupIntent.payment_method_types,
|
|
58
|
+
usage: setupIntent.usage,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
logger.warn('Registration declined', setupIntentId);
|
|
62
|
+
return null;
|
|
63
|
+
},
|
|
64
|
+
sign: async (transactionContext = {}) => {
|
|
65
|
+
const { orderPayment, order, paymentProvider } = context;
|
|
66
|
+
const { userId, name, email } = await assertUserData(order?.userId);
|
|
67
|
+
if (orderPayment) {
|
|
68
|
+
if (!order)
|
|
69
|
+
throw new Error('order not found in context');
|
|
70
|
+
const pricing = OrderPricingSheet({
|
|
71
|
+
calculation: order?.calculation,
|
|
72
|
+
currencyCode: order?.currencyCode,
|
|
73
|
+
});
|
|
74
|
+
const paymentIntent = await createOrderPaymentIntent({ userId, name, email, order, orderPayment, pricing, descriptorPrefix }, transactionContext);
|
|
75
|
+
return paymentIntent.client_secret;
|
|
76
|
+
}
|
|
77
|
+
const paymentIntent = await createRegistrationIntent({ userId, name, email, paymentProviderId: paymentProvider._id, descriptorPrefix }, transactionContext);
|
|
78
|
+
return paymentIntent.client_secret;
|
|
79
|
+
},
|
|
80
|
+
charge: async ({ paymentIntentId, paymentCredentials }) => {
|
|
81
|
+
if (!paymentIntentId && !paymentCredentials) {
|
|
82
|
+
throw new Error('You have to provide paymentIntentId or paymentCredentials');
|
|
83
|
+
}
|
|
84
|
+
const { order, orderPayment } = context;
|
|
85
|
+
if (!order)
|
|
86
|
+
throw new Error('order not found in context');
|
|
87
|
+
if (!orderPayment)
|
|
88
|
+
throw new Error('orderPayment not found in context');
|
|
89
|
+
const { userId, name, email } = await assertUserData(order?.userId);
|
|
90
|
+
const pricing = OrderPricingSheet({
|
|
91
|
+
calculation: order.calculation,
|
|
92
|
+
currencyCode: order.currencyCode,
|
|
93
|
+
});
|
|
94
|
+
const paymentIntentObject = paymentIntentId
|
|
95
|
+
? await stripe.paymentIntents.retrieve(paymentIntentId)
|
|
96
|
+
: await createOrderPaymentIntent({ userId, name, email, orderPayment, order, pricing, descriptorPrefix }, {
|
|
97
|
+
customer: paymentCredentials.meta?.customer,
|
|
98
|
+
confirm: true,
|
|
99
|
+
payment_method: paymentCredentials.token,
|
|
100
|
+
payment_method_types: paymentCredentials.meta?.payment_method_types,
|
|
101
|
+
});
|
|
102
|
+
const { currencyCode, amount } = pricing.total({ useNetPrice: false });
|
|
103
|
+
if (paymentIntentObject.currency !== currencyCode.toLowerCase() ||
|
|
104
|
+
paymentIntentObject.amount !== Math.round(amount)) {
|
|
105
|
+
throw new Error('The price has changed since the intent has been created');
|
|
106
|
+
}
|
|
107
|
+
if (paymentIntentObject.metadata?.orderPaymentId !== orderPayment?._id) {
|
|
108
|
+
throw new Error('The order payment is different from the initiating intent');
|
|
109
|
+
}
|
|
110
|
+
if (paymentIntentObject.status === 'succeeded') {
|
|
111
|
+
return paymentIntentObject;
|
|
112
|
+
}
|
|
113
|
+
logger.info('Charge postponed because paymentIntent has wrong status', {
|
|
114
|
+
orderPaymentId: paymentIntentObject.id,
|
|
115
|
+
});
|
|
116
|
+
return false;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
return adapterActions;
|
|
120
|
+
},
|
|
121
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
+
export declare const WebhookEventTypes: {
|
|
3
|
+
PAYMENT_INTENT_SUCCEEDED: string;
|
|
4
|
+
SETUP_INTENT_SUCCEEDED: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function stripeWebhookHandler(request: Request, context: UnchainedCore): Promise<Response>;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
2
|
+
import { stripe } from "./stripe.js";
|
|
3
|
+
const logger = createLogger('unchained:stripe:handler');
|
|
4
|
+
export const WebhookEventTypes = {
|
|
5
|
+
PAYMENT_INTENT_SUCCEEDED: 'payment_intent.succeeded',
|
|
6
|
+
SETUP_INTENT_SUCCEEDED: 'setup_intent.succeeded',
|
|
7
|
+
};
|
|
8
|
+
export async function stripeWebhookHandler(request, context) {
|
|
9
|
+
try {
|
|
10
|
+
const { modules, services } = context;
|
|
11
|
+
const sig = request.headers.get('stripe-signature');
|
|
12
|
+
if (!sig) {
|
|
13
|
+
logger.error('stripe-signature header was not provided for webhook');
|
|
14
|
+
return new Response(JSON.stringify({
|
|
15
|
+
success: false,
|
|
16
|
+
message: 'stripe-signature header was not provided for webhook',
|
|
17
|
+
name: 'MISSING_SIGNATURE',
|
|
18
|
+
}), {
|
|
19
|
+
status: 400,
|
|
20
|
+
headers: { 'Content-Type': 'application/json' },
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (!process.env.STRIPE_ENDPOINT_SECRET) {
|
|
24
|
+
logger.error('env STRIPE_ENDPOINT_SECRET is required for webhook handling');
|
|
25
|
+
return new Response(JSON.stringify({
|
|
26
|
+
success: false,
|
|
27
|
+
message: 'env STRIPE_ENDPOINT_SECRET is required for webhook handling',
|
|
28
|
+
name: 'MISSING_ENDPOINT_SECRET',
|
|
29
|
+
}), {
|
|
30
|
+
status: 500,
|
|
31
|
+
headers: { 'Content-Type': 'application/json' },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const rawBody = await request.text();
|
|
35
|
+
let event;
|
|
36
|
+
try {
|
|
37
|
+
event = stripe.webhooks.constructEvent(rawBody, sig, process.env.STRIPE_ENDPOINT_SECRET);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
logger.error(`Error constructing event: ${err.message}`);
|
|
41
|
+
return new Response(JSON.stringify({
|
|
42
|
+
success: false,
|
|
43
|
+
message: err.message,
|
|
44
|
+
name: err.name || 'SIGNATURE_VERIFICATION_FAILED',
|
|
45
|
+
}), {
|
|
46
|
+
status: 400,
|
|
47
|
+
headers: { 'Content-Type': 'application/json' },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (!Object.values(WebhookEventTypes).includes(event.type)) {
|
|
51
|
+
logger.info(`unhandled event type`, {
|
|
52
|
+
type: event.type,
|
|
53
|
+
});
|
|
54
|
+
return new Response(JSON.stringify({
|
|
55
|
+
success: false,
|
|
56
|
+
ignored: true,
|
|
57
|
+
name: 'UNHANDLED_EVENT_TYPE',
|
|
58
|
+
message: `Unhandled event type: ${event.type}. Supported types: ${Object.values(WebhookEventTypes).join(', ')}`,
|
|
59
|
+
}), {
|
|
60
|
+
status: 200,
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const environmentInMetadata = event.data?.object?.metadata?.environment || '';
|
|
65
|
+
const environmentInEnv = process.env.STRIPE_WEBHOOK_ENVIRONMENT || '';
|
|
66
|
+
if (environmentInMetadata !== environmentInEnv) {
|
|
67
|
+
logger.info(`unhandled event environment`, {
|
|
68
|
+
type: event.type,
|
|
69
|
+
environment: environmentInMetadata,
|
|
70
|
+
});
|
|
71
|
+
return new Response(JSON.stringify({
|
|
72
|
+
success: false,
|
|
73
|
+
ignored: true,
|
|
74
|
+
name: 'UNHANDLED_EVENT_ENVIRONMENT',
|
|
75
|
+
message: `Unhandled event environment: ${environmentInMetadata}. Supported environment: ${environmentInEnv}`,
|
|
76
|
+
}), {
|
|
77
|
+
status: 200,
|
|
78
|
+
headers: { 'Content-Type': 'application/json' },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
logger.info(`Processing event`, {
|
|
82
|
+
type: event.type,
|
|
83
|
+
});
|
|
84
|
+
if (event.type === WebhookEventTypes.PAYMENT_INTENT_SUCCEEDED) {
|
|
85
|
+
const paymentIntent = event.data.object;
|
|
86
|
+
const { orderPaymentId } = paymentIntent.metadata || {};
|
|
87
|
+
logger.info(`checkout with orderPaymentId: ${orderPaymentId}`, {
|
|
88
|
+
type: event.type,
|
|
89
|
+
});
|
|
90
|
+
await modules.orders.payments.logEvent(orderPaymentId, event);
|
|
91
|
+
const orderPayment = await modules.orders.payments.findOrderPayment({
|
|
92
|
+
orderPaymentId,
|
|
93
|
+
});
|
|
94
|
+
if (!orderPayment) {
|
|
95
|
+
throw new Error(`order payment not found with orderPaymentId: ${orderPaymentId}`);
|
|
96
|
+
}
|
|
97
|
+
const order = await services.orders.checkoutOrder(orderPayment.orderId, {
|
|
98
|
+
paymentContext: {
|
|
99
|
+
paymentIntentId: paymentIntent.id,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
if (!order)
|
|
103
|
+
throw new Error(`Order with id ${orderPayment.orderId} not found`);
|
|
104
|
+
logger.info(`checkout successful`, {
|
|
105
|
+
orderPaymentId,
|
|
106
|
+
orderId: order._id,
|
|
107
|
+
type: event.type,
|
|
108
|
+
});
|
|
109
|
+
return new Response(JSON.stringify({
|
|
110
|
+
success: true,
|
|
111
|
+
message: 'checkout successful',
|
|
112
|
+
orderId: order._id,
|
|
113
|
+
}), {
|
|
114
|
+
status: 200,
|
|
115
|
+
headers: { 'Content-Type': 'application/json' },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (event.type === WebhookEventTypes.SETUP_INTENT_SUCCEEDED) {
|
|
119
|
+
const setupIntent = event.data.object;
|
|
120
|
+
const { paymentProviderId, userId } = setupIntent.metadata || {};
|
|
121
|
+
logger.info(`registered payment credential with paymentProviderId: ${paymentProviderId}`, {
|
|
122
|
+
type: event.type,
|
|
123
|
+
userId,
|
|
124
|
+
});
|
|
125
|
+
const paymentCredentials = await services.orders.registerPaymentCredentials(paymentProviderId, {
|
|
126
|
+
transactionContext: {
|
|
127
|
+
setupIntentId: setupIntent.id,
|
|
128
|
+
},
|
|
129
|
+
userId,
|
|
130
|
+
});
|
|
131
|
+
logger.info(`payment credentials registration successful`, {
|
|
132
|
+
userId,
|
|
133
|
+
paymentProviderId,
|
|
134
|
+
paymentCredentialsId: paymentCredentials?._id,
|
|
135
|
+
type: event.type,
|
|
136
|
+
});
|
|
137
|
+
return new Response(JSON.stringify({
|
|
138
|
+
success: true,
|
|
139
|
+
message: 'payment credentials registration successful',
|
|
140
|
+
paymentCredentialsId: paymentCredentials?._id,
|
|
141
|
+
}), {
|
|
142
|
+
status: 200,
|
|
143
|
+
headers: { 'Content-Type': 'application/json' },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return new Response(JSON.stringify({
|
|
147
|
+
success: false,
|
|
148
|
+
message: 'Unhandled event type',
|
|
149
|
+
}), {
|
|
150
|
+
status: 200,
|
|
151
|
+
headers: { 'Content-Type': 'application/json' },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
logger.error(error);
|
|
156
|
+
return new Response(JSON.stringify({
|
|
157
|
+
success: false,
|
|
158
|
+
message: error.message,
|
|
159
|
+
name: error.name,
|
|
160
|
+
}), {
|
|
161
|
+
status: 500,
|
|
162
|
+
headers: { 'Content-Type': 'application/json' },
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { isEuMemberCountry, resolveEuTaxCategoryFromDeliveryProvider, resolveEuTaxRate, } from "../tax/eu.js";
|
|
3
|
+
import resolveDeliveryLocation from "../utils/resolveDeliveryLocation.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryEuTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-eu-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply EU VAT on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
});
|
|
21
|
+
return isEuMemberCountry(countryCode);
|
|
22
|
+
},
|
|
23
|
+
actions: (params) => {
|
|
24
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
25
|
+
const { context } = params;
|
|
26
|
+
return {
|
|
27
|
+
...pricingAdapter,
|
|
28
|
+
calculate: async () => {
|
|
29
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
30
|
+
order: context.order,
|
|
31
|
+
orderDelivery: context.orderDelivery,
|
|
32
|
+
countryCode: context.countryCode,
|
|
33
|
+
});
|
|
34
|
+
const category = resolveEuTaxCategoryFromDeliveryProvider(context.provider);
|
|
35
|
+
const taxRate = resolveEuTaxRate({
|
|
36
|
+
countryCode,
|
|
37
|
+
category,
|
|
38
|
+
referenceDate: context.order?.ordered,
|
|
39
|
+
});
|
|
40
|
+
if (taxRate === null)
|
|
41
|
+
return pricingAdapter.calculate();
|
|
42
|
+
DeliveryPricingAdapter.log(`DeliveryEuTax -> Tax Multiplicator: ${taxRate}`);
|
|
43
|
+
applyTaxRateToTaxableRows({
|
|
44
|
+
calculationSheet: params.calculationSheet,
|
|
45
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
46
|
+
taxRate,
|
|
47
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
48
|
+
adapterKey: DeliveryEuTax.key,
|
|
49
|
+
});
|
|
50
|
+
return pricingAdapter.calculate();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
export default DeliveryEuTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliveryEuTax } from "./adapter.js";
|
|
3
|
+
export const DeliveryEuTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-eu-tax',
|
|
5
|
+
label: 'Delivery EU Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliveryEuTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliveryEuTaxPlugin;
|
|
10
|
+
export { DeliveryEuTax } from "./adapter.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { resolveTaxCategoryFromDeliveryProvider, SwissTaxCategories } from "../tax/ch.js";
|
|
3
|
+
import isDeliveryAddressInCountry from "../utils/isDeliveryAddressInCountry.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliverySwissTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-swiss-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply Swiss Tax on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
return isDeliveryAddressInCountry({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
}, ['CH', 'LI']);
|
|
21
|
+
},
|
|
22
|
+
actions: (params) => {
|
|
23
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
24
|
+
const { context } = params;
|
|
25
|
+
return {
|
|
26
|
+
...pricingAdapter,
|
|
27
|
+
calculate: async () => {
|
|
28
|
+
const taxCategory = resolveTaxCategoryFromDeliveryProvider(context.provider) || SwissTaxCategories.DEFAULT;
|
|
29
|
+
const taxRate = taxCategory.rate(context.order?.ordered);
|
|
30
|
+
DeliveryPricingAdapter.log(`DeliverySwissTax -> Tax Multiplicator: ${taxRate}`);
|
|
31
|
+
applyTaxRateToTaxableRows({
|
|
32
|
+
calculationSheet: params.calculationSheet,
|
|
33
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
34
|
+
taxRate,
|
|
35
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
36
|
+
adapterKey: DeliverySwissTax.key,
|
|
37
|
+
});
|
|
38
|
+
return pricingAdapter.calculate();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export default DeliverySwissTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliverySwissTax } from "./adapter.js";
|
|
3
|
+
export const DeliverySwissTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-swiss-tax',
|
|
5
|
+
label: 'Delivery Swiss Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliverySwissTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliverySwissTaxPlugin;
|
|
10
|
+
export { DeliverySwissTax } from "./adapter.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { resolveUkTaxCategoryFromDeliveryProvider, UkTaxCategories, UK_VAT_COUNTRY_CODES, } from "../tax/uk.js";
|
|
3
|
+
import isDeliveryAddressInCountry from "../utils/isDeliveryAddressInCountry.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryUkTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-uk-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply UK VAT on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
return isDeliveryAddressInCountry({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
}, UK_VAT_COUNTRY_CODES);
|
|
21
|
+
},
|
|
22
|
+
actions: (params) => {
|
|
23
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
24
|
+
const { context } = params;
|
|
25
|
+
return {
|
|
26
|
+
...pricingAdapter,
|
|
27
|
+
calculate: async () => {
|
|
28
|
+
const taxCategory = resolveUkTaxCategoryFromDeliveryProvider(context.provider) || UkTaxCategories.STANDARD;
|
|
29
|
+
const taxRate = taxCategory.rate(context.order?.ordered);
|
|
30
|
+
DeliveryPricingAdapter.log(`DeliveryUkTax -> Tax Multiplicator: ${taxRate}`);
|
|
31
|
+
applyTaxRateToTaxableRows({
|
|
32
|
+
calculationSheet: params.calculationSheet,
|
|
33
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
34
|
+
taxRate,
|
|
35
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
36
|
+
adapterKey: DeliveryUkTax.key,
|
|
37
|
+
});
|
|
38
|
+
return pricingAdapter.calculate();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export default DeliveryUkTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliveryUkTax } from "./adapter.js";
|
|
3
|
+
export const DeliveryUkTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-uk-tax',
|
|
5
|
+
label: 'Delivery UK Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliveryUkTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliveryUkTaxPlugin;
|
|
10
|
+
export { DeliveryUkTax } from "./adapter.js";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { US_COUNTRY_CODE, isDeliveryExemptFromUsSalesTax, resolveUsSalesTaxRate } from "../tax/us.js";
|
|
3
|
+
import resolveDeliveryLocation from "../utils/resolveDeliveryLocation.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryUsSalesTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-us-sales-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply US State Sales Tax on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
});
|
|
21
|
+
return countryCode === US_COUNTRY_CODE;
|
|
22
|
+
},
|
|
23
|
+
actions: (params) => {
|
|
24
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
25
|
+
const { context } = params;
|
|
26
|
+
return {
|
|
27
|
+
...pricingAdapter,
|
|
28
|
+
calculate: async () => {
|
|
29
|
+
if (isDeliveryExemptFromUsSalesTax(context.provider)) {
|
|
30
|
+
return pricingAdapter.calculate();
|
|
31
|
+
}
|
|
32
|
+
const { regionCode } = resolveDeliveryLocation({
|
|
33
|
+
order: context.order,
|
|
34
|
+
orderDelivery: context.orderDelivery,
|
|
35
|
+
countryCode: context.countryCode,
|
|
36
|
+
});
|
|
37
|
+
const taxRate = resolveUsSalesTaxRate({
|
|
38
|
+
regionCode,
|
|
39
|
+
referenceDate: context.order?.ordered,
|
|
40
|
+
});
|
|
41
|
+
if (taxRate === null) {
|
|
42
|
+
DeliveryPricingAdapter.log(`DeliveryUsSalesTax -> unknown state '${regionCode}', no sales tax applied`);
|
|
43
|
+
return pricingAdapter.calculate();
|
|
44
|
+
}
|
|
45
|
+
DeliveryPricingAdapter.log(`DeliveryUsSalesTax -> Tax Multiplicator: ${taxRate}`);
|
|
46
|
+
applyTaxRateToTaxableRows({
|
|
47
|
+
calculationSheet: params.calculationSheet,
|
|
48
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
49
|
+
taxRate,
|
|
50
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
51
|
+
adapterKey: DeliveryUsSalesTax.key,
|
|
52
|
+
});
|
|
53
|
+
return pricingAdapter.calculate();
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
export default DeliveryUsSalesTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliveryUsSalesTax } from "./adapter.js";
|
|
3
|
+
export const DeliveryUsSalesTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-us-sales-tax',
|
|
5
|
+
label: 'Delivery US Sales Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliveryUsSalesTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliveryUsSalesTaxPlugin;
|
|
10
|
+
export { DeliveryUsSalesTax } from "./adapter.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OrderDiscountAdapter, } from '@unchainedshop/core';
|
|
2
|
+
export const HundredOff = {
|
|
3
|
+
...OrderDiscountAdapter,
|
|
4
|
+
key: 'shop.unchained.discount.100-off',
|
|
5
|
+
label: '100 Off',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
orderIndex: 10,
|
|
8
|
+
isManualAdditionAllowed: async () => {
|
|
9
|
+
return true;
|
|
10
|
+
},
|
|
11
|
+
isManualRemovalAllowed: async () => {
|
|
12
|
+
return true;
|
|
13
|
+
},
|
|
14
|
+
actions: async ({ context }) => ({
|
|
15
|
+
...(await OrderDiscountAdapter.actions({ context })),
|
|
16
|
+
isValidForSystemTriggering: async () => {
|
|
17
|
+
return false;
|
|
18
|
+
},
|
|
19
|
+
isValidForCodeTriggering: async ({ code }) => {
|
|
20
|
+
return code.toUpperCase() === '100OFF';
|
|
21
|
+
},
|
|
22
|
+
discountForPricingAdapterKey: ({ pricingAdapterKey }) => {
|
|
23
|
+
if (pricingAdapterKey === 'shop.unchained.pricing.order-discount') {
|
|
24
|
+
return { fixedRate: 10000 };
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
export default HundredOff;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { HundredOff } from "./adapter.js";
|
|
3
|
+
export const HundredOffPlugin = {
|
|
4
|
+
key: 'shop.unchained.discount.100-off',
|
|
5
|
+
label: '100 Off Discount Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [HundredOff],
|
|
8
|
+
};
|
|
9
|
+
export default HundredOffPlugin;
|
|
10
|
+
export { HundredOff } from "./adapter.js";
|