@xiashe/sdk 0.1.11 → 0.1.13
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/alipayWallet.mjs +266 -37
- package/index.mjs +2 -1
- package/package.json +1 -1
package/alipayWallet.mjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
2
|
import { execFile } from 'node:child_process';
|
|
3
|
+
import { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
3
6
|
|
|
4
7
|
const DEFAULT_TIMEOUT_MS = 8 * 60 * 1000;
|
|
8
|
+
const RESOURCE_FETCH_TIMEOUT_MS = 20 * 1000;
|
|
5
9
|
const MAX_OUTPUT_BYTES = 32 * 1024;
|
|
6
10
|
const SENSITIVE_OUTPUT = /payment[-_ ]?proof|payment[-_ ]?needed|seller_signature|runtimeToken|authorization\s*:/i;
|
|
11
|
+
const SENSITIVE_USER_OUTPUT = /payment[-_ ]?proof|payment[-_ ]?needed|seller_signature|runtimeToken|authorization\s*:|trade[_ -]?no|交易(?:流水)?号|out[_ -]?shake|client[_ -]?session/i;
|
|
12
|
+
const DEFAULT_STATE_DIR = path.join(os.homedir(), '.xiashe', 'alipay-402');
|
|
7
13
|
|
|
8
14
|
export class AlipayWalletError extends Error {
|
|
9
15
|
constructor(code, message, options = {}) {
|
|
@@ -19,14 +25,14 @@ function safeText(value, maxLength = 240) {
|
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
function digest(value) {
|
|
22
|
-
return createHash('sha256').update(String(value || '')).digest('hex')
|
|
28
|
+
return createHash('sha256').update(String(value || '')).digest('hex');
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
function safeDiagnostic(value) {
|
|
26
32
|
const text = safeText(value, MAX_OUTPUT_BYTES);
|
|
27
33
|
if (!text) return 'no_wallet_output';
|
|
28
|
-
//
|
|
29
|
-
//
|
|
34
|
+
// Vendor output is not a stable public API. Never forward it because a new
|
|
35
|
+
// version could include a protocol proof or another credential.
|
|
30
36
|
return SENSITIVE_OUTPUT.test(text) ? 'protocol_payload_processed' : 'official_wallet_response_received';
|
|
31
37
|
}
|
|
32
38
|
|
|
@@ -51,6 +57,48 @@ function normalizeIntentSummary(value) {
|
|
|
51
57
|
return summary;
|
|
52
58
|
}
|
|
53
59
|
|
|
60
|
+
function stateDirectory(options = {}) {
|
|
61
|
+
return path.resolve(options.stateDir || process.env.XIASHE_ALIPAY_PAYMENT_STATE_DIR || DEFAULT_STATE_DIR);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function statePaths(resourceUrl, options = {}) {
|
|
65
|
+
const base = digest(resourceUrl);
|
|
66
|
+
const directory = stateDirectory(options);
|
|
67
|
+
return {
|
|
68
|
+
directory,
|
|
69
|
+
paymentNeededPath: path.join(directory, `${base}.txt`),
|
|
70
|
+
statePath: path.join(directory, `${base}.json`)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function ensurePrivateDirectory(directory) {
|
|
75
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
76
|
+
// mkdir does not change permissions of an existing directory.
|
|
77
|
+
await chmod(directory, 0o700);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function writePrivateFile(filePath, contents) {
|
|
81
|
+
await writeFile(filePath, contents, { encoding: 'utf8', mode: 0o600 });
|
|
82
|
+
await chmod(filePath, 0o600);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function readPaymentState(resourceUrl, options = {}) {
|
|
86
|
+
const { statePath } = statePaths(resourceUrl, options);
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(await readFile(statePath, 'utf8'));
|
|
89
|
+
return parsed && parsed.version === 1 && parsed.resourceDigest === digest(resourceUrl) ? parsed : null;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (error?.code === 'ENOENT') return null;
|
|
92
|
+
throw new AlipayWalletError('ALIPAY_PAYMENT_STATE_INVALID', '本地支付宝付款状态无法读取;请重新发起本次付款。');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function writePaymentState(state, options = {}) {
|
|
97
|
+
const { directory, statePath } = statePaths(state.resourceUrl, options);
|
|
98
|
+
await ensurePrivateDirectory(directory);
|
|
99
|
+
await writePrivateFile(statePath, `${JSON.stringify(state)}\n`);
|
|
100
|
+
}
|
|
101
|
+
|
|
54
102
|
function defaultRunFile(command, args, options) {
|
|
55
103
|
return new Promise((resolve, reject) => {
|
|
56
104
|
execFile(command, args, {
|
|
@@ -71,8 +119,12 @@ function defaultRunFile(command, args, options) {
|
|
|
71
119
|
}
|
|
72
120
|
|
|
73
121
|
function normalizedRunnerResult(result) {
|
|
74
|
-
if (typeof result === 'string') return { stdout: result, stderr: '' };
|
|
75
|
-
return {
|
|
122
|
+
if (typeof result === 'string') return { stdout: result, stderr: '', exitCode: 0 };
|
|
123
|
+
return {
|
|
124
|
+
stdout: String(result?.stdout || ''),
|
|
125
|
+
stderr: String(result?.stderr || ''),
|
|
126
|
+
exitCode: Number.isInteger(result?.exitCode) ? result.exitCode : 0
|
|
127
|
+
};
|
|
76
128
|
}
|
|
77
129
|
|
|
78
130
|
async function runOfficialCli(args, options = {}) {
|
|
@@ -91,9 +143,19 @@ async function runOfficialCli(args, options = {}) {
|
|
|
91
143
|
throw new AlipayWalletError('ALIPAY_BOT_NOT_INSTALLED', '未找到支付宝官方钱包工具。请先在当前 Agent 环境安装并授权 @alipay/agent-payment。');
|
|
92
144
|
}
|
|
93
145
|
if (error?.killed || error?.signal === 'SIGTERM') {
|
|
94
|
-
throw new AlipayWalletError('ALIPAY_WALLET_TIMEOUT', '
|
|
146
|
+
throw new AlipayWalletError('ALIPAY_WALLET_TIMEOUT', '支付宝钱包等待确认超时;请用同一支付命令的 status 查询状态。');
|
|
95
147
|
}
|
|
96
|
-
|
|
148
|
+
// The official buyer CLI can use a non-zero process exit for a user-action
|
|
149
|
+
// state such as “payment pending”. Preserve this invocation's output for
|
|
150
|
+
// the caller to parse before classifying it as a real command failure.
|
|
151
|
+
if (Number.isInteger(error?.code)) {
|
|
152
|
+
return {
|
|
153
|
+
stdout: String(error.stdout || ''),
|
|
154
|
+
stderr: String(error.stderr || ''),
|
|
155
|
+
exitCode: error.code
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
throw new AlipayWalletError('ALIPAY_WALLET_COMMAND_FAILED', '支付宝官方钱包未完成该操作。');
|
|
97
159
|
}
|
|
98
160
|
}
|
|
99
161
|
|
|
@@ -104,10 +166,101 @@ function walletStateFromOutput(stdout, stderr) {
|
|
|
104
166
|
return enabled ? 'ready' : unavailable ? 'unavailable' : 'unknown';
|
|
105
167
|
}
|
|
106
168
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
169
|
+
function queryCredentialFromOutput(output) {
|
|
170
|
+
const tradeNo = output.match(/(?:"tradeNo"|trade\s*no|交易(?:流水)?号)\s*["::=]\s*["']?([A-Za-z0-9_-]{8,128})/i)?.[1] || null;
|
|
171
|
+
const outShakeNo = output.match(/(?:"outShakeNo"|out[_ -]?shake[_ -]?no|外部(?:摇一摇)?编号)\s*["::=]\s*["']?([A-Za-z0-9_-]{8,128})/i)?.[1] || null;
|
|
172
|
+
return tradeNo ? { type: 'trade_no', value: tradeNo } : outShakeNo ? { type: 'out_shake_no', value: outShakeNo } : null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function paymentStatusFromOutput(stdout, stderr) {
|
|
176
|
+
const output = `${stdout}\n${stderr}`;
|
|
177
|
+
const completed = /支付(?:已)?成功|交易成功|支付已完成|payment\s+(?:was\s+)?(?:successful|completed)|(?:resource|资源).*(?:obtained|success|成功)/i.test(output);
|
|
178
|
+
const pending = /支付待确认|等待.*确认|待确认|支付处理中|pending(?:\s+confirmation)?|waiting.*confirm/i.test(output);
|
|
179
|
+
const failed = /支付失败|交易失败|payment\s+failed/i.test(output);
|
|
180
|
+
return {
|
|
181
|
+
status: completed ? 'completed' : pending ? 'pending_confirmation' : failed ? 'failed' : 'unknown',
|
|
182
|
+
credential: queryCredentialFromOutput(output),
|
|
183
|
+
diagnostic: safeDiagnostic(output)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function userVisibleWalletOutput(stdout, stderr) {
|
|
188
|
+
const lines = `${stdout}\n${stderr}`
|
|
189
|
+
.replace(/\u001B\[[0-?]*[ -/]*[@-~]/g, '')
|
|
190
|
+
.split(/\r?\n/)
|
|
191
|
+
.map((line) => line.trim())
|
|
192
|
+
.filter((line) => line && !SENSITIVE_USER_OUTPUT.test(line))
|
|
193
|
+
.slice(0, 12);
|
|
194
|
+
return lines.length ? lines.join('\n').slice(0, 1_200) : null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function walletFailureCode(stdout, stderr, exitCode) {
|
|
198
|
+
const output = `${stdout}\n${stderr}`;
|
|
199
|
+
if (/余额不足|insufficient\s+balance/i.test(output)) return 'insufficient_balance';
|
|
200
|
+
if (/已过期|过期|expired/i.test(output)) return 'payment_expired';
|
|
201
|
+
if (/钱包.*(?:未开启|未授权)|wallet.*(?:not\s+enabled|not\s+authorized)/i.test(output)) return 'wallet_not_ready';
|
|
202
|
+
if (/买家.*(?:不匹配|校验失败)|buyer.*(?:mismatch|identity)/i.test(output)) return 'buyer_identity_rejected';
|
|
203
|
+
if (/账单.*(?:无效|签名)|签名.*(?:无效|失败)|bill.*(?:invalid|signature)/i.test(output)) return 'payment_needed_rejected';
|
|
204
|
+
if (/network|网络|timeout|超时/i.test(output)) return 'wallet_network_error';
|
|
205
|
+
return Number.isInteger(exitCode) && exitCode !== 0 ? 'official_cli_nonzero_exit' : 'official_cli_unclassified';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function paymentMessage(status) {
|
|
209
|
+
if (status === 'completed') return '支付宝钱包显示本次付款已完成;正在由服务端确认权益。';
|
|
210
|
+
if (status === 'pending_confirmation') return '支付宝已发起本次付款确认;请打开支付宝 App 完成确认,然后运行 status。';
|
|
211
|
+
if (status === 'failed') return '支付宝钱包显示本次付款未完成;未授予付费 Skill 权益。';
|
|
212
|
+
return '支付宝官方钱包已被调用,但尚未返回可确认的付款状态;请运行 status 查询,或重新发起付款。';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function fetchPaymentNeeded(resourceUrl, options = {}) {
|
|
216
|
+
const fetchFn = options.fetch || globalThis.fetch;
|
|
217
|
+
const controller = new AbortController();
|
|
218
|
+
const timeout = setTimeout(() => controller.abort(), options.resourceFetchTimeoutMs || RESOURCE_FETCH_TIMEOUT_MS);
|
|
219
|
+
try {
|
|
220
|
+
const response = await fetchFn(resourceUrl, {
|
|
221
|
+
method: 'GET',
|
|
222
|
+
redirect: 'error',
|
|
223
|
+
headers: { Accept: 'application/json' },
|
|
224
|
+
signal: controller.signal
|
|
225
|
+
});
|
|
226
|
+
if (response.status === 200) return { alreadyPaid: true };
|
|
227
|
+
if (response.status !== 402) {
|
|
228
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_PAYMENT_NEEDED_FAILED', `支付资源未返回付款请求(HTTP ${response.status})。`, { status: response.status });
|
|
229
|
+
}
|
|
230
|
+
const paymentNeeded = response.headers.get('Payment-Needed');
|
|
231
|
+
if (!paymentNeeded) {
|
|
232
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_PAYMENT_NEEDED_MISSING', '支付资源未返回有效的支付宝付款请求。');
|
|
233
|
+
}
|
|
234
|
+
return { paymentNeeded };
|
|
235
|
+
} catch (error) {
|
|
236
|
+
if (error instanceof AlipayWalletError) throw error;
|
|
237
|
+
if (error?.name === 'AbortError') {
|
|
238
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_TIMEOUT', '请求支付宝支付资源超时,请重试。');
|
|
239
|
+
}
|
|
240
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_REQUEST_FAILED', '无法请求支付宝支付资源,请检查网络后重试。');
|
|
241
|
+
} finally {
|
|
242
|
+
clearTimeout(timeout);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function publicPaymentResult(state, status, diagnostic, options = {}) {
|
|
247
|
+
const commandFailed = options.commandFailed === true;
|
|
248
|
+
return {
|
|
249
|
+
ok: status !== 'failed' && status !== 'wallet_command_failed',
|
|
250
|
+
status,
|
|
251
|
+
provider: 'alipay-agent-payment',
|
|
252
|
+
attemptId: `alipay-402:${state.resourceDigest.slice(0, 16)}`,
|
|
253
|
+
walletInvoked: true,
|
|
254
|
+
message: status === 'wallet_command_failed'
|
|
255
|
+
? '支付宝官方钱包没有生成可确认的付款状态;未授予付费 Skill 权益。'
|
|
256
|
+
: paymentMessage(status),
|
|
257
|
+
diagnostic,
|
|
258
|
+
...(options.userVisible ? { userVisible: options.userVisible } : {}),
|
|
259
|
+
...(commandFailed ? { failureCode: options.failureCode || 'official_cli_nonzero_exit' } : {})
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Runs only the official local wallet client and never exposes its raw output. */
|
|
111
264
|
export async function checkAlipayWallet(options = {}) {
|
|
112
265
|
const { stdout, stderr } = await runOfficialCli(['check-wallet'], options);
|
|
113
266
|
const state = walletStateFromOutput(stdout, stderr);
|
|
@@ -120,9 +273,23 @@ export async function checkAlipayWallet(options = {}) {
|
|
|
120
273
|
};
|
|
121
274
|
}
|
|
122
275
|
|
|
276
|
+
/** Checks that the official buyer CLI is present, without querying wallet state. */
|
|
277
|
+
export async function getAlipayWalletBridgeInfo(options = {}) {
|
|
278
|
+
const { stdout, stderr } = await runOfficialCli(['--version'], options);
|
|
279
|
+
return {
|
|
280
|
+
ok: true,
|
|
281
|
+
state: 'available',
|
|
282
|
+
provider: 'alipay-agent-payment',
|
|
283
|
+
message: '支付宝官方付款桥已可用;付款时将由支付宝 App 请求确认。',
|
|
284
|
+
diagnostic: safeDiagnostic(stdout || stderr)
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
123
288
|
/**
|
|
124
|
-
* Starts
|
|
125
|
-
*
|
|
289
|
+
* Starts a buyer-side 402 payment according to the official sequence:
|
|
290
|
+
* request the resource once, preserve its exact Payment-Needed header only in
|
|
291
|
+
* a private local file, then invoke the official buyer CLI with that file and
|
|
292
|
+
* a stable session id. No protocol data leaves this module.
|
|
126
293
|
*/
|
|
127
294
|
export async function payAlipay402Resource(input, options = {}) {
|
|
128
295
|
if (input?.confirm !== true) {
|
|
@@ -130,36 +297,98 @@ export async function payAlipay402Resource(input, options = {}) {
|
|
|
130
297
|
}
|
|
131
298
|
const resourceUrl = normalizeResourceUrl(input?.resourceUrl);
|
|
132
299
|
const intentSummary = normalizeIntentSummary(input?.intentSummary);
|
|
133
|
-
const
|
|
134
|
-
if (
|
|
135
|
-
|
|
300
|
+
const resource = await fetchPaymentNeeded(resourceUrl, options);
|
|
301
|
+
if (resource.alreadyPaid) {
|
|
302
|
+
const state = (await readPaymentState(resourceUrl, options)) || {
|
|
303
|
+
version: 1,
|
|
304
|
+
resourceUrl,
|
|
305
|
+
resourceDigest: digest(resourceUrl),
|
|
306
|
+
sessionId: null,
|
|
307
|
+
paymentNeededPath: null,
|
|
308
|
+
createdAt: new Date().toISOString(),
|
|
309
|
+
updatedAt: new Date().toISOString()
|
|
310
|
+
};
|
|
311
|
+
return publicPaymentResult(state, 'completed', 'resource_already_available');
|
|
136
312
|
}
|
|
137
|
-
|
|
313
|
+
|
|
314
|
+
const paths = statePaths(resourceUrl, options);
|
|
315
|
+
await ensurePrivateDirectory(paths.directory);
|
|
316
|
+
await writePrivateFile(paths.paymentNeededPath, resource.paymentNeeded);
|
|
317
|
+
const state = {
|
|
318
|
+
version: 1,
|
|
319
|
+
resourceUrl,
|
|
320
|
+
resourceDigest: digest(resourceUrl),
|
|
321
|
+
sessionId: randomUUID(),
|
|
322
|
+
paymentNeededPath: paths.paymentNeededPath,
|
|
323
|
+
queryCredential: null,
|
|
324
|
+
status: 'started',
|
|
325
|
+
createdAt: new Date().toISOString(),
|
|
326
|
+
updatedAt: new Date().toISOString()
|
|
327
|
+
};
|
|
328
|
+
await writePaymentState(state, options);
|
|
329
|
+
|
|
330
|
+
const walletInvocation = await runOfficialCli([
|
|
138
331
|
'402-buyer-pay',
|
|
332
|
+
'--session-id', state.sessionId,
|
|
333
|
+
'--file', state.paymentNeededPath,
|
|
139
334
|
'--resource-url', resourceUrl,
|
|
140
335
|
'--intent-summary', intentSummary
|
|
141
336
|
], options);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
};
|
|
337
|
+
const result = paymentStatusFromOutput(walletInvocation.stdout, walletInvocation.stderr);
|
|
338
|
+
const commandFailed = walletInvocation.exitCode !== 0 && result.status === 'unknown';
|
|
339
|
+
const status = commandFailed ? 'wallet_command_failed' : result.status;
|
|
340
|
+
state.status = status;
|
|
341
|
+
state.queryCredential = result.credential;
|
|
342
|
+
state.updatedAt = new Date().toISOString();
|
|
343
|
+
await writePaymentState(state, options);
|
|
344
|
+
if (status === 'completed') await rm(paths.paymentNeededPath, { force: true });
|
|
345
|
+
return publicPaymentResult(state, status, result.diagnostic, {
|
|
346
|
+
commandFailed,
|
|
347
|
+
failureCode: commandFailed ? walletFailureCode(walletInvocation.stdout, walletInvocation.stderr, walletInvocation.exitCode) : undefined,
|
|
348
|
+
userVisible: ['pending_confirmation', 'completed', 'failed'].includes(status)
|
|
349
|
+
? userVisibleWalletOutput(walletInvocation.stdout, walletInvocation.stderr)
|
|
350
|
+
: null
|
|
351
|
+
});
|
|
150
352
|
}
|
|
151
353
|
|
|
354
|
+
/** Queries an existing local payment attempt using the official query credential. */
|
|
152
355
|
export async function queryAlipay402Resource(input, options = {}) {
|
|
153
356
|
const resourceUrl = normalizeResourceUrl(input?.resourceUrl);
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
357
|
+
const state = await readPaymentState(resourceUrl, options);
|
|
358
|
+
if (!state?.queryCredential?.value) {
|
|
359
|
+
return {
|
|
360
|
+
ok: false,
|
|
361
|
+
status: 'no_active_payment',
|
|
362
|
+
provider: 'alipay-agent-payment',
|
|
363
|
+
walletInvoked: false,
|
|
364
|
+
message: '没有可查询的本地支付宝付款记录;请重新发起付款,不要把付款凭证粘贴到对话中。',
|
|
365
|
+
diagnostic: 'payment_state_not_found'
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
const queryArg = state.queryCredential.type === 'out_shake_no'
|
|
369
|
+
? ['--out-shake-no', state.queryCredential.value]
|
|
370
|
+
: ['-t', state.queryCredential.value];
|
|
371
|
+
const walletInvocation = await runOfficialCli([
|
|
372
|
+
'402-query-payment-status',
|
|
373
|
+
...queryArg,
|
|
374
|
+
'--resource-url', resourceUrl
|
|
375
|
+
], options);
|
|
376
|
+
const result = paymentStatusFromOutput(walletInvocation.stdout, walletInvocation.stderr);
|
|
377
|
+
const commandFailed = walletInvocation.exitCode !== 0 && result.status === 'unknown';
|
|
378
|
+
const status = commandFailed ? 'wallet_command_failed' : result.status;
|
|
379
|
+
state.status = status;
|
|
380
|
+
state.queryCredential = result.credential || state.queryCredential;
|
|
381
|
+
state.updatedAt = new Date().toISOString();
|
|
382
|
+
await writePaymentState(state, options);
|
|
383
|
+
if (status === 'completed') {
|
|
384
|
+
const { paymentNeededPath } = statePaths(resourceUrl, options);
|
|
385
|
+
await rm(paymentNeededPath, { force: true });
|
|
386
|
+
}
|
|
387
|
+
return publicPaymentResult(state, status, result.diagnostic, {
|
|
388
|
+
commandFailed,
|
|
389
|
+
failureCode: commandFailed ? walletFailureCode(walletInvocation.stdout, walletInvocation.stderr, walletInvocation.exitCode) : undefined,
|
|
390
|
+
userVisible: ['pending_confirmation', 'completed', 'failed'].includes(status)
|
|
391
|
+
? userVisibleWalletOutput(walletInvocation.stdout, walletInvocation.stderr)
|
|
392
|
+
: null
|
|
393
|
+
});
|
|
165
394
|
}
|
package/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { ConvexHttpClient } from 'convex/browser';
|
|
7
7
|
import { anyApi as api } from 'convex/server';
|
|
8
8
|
|
|
9
|
-
export const VERSION = '0.1.
|
|
9
|
+
export const VERSION = '0.1.13';
|
|
10
10
|
|
|
11
11
|
export const DEFAULTS = {
|
|
12
12
|
cn: {
|
|
@@ -1361,6 +1361,7 @@ export function stableTaskId() {
|
|
|
1361
1361
|
export {
|
|
1362
1362
|
AlipayWalletError,
|
|
1363
1363
|
checkAlipayWallet,
|
|
1364
|
+
getAlipayWalletBridgeInfo,
|
|
1364
1365
|
payAlipay402Resource,
|
|
1365
1366
|
queryAlipay402Resource
|
|
1366
1367
|
} from './alipayWallet.mjs';
|