payment-kit 1.15.7 → 1.15.9

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.
@@ -0,0 +1,36 @@
1
+ import { Op } from 'sequelize';
2
+ import { getUrl } from '@blocklet/sdk';
3
+ import { PaymentMethod, PaymentCurrency } from '../store/models';
4
+ import logger from '../libs/logger';
5
+
6
+ export async function syncCurrencyLogo() {
7
+ const where = {
8
+ logo: {
9
+ [Op.like]: '%/methods/%.png',
10
+ },
11
+ };
12
+
13
+ const [paymentMethods, paymentCurrencies] = await Promise.all([
14
+ PaymentMethod.findAll({ where }),
15
+ PaymentCurrency.findAll({ where }),
16
+ ]);
17
+
18
+ const promises: Promise<any>[] = [];
19
+
20
+ const updateLogo = (item: PaymentMethod | PaymentCurrency) => {
21
+ const { logo } = item;
22
+ if (/\/methods\/(stripe|arcblock|ethereum)\.png$/.test(logo)) {
23
+ const newLogo = getUrl(logo.replace(/^.*?(\/methods\/.*)$/, '$1'));
24
+ promises.push((item as any).update({ logo: newLogo }));
25
+ }
26
+ };
27
+
28
+ paymentMethods.forEach(updateLogo);
29
+ paymentCurrencies.forEach(updateLogo);
30
+
31
+ try {
32
+ await Promise.all(promises);
33
+ } catch (error) {
34
+ logger.error('syncCurrency error', error);
35
+ }
36
+ }
@@ -6,6 +6,7 @@ import { ensurePaymentStats } from '../crons/payment-stat';
6
6
  import { initPaywallResources } from '../libs/resource';
7
7
  import { initialize } from '../store/models';
8
8
  import { sequelize } from '../store/sequelize';
9
+ import { syncCurrencyLogo } from '../crons/currency';
9
10
 
10
11
  dotenv.config({ silent: true });
11
12
 
@@ -14,6 +15,7 @@ dotenv.config({ silent: true });
14
15
  initialize(sequelize);
15
16
  await initPaywallResources();
16
17
  await ensurePaymentStats();
18
+ await syncCurrencyLogo();
17
19
  process.exit(0);
18
20
  } catch (err) {
19
21
  console.error('pre-start error', err);
package/api/src/index.ts CHANGED
@@ -11,6 +11,7 @@ import morgan from 'morgan';
11
11
 
12
12
  // eslint-disable-next-line import/no-extraneous-dependencies
13
13
  import { xss } from '@blocklet/xss';
14
+ import { csrf } from '@blocklet/sdk/lib/middlewares';
14
15
 
15
16
  import crons from './crons/index';
16
17
  import { ensureStakedForGas } from './integrations/arcblock/stake';
@@ -57,6 +58,7 @@ app.use((req, res, next) => {
57
58
  app.use(express.urlencoded({ extended: true, limit: '1 mb' }));
58
59
  app.use(cors());
59
60
  app.use(xss({ allowedKeys: [] }));
61
+ app.use(csrf());
60
62
  app.use(ensureI18n());
61
63
 
62
64
  const router = express.Router();
@@ -44,6 +44,7 @@ interface CustomerRewardSucceededEmailTemplateContext {
44
44
  title: string;
45
45
  appDID: string;
46
46
  logo?: string;
47
+ desc?: string;
47
48
  }[]
48
49
  | null;
49
50
  donationSettings: DonationSettings;
@@ -187,6 +188,7 @@ export class CustomerRewardSucceededEmailTemplate
187
188
  title: string;
188
189
  appDID: string;
189
190
  logo?: string;
191
+ desc?: string;
190
192
  }[]
191
193
  | null
192
194
  > {
@@ -215,6 +217,7 @@ export class CustomerRewardSucceededEmailTemplate
215
217
  ? joinURL(process.env.BLOCKLET_APP_URL, users[index]?.user?.avatar as string)
216
218
  : '',
217
219
  appDID: x.address,
220
+ desc: '',
218
221
  };
219
222
  });
220
223
 
@@ -296,6 +299,13 @@ export class CustomerRewardSucceededEmailTemplate
296
299
  text: translate('notification.common.rewardDetail', locale),
297
300
  },
298
301
  },
