payment-kit 1.13.15

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.
Files changed (222) hide show
  1. package/.eslintrc.js +15 -0
  2. package/README.md +3 -0
  3. package/api/dev.ts +6 -0
  4. package/api/hooks/pre-start.js +12 -0
  5. package/api/src/hooks/pre-start.ts +21 -0
  6. package/api/src/index.ts +92 -0
  7. package/api/src/jobs/event.ts +72 -0
  8. package/api/src/jobs/invoice.ts +148 -0
  9. package/api/src/jobs/payment.ts +208 -0
  10. package/api/src/jobs/subscription.ts +301 -0
  11. package/api/src/jobs/webhook.ts +113 -0
  12. package/api/src/libs/audit.ts +73 -0
  13. package/api/src/libs/auth.ts +40 -0
  14. package/api/src/libs/chain/arcblock.ts +13 -0
  15. package/api/src/libs/dayjs.ts +17 -0
  16. package/api/src/libs/env.ts +5 -0
  17. package/api/src/libs/hooks.ts +42 -0
  18. package/api/src/libs/logger.ts +27 -0
  19. package/api/src/libs/middleware.ts +12 -0
  20. package/api/src/libs/payment.ts +53 -0
  21. package/api/src/libs/queue/index.ts +263 -0
  22. package/api/src/libs/queue/store.ts +47 -0
  23. package/api/src/libs/security.ts +95 -0
  24. package/api/src/libs/session.ts +164 -0
  25. package/api/src/libs/util.ts +93 -0
  26. package/api/src/locales/en.ts +3 -0
  27. package/api/src/locales/index.ts +37 -0
  28. package/api/src/locales/zh.ts +3 -0
  29. package/api/src/routes/checkout-sessions.ts +536 -0
  30. package/api/src/routes/connect/collect.ts +109 -0
  31. package/api/src/routes/connect/pay.ts +116 -0
  32. package/api/src/routes/connect/setup.ts +121 -0
  33. package/api/src/routes/connect/shared.ts +410 -0
  34. package/api/src/routes/connect/subscribe.ts +128 -0
  35. package/api/src/routes/customers.ts +70 -0
  36. package/api/src/routes/events.ts +76 -0
  37. package/api/src/routes/index.ts +59 -0
  38. package/api/src/routes/invoices.ts +126 -0
  39. package/api/src/routes/payment-currencies.ts +38 -0
  40. package/api/src/routes/payment-intents.ts +122 -0
  41. package/api/src/routes/payment-links.ts +221 -0
  42. package/api/src/routes/payment-methods.ts +39 -0
  43. package/api/src/routes/prices.ts +134 -0
  44. package/api/src/routes/products.ts +191 -0
  45. package/api/src/routes/settings.ts +33 -0
  46. package/api/src/routes/subscription-items.ts +148 -0
  47. package/api/src/routes/subscriptions.ts +254 -0
  48. package/api/src/routes/usage-records.ts +120 -0
  49. package/api/src/routes/webhook-attempts.ts +57 -0
  50. package/api/src/routes/webhook-endpoints.ts +105 -0
  51. package/api/src/store/migrate.ts +16 -0
  52. package/api/src/store/migrations/20230905-genesis.ts +52 -0
  53. package/api/src/store/migrations/20230911-seeding.ts +145 -0
  54. package/api/src/store/models/checkout-session.ts +395 -0
  55. package/api/src/store/models/coupon.ts +137 -0
  56. package/api/src/store/models/customer.ts +199 -0
  57. package/api/src/store/models/discount.ts +116 -0
  58. package/api/src/store/models/event.ts +111 -0
  59. package/api/src/store/models/index.ts +165 -0
  60. package/api/src/store/models/invoice-item.ts +185 -0
  61. package/api/src/store/models/invoice.ts +492 -0
  62. package/api/src/store/models/job.ts +75 -0
  63. package/api/src/store/models/payment-currency.ts +139 -0
  64. package/api/src/store/models/payment-intent.ts +282 -0
  65. package/api/src/store/models/payment-link.ts +219 -0
  66. package/api/src/store/models/payment-method.ts +169 -0
  67. package/api/src/store/models/price.ts +266 -0
  68. package/api/src/store/models/product.ts +162 -0
  69. package/api/src/store/models/promotion-code.ts +112 -0
  70. package/api/src/store/models/setup-intent.ts +206 -0
  71. package/api/src/store/models/subscription-item.ts +103 -0
  72. package/api/src/store/models/subscription-schedule.ts +157 -0
  73. package/api/src/store/models/subscription.ts +307 -0
  74. package/api/src/store/models/types.ts +406 -0
  75. package/api/src/store/models/usage-record.ts +132 -0
  76. package/api/src/store/models/webhook-attempt.ts +96 -0
  77. package/api/src/store/models/webhook-endpoint.ts +96 -0
  78. package/api/src/store/sequelize.ts +15 -0
  79. package/api/third.d.ts +28 -0
  80. package/blocklet.md +3 -0
  81. package/blocklet.yml +89 -0
  82. package/index.html +14 -0
  83. package/logo.png +0 -0
  84. package/package.json +133 -0
  85. package/public/.gitkeep +0 -0
  86. package/screenshots/.gitkeep +0 -0
  87. package/screenshots/1-subscription.png +0 -0
  88. package/screenshots/2-customer-1.png +0 -0
  89. package/screenshots/3-customer-2.png +0 -0
  90. package/screenshots/4-admin-3.png +0 -0
  91. package/screenshots/5-admin-4.png +0 -0
  92. package/scripts/build-clean.js +6 -0
  93. package/scripts/bump-version.mjs +35 -0
  94. package/src/app.tsx +68 -0
  95. package/src/components/actions.tsx +85 -0
  96. package/src/components/blockchain/tx.tsx +29 -0
  97. package/src/components/checkout/amount.tsx +24 -0
  98. package/src/components/checkout/error.tsx +30 -0
  99. package/src/components/checkout/footer.tsx +12 -0
  100. package/src/components/checkout/form/address.tsx +38 -0
  101. package/src/components/checkout/form/index.tsx +295 -0
  102. package/src/components/checkout/header.tsx +23 -0
  103. package/src/components/checkout/pay.tsx +222 -0
  104. package/src/components/checkout/product-card.tsx +56 -0
  105. package/src/components/checkout/product-item.tsx +37 -0
  106. package/src/components/checkout/skeleton/overview.tsx +21 -0
  107. package/src/components/checkout/skeleton/payment.tsx +35 -0
  108. package/src/components/checkout/success.tsx +183 -0
  109. package/src/components/checkout/summary.tsx +34 -0
  110. package/src/components/collapse.tsx +50 -0
  111. package/src/components/confirm.tsx +55 -0
  112. package/src/components/copyable.tsx +38 -0
  113. package/src/components/currency.tsx +15 -0
  114. package/src/components/customer/actions.tsx +73 -0
  115. package/src/components/data.tsx +20 -0
  116. package/src/components/drawer-form.tsx +77 -0
  117. package/src/components/error-fallback.tsx +7 -0
  118. package/src/components/error.tsx +39 -0
  119. package/src/components/event/list.tsx +217 -0
  120. package/src/components/info-card.tsx +40 -0
  121. package/src/components/info-metric.tsx +35 -0
  122. package/src/components/info-row.tsx +28 -0
  123. package/src/components/input.tsx +40 -0
  124. package/src/components/invoice/action.tsx +94 -0
  125. package/src/components/invoice/list.tsx +225 -0
  126. package/src/components/invoice/table.tsx +110 -0
  127. package/src/components/layout.tsx +70 -0
  128. package/src/components/livemode.tsx +23 -0
  129. package/src/components/metadata/editor.tsx +57 -0
  130. package/src/components/metadata/form.tsx +45 -0
  131. package/src/components/payment-intent/actions.tsx +81 -0
  132. package/src/components/payment-intent/list.tsx +204 -0
  133. package/src/components/payment-link/actions.tsx +114 -0
  134. package/src/components/payment-link/after-pay.tsx +87 -0
  135. package/src/components/payment-link/before-pay.tsx +175 -0
  136. package/src/components/payment-link/item.tsx +135 -0
  137. package/src/components/payment-link/product-select.tsx +66 -0
  138. package/src/components/payment-link/rename.tsx +64 -0
  139. package/src/components/portal/invoice/list.tsx +110 -0
  140. package/src/components/portal/subscription/cancel.tsx +83 -0
  141. package/src/components/portal/subscription/list.tsx +232 -0
  142. package/src/components/price/actions.tsx +21 -0
  143. package/src/components/price/form.tsx +292 -0
  144. package/src/components/product/actions.tsx +125 -0
  145. package/src/components/product/add-price.tsx +59 -0
  146. package/src/components/product/create.tsx +97 -0
  147. package/src/components/product/edit-price.tsx +75 -0
  148. package/src/components/product/edit.tsx +67 -0
  149. package/src/components/product/features.tsx +32 -0
  150. package/src/components/product/form.tsx +76 -0
  151. package/src/components/relative-time.tsx +41 -0
  152. package/src/components/section/header.tsx +29 -0
  153. package/src/components/status.tsx +12 -0
  154. package/src/components/subscription/actions/cancel.tsx +66 -0
  155. package/src/components/subscription/actions/index.tsx +172 -0
  156. package/src/components/subscription/actions/pause.tsx +83 -0
  157. package/src/components/subscription/items/actions.tsx +31 -0
  158. package/src/components/subscription/items/index.tsx +107 -0
  159. package/src/components/subscription/list.tsx +200 -0
  160. package/src/components/switch.tsx +48 -0
  161. package/src/components/table.tsx +66 -0
  162. package/src/components/uploader.tsx +81 -0
  163. package/src/components/webhook/attempts.tsx +149 -0
  164. package/src/contexts/products.tsx +42 -0
  165. package/src/contexts/session.ts +10 -0
  166. package/src/contexts/settings.tsx +54 -0
  167. package/src/env.d.ts +17 -0
  168. package/src/global.css +97 -0
  169. package/src/hooks/mobile.ts +15 -0
  170. package/src/index.tsx +6 -0
  171. package/src/libs/api.ts +19 -0
  172. package/src/libs/dayjs.ts +17 -0
  173. package/src/libs/util.ts +474 -0
  174. package/src/locales/en.tsx +395 -0
  175. package/src/locales/index.tsx +8 -0
  176. package/src/locales/zh.tsx +389 -0
  177. package/src/pages/admin/billing/index.tsx +56 -0
  178. package/src/pages/admin/billing/invoices/detail.tsx +215 -0
  179. package/src/pages/admin/billing/invoices/index.tsx +5 -0
  180. package/src/pages/admin/billing/subscriptions/detail.tsx +237 -0
  181. package/src/pages/admin/billing/subscriptions/index.tsx +5 -0
  182. package/src/pages/admin/customers/customers/detail.tsx +209 -0
  183. package/src/pages/admin/customers/customers/index.tsx +109 -0
  184. package/src/pages/admin/customers/index.tsx +47 -0
  185. package/src/pages/admin/developers/events/detail.tsx +77 -0
  186. package/src/pages/admin/developers/events/index.tsx +5 -0
  187. package/src/pages/admin/developers/index.tsx +60 -0
  188. package/src/pages/admin/developers/logs.tsx +3 -0
  189. package/src/pages/admin/developers/overview.tsx +3 -0
  190. package/src/pages/admin/developers/webhooks/detail.tsx +109 -0
  191. package/src/pages/admin/developers/webhooks/index.tsx +102 -0
  192. package/src/pages/admin/index.tsx +120 -0
  193. package/src/pages/admin/overview.tsx +3 -0
  194. package/src/pages/admin/payments/index.tsx +65 -0
  195. package/src/pages/admin/payments/intents/detail.tsx +205 -0
  196. package/src/pages/admin/payments/intents/index.tsx +5 -0
  197. package/src/pages/admin/payments/links/create.tsx +141 -0
  198. package/src/pages/admin/payments/links/detail.tsx +318 -0
  199. package/src/pages/admin/payments/links/index.tsx +167 -0
  200. package/src/pages/admin/products/coupons/index.tsx +3 -0
  201. package/src/pages/admin/products/index.tsx +81 -0
  202. package/src/pages/admin/products/prices/actions.tsx +151 -0
  203. package/src/pages/admin/products/prices/detail.tsx +203 -0
  204. package/src/pages/admin/products/prices/list.tsx +95 -0
  205. package/src/pages/admin/products/pricing-tables.tsx +3 -0
  206. package/src/pages/admin/products/products/create.tsx +105 -0
  207. package/src/pages/admin/products/products/detail.tsx +246 -0
  208. package/src/pages/admin/products/products/index.tsx +154 -0
  209. package/src/pages/admin/settings/branding.tsx +3 -0
  210. package/src/pages/admin/settings/business.tsx +3 -0
  211. package/src/pages/admin/settings/index.tsx +47 -0
  212. package/src/pages/admin/settings/payment-methods.tsx +80 -0
  213. package/src/pages/checkout/index.tsx +38 -0
  214. package/src/pages/checkout/pay.tsx +89 -0
  215. package/src/pages/customer/index.tsx +93 -0
  216. package/src/pages/customer/invoice.tsx +147 -0
  217. package/src/pages/home.tsx +9 -0
  218. package/tsconfig.api.json +9 -0
  219. package/tsconfig.eslint.json +7 -0
  220. package/tsconfig.json +99 -0
  221. package/tsconfig.types.json +11 -0
  222. package/vite.config.ts +19 -0
