payment-kit 1.13.25 → 1.13.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/api/src/index.ts +8 -1
- package/api/src/integrations/blockchain/nft.ts +125 -0
- package/api/src/integrations/blockchain/stake.ts +55 -0
- package/api/src/integrations/blocklet/notification.ts +101 -0
- package/api/src/integrations/blocklet/passport.ts +139 -0
- package/api/src/integrations/stripe/handlers/invoice.ts +1 -1
- package/api/src/integrations/stripe/resource.ts +7 -7
- package/api/src/integrations/stripe/setup.ts +1 -1
- package/api/src/jobs/checkout-session.ts +23 -0
- package/api/src/jobs/payment.ts +1 -2
- package/api/src/libs/audit.ts +44 -2
- package/api/src/libs/payment.ts +3 -4
- package/api/src/locales/en.ts +9 -1
- package/api/src/locales/zh.ts +9 -1
- package/api/src/routes/checkout-sessions.ts +44 -14
- package/api/src/routes/connect/collect.ts +1 -2
- package/api/src/routes/connect/pay.ts +1 -2
- package/api/src/routes/connect/setup.ts +1 -2
- package/api/src/routes/connect/shared.ts +7 -3
- package/api/src/routes/connect/subscribe.ts +2 -3
- package/api/src/routes/index.ts +4 -0
- package/api/src/routes/integrations/stripe.ts +1 -1
- package/api/src/routes/passports.ts +74 -0
- package/api/src/routes/payment-links.ts +12 -2
- package/api/src/routes/pricing-table.ts +17 -3
- package/api/src/routes/products.ts +3 -3
- package/api/src/routes/redirect.ts +18 -0
- package/api/src/routes/subscriptions.ts +2 -5
- package/api/src/store/migrations/20231021-nft.ts +22 -0
- package/api/src/store/models/checkout-session.ts +76 -20
- package/api/src/store/models/invoice.ts +2 -0
- package/api/src/store/models/payment-intent.ts +2 -0
- package/api/src/store/models/payment-link.ts +26 -15
- package/api/src/store/models/payment-method.ts +22 -1
- package/api/src/store/models/price.ts +2 -0
- package/api/src/store/models/subscription.ts +26 -4
- package/api/src/store/models/types.ts +32 -1
- package/api/third.d.ts +2 -0
- package/blocklet.yml +1 -1
- package/package.json +7 -5
- package/src/components/customer/actions.tsx +15 -17
- package/src/components/customer/form.tsx +1 -1
- package/src/components/invoice/list.tsx +2 -1
- package/src/components/passport/actions.tsx +62 -0
- package/src/components/passport/assign.tsx +82 -0
- package/src/components/payment-intent/list.tsx +5 -1
- package/src/components/payment-link/actions.tsx +14 -1
- package/src/components/payment-link/after-pay.tsx +33 -1
- package/src/components/payment-link/preview.tsx +3 -6
- package/src/components/price/form.tsx +22 -23
- package/src/components/pricing-table/actions.tsx +14 -1
- package/src/components/pricing-table/payment-settings.tsx +33 -1
- package/src/components/pricing-table/preview.tsx +3 -7
- package/src/components/pricing-table/product-settings.tsx +4 -0
- package/src/components/pricing-table/product-skeleton.tsx +39 -0
- package/src/components/product/actions.tsx +14 -1
- package/src/components/status.tsx +1 -1
- package/src/components/subscription/status.tsx +3 -3
- package/src/components/table.tsx +14 -4
- package/src/global.css +7 -5
- package/src/libs/util.ts +6 -0
- package/src/locales/en.tsx +53 -2
- package/src/locales/zh.tsx +272 -116
- package/src/pages/admin/payments/links/create.tsx +4 -0
- package/src/pages/admin/payments/links/detail.tsx +9 -4
- package/src/pages/admin/products/index.tsx +2 -0
- package/src/pages/admin/products/passports/index.tsx +154 -0
- package/src/pages/admin/products/pricing-tables/create.tsx +1 -1
- package/src/pages/admin/settings/index.tsx +1 -1
- package/src/pages/admin/settings/payment-methods/index.tsx +17 -7
- package/src/pages/checkout/pay.tsx +15 -13
- package/src/pages/checkout/pricing-table.tsx +127 -91
- package/api/src/libs/chain/arcblock.ts +0 -13
|
@@ -11,9 +11,18 @@ import {
|
|
|
11
11
|
} from 'sequelize';
|
|
12
12
|
import type { LiteralUnion } from 'type-fest';
|
|
13
13
|
|
|
14
|
-
import { createStatusEvent } from '../../libs/audit';
|
|
14
|
+
import { createCustomEvent, createStatusEvent } from '../../libs/audit';
|
|
15
15
|
import { createIdGenerator } from '../../libs/util';
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
CurrencyConversion,
|
|
18
|
+
CustomField,
|
|
19
|
+
CustomerDetail,
|
|
20
|
+
InvoiceData,
|
|
21
|
+
LineItem,
|
|
22
|
+
NftMintDetails,
|
|
23
|
+
NftMintSettings,
|
|
24
|
+
PaymentDetails,
|
|
25
|
+
} from './types';
|
|
17
26
|
|
|
18
27
|
const nextId = createIdGenerator('cs', 58);
|
|
19
28
|
|
|
@@ -162,13 +171,24 @@ export class CheckoutSession extends Model<InferAttributes<CheckoutSession>, Inf
|
|
|
162
171
|
// 3rd party payment tx hash
|
|
163
172
|
declare payment_details?: PaymentDetails;
|
|
164
173
|
|
|
174
|
+
// A subset of parameters to be passed to PaymentIntent creation for Checkout Sessions in payment mode.
|
|
175
|
+
declare payment_intent_data?: {
|
|
176
|
+
description?: string;
|
|
177
|
+
statement_descriptor?: string;
|
|
178
|
+
metadata?: Record<string, any>;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Whether should we mint an nft to the customer on checkout complete
|
|
182
|
+
// Will use setting from payment method
|
|
183
|
+
declare nft_mint_status: LiteralUnion<'disabled' | 'pending' | 'minted' | 'sent' | 'error', string>;
|
|
184
|
+
declare nft_mint_settings?: NftMintSettings;
|
|
185
|
+
declare nft_mint_details?: NftMintDetails;
|
|
186
|
+
|
|
165
187
|
// FIXME: Only exist on creation
|
|
166
188
|
// declare discounts?: {
|
|
167
189
|
// coupon?: string;
|
|
168
190
|
// promotion_code?: string;
|
|
169
191
|
// };
|
|
170
|
-
// A subset of parameters to be passed to PaymentIntent creation for Checkout Sessions in payment mode.
|
|
171
|
-
// declare payment_intent_data?: any;
|
|
172
192
|
|
|
173
193
|
// TODO: following fields not supported yet
|
|
174
194
|
// automatic_tax
|
|
@@ -236,12 +256,19 @@ export class CheckoutSession extends Model<InferAttributes<CheckoutSession>, Inf
|
|
|
236
256
|
},
|
|
237
257
|
mode: {
|
|
238
258
|
type: DataTypes.ENUM('payment', 'setup', 'subscription'),
|
|
259
|
+
allowNull: false,
|
|
239
260
|
},
|
|
240
261
|
status: {
|
|
241
262
|
type: DataTypes.ENUM('complete', 'open', 'expired'),
|
|
263
|
+
allowNull: false,
|
|
242
264
|
},
|
|
243
265
|
payment_status: {
|
|
244
266
|
type: DataTypes.ENUM('paid', 'unpaid', 'no_payment_required'),
|
|
267
|
+
allowNull: false,
|
|
268
|
+
},
|
|
269
|
+
nft_mint_status: {
|
|
270
|
+
type: DataTypes.ENUM('disabled', 'pending', 'minted', 'sent', 'error'),
|
|
271
|
+
allowNull: false,
|
|
245
272
|
},
|
|
246
273
|
line_items: {
|
|
247
274
|
type: DataTypes.JSON,
|
|
@@ -364,24 +391,53 @@ export class CheckoutSession extends Model<InferAttributes<CheckoutSession>, Inf
|
|
|
364
391
|
};
|
|
365
392
|
|
|
366
393
|
public static initialize(sequelize: any) {
|
|
367
|
-
this.init(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
).catch(console.error);
|
|
394
|
+
this.init(
|
|
395
|
+
{
|
|
396
|
+
...CheckoutSession.GENESIS_ATTRIBUTES,
|
|
397
|
+
payment_intent_data: {
|
|
398
|
+
type: DataTypes.JSON,
|
|
399
|
+
allowNull: true,
|
|
400
|
+
},
|
|
401
|
+
nft_mint_settings: {
|
|
402
|
+
type: DataTypes.JSON,
|
|
403
|
+
allowNull: true,
|
|
404
|
+
},
|
|
405
|
+
nft_mint_details: {
|
|
406
|
+
type: DataTypes.JSON,
|
|
407
|
+
allowNull: true,
|
|
382
408
|
},
|
|
383
409
|
},
|
|
384
|
-
|
|
410
|
+
{
|
|
411
|
+
sequelize,
|
|
412
|
+
modelName: 'CheckoutSession',
|
|
413
|
+
tableName: 'checkout_sessions',
|
|
414
|
+
createdAt: 'created_at',
|
|
415
|
+
updatedAt: 'updated_at',
|
|
416
|
+
hooks: {
|
|
417
|
+
afterUpdate: (model: CheckoutSession, options) => {
|
|
418
|
+
createStatusEvent(
|
|
419
|
+
'CheckoutSession',
|
|
420
|
+
'checkout.session',
|
|
421
|
+
{ complete: 'completed', expired: 'expired' },
|
|
422
|
+
model,
|
|
423
|
+
options
|
|
424
|
+
).catch(console.error);
|
|
425
|
+
createCustomEvent(
|
|
426
|
+
'CheckoutSession',
|
|
427
|
+
'checkout.session',
|
|
428
|
+
(current, previous) => {
|
|
429
|
+
if (previous.nft_mint_status === 'pending' && current.nft_mint_status === 'minted') {
|
|
430
|
+
return 'nft_minted';
|
|
431
|
+
}
|
|
432
|
+
return '';
|
|
433
|
+
},
|
|
434
|
+
model,
|
|
435
|
+
options
|
|
436
|
+
).catch(console.error);
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
}
|
|
440
|
+
);
|
|
385
441
|
}
|
|
386
442
|
|
|
387
443
|
public static associate(models: any) {
|
|
@@ -173,6 +173,7 @@ export class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttrib
|
|
|
173
173
|
},
|
|
174
174
|
collection_method: {
|
|
175
175
|
type: DataTypes.ENUM('charge_automatically', 'send_invoice'),
|
|
176
|
+
allowNull: false,
|
|
176
177
|
},
|
|
177
178
|
currency_id: {
|
|
178
179
|
type: DataTypes.STRING(15),
|
|
@@ -204,6 +205,7 @@ export class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttrib
|
|
|
204
205
|
},
|
|
205
206
|
status: {
|
|
206
207
|
type: DataTypes.ENUM('draft', 'open', 'void', 'paid', 'uncollectible'),
|
|
208
|
+
allowNull: false,
|
|
207
209
|
},
|
|
208
210
|
checkout_session_id: {
|
|
209
211
|
type: DataTypes.STRING(64),
|
|
@@ -196,9 +196,11 @@ export class PaymentIntent extends Model<InferAttributes<PaymentIntent>, InferCr
|
|
|
196
196
|
},
|
|
197
197
|
capture_method: {
|
|
198
198
|
type: DataTypes.ENUM('automatic', 'manual'),
|
|
199
|
+
allowNull: false,
|
|
199
200
|
},
|
|
200
201
|
confirmation_method: {
|
|
201
202
|
type: DataTypes.ENUM('automatic', 'manual'),
|
|
203
|
+
allowNull: false,
|
|
202
204
|
},
|
|
203
205
|
payment_method_types: {
|
|
204
206
|
type: DataTypes.JSON,
|
|
@@ -4,7 +4,7 @@ import type { LiteralUnion } from 'type-fest';
|
|
|
4
4
|
|
|
5
5
|
import { createEvent } from '../../libs/audit';
|
|
6
6
|
import { createIdGenerator } from '../../libs/util';
|
|
7
|
-
import type { AfterPayment, CustomField, LineItem } from './types';
|
|
7
|
+
import type { AfterPayment, CustomField, LineItem, NftMintSettings } from './types';
|
|
8
8
|
|
|
9
9
|
const nextId = createIdGenerator('plink', 24);
|
|
10
10
|
|
|
@@ -71,6 +71,8 @@ export class PaymentLink extends Model<InferAttributes<PaymentLink>, InferCreati
|
|
|
71
71
|
trial_period_days: number;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
declare nft_mint_settings?: NftMintSettings;
|
|
75
|
+
|
|
74
76
|
declare metadata?: Record<string, any>;
|
|
75
77
|
|
|
76
78
|
// TODO: following fields not supported
|
|
@@ -190,21 +192,30 @@ export class PaymentLink extends Model<InferAttributes<PaymentLink>, InferCreati
|
|
|
190
192
|
};
|
|
191
193
|
|
|
192
194
|
public static initialize(sequelize: any) {
|
|
193
|
-
this.init(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
afterCreate: (model: PaymentLink, options) =>
|
|
201
|
-
createEvent('PaymentLink', 'payment_link.created', model, options).catch(console.error),
|
|
202
|
-
afterUpdate: (model: PaymentLink, options) =>
|
|
203
|
-
createEvent('PaymentLink', 'payment_link.updated', model, options).catch(console.error),
|
|
204
|
-
afterDestroy: (model: PaymentLink, options) =>
|
|
205
|
-
createEvent('PaymentLink', 'payment_link.deleted', model, options).catch(console.error),
|
|
195
|
+
this.init(
|
|
196
|
+
{
|
|
197
|
+
...PaymentLink.GENESIS_ATTRIBUTES,
|
|
198
|
+
nft_mint_settings: {
|
|
199
|
+
type: DataTypes.JSON,
|
|
200
|
+
allowNull: true,
|
|
201
|
+
},
|
|
206
202
|
},
|
|
207
|
-
|
|
203
|
+
{
|
|
204
|
+
sequelize,
|
|
205
|
+
modelName: 'PaymentLink',
|
|
206
|
+
tableName: 'payment_links',
|
|
207
|
+
createdAt: 'created_at',
|
|
208
|
+
updatedAt: 'updated_at',
|
|
209
|
+
hooks: {
|
|
210
|
+
afterCreate: (model: PaymentLink, options) =>
|
|
211
|
+
createEvent('PaymentLink', 'payment_link.created', model, options).catch(console.error),
|
|
212
|
+
afterUpdate: (model: PaymentLink, options) =>
|
|
213
|
+
createEvent('PaymentLink', 'payment_link.updated', model, options).catch(console.error),
|
|
214
|
+
afterDestroy: (model: PaymentLink, options) =>
|
|
215
|
+
createEvent('PaymentLink', 'payment_link.deleted', model, options).catch(console.error),
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
);
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
public static associate(models: any) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
2
|
import security from '@blocklet/sdk/lib/security';
|
|
3
|
+
import OcapClient from '@ocap/client';
|
|
3
4
|
import cloneDeep from 'lodash/cloneDeep';
|
|
4
5
|
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
|
|
5
6
|
import Stripe from 'stripe';
|
|
@@ -12,6 +13,7 @@ import type { PaymentMethodSettings } from './types';
|
|
|
12
13
|
const nextId = createIdGenerator('pm', 24);
|
|
13
14
|
|
|
14
15
|
const stripeClients = new Map<string, Stripe>();
|
|
16
|
+
const ocapClients = new Map<string, OcapClient>();
|
|
15
17
|
|
|
16
18
|
// eslint-disable-next-line prettier/prettier
|
|
17
19
|
export class PaymentMethod extends Model<InferAttributes<PaymentMethod>, InferCreationAttributes<PaymentMethod>> {
|
|
@@ -162,7 +164,7 @@ export class PaymentMethod extends Model<InferAttributes<PaymentMethod>, InferCr
|
|
|
162
164
|
return tmp;
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
|
|
167
|
+
getStripeClient() {
|
|
166
168
|
if (this.type !== 'stripe') {
|
|
167
169
|
throw new Error('payment method is not stripe');
|
|
168
170
|
}
|
|
@@ -181,6 +183,25 @@ export class PaymentMethod extends Model<InferAttributes<PaymentMethod>, InferCr
|
|
|
181
183
|
return client as Stripe;
|
|
182
184
|
}
|
|
183
185
|
|
|
186
|
+
getOcapClient() {
|
|
187
|
+
if (this.type !== 'arcblock') {
|
|
188
|
+
throw new Error('payment method is not arcblock');
|
|
189
|
+
}
|
|
190
|
+
if (!this.settings.arcblock) {
|
|
191
|
+
throw new Error('payment method config insufficient to create ocap client');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const host = this.settings.arcblock?.api_host;
|
|
195
|
+
const cached = ocapClients.has(host);
|
|
196
|
+
if (!cached) {
|
|
197
|
+
const created = new OcapClient(host);
|
|
198
|
+
ocapClients.set(host, created);
|
|
199
|
+
return created;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return ocapClients.get(host) as OcapClient;
|
|
203
|
+
}
|
|
204
|
+
|
|
184
205
|
public static async supportAutoCharge(id: string) {
|
|
185
206
|
const method = await PaymentMethod.findByPk(id);
|
|
186
207
|
return method && ['arcblock', 'ethereum'].includes(method.type);
|
|
@@ -103,9 +103,11 @@ export class Price extends Model<InferAttributes<Price>, InferCreationAttributes
|
|
|
103
103
|
},
|
|
104
104
|
type: {
|
|
105
105
|
type: DataTypes.ENUM('one_time', 'recurring'),
|
|
106
|
+
allowNull: false,
|
|
106
107
|
},
|
|
107
108
|
billing_scheme: {
|
|
108
109
|
type: DataTypes.ENUM('per_unit', 'tiered'),
|
|
110
|
+
allowNull: false,
|
|
109
111
|
},
|
|
110
112
|
unit_amount: {
|
|
111
113
|
type: DataTypes.STRING(32),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
|
|
4
4
|
import type { LiteralUnion } from 'type-fest';
|
|
5
5
|
|
|
6
|
-
import { createEvent, createStatusEvent } from '../../libs/audit';
|
|
6
|
+
import { createCustomEvent, createEvent, createStatusEvent } from '../../libs/audit';
|
|
7
7
|
import { createIdGenerator } from '../../libs/util';
|
|
8
8
|
import type { PaymentDetails, PaymentSettings, PriceRecurring } from './types';
|
|
9
9
|
|
|
@@ -188,6 +188,7 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
|
|
|
188
188
|
},
|
|
189
189
|
collection_method: {
|
|
190
190
|
type: DataTypes.ENUM('charge_automatically', 'send_invoice'),
|
|
191
|
+
allowNull: false,
|
|
191
192
|
},
|
|
192
193
|
days_until_due: {
|
|
193
194
|
type: DataTypes.NUMBER,
|
|
@@ -269,12 +270,13 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
|
|
|
269
270
|
createEvent('Subscription', 'customer.subscription.created', model, options).catch(console.error),
|
|
270
271
|
afterUpdate: (model: Subscription, options) => {
|
|
271
272
|
createEvent('Subscription', 'customer.subscription.updated', model, options).catch(console.error);
|
|
272
|
-
createStatusEvent('Subscription', 'customer.subscription', { canceled: '
|
|
273
|
+
createStatusEvent('Subscription', 'customer.subscription', { canceled: 'deleted' }, model, options).catch(
|
|
274
|
+
console.error
|
|
275
|
+
);
|
|
276
|
+
createCustomEvent('Subscription', 'customer.subscription', getSubscriptionEventType, model, options).catch(
|
|
273
277
|
console.error
|
|
274
278
|
);
|
|
275
279
|
},
|
|
276
|
-
afterDestroy: (model: Subscription, options) =>
|
|
277
|
-
createEvent('Subscription', 'customer.subscription.deleted', model, options).catch(console.error),
|
|
278
280
|
},
|
|
279
281
|
});
|
|
280
282
|
}
|
|
@@ -303,3 +305,23 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
|
|
|
303
305
|
}
|
|
304
306
|
|
|
305
307
|
export type TSubscription = InferAttributes<Subscription>;
|
|
308
|
+
|
|
309
|
+
export function getSubscriptionEventType(current: TSubscription, previous: Partial<TSubscription>) {
|
|
310
|
+
if (current.pause_collection && !previous.pause_collection) {
|
|
311
|
+
return 'paused';
|
|
312
|
+
}
|
|
313
|
+
if (!current.pause_collection && previous.pause_collection) {
|
|
314
|
+
return 'resumed';
|
|
315
|
+
}
|
|
316
|
+
if (
|
|
317
|
+
current.status === 'active' &&
|
|
318
|
+
current.current_period_end &&
|
|
319
|
+
current.current_period_end !== previous.current_period_end &&
|
|
320
|
+
current.current_period_start &&
|
|
321
|
+
current.current_period_start !== previous.current_period_start
|
|
322
|
+
) {
|
|
323
|
+
return 'renewed';
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return '';
|
|
327
|
+
}
|
|
@@ -152,7 +152,12 @@ export type LineItem = {
|
|
|
152
152
|
// tax_rates?: any;
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
-
export type InvoiceData =
|
|
155
|
+
export type InvoiceData = {
|
|
156
|
+
description?: string;
|
|
157
|
+
footer?: string;
|
|
158
|
+
metadata?: Record<string, any>;
|
|
159
|
+
custom_fields?: SimpleCustomField[];
|
|
160
|
+
};
|
|
156
161
|
|
|
157
162
|
// @see https://stripe.com/docs/currencies/conversions
|
|
158
163
|
// If presentment currency is different from settlement currency, this is the exchange rate snapshot used.
|
|
@@ -262,6 +267,28 @@ export type PaymentDetails = {
|
|
|
262
267
|
};
|
|
263
268
|
};
|
|
264
269
|
|
|
270
|
+
export type NftMintSettings = {
|
|
271
|
+
enabled: boolean;
|
|
272
|
+
behavior?: LiteralUnion<'per_customer' | 'per_checkout_session', string>;
|
|
273
|
+
factory?: string;
|
|
274
|
+
inputs?: Record<string, string>;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export type NftMintDetails = {
|
|
278
|
+
arcblock?: {
|
|
279
|
+
tx_hash?: string;
|
|
280
|
+
address: string;
|
|
281
|
+
owner: string;
|
|
282
|
+
error?: string;
|
|
283
|
+
};
|
|
284
|
+
ethereum?: {
|
|
285
|
+
tx_hash?: string;
|
|
286
|
+
address: string;
|
|
287
|
+
owner: string;
|
|
288
|
+
error?: string;
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
|
|
265
292
|
// Very similar to PaymentLink
|
|
266
293
|
export type PricingTableItem = {
|
|
267
294
|
price_id: string;
|
|
@@ -306,6 +333,8 @@ export type PricingTableItem = {
|
|
|
306
333
|
description: string;
|
|
307
334
|
trial_period_days: number;
|
|
308
335
|
};
|
|
336
|
+
|
|
337
|
+
nft_mint_settings?: NftMintSettings;
|
|
309
338
|
};
|
|
310
339
|
|
|
311
340
|
export type BrandSettings = {
|
|
@@ -346,6 +375,7 @@ export type EventType = LiteralUnion<
|
|
|
346
375
|
| 'charge.updated'
|
|
347
376
|
| 'checkout.session.async_payment_failed'
|
|
348
377
|
| 'checkout.session.async_payment_succeeded'
|
|
378
|
+
| 'checkout.session.nft_minted'
|
|
349
379
|
| 'checkout.session.completed'
|
|
350
380
|
| 'checkout.session.expired'
|
|
351
381
|
| 'coupon.created'
|
|
@@ -370,6 +400,7 @@ export type EventType = LiteralUnion<
|
|
|
370
400
|
| 'customer.subscription.pending_update_applied'
|
|
371
401
|
| 'customer.subscription.pending_update_expired'
|
|
372
402
|
| 'customer.subscription.resumed'
|
|
403
|
+
| 'customer.subscription.renewed'
|
|
373
404
|
| 'customer.subscription.trial_will_end'
|
|
374
405
|
| 'customer.subscription.updated'
|
|
375
406
|
| 'customer.tax_id.created'
|
package/api/third.d.ts
CHANGED
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.27",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"@arcblock/did-connect": "^2.7.28",
|
|
46
46
|
"@arcblock/did-util": "^1.18.92",
|
|
47
47
|
"@arcblock/ux": "^2.7.28",
|
|
48
|
-
"@blocklet/logger": "
|
|
49
|
-
"@blocklet/sdk": "
|
|
48
|
+
"@blocklet/logger": "1.16.17-beta-703fb879",
|
|
49
|
+
"@blocklet/sdk": "1.16.17-beta-703fb879",
|
|
50
50
|
"@blocklet/ui-react": "^2.7.28",
|
|
51
51
|
"@blocklet/uploader": "^0.0.26",
|
|
52
52
|
"@mui/icons-material": "^5.14.13",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@mui/material": "^5.14.13",
|
|
55
55
|
"@mui/styles": "^5.14.13",
|
|
56
56
|
"@mui/system": "^5.14.13",
|
|
57
|
+
"@ocap/asset": "^1.18.92",
|
|
57
58
|
"@ocap/client": "^1.18.92",
|
|
58
59
|
"@ocap/mcrypto": "^1.18.92",
|
|
59
60
|
"@ocap/util": "^1.18.92",
|
|
@@ -99,9 +100,10 @@
|
|
|
99
100
|
"validator": "^13.11.0"
|
|
100
101
|
},
|
|
101
102
|
"devDependencies": {
|
|
103
|
+
"@abtnode/types": "1.16.17-beta-703fb879",
|
|
102
104
|
"@arcblock/eslint-config": "^0.2.4",
|
|
103
105
|
"@arcblock/eslint-config-ts": "^0.2.4",
|
|
104
|
-
"@did-pay/types": "1.13.
|
|
106
|
+
"@did-pay/types": "1.13.27",
|
|
105
107
|
"@types/cookie-parser": "^1.4.4",
|
|
106
108
|
"@types/cors": "^2.8.14",
|
|
107
109
|
"@types/dotenv-flow": "^3.3.1",
|
|
@@ -138,5 +140,5 @@
|
|
|
138
140
|
"parser": "typescript"
|
|
139
141
|
}
|
|
140
142
|
},
|
|
141
|
-
"gitHead": "
|
|
143
|
+
"gitHead": "7f11915be75b7419085508377566b02495b423a1"
|
|
142
144
|
}
|
|
@@ -8,7 +8,7 @@ import api from '../../libs/api';
|
|
|
8
8
|
import { formatError } from '../../libs/util';
|
|
9
9
|
import Actions from '../actions';
|
|
10
10
|
import ClickBoundary from '../click-boundary';
|
|
11
|
-
import
|
|
11
|
+
import EditCustomer from './edit';
|
|
12
12
|
|
|
13
13
|
type Props = {
|
|
14
14
|
data: TCustomerExpanded;
|
|
@@ -27,12 +27,12 @@ export default function CustomerActions({ data, onChange, variant }: Props) {
|
|
|
27
27
|
loading: false,
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
const
|
|
30
|
+
const onUpdateInfo = async (updates: TCustomerExpanded) => {
|
|
31
31
|
try {
|
|
32
32
|
setState({ loading: true });
|
|
33
|
-
await api.put(`/api/customers/${data.id}
|
|
33
|
+
await api.put(`/api/customers/${data.id}`, updates).then((res) => res.data);
|
|
34
34
|
Toast.success(t('common.saved'));
|
|
35
|
-
onChange(
|
|
35
|
+
onChange('update');
|
|
36
36
|
} catch (err) {
|
|
37
37
|
console.error(err);
|
|
38
38
|
Toast.error(formatError(err));
|
|
@@ -46,27 +46,25 @@ export default function CustomerActions({ data, onChange, variant }: Props) {
|
|
|
46
46
|
<Actions
|
|
47
47
|
variant={variant}
|
|
48
48
|
actions={[
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
},
|
|
49
|
+
// {
|
|
50
|
+
// label: t('admin.payments'),
|
|
51
|
+
// handler: () => setState({ action: 'refund' }),
|
|
52
|
+
// color: 'primary',
|
|
53
|
+
// disabled: true,
|
|
54
|
+
// },
|
|
55
55
|
{
|
|
56
56
|
label: t('admin.customer.edit'),
|
|
57
57
|
handler: () => setState({ action: 'edit' }),
|
|
58
58
|
color: 'primary',
|
|
59
|
-
disabled: true,
|
|
60
59
|
},
|
|
61
60
|
]}
|
|
62
61
|
/>
|
|
63
|
-
{state.action === '
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
onCancel={() => setState({ action: '' })}
|
|
67
|
-
title={t('admin.customer.refund')}
|
|
68
|
-
message={t('admin.customer.refundTip')}
|
|
62
|
+
{state.action === 'edit' && (
|
|
63
|
+
<EditCustomer
|
|
64
|
+
data={data}
|
|
69
65
|
loading={state.loading}
|
|
66
|
+
onSave={onUpdateInfo}
|
|
67
|
+
onCancel={() => setState({ action: '' })}
|
|
70
68
|
/>
|
|
71
69
|
)}
|
|
72
70
|
</ClickBoundary>
|
|
@@ -64,7 +64,7 @@ export default function CustomerForm() {
|
|
|
64
64
|
}}
|
|
65
65
|
/>
|
|
66
66
|
|
|
67
|
-
<Typography component="h6" sx={{
|
|
67
|
+
<Typography component="h6" sx={{ pt: 2, color: 'text.primary', fontWeight: 600 }}>
|
|
68
68
|
{t('checkout.billing.required')}
|
|
69
69
|
</Typography>
|
|
70
70
|
<Controller
|
|
@@ -94,11 +94,12 @@ export default function InvoiceList({ customer_id, subscription_id, features, st
|
|
|
94
94
|
label: t('common.amount'),
|
|
95
95
|
name: 'total',
|
|
96
96
|
width: 60,
|
|
97
|
+
align: 'right',
|
|
97
98
|
options: {
|
|
98
99
|
customBodyRenderLite: (_: string, index: number) => {
|
|
99
100
|
const item = data.list[index];
|
|
100
101
|
return (
|
|
101
|
-
<Typography component="
|
|
102
|
+
<Typography component="strong" fontWeight={600}>
|
|
102
103
|
{fromUnitToToken(item?.total, item?.paymentCurrency.decimal)}
|
|
103
104
|
{item?.paymentCurrency.symbol}
|
|
104
105
|
</Typography>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
2
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
3
|
+
import { useSetState } from 'ahooks';
|
|
4
|
+
|
|
5
|
+
import api from '../../libs/api';
|
|
6
|
+
import { formatError } from '../../libs/util';
|
|
7
|
+
import Actions from '../actions';
|
|
8
|
+
import ClickBoundary from '../click-boundary';
|
|
9
|
+
import ConfirmDialog from '../confirm';
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
data: any;
|
|
13
|
+
variant?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
PassportActions.defaultProps = {
|
|
17
|
+
variant: 'compact',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default function PassportActions(props: Props) {
|
|
21
|
+
const { t } = useLocaleContext();
|
|
22
|
+
|
|
23
|
+
const [state, setState] = useSetState({
|
|
24
|
+
action: '',
|
|
25
|
+
loading: false,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const onUnassign = async () => {
|
|
29
|
+
try {
|
|
30
|
+
setState({ loading: true });
|
|
31
|
+
await api.delete(`/api/passports/assign/${props.data.name}`).then((res) => res.data);
|
|
32
|
+
Toast.success(t('common.saved'));
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.error(err);
|
|
35
|
+
Toast.error(formatError(err));
|
|
36
|
+
} finally {
|
|
37
|
+
setState({ loading: false, action: '' });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const actions = [
|
|
42
|
+
{
|
|
43
|
+
label: t('admin.passport.unassign'),
|
|
44
|
+
handler: () => setState({ action: 'unassign' }),
|
|
45
|
+
color: 'error',
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<ClickBoundary>
|
|
51
|
+
<Actions variant={props.variant} actions={actions} />
|
|
52
|
+
{state.action === 'unassign' && (
|
|
53
|
+
<ConfirmDialog
|
|
54
|
+
onConfirm={onUnassign}
|
|
55
|
+
onCancel={() => setState({ action: '' })}
|
|
56
|
+
title={t('admin.passport.unassign')}
|
|
57
|
+
message={t('admin.passport.unassignTip')}
|
|
58
|
+
/>
|
|
59
|
+
)}
|
|
60
|
+
</ClickBoundary>
|
|
61
|
+
);
|
|
62
|
+
}
|