payment-kit 1.16.3 → 1.16.4
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/libs/util.ts
CHANGED
|
@@ -319,6 +319,26 @@ export async function getOwnerDid() {
|
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
export async function getDidListByRole(role: string | string[]) {
|
|
323
|
+
try {
|
|
324
|
+
if (Array.isArray(role)) {
|
|
325
|
+
const didSet = new Set<string>();
|
|
326
|
+
await Promise.all(
|
|
327
|
+
role.map(async (r: string) => {
|
|
328
|
+
const { users } = await blocklet.getUsers({ query: { role: r } });
|
|
329
|
+
users.forEach((u) => didSet.add(u.did));
|
|
330
|
+
})
|
|
331
|
+
);
|
|
332
|
+
return Array.from(didSet);
|
|
333
|
+
}
|
|
334
|
+
const { users } = await blocklet.getUsers({ query: { role } });
|
|
335
|
+
return users.map((x: any) => x?.did);
|
|
336
|
+
} catch (error) {
|
|
337
|
+
logger.error('getDidListByRole error', error);
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
322
342
|
export function getSubscriptionNotificationCustomActions(
|
|
323
343
|
subscription: Subscription,
|
|
324
344
|
eventType: string,
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
import type { Transaction } from '@ocap/client';
|
|
3
3
|
import { fromAddress } from '@ocap/wallet';
|
|
4
4
|
|
|
5
|
+
import { toBase58 } from '@ocap/util';
|
|
6
|
+
import { encodeTransferItx } from 'api/src/integrations/ethereum/token';
|
|
7
|
+
import { waitForEvmTxConfirm, waitForEvmTxReceipt } from 'api/src/integrations/ethereum/tx';
|
|
5
8
|
import type { CallbackArgs } from '../../libs/auth';
|
|
6
|
-
import { wallet } from '../../libs/auth';
|
|
9
|
+
import { ethWallet, wallet } from '../../libs/auth';
|
|
7
10
|
import { getGasPayerExtra } from '../../libs/payment';
|
|
8
11
|
import { getTxMetadata } from '../../libs/util';
|
|
9
12
|
import { invoiceQueue } from '../../queues/invoice';
|
|
@@ -59,30 +62,30 @@ export default {
|
|
|
59
62
|
return claims;
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
if (paymentMethod.type === 'ethereum') {
|
|
66
|
+
return {
|
|
67
|
+
signature: {
|
|
68
|
+
type: 'eth:transaction',
|
|
69
|
+
data: toBase58(
|
|
70
|
+
Buffer.from(
|
|
71
|
+
JSON.stringify({
|
|
72
|
+
network: paymentMethod.settings?.ethereum?.chain_id,
|
|
73
|
+
tx: encodeTransferItx(ethWallet.address, amount!, paymentCurrency.contract),
|
|
74
|
+
}),
|
|
75
|
+
'utf-8'
|
|
76
|
+
)
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
62
82
|
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
63
83
|
},
|
|
64
84
|
onAuth: async ({ request, userDid, claims, extraParams }: CallbackArgs) => {
|
|
65
85
|
const { subscriptionId, currencyId } = extraParams;
|
|
66
86
|
const { invoices, paymentMethod } = await ensureSubscriptionForCollectBatch(subscriptionId, currencyId);
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
const client = paymentMethod.getOcapClient();
|
|
70
|
-
const claim = claims.find((x) => x.type === 'prepareTx');
|
|
71
|
-
|
|
72
|
-
const tx: Partial<Transaction> = client.decodeTx(claim.finalTx);
|
|
73
|
-
if (claim.delegator && claim.from) {
|
|
74
|
-
tx.delegator = claim.delegator;
|
|
75
|
-
tx.from = claim.from;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
const { buffer } = await client.encodeTransferV3Tx({ tx });
|
|
80
|
-
const txHash = await client.sendTransferV3Tx(
|
|
81
|
-
// @ts-ignore
|
|
82
|
-
{ tx, wallet: fromAddress(userDid) },
|
|
83
|
-
getGasPayerExtra(buffer, client.pickGasPayerHeaders(request))
|
|
84
|
-
);
|
|
85
|
-
|
|
88
|
+
const afterTxExecution = async (paymentDetails: any) => {
|
|
86
89
|
const paymentIntents = await PaymentIntent.findAll({
|
|
87
90
|
where: {
|
|
88
91
|
invoice_id: invoices,
|
|
@@ -95,11 +98,7 @@ export default {
|
|
|
95
98
|
capture_method: 'manual',
|
|
96
99
|
last_payment_error: null,
|
|
97
100
|
payment_details: {
|
|
98
|
-
|
|
99
|
-
tx_hash: txHash,
|
|
100
|
-
payer: userDid,
|
|
101
|
-
type: 'transfer',
|
|
102
|
-
},
|
|
101
|
+
[paymentMethod.type]: paymentDetails,
|
|
103
102
|
},
|
|
104
103
|
});
|
|
105
104
|
|
|
@@ -117,10 +116,52 @@ export default {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (paymentMethod.type === 'arcblock') {
|
|
122
|
+
const client = paymentMethod.getOcapClient();
|
|
123
|
+
const claim = claims.find((x) => x.type === 'prepareTx');
|
|
124
|
+
|
|
125
|
+
const tx: Partial<Transaction> = client.decodeTx(claim.finalTx);
|
|
126
|
+
if (claim.delegator && claim.from) {
|
|
127
|
+
tx.delegator = claim.delegator;
|
|
128
|
+
tx.from = claim.from;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
const { buffer } = await client.encodeTransferV3Tx({ tx });
|
|
133
|
+
const txHash = await client.sendTransferV3Tx(
|
|
134
|
+
// @ts-ignore
|
|
135
|
+
{ tx, wallet: fromAddress(userDid) },
|
|
136
|
+
getGasPayerExtra(buffer, client.pickGasPayerHeaders(request))
|
|
137
|
+
);
|
|
138
|
+
await afterTxExecution({ tx_hash: txHash, payer: userDid, type: 'transfer' });
|
|
120
139
|
|
|
121
140
|
return { hash: txHash };
|
|
122
141
|
}
|
|
142
|
+
if (paymentMethod.type === 'ethereum') {
|
|
143
|
+
const client = paymentMethod.getEvmClient();
|
|
144
|
+
const claim = claims.find((x) => x.type === 'signature');
|
|
123
145
|
|
|
146
|
+
const receipt = await waitForEvmTxReceipt(client, claim.hash);
|
|
147
|
+
if (!receipt.status) {
|
|
148
|
+
throw new Error(`EVM Transaction failed: ${claim.hash}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
waitForEvmTxConfirm(client, Number(receipt.blockNumber), paymentMethod.confirmation.block)
|
|
152
|
+
.then(async () => {
|
|
153
|
+
await afterTxExecution({
|
|
154
|
+
tx_hash: claim.hash,
|
|
155
|
+
block_height: receipt.blockNumber.toString(),
|
|
156
|
+
gas_used: receipt.gasUsed.toString(),
|
|
157
|
+
gas_price: receipt.gasPrice.toString(),
|
|
158
|
+
payer: userDid,
|
|
159
|
+
type: 'transfer',
|
|
160
|
+
});
|
|
161
|
+
})
|
|
162
|
+
.catch(console.error);
|
|
163
|
+
return { hash: claim.hash };
|
|
164
|
+
}
|
|
124
165
|
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
125
166
|
},
|
|
126
167
|
};
|
|
@@ -6,7 +6,8 @@ import isObject from 'lodash/isObject';
|
|
|
6
6
|
import pick from 'lodash/pick';
|
|
7
7
|
import uniq from 'lodash/uniq';
|
|
8
8
|
|
|
9
|
-
import { literal, OrderItem } from 'sequelize';
|
|
9
|
+
import { literal, Op, OrderItem } from 'sequelize';
|
|
10
|
+
import { BN } from '@ocap/util';
|
|
10
11
|
import { createEvent } from '../libs/audit';
|
|
11
12
|
import {
|
|
12
13
|
ensureStripeCustomer,
|
|
@@ -1858,4 +1859,60 @@ router.get('/:id/recharge', authMine, async (req, res) => {
|
|
|
1858
1859
|
return res.status(400).json({ error: err.message });
|
|
1859
1860
|
}
|
|
1860
1861
|
});
|
|
1862
|
+
|
|
1863
|
+
router.get('/:id/overdue/invoices', authPortal, async (req, res) => {
|
|
1864
|
+
try {
|
|
1865
|
+
const subscription = await Subscription.findByPk(req.params.id, {
|
|
1866
|
+
include: [{ model: Customer, as: 'customer' }],
|
|
1867
|
+
});
|
|
1868
|
+
if (!subscription) {
|
|
1869
|
+
return res.status(404).json({ error: 'Subscription not found' });
|
|
1870
|
+
}
|
|
1871
|
+
// @ts-ignore
|
|
1872
|
+
if (subscription.customer?.did !== req.user?.did) {
|
|
1873
|
+
return res.status(403).json({ error: 'You are not allowed to access this subscription' });
|
|
1874
|
+
}
|
|
1875
|
+
const { rows: invoices, count } = await Invoice.findAndCountAll({
|
|
1876
|
+
where: {
|
|
1877
|
+
subscription_id: subscription.id,
|
|
1878
|
+
status: ['uncollectible'],
|
|
1879
|
+
amount_remaining: { [Op.gt]: '0' },
|
|
1880
|
+
},
|
|
1881
|
+
include: [
|
|
1882
|
+
{ model: PaymentCurrency, as: 'paymentCurrency' },
|
|
1883
|
+
{ model: PaymentMethod, as: 'paymentMethod' },
|
|
1884
|
+
],
|
|
1885
|
+
});
|
|
1886
|
+
if (count === 0) {
|
|
1887
|
+
return res.json({ subscription, invoices: [], summary: null });
|
|
1888
|
+
}
|
|
1889
|
+
const summary: Record<string, { amount: string; currency: PaymentCurrency; method: PaymentMethod }> = {};
|
|
1890
|
+
invoices.forEach((invoice) => {
|
|
1891
|
+
const key = invoice.currency_id;
|
|
1892
|
+
if (!summary[key]) {
|
|
1893
|
+
summary[key] = {
|
|
1894
|
+
amount: '0',
|
|
1895
|
+
// @ts-ignore
|
|
1896
|
+
currency: invoice.paymentCurrency,
|
|
1897
|
+
// @ts-ignore
|
|
1898
|
+
method: invoice.paymentMethod,
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
if (invoice && summary[key]) {
|
|
1902
|
+
// @ts-ignore
|
|
1903
|
+
summary[key].amount = new BN(summary[key]?.amount || '0')
|
|
1904
|
+
.add(new BN(invoice.amount_remaining || '0'))
|
|
1905
|
+
.toString();
|
|
1906
|
+
}
|
|
1907
|
+
});
|
|
1908
|
+
return res.json({
|
|
1909
|
+
subscription,
|
|
1910
|
+
summary,
|
|
1911
|
+
invoices,
|
|
1912
|
+
});
|
|
1913
|
+
} catch (err) {
|
|
1914
|
+
console.error(err);
|
|
1915
|
+
return res.status(400).json({ error: err.message });
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1861
1918
|
export default router;
|
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.4",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@arcblock/validator": "^1.18.147",
|
|
54
54
|
"@blocklet/js-sdk": "1.16.33-beta-20241031-073543-49b1ff9b",
|
|
55
55
|
"@blocklet/logger": "1.16.33-beta-20241031-073543-49b1ff9b",
|
|
56
|
-
"@blocklet/payment-react": "1.16.
|
|
56
|
+
"@blocklet/payment-react": "1.16.4",
|
|
57
57
|
"@blocklet/sdk": "1.16.33-beta-20241031-073543-49b1ff9b",
|
|
58
58
|
"@blocklet/ui-react": "^2.10.67",
|
|
59
59
|
"@blocklet/uploader": "^0.1.52",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"devDependencies": {
|
|
121
121
|
"@abtnode/types": "1.16.33-beta-20241031-073543-49b1ff9b",
|
|
122
122
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
123
|
-
"@blocklet/payment-types": "1.16.
|
|
123
|
+
"@blocklet/payment-types": "1.16.4",
|
|
124
124
|
"@types/cookie-parser": "^1.4.7",
|
|
125
125
|
"@types/cors": "^2.8.17",
|
|
126
126
|
"@types/debug": "^4.1.12",
|
|
@@ -166,5 +166,5 @@
|
|
|
166
166
|
"parser": "typescript"
|
|
167
167
|
}
|
|
168
168
|
},
|
|
169
|
-
"gitHead": "
|
|
169
|
+
"gitHead": "d2c53c8bec3a4a34d0ef3a011ec215b69bc9a5ab"
|
|
170
170
|
}
|