302
+ {
303
+ type: 'text',
304
+ data: {
305
+ type: 'plain',
306
+ text: ' ', // TODO: ios bug fix, wait for next release
307
+ },
308
+ },
299
309
  ].filter(Boolean),
300
310
  },
301
311
  ...(rewardDetail
@@ -100,11 +100,14 @@ export class SubscriptionWillRenewEmailTemplate
100
100
  // paymentDetail.price = +amount;
101
101
 
102
102
  const paymentAmount = await getPaymentAmountForCycleSubscription(subscription, paymentCurrency);
103
- const paymentDetail = { price: paymentAmount, balance: 0, symbol: paymentCurrency.symbol };
103
+ const paymentDetail = { price: paymentAmount, balance: 0, symbol: paymentCurrency.symbol, balanceFormatted: '0' };
104
104
 
105
105
  const token = await getTokenSummaryByDid(userDid, customer.livemode);
106
106
 
107
- paymentDetail.balance = +fromUnitToToken(token?.[paymentCurrency.id] || '0', paymentCurrency.decimal);
107
+ const balance = fromUnitToToken(token?.[paymentCurrency.id] || '0', paymentCurrency.decimal);
108
+ paymentDetail.balanceFormatted = balance;
109
+ paymentDetail.balance = +balance;
110
+
108
111
  const { isPrePaid, interval } = await this.getPaymentCategory({
109
112
  subscriptionId: subscription.id,
110
113
  });
@@ -173,9 +176,10 @@ export class SubscriptionWillRenewEmailTemplate
173
176
 
174
177
  const lineItemExpanded = await Price.expand(subscriptionItems);
175
178
  const metered = lineItemExpanded.find((lineItem) => lineItem.price.recurring?.usage_type === 'metered');
179
+ const recurringItems = lineItemExpanded.filter((lineItem) => lineItem.price.type === 'recurring');
176
180
 
177
181
  const isPrePaid = !metered;
178
- const interval = metered?.price.recurring?.interval;
182
+ const interval = recurringItems?.[0]?.price.recurring?.interval;
179
183
 
180
184
  return {
181
185
  isPrePaid,
@@ -269,7 +273,7 @@ export class SubscriptionWillRenewEmailTemplate
269
273
  at,
270
274
  productName,
271
275
  willRenewDuration,
272
- balance: `${paymentDetail.balance} ${paymentDetail.symbol}`,
276
+ balance: `${paymentDetail.balanceFormatted} ${paymentDetail.symbol}`,
273
277
  })}`
274
278
  : `${translate('notification.subscriptionWillRenew.unableToPayBody', locale, {
275
279
  at,
@@ -326,25 +330,28 @@ export class SubscriptionWillRenewEmailTemplate
326
330
  text: paymentInfo,
327
331
  },
328
332
  },
329
- {
330
- type: 'text',
331
- data: {
332
- type: 'plain',
333
- color: '#9397A1',
334
- text: translate('notification.common.currentBalance', locale),
335
- },
336
- },
337
- {
338
- type: 'text',
339
- data: {
340
- type: 'plain',
341
- ...(!canPay &&
342
- !isStripe && {
343
- color: '#FF0000',
344
- }),
345
- text: `${paymentDetail.balance} ${paymentDetail.symbol}`,
346
- },
347
- },
333
+ ...(!isStripe
334
+ ? [
335
+ {
336
+ type: 'text',
337
+ data: {
338
+ type: 'plain',
339
+ color: '#9397A1',
340
+ text: translate('notification.common.currentBalance', locale),
341
+ },
342
+ },
343
+ {
344
+ type: 'text',
345
+ data: {
346
+ type: 'plain',
347
+ ...(!canPay && {
348
+ color: '#FF0000',
349
+ }),
350
+ text: `${paymentDetail.balanceFormatted} ${paymentDetail.symbol}`,
351
+ },
352
+ },
353
+ ]
354
+ : []),
348
355
  ...(!canPay && !isStripe
349
356
  ? [
350
357
  {
@@ -368,7 +375,6 @@ export class SubscriptionWillRenewEmailTemplate
368
375
  },
369
376
  ]
370
377
  : []),
371
-
372
378
  {
373
379
  type: 'text',
374
380
  data: {
@@ -185,6 +185,7 @@ export interface PaymentDetail {
185
185
  balance: number;
186
186
  price: number;
187
187
  symbol: LiteralUnion<'ABT' | 'USD', string>;
188
+ balanceFormatted?: string;
188
189
  }
189
190
  export async function getPaymentDetail(
190
191
  userDid: string,
@@ -134,13 +134,14 @@ router.get('/', authMine, async (req, res) => {
134
134
  const client = method.getOcapClient();
135
135
  const { address } = subscription.payment_details.arcblock.staking;
136
136
  const { state } = await client.getStakeState({ address });
137
- const last =
138
- list[list.length - 1] ||
139
- (await Invoice.findOne({ where: { subscription_id: subscription.id }, order: [['created_at', 'ASC']] }));
140
-
141
- if (state && last) {
137
+ const firstInvoice = await Invoice.findOne({
138
+ where: { subscription_id: subscription.id },
139
+ order: [['created_at', 'ASC']],
140
+ });
141
+ const last = query.o === 'asc' ? list?.[list.length - 1] : list?.[0];
142
+ if (state && firstInvoice) {
142
143
  const data = JSON.parse(state.data?.value || '{}');
143
- const customer = await Customer.findByPk(last.customer_id);
144
+ const customer = await Customer.findByPk(firstInvoice.customer_id);
144
145
  const currency = await PaymentCurrency.findOne({
145
146
  where: { payment_method_id: method.id, is_base_currency: true },
146
147
  });
@@ -178,7 +179,7 @@ router.get('/', authMine, async (req, res) => {
178
179
  amount_due: '0',
179
180
  amount_paid: stakeAmount,
180
181
  amount_remaining: '0',
181
- ...pick(last, [
182
+ ...pick(firstInvoice, [
182
183
  'number',
183
184
  'paid',
184
185
  'auto_advance',
@@ -305,7 +305,7 @@ router.put('/:id', auth, async (req, res) => {
305
305
  pick(
306
306
  req.body,
307
307
  locked
308
- ? ['nickname', 'description', 'metadata', 'currency_options', 'upsell', ...quantityKeys]
308
+ ? ['nickname', 'description', 'metadata', 'currency_options', 'upsell', 'lookup_key', ...quantityKeys]
309
309
  : ['type', 'model', 'active', 'livemode', 'nickname', 'recurring', 'description', 'tiers', 'unit_amount', 'transform_quantity', 'metadata', 'lookup_key', 'currency_options', 'upsell', ...quantityKeys] // prettier-ignore
310
310
  )
311
311
  );
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.15.7
17
+ version: 1.15.9
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.15.7",
3
+ "version": "1.15.9",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -42,7 +42,7 @@
42
42
  ]
43
43
  },
44
44
  "dependencies": {
45
- "@abtnode/cron": "1.16.30",
45
+ "@abtnode/cron": "^1.16.31",
46
46
  "@arcblock/did": "^1.18.135",
47
47
  "@arcblock/did-auth-storage-nedb": "^1.7.1",
48
48
  "@arcblock/did-connect": "^2.10.33",
@@ -50,12 +50,12 @@
50
50
  "@arcblock/jwt": "^1.18.135",
51
51
  "@arcblock/ux": "^2.10.33",
52
52
  "@arcblock/validator": "^1.18.135",
53
- "@blocklet/js-sdk": "1.16.30",
54
- "@blocklet/logger": "1.16.30",
55
- "@blocklet/payment-react": "1.15.7",
56
- "@blocklet/sdk": "1.16.30",
53
+ "@blocklet/js-sdk": "^1.16.31",
54
+ "@blocklet/logger": "^1.16.31",
55
+ "@blocklet/payment-react": "1.15.9",
56
+ "@blocklet/sdk": "^1.16.31",
57
57
  "@blocklet/ui-react": "^2.10.33",
58
- "@blocklet/uploader": "^0.1.35",
58
+ "@blocklet/uploader": "^0.1.36",
59
59
  "@blocklet/xss": "^0.1.7",
60
60
  "@mui/icons-material": "^5.16.6",
61
61
  "@mui/lab": "^5.0.0-alpha.173",
@@ -116,9 +116,9 @@
116
116
  "validator": "^13.12.0"
117
117
  },
118
118
  "devDependencies": {
119
- "@abtnode/types": "1.16.30",
119
+ "@abtnode/types": "^1.16.31",
120
120
  "@arcblock/eslint-config-ts": "^0.3.2",
121
- "@blocklet/payment-types": "1.15.7",
121
+ "@blocklet/payment-types": "1.15.9",
122
122
  "@types/cookie-parser": "^1.4.7",
123
123
  "@types/cors": "^2.8.17",
124
124
  "@types/debug": "^4.1.12",
@@ -160,5 +160,5 @@
160
160
  "parser": "typescript"
161
161
  }
162
162
  },
163
- "gitHead": "9aae61000ca85dc8199f750e3989d756a8747307"
163
+ "gitHead": "d2919fe52ba2b7aee1c6c1275c325f91b81027da"
164
164
  }
@@ -29,7 +29,7 @@ export default function CreateProduct({
29
29
  name: '',
30
30
  description: '',
31
31
  images: [],
32
- statement_descriptor: window.blocklet.appName,
32
+ statement_descriptor: '',
33
33
  unit_label: '',
34
34
  features: [],
35
35
  prices: [{ ...DEFAULT_PRICE, currency_id: settings.baseCurrency.id }],
@@ -47,7 +47,7 @@ export default function CreateProduct({
47
47
 
48
48
  const onCreate = (data: Product) => {
49
49
  setState({ loading: true });
50
- api
50
+ return api
51
51
  .post('/api/products', data)
52
52
  .then(() => {
53
53
  Toast.success(t('admin.product.saved'));
@@ -15,7 +15,7 @@ const { Provider, Consumer } = ProductsContext;
15
15
 
16
16
  const getProducts = async (): Promise<TProductExpanded[]> => {
17
17
  // FIXME: pagination here
18
- const { data } = await api.get('/api/products?active=true&page=1&pageSize=100');
18
+ const { data } = await api.get('/api/products?active=true&page=1&pageSize=100&donation=hide');
19
19
  return data.list || [];
20
20
  };
21
21
 
@@ -116,7 +116,7 @@ export default function CustomerHome() {
116
116
 
117
117
  useEffect(() => {
118
118
  runAsync();
119
- events.once('switch-did', () => {
119
+ events.on('switch-did', () => {
120
120
  runAsync();
121
121
  });
122
122
  }, []);
@@ -30,7 +30,7 @@ export default function CustomerInvoicePastDue() {
30
30
  const { loading, error, data, runAsync } = useRequest(fetchData);
31
31
 
32
32
  useEffect(() => {
33
- events.once('switch-did', () => {
33
+ events.on('switch-did', () => {
34
34
  runAsync().catch(console.error);
35
35
  });
36
36
  }, []);
@@ -281,6 +281,7 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
281
281
  mode="setup"
282
282
  onConfirm={onStripeConfirm}
283
283
  onCancel={onStripeCancel}
284
+ returnUrl={window.location.href.replace(/\/[^/]+$/, '')}
284
285
  />
285
286
  )}
286
287
  </Root>
@@ -60,16 +60,21 @@ export default function SubscriptionEmbed() {
60
60
  const authToken = params.get('authToken') || '';
61
61
  const defaultPageSize = useDefaultPageSize(20);
62
62
  const { data: subscription, error, loading } = useRequest(() => fetchSubscriptionData(subscriptionId, authToken));
63
- const { data } = useRequest(() =>
64
- fetchInvoiceData({
65
- page: 1,
66
- pageSize: defaultPageSize,
67
- status: 'open,paid,uncollectible',
68
- subscription_id: subscriptionId,
69
- authToken,
70
- ignore_zero: true,
71
- include_staking: true,
72
- })
63
+ const { data } = useRequest(
64
+ () =>
65
+ fetchInvoiceData({
66
+ page: 1,
67
+ pageSize: defaultPageSize,
68
+ status: 'open,paid,uncollectible',
69
+ subscription_id: subscriptionId,
70
+ authToken,
71
+ ignore_zero: true,
72
+ include_staking: true,
73
+ customer_id: subscription?.customer_id,
74
+ }),
75
+ {
76
+ refreshDeps: [subscriptionId, authToken, subscription?.customer_id],
77
+ }
73
78
  );
74
79
 
75
80
  const subscriptionPageUrl: string = useMemo(() => {