@@ -0,0 +1,145 @@
1
+ import { fromTokenToUnit } from '@ocap/util';
2
+ import Sequelize from 'sequelize';
3
+
4
+ import { createIdGenerator } from '../../libs/util';
5
+ import type { Migration } from '../migrate';
6
+
7
+ const genPaymentMethodId = createIdGenerator('pm', 24);
8
+ const genPaymentCurrencyId = createIdGenerator('pc', 12);
9
+
10
+ const abtId = genPaymentCurrencyId();
11
+ const tbaId = genPaymentCurrencyId();
12
+ const mainId = genPaymentMethodId();
13
+ const betaId = genPaymentMethodId();
14
+ const now = new Date();
15
+
16
+ const logo = 'https://new.arcblock.io/.well-known/service/blocklet/logo?imageFilter=resize&w=80';
17
+
18
+ const paymentCurrencies = [
19
+ {
20
+ id: abtId,
21
+ active: true,
22
+ livemode: true,
23
+ locked: true,
24
+ is_base_currency: true,
25
+ payment_method_id: mainId,
26
+ name: 'Native ABT',
27
+ description: 'ABT on ArcBlock main chain',
28
+ logo,
29
+ symbol: 'ABT',
30
+ decimal: 18,
31
+ minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
32
+ maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
33
+ contract: 'z35nNRvYxBoHitx9yZ5ATS88psfShzPPBLxYD',
34
+ metadata: {},
35
+ created_at: now,
36
+ updated_at: now,
37
+ },
38
+ {
39
+ id: tbaId,
40
+ active: true,
41
+ livemode: false,
42
+ locked: true,
43
+ is_base_currency: true,
44
+ payment_method_id: betaId,
45
+ name: 'Test ABT',
46
+ description: 'ABT on ArcBlock beta chain',
47
+ logo,
48
+ symbol: 'TBA',
49
+ decimal: 18,
50
+ minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
51
+ maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
52
+ contract: 'z35n6UoHSi9MED4uaQy6ozFgKPaZj2UKrurBG',
53
+ metadata: {},
54
+ created_at: now,
55
+ updated_at: now,
56
+ },
57
+ ];
58
+
59
+ const paymentMethods = [
60
+ {
61
+ id: mainId,
62
+ active: true,
63
+ livemode: true,
64
+ locked: true,
65
+ type: 'arcblock',
66
+ name: 'ArcBlock Main',
67
+ description: 'Process payments with tokens on ArcBlock main chain',
68
+ logo,
69
+ default_currency_id: abtId,
70
+ confirmation: {
71
+ type: 'immediate',
72
+ },
73
+ settings: {
74
+ arcblock: {
75
+ chain_id: 'main',
76
+ api_host: 'https://main.abtnetwork.io/api/',
77
+ explorer_host: 'https://main.abtnetwork.io/explorer/',
78
+ },
79
+ },
80
+ features: {
81
+ recurring: true,
82
+ refund: true,
83
+ dispute: true,
84
+ },
85
+ metadata: {},
86
+ created_at: now,
87
+ updated_at: now,
88
+ },
89
+ {
90
+ id: betaId,
91
+ active: true,
92
+ livemode: false,
93
+ locked: true,
94
+ type: 'arcblock',
95
+ name: 'ArcBlock Beta',
96
+ description: 'Process payments with tokens on ArcBlock beta chain, just for test purpose',
97
+ logo,
98
+ default_currency_id: tbaId,
99
+ confirmation: {
100
+ type: 'immediate',
101
+ },
102
+ settings: {
103
+ arcblock: {
104
+ chain_id: 'beta',
105
+ api_host: 'https://beta.abtnetwork.io/api/',
106
+ explorer_host: 'https://beta.abtnetwork.io/explorer/',
107
+ },
108
+ },
109
+ features: {
110
+ recurring: true,
111
+ refund: true,
112
+ dispute: true,
113
+ },
114
+ metadata: {},
115
+ created_at: now,
116
+ updated_at: now,
117
+ },
118
+ ];
119
+
120
+ export const up: Migration = async ({ context: queryInterface }) => {
121
+ await queryInterface.bulkInsert(
122
+ 'payment_methods',
123
+ paymentMethods,
124
+ {},
125
+ {
126
+ confirmation: { type: new Sequelize.JSON() },
127
+ settings: { type: new Sequelize.JSON() },
128
+ features: { type: new Sequelize.JSON() },
129
+ metadata: { type: new Sequelize.JSON() },
130
+ }
131
+ );
132
+ await queryInterface.bulkInsert(
133
+ 'payment_currencies',
134
+ paymentCurrencies,
135
+ {},
136
+ {
137
+ metadata: { type: new Sequelize.JSON() },
138
+ }
139
+ );
140
+ };
141
+
142
+ export const down: Migration = async ({ context: queryInterface }) => {
143
+ await queryInterface.bulkDelete('payment_methods', {});
144
+ await queryInterface.bulkDelete('payment_currencies', {});
145
+ };
@@ -0,0 +1,395 @@
1
+ /* eslint-disable @typescript-eslint/lines-between-class-members */
2
+ /* eslint-disable @typescript-eslint/indent */
3
+ import {
4
+ CreationOptional,
5
+ DataTypes,
6
+ FindOptions,
7
+ InferAttributes,
8
+ InferCreationAttributes,
9
+ Model,
10
+ Op,
11
+ } from 'sequelize';
12
+ import type { LiteralUnion } from 'type-fest';
13
+
14
+ import { createStatusEvent } from '../../libs/audit';
15
+ import { createIdGenerator } from '../../libs/util';
16
+ import type { CurrencyConversion, CustomField, CustomerDetail, InvoiceData, LineItem } from './types';
17
+
18
+ const nextId = createIdGenerator('cs', 58);
19
+
20
+ // @link https://stripe.com/docs/api/checkout/sessions
21
+ // eslint-disable-next-line prettier/prettier
22
+ export class CheckoutSession extends Model<InferAttributes<CheckoutSession>, InferCreationAttributes<CheckoutSession>> {
23
+ // Unique identifier for the object.
24
+ declare id: CreationOptional<string>;
25
+ declare livemode: boolean;
26
+ declare client_reference_id?: string;
27
+
28
+ // ID of the payment currency
29
+ declare currency_id: string;
30
+
31
+ // ID of the invoice created by the Checkout Session, if it exists.
32
+ declare invoice_id?: string;
33
+
34
+ // The ID of the Payment Link that created this Session.
35
+ declare payment_link_id?: string;
36
+
37
+ // The ID of the subscription for Checkout Sessions in subscription mode.
38
+ declare subscription_id?: string;
39
+
40
+ // The ID of the original expired Checkout Session that triggered the recovery flow.
41
+ declare recovered_from?: string;
42
+
43
+ // The ID of the PaymentIntent for Checkout Sessions in payment mode.
44
+ declare payment_intent_id?: string;
45
+
46
+ // The ID of the SetupIntent for Checkout Sessions in setup mode.
47
+ declare setup_intent_id?: string;
48
+
49
+ // Pass subscription if the Checkout Session includes at least one recurring item.
50
+ declare mode: LiteralUnion<'payment' | 'setup' | 'subscription', string>;
51
+
52
+ declare status: LiteralUnion<'complete' | 'open' | 'expired', string>;
53
+ declare payment_status: LiteralUnion<'paid' | 'unpaid' | 'no_payment_required', string>;
54
+
55
+ declare line_items: LineItem[];
56
+
57
+ // Total of all items before discounts or taxes are applied.
58
+ declare amount_subtotal: string;
59
+ // Total of all items after discounts and taxes are applied.
60
+ declare amount_total: string;
61
+ // Tax and discount details for the computed total amount.
62
+ declare total_details?: {
63
+ amount_discount?: string;
64
+ amount_shipping?: string;
65
+ amount_tax?: string;
66
+ breakdown?: {
67
+ discounts?: {
68
+ amount?: string;
69
+ discount?: string;
70
+ }[];
71
+ taxes?: {
72
+ amount?: string;
73
+ rate?: string;
74
+ }[];
75
+ };
76
+ };
77
+
78
+ declare url?: string;
79
+ declare cancel_url?: string;
80
+ declare success_url?: string;
81
+
82
+ declare currency_conversion?: CurrencyConversion;
83
+
84
+ // customer_email field on creation is stored here?
85
+ declare customer_details?: CustomerDetail;
86
+ declare customer_creation: LiteralUnion<'if_required' | 'always', string>;
87
+ declare customer_update?: {
88
+ address: LiteralUnion<'auto' | 'never', string>;
89
+ name: LiteralUnion<'auto' | 'never', string>;
90
+ shipping: LiteralUnion<'auto' | 'never', string>;
91
+ };
92
+
93
+ // When set, provides configuration for actions to take if this Checkout Session expires
94
+ declare after_expiration?: {
95
+ recovery: {
96
+ enabled: boolean;
97
+ allow_promotion_codes?: boolean;
98
+ };
99
+ };
100
+
101
+ declare allow_promotion_codes?: boolean;
102
+
103
+ declare consent_collection?: {
104
+ promotions?: LiteralUnion<'auto' | 'none', string>;
105
+ terms_of_service?: LiteralUnion<'required' | 'none', string>;
106
+ };
107
+ declare consent?: {
108
+ promotions?: LiteralUnion<'opt_in', string>;
109
+ terms_of_service?: LiteralUnion<'accepted', string>;
110
+ };
111
+
112
+ declare custom_fields?: CustomField[];
113
+ declare custom_text?: {
114
+ shipping_address?: string;
115
+ submit?: string;
116
+ };
117
+
118
+ // By default, this value is 24 hours from creation.
119
+ declare expires_at: number;
120
+
121
+ // Generate a post-purchase Invoice for one-time payments.
122
+ declare invoice_creation?: {
123
+ enabled: boolean;
124
+ invoice_data?: InvoiceData;
125
+ };
126
+
127
+ // The list of payment method types that customers can use
128
+ declare payment_method_types?: string[];
129
+
130
+ // Controls phone number collection settings during checkout.
131
+ declare phone_number_collection?: {
132
+ enabled: boolean;
133
+ };
134
+
135
+ // Describes the type of transaction being performed in order to customize relevant text
136
+ declare submit_type: LiteralUnion<'auto' | 'book' | 'donate' | 'pay', string>;
137
+
138
+ declare metadata?: Record<string, any>;
139
+
140
+ // Configuration for collecting the customer’s billing address.
141
+ declare billing_address_collection?: LiteralUnion<'auto' | 'required', string>;
142
+
143
+ // When creating a subscription, the specified configuration data will be used.
144
+ declare subscription_data?: {
145
+ description: string;
146
+ trial_period_days: number;
147
+ billing_cycle_anchor?: number;
148
+ metadata?: Record<string, any>;
149
+ proration_behavior?: LiteralUnion<'create_prorations' | 'none', string>;
150
+ trial_end?: number;
151
+ trial_settings?: {
152
+ end_behavior: {
153
+ missing_payment_method: LiteralUnion<'cancel' | 'pause' | 'create_invoice', string>;
154
+ };
155
+ };
156
+ };
157
+
158
+ // 3rd party payment tx hash
159
+ declare payment_details?: {
160
+ tx_hash?: string;
161
+ payer?: string;
162
+ };
163
+
164
+ // FIXME: Only exist on creation
165
+ // declare discounts?: {
166
+ // coupon?: string;
167
+ // promotion_code?: string;
168
+ // };
169
+ // A subset of parameters to be passed to PaymentIntent creation for Checkout Sessions in payment mode.
170
+ // declare payment_intent_data?: any;
171
+
172
+ // TODO: following fields not supported yet
173
+ // automatic_tax
174
+ // locale --> auto selected
175
+ // payment_method_collection // FIXME:
176
+ // payment_method_options
177
+ // setup_intent_data
178
+ // shipping_address_collection
179
+ // shipping_options
180
+ // tax_id_collection
181
+ // shipping_cost
182
+ // shipping_details
183
+ // shipping_options
184
+
185
+ declare created_at: CreationOptional<Date>;
186
+ declare created_via: LiteralUnion<'api' | 'dashboard' | 'portal', string>;
187
+ declare updated_at: CreationOptional<Date>;
188
+
189
+ public static readonly GENESIS_ATTRIBUTES = {
190
+ id: {
191
+ type: DataTypes.STRING(64),
192
+ primaryKey: true,
193
+ allowNull: false,
194
+ defaultValue: nextId,
195
+ },
196
+ livemode: {
197
+ type: DataTypes.BOOLEAN,
198
+ allowNull: false,
199
+ },
200
+ client_reference_id: {
201
+ type: DataTypes.STRING(128),
202
+ allowNull: true,
203
+ },
204
+ currency_id: {
205
+ type: DataTypes.STRING(15),
206
+ allowNull: false,
207
+ },
208
+ invoice_id: {
209
+ type: DataTypes.STRING(30),
210
+ allowNull: true,
211
+ },
212
+ payment_link_id: {
213
+ type: DataTypes.STRING(30),
214
+ allowNull: true,
215
+ },
216
+ subscription_id: {
217
+ type: DataTypes.STRING(30),
218
+ allowNull: true,
219
+ },
220
+ recovered_from: {
221
+ type: DataTypes.STRING(30),
222
+ allowNull: true,
223
+ },
224
+ payment_intent_id: {
225
+ type: DataTypes.STRING(30),
226
+ allowNull: true,
227
+ },
228
+ mode: {
229
+ type: DataTypes.ENUM('payment', 'setup', 'subscription'),
230
+ },
231
+ status: {
232
+ type: DataTypes.ENUM('complete', 'open', 'expired'),
233
+ },
234
+ payment_status: {
235
+ type: DataTypes.ENUM('paid', 'unpaid', 'no_payment_required'),
236
+ },
237
+ line_items: {
238
+ type: DataTypes.JSON,
239
+ allowNull: false,
240
+ },
241
+ amount_subtotal: {
242
+ type: DataTypes.STRING(32),
243
+ allowNull: false,
244
+ },
245
+ amount_total: {
246
+ type: DataTypes.STRING(32),
247
+ allowNull: false,
248
+ },
249
+ total_details: {
250
+ type: DataTypes.JSON,
251
+ allowNull: false,
252
+ },
253
+ url: {
254
+ type: DataTypes.STRING(512),
255
+ allowNull: true,
256
+ },
257
+ cancel_url: {
258
+ type: DataTypes.STRING(512),
259
+ allowNull: true,
260
+ },
261
+ success_url: {
262
+ type: DataTypes.STRING(512),
263
+ allowNull: true,
264
+ },
265
+ currency_conversion: {
266
+ type: DataTypes.JSON,
267
+ allowNull: true,
268
+ },
269
+ after_expiration: {
270
+ type: DataTypes.JSON,
271
+ allowNull: true,
272
+ },
273
+ allow_promotion_codes: {
274
+ type: DataTypes.BOOLEAN,
275
+ defaultValue: false,
276
+ },
277
+ consent_collection: {
278
+ type: DataTypes.JSON,
279
+ allowNull: true,
280
+ },
281
+ consent: {
282
+ type: DataTypes.JSON,
283
+ allowNull: true,
284
+ },
285
+ custom_fields: {
286
+ type: DataTypes.JSON,
287
+ defaultValue: [],
288
+ },
289
+ custom_text: {
290
+ type: DataTypes.JSON,
291
+ allowNull: true,
292
+ },
293
+ customer_creation: {
294
+ type: DataTypes.ENUM('if_required', 'always'),
295
+ allowNull: false,
296
+ },
297
+ customer_update: {
298
+ type: DataTypes.JSON,
299
+ defaultValue: {
300
+ address: 'never',
301
+ name: 'never',
302
+ shipping: 'never',
303
+ },
304
+ },
305
+ expires_at: {
306
+ type: DataTypes.INTEGER,
307
+ allowNull: true,
308
+ },
309
+ invoice_creation: {
310
+ type: DataTypes.JSON,
311
+ allowNull: true,
312
+ },
313
+ payment_method_types: {
314
+ type: DataTypes.JSON,
315
+ defaultValue: [],
316
+ },
317
+ phone_number_collection: {
318
+ type: DataTypes.JSON,
319
+ allowNull: true,
320
+ },
321
+ billing_address_collection: {
322
+ type: DataTypes.ENUM('auto', 'required'),
323
+ defaultValue: 'auto',
324
+ allowNull: false,
325
+ },
326
+ submit_type: {
327
+ type: DataTypes.ENUM('auto', 'book', 'donate', 'pay'),
328
+ allowNull: false,
329
+ },
330
+ subscription_data: {
331
+ type: DataTypes.JSON,
332
+ allowNull: true,
333
+ },
334
+ payment_details: {
335
+ type: DataTypes.JSON,
336
+ allowNull: true,
337
+ },
338
+ metadata: {
339
+ type: DataTypes.JSON,
340
+ allowNull: true,
341
+ },
342
+ created_at: {
343
+ type: DataTypes.DATE,
344
+ defaultValue: DataTypes.NOW,
345
+ allowNull: false,
346
+ },
347
+ created_via: {
348
+ type: DataTypes.ENUM('api', 'dashboard', 'portal'),
349
+ },
350
+ updated_at: {
351
+ type: DataTypes.DATE,
352
+ defaultValue: DataTypes.NOW,
353
+ allowNull: false,
354
+ },
355
+ };
356
+
357
+ public static initialize(sequelize: any) {
358
+ this.init(CheckoutSession.GENESIS_ATTRIBUTES, {
359
+ sequelize,
360
+ modelName: 'CheckoutSession',
361
+ tableName: 'checkout_sessions',
362
+ createdAt: 'created_at',
363
+ updatedAt: 'updated_at',
364
+ hooks: {
365
+ afterUpdate: (model: CheckoutSession, options) => {
366
+ createStatusEvent(
367
+ 'CheckoutSession',
368
+ 'checkout.session',
369
+ { complete: 'completed', expired: 'expired' },
370
+ model,
371
+ options
372
+ ).catch(console.error);
373
+ },
374
+ },
375
+ });
376
+ }
377
+
378
+ // FIXME:
379
+ public static associate(models: any) {
380
+ this.hasOne(models.PaymentCurrency, {
381
+ sourceKey: 'currency_id',
382
+ foreignKey: 'id',
383
+ as: 'currency',
384
+ });
385
+ }
386
+
387
+ public static findByPkOrClientRefId(id: string, options: FindOptions<CheckoutSession> = {}) {
388
+ return this.findOne({
389
+ where: { [Op.or]: [{ id }, { client_reference_id: id }] },
390
+ ...options,
391
+ });
392
+ }
393
+ }
394
+
395
+ export type TCheckoutSession = InferAttributes<CheckoutSession>;
@@ -0,0 +1,137 @@
1
+ /* eslint-disable @typescript-eslint/lines-between-class-members */
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
3
+ import type { LiteralUnion } from 'type-fest';
4
+
5
+ import { createCodeGenerator } from '../../libs/util';
6
+
7
+ const nextId = createCodeGenerator('', 8);
8
+
9
+ // eslint-disable-next-line prettier/prettier
10
+ export class Coupon extends Model<InferAttributes<Coupon>, InferCreationAttributes<Coupon>> {
11
+ declare id: CreationOptional<string>;
12
+ declare livemode: boolean;
13
+
14
+ declare amount_off: string;
15
+ declare percent_off: number;
16
+
17
+ declare currency_id: string;
18
+
19
+ declare duration: LiteralUnion<'forever' | 'once' | 'repeating', string>;
20
+
21
+ declare duration_in_months: number;
22
+
23
+ declare name: string;
24
+
25
+ declare metadata: Record<string, any>;
26
+
27
+ declare applies_to?: {
28
+ products: string[];
29
+ };
30
+
31
+ declare currency_options?: Record<string, number>;
32
+
33
+ declare max_redemptions?: number;
34
+
35
+ declare redeem_by?: Date;
36
+
37
+ declare times_redeemed?: number;
38
+
39
+ declare valid?: boolean;
40
+
41
+ declare created_at: CreationOptional<Date>;
42
+ declare updated_at: CreationOptional<Date>;
43
+
44
+ public static readonly GENESIS_ATTRIBUTES = {
45
+ id: {
46
+ type: DataTypes.STRING(15),
47
+ primaryKey: true,
48
+ allowNull: false,
49
+ defaultValue: nextId,
50
+ },
51
+ livemode: {
52
+ type: DataTypes.BOOLEAN,
53
+ allowNull: false,
54
+ },
55
+ amount_off: {
56
+ type: DataTypes.STRING(32),
57
+ defaultValue: '0',
58
+ },
59
+ percent_off: {
60
+ type: DataTypes.INTEGER,
61
+ defaultValue: 0,
62
+ },
63
+ currency_id: {
64
+ type: DataTypes.STRING(15),
65
+ allowNull: false,
66
+ },
67
+ duration: {
68
+ type: DataTypes.ENUM('forever', 'once', 'repeating'),
69
+ },
70
+ duration_in_months: {
71
+ type: DataTypes.INTEGER,
72
+ allowNull: false,
73
+ },
74
+ name: {
75
+ type: DataTypes.STRING(64),
76
+ allowNull: false,
77
+ },
78
+ applies_to: {
79
+ type: DataTypes.JSON,
80
+ allowNull: true,
81
+ },
82
+ currency_options: {
83
+ type: DataTypes.JSON,
84
+ defaultValue: {},
85
+ },
86
+ max_redemptions: {
87
+ type: DataTypes.INTEGER,
88
+ allowNull: true,
89
+ },
90
+ redeem_by: {
91
+ type: DataTypes.DATE,
92
+ allowNull: true,
93
+ },
94
+ times_redeemed: {
95
+ type: DataTypes.INTEGER,
96
+ defaultValue: 0,
97
+ },
98
+ valid: {
99
+ type: DataTypes.BOOLEAN,
100
+ defaultValue: false,
101
+ },
102
+ metadata: {
103
+ type: DataTypes.JSON,
104
+ allowNull: true,
105
+ },
106
+ created_at: {
107
+ type: DataTypes.DATE,
108
+ defaultValue: DataTypes.NOW,
109
+ allowNull: false,
110
+ },
111
+ updated_at: {
112
+ type: DataTypes.DATE,
113
+ defaultValue: DataTypes.NOW,
114
+ allowNull: false,
115
+ },
116
+ };
117
+
118
+ public static initialize(sequelize: any) {
119
+ this.init(Coupon.GENESIS_ATTRIBUTES, {
120
+ sequelize,
121
+ modelName: 'Coupon',
122
+ tableName: 'coupons',
123
+ createdAt: 'created_at',
124
+ updatedAt: 'updated_at',
125
+ });
126
+ }
127
+
128
+ public static associate(models: any) {
129
+ this.hasOne(models.PaymentCurrency, {
130
+ sourceKey: 'currency_id',
131
+ foreignKey: 'id',
132
+ as: 'currency',
133
+ });
134
+ }
135
+ }
136
+
137
+ export type TCoupon = InferAttributes<Coupon>;