@unchainedshop/plugins 2.11.0 → 2.11.3

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.
@@ -1,14 +1,22 @@
1
+ import { Order } from '@unchainedshop/types/orders.js';
2
+ import { OrderPayment } from '@unchainedshop/types/orders.payments.js';
3
+ import { IOrderPricingSheet } from '@unchainedshop/types/orders.pricing.js';
1
4
  import Stripe from 'stripe';
2
5
  declare const stripe: Stripe;
3
6
  export default stripe;
7
+ export declare const upsertCustomer: ({ userId, name, email }: {
8
+ userId: any;
9
+ name: any;
10
+ email: any;
11
+ }) => Promise<Stripe.Customer>;
4
12
  export declare const createRegistrationIntent: ({ userId, name, email, paymentProviderId }: {
5
13
  userId: any;
6
14
  name: any;
7
15
  email: any;
8
16
  paymentProviderId: any;
9
17
  }, options?: {}) => Promise<Stripe.Response<Stripe.SetupIntent>>;
10
- export declare const createOrderPaymentIntent: ({ order, orderPayment, pricing }: {
11
- order: any;
12
- orderPayment: any;
13
- pricing: any;
18
+ export declare const createOrderPaymentIntent: ({ order, orderPayment, pricing, }: {
19
+ order: Order;
20
+ orderPayment: OrderPayment;
21
+ pricing: IOrderPricingSheet;
14
22
  }, options?: {}) => Promise<Stripe.Response<Stripe.PaymentIntent>>;
@@ -1,19 +1,43 @@
1
- import { slugify } from '@unchainedshop/utils';
2
1
  import Stripe from 'stripe';
3
2
  const { STRIPE_SECRET, STRIPE_WEBHOOK_ENVIRONMENT, EMAIL_WEBSITE_NAME } = process.env;
4
3
  const stripe = new Stripe(STRIPE_SECRET, {
5
4
  apiVersion: '2024-04-10',
6
5
  });
7
6
  export default stripe;
7
+ export const upsertCustomer = async ({ userId, name, email }) => {
8
+ try {
9
+ const { data } = await stripe.customers.search({ query: `metadata["userId"]:"${userId}"` });
10
+ const existingCustomer = data[0];
11
+ const environment = STRIPE_WEBHOOK_ENVIRONMENT ?? null;
12
+ if (existingCustomer.name !== name ||
13
+ existingCustomer.email !== email ||
14
+ existingCustomer.metadata.environment !== environment) {
15
+ const updatedCustomer = await stripe.customers.update(existingCustomer.id, {
16
+ metadata: {
17
+ userId,
18
+ environment,
19
+ },
20
+ name,
21
+ email,
22
+ });
23
+ return updatedCustomer;
24
+ }
25
+ return existingCustomer;
26
+ }
27
+ catch (e) {
28
+ const customer = await stripe.customers.create({
29
+ metadata: {
30
+ userId,
31
+ environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
32
+ },
33
+ name,
34
+ email,
35
+ });
36
+ return customer;
37
+ }
38
+ };
8
39
  export const createRegistrationIntent = async ({ userId, name, email, paymentProviderId }, options = {}) => {
9
- const customer = await stripe.customers.create({
10
- metadata: {
11
- userId,
12
- environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
13
- },
14
- name,
15
- email,
16
- });
40
+ const customer = await upsertCustomer({ userId, name, email });
17
41
  const setupIntent = await stripe.setupIntents.create({
18
42
  customer: customer.id,
19
43
  metadata: {
@@ -26,16 +50,23 @@ export const createRegistrationIntent = async ({ userId, name, email, paymentPro
26
50
  });
27
51
  return setupIntent;
28
52
  };
29
- export const createOrderPaymentIntent = async ({ order, orderPayment, pricing }, options = {}) => {
30
- const reference = EMAIL_WEBSITE_NAME || order._id;
53
+ export const createOrderPaymentIntent = async ({ order, orderPayment, pricing, }, options = {}) => {
54
+ const name = [order.billingAddress?.firstName, order.billingAddress?.lastName].filter(Boolean).join(' ') ||
55
+ order.billingAddress?.company;
56
+ const customer = await upsertCustomer({
57
+ userId: order.userId,
58
+ name,
59
+ email: order.contact?.emailAddress,
60
+ });
61
+ const reference = EMAIL_WEBSITE_NAME || 'Unchained';
31
62
  const { currency, amount } = pricing.total({ useNetPrice: false });
32
63
  const paymentIntent = await stripe.paymentIntents.create({
33
64
  amount: Math.round(amount),
34
65
  currency: currency.toLowerCase(),
35
- description: `${reference}`,
36
- statement_descriptor_suffix: slugify(reference),
37
- receipt_email: order.contact?.emailAddress,
66
+ description: `${reference}${STRIPE_WEBHOOK_ENVIRONMENT ? ` (${STRIPE_WEBHOOK_ENVIRONMENT})` : ''}: ${order._id}${order.orderNumber ? ` (#${order.orderNumber})` : ''}`,
67
+ statement_descriptor_suffix: order._id,
38
68
  setup_future_usage: 'off_session', // Verify your integration in this guide by including this parameter
69
+ customer: customer.id,
39
70
  metadata: {
40
71
  orderPaymentId: orderPayment._id,
41
72
  environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
@@ -1 +1 @@
1
- {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../src/payment/stripe/stripe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,EAAE,aAAa,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAEtF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,EAAE;IACvC,UAAU,EAAE,YAAY;CACzB,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC;AAEtB,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAC1C,OAAO,GAAG,EAAE,EACZ,EAAE;IACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAC7C,QAAQ,EAAE;YACR,MAAM;YACN,WAAW,EAAE,0BAA0B,IAAI,IAAI;SAChD;QACD,IAAI;QACJ,KAAK;KACN,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;QACnD,QAAQ,EAAE,QAAQ,CAAC,EAAE;QACrB,QAAQ,EAAE;YACR,MAAM;YACN,iBAAiB;YACjB,WAAW,EAAE,0BAA0B,IAAI,IAAI;SAChD;QACD,KAAK,EAAE,aAAa;QACpB,GAAG,OAAO;KACX,CAAC,CAAC;IACH,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE;IAC/F,MAAM,SAAS,GAAG,kBAAkB,IAAI,KAAK,CAAC,GAAG,CAAC;IAClD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC;QACvD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC1B,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;QAChC,WAAW,EAAE,GAAG,SAAS,EAAE;QAC3B,2BAA2B,EAAE,OAAO,CAAC,SAAS,CAAC;QAC/C,aAAa,EAAE,KAAK,CAAC,OAAO,EAAE,YAAY;QAC1C,kBAAkB,EAAE,aAAa,EAAE,oEAAoE;QACvG,QAAQ,EAAE;YACR,cAAc,EAAE,YAAY,CAAC,GAAG;YAChC,WAAW,EAAE,0BAA0B,IAAI,IAAI;SAChD;QACD,GAAG,OAAO;KACX,CAAC,CAAC;IACH,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC"}
1
+ {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../src/payment/stripe/stripe.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/plugins",
3
- "version": "2.11.0",
3
+ "version": "2.11.3",
4
4
  "main": "lib/plugins-index.js",
5
5
  "types": "lib/plugins-index.d.ts",
6
6
  "exports": {
@@ -81,34 +81,34 @@
81
81
  "postfinancecheckout": "^4.1.1",
82
82
  "stripe": "^15.12.0",
83
83
  "tiny-secp256k1": "^2.2.3",
84
- "twilio": "^5.2.0",
84
+ "twilio": "^5.2.2",
85
85
  "web-push": "^3.6.3"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@redis/client": "^1.5.16",
89
- "@types/node": "^20.14.8",
90
- "@unchainedshop/api": "^2.11.0",
91
- "@unchainedshop/core-delivery": "^2.11.0",
92
- "@unchainedshop/core-enrollments": "^2.11.0",
93
- "@unchainedshop/core-filters": "^2.11.0",
94
- "@unchainedshop/core-messaging": "^2.11.0",
95
- "@unchainedshop/core-orders": "^2.11.0",
96
- "@unchainedshop/core-payment": "^2.11.0",
97
- "@unchainedshop/core-products": "^2.11.0",
98
- "@unchainedshop/core-quotations": "^2.11.0",
99
- "@unchainedshop/core-warehousing": "^2.11.0",
100
- "@unchainedshop/core-worker": "^2.11.0",
101
- "@unchainedshop/events": "^2.11.0",
102
- "@unchainedshop/file-upload": "^2.11.0",
103
- "@unchainedshop/logger": "^2.11.0",
104
- "@unchainedshop/types": "^2.11.0",
105
- "@unchainedshop/utils": "^2.11.0",
89
+ "@types/node": "^20.14.9",
90
+ "@unchainedshop/api": "^2.11.3",
91
+ "@unchainedshop/core-delivery": "^2.11.3",
92
+ "@unchainedshop/core-enrollments": "^2.11.3",
93
+ "@unchainedshop/core-filters": "^2.11.3",
94
+ "@unchainedshop/core-messaging": "^2.11.3",
95
+ "@unchainedshop/core-orders": "^2.11.3",
96
+ "@unchainedshop/core-payment": "^2.11.3",
97
+ "@unchainedshop/core-products": "^2.11.3",
98
+ "@unchainedshop/core-quotations": "^2.11.3",
99
+ "@unchainedshop/core-warehousing": "^2.11.3",
100
+ "@unchainedshop/core-worker": "^2.11.3",
101
+ "@unchainedshop/events": "^2.11.3",
102
+ "@unchainedshop/file-upload": "^2.11.3",
103
+ "@unchainedshop/logger": "^2.11.3",
104
+ "@unchainedshop/types": "^2.11.3",
105
+ "@unchainedshop/utils": "^2.11.3",
106
106
  "bluebird": "^3.7.2",
107
107
  "event-iterator": "^2.0.0",
108
108
  "express": "^4.19.2",
109
109
  "jest": "^29.7.0",
110
110
  "JSONStream": "^1.3.5",
111
- "lru-cache": "^10.2.2",
111
+ "lru-cache": "^10.3.0",
112
112
  "minio": "^8.0.1",
113
113
  "node-sheets": "^1.2.0",
114
114
  "nodemailer": "^6.9.14",
@@ -1,4 +1,6 @@
1
- import { slugify } from '@unchainedshop/utils';
1
+ import { Order } from '@unchainedshop/types/orders.js';
2
+ import { OrderPayment } from '@unchainedshop/types/orders.payments.js';
3
+ import { IOrderPricingSheet, OrderPricingCalculation } from '@unchainedshop/types/orders.pricing.js';
2
4
  import Stripe from 'stripe';
3
5
 
4
6
  const { STRIPE_SECRET, STRIPE_WEBHOOK_ENVIRONMENT, EMAIL_WEBSITE_NAME } = process.env;
@@ -9,18 +11,47 @@ const stripe = new Stripe(STRIPE_SECRET, {
9
11
 
10
12
  export default stripe;
11
13
 
14
+ export const upsertCustomer = async ({ userId, name, email }) => {
15
+ try {
16
+ const { data } = await stripe.customers.search({ query: `metadata["userId"]:"${userId}"` });
17
+ const existingCustomer = data[0];
18
+ const environment = STRIPE_WEBHOOK_ENVIRONMENT ?? null;
19
+
20
+ if (
21
+ existingCustomer.name !== name ||
22
+ existingCustomer.email !== email ||
23
+ existingCustomer.metadata.environment !== environment
24
+ ) {
25
+ const updatedCustomer = await stripe.customers.update(existingCustomer.id, {
26
+ metadata: {
27
+ userId,
28
+ environment,
29
+ },
30
+ name,
31
+ email,
32
+ });
33
+ return updatedCustomer;
34
+ }
35
+
36
+ return existingCustomer;
37
+ } catch (e) {
38
+ const customer = await stripe.customers.create({
39
+ metadata: {
40
+ userId,
41
+ environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
42
+ },
43
+ name,
44
+ email,
45
+ });
46
+ return customer;
47
+ }
48
+ };
49
+
12
50
  export const createRegistrationIntent = async (
13
51
  { userId, name, email, paymentProviderId },
14
52
  options = {},
15
53
  ) => {
16
- const customer = await stripe.customers.create({
17
- metadata: {
18
- userId,
19
- environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
20
- },
21
- name,
22
- email,
23
- });
54
+ const customer = await upsertCustomer({ userId, name, email });
24
55
  const setupIntent = await stripe.setupIntents.create({
25
56
  customer: customer.id,
26
57
  metadata: {
@@ -34,16 +65,33 @@ export const createRegistrationIntent = async (
34
65
  return setupIntent;
35
66
  };
36
67
 
37
- export const createOrderPaymentIntent = async ({ order, orderPayment, pricing }, options = {}) => {
38
- const reference = EMAIL_WEBSITE_NAME || order._id;
68
+ export const createOrderPaymentIntent = async (
69
+ {
70
+ order,
71
+ orderPayment,
72
+ pricing,
73
+ }: { order: Order; orderPayment: OrderPayment; pricing: IOrderPricingSheet },
74
+ options = {},
75
+ ) => {
76
+ const name =
77
+ [order.billingAddress?.firstName, order.billingAddress?.lastName].filter(Boolean).join(' ') ||
78
+ order.billingAddress?.company;
79
+
80
+ const customer = await upsertCustomer({
81
+ userId: order.userId,
82
+ name,
83
+ email: order.contact?.emailAddress,
84
+ });
85
+
86
+ const reference = EMAIL_WEBSITE_NAME || 'Unchained';
39
87
  const { currency, amount } = pricing.total({ useNetPrice: false });
40
88
  const paymentIntent = await stripe.paymentIntents.create({
41
89
  amount: Math.round(amount),
42
90
  currency: currency.toLowerCase(),
43
- description: `${reference}`,
44
- statement_descriptor_suffix: slugify(reference),
45
- receipt_email: order.contact?.emailAddress,
91
+ description: `${reference}${STRIPE_WEBHOOK_ENVIRONMENT ? ` (${STRIPE_WEBHOOK_ENVIRONMENT})` : ''}: ${order._id}${order.orderNumber ? ` (#${order.orderNumber})` : ''}`,
92
+ statement_descriptor_suffix: order._id,
46
93
  setup_future_usage: 'off_session', // Verify your integration in this guide by including this parameter
94
+ customer: customer.id,
47
95
  metadata: {
48
96
  orderPaymentId: orderPayment._id,
49
97
  environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,