@xiashe/sdk 0.1.8 → 0.1.10
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 +165 -0
- package/index.mjs +423 -6
- package/package.json +1 -1
package/alipayWallet.mjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 8 * 60 * 1000;
|
|
5
|
+
const MAX_OUTPUT_BYTES = 32 * 1024;
|
|
6
|
+
const SENSITIVE_OUTPUT = /payment[-_ ]?proof|payment[-_ ]?needed|seller_signature|runtimeToken|authorization\s*:/i;
|
|
7
|
+
|
|
8
|
+
export class AlipayWalletError extends Error {
|
|
9
|
+
constructor(code, message, options = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'AlipayWalletError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.status = options.status;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function safeText(value, maxLength = 240) {
|
|
18
|
+
return String(value || '').replace(/\s+/g, ' ').trim().slice(0, maxLength);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function digest(value) {
|
|
22
|
+
return createHash('sha256').update(String(value || '')).digest('hex').slice(0, 16);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function safeDiagnostic(value) {
|
|
26
|
+
const text = safeText(value, MAX_OUTPUT_BYTES);
|
|
27
|
+
if (!text) return 'no_wallet_output';
|
|
28
|
+
// CLI output is not a protocol API: never forward it to an Agent. This
|
|
29
|
+
// protects future vendor versions even when they add fields we do not know.
|
|
30
|
+
return SENSITIVE_OUTPUT.test(text) ? 'protocol_payload_processed' : 'official_wallet_response_received';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeResourceUrl(value) {
|
|
34
|
+
let url;
|
|
35
|
+
try {
|
|
36
|
+
url = new URL(String(value || '').trim());
|
|
37
|
+
} catch {
|
|
38
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_URL_INVALID', '支付资源地址无效。');
|
|
39
|
+
}
|
|
40
|
+
if (url.protocol !== 'https:' || !url.hostname || url.username || url.password) {
|
|
41
|
+
throw new AlipayWalletError('ALIPAY_RESOURCE_URL_UNSAFE', '支付资源必须是没有凭据的 HTTPS 地址。');
|
|
42
|
+
}
|
|
43
|
+
return url.toString();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeIntentSummary(value) {
|
|
47
|
+
const summary = safeText(value, 180);
|
|
48
|
+
if (!summary) {
|
|
49
|
+
throw new AlipayWalletError('ALIPAY_INTENT_SUMMARY_REQUIRED', '必须提供付款用途摘要。');
|
|
50
|
+
}
|
|
51
|
+
return summary;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function defaultRunFile(command, args, options) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
execFile(command, args, {
|
|
57
|
+
timeout: options.timeoutMs,
|
|
58
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
59
|
+
windowsHide: true,
|
|
60
|
+
env: options.env
|
|
61
|
+
}, (error, stdout, stderr) => {
|
|
62
|
+
if (error) {
|
|
63
|
+
error.stdout = stdout;
|
|
64
|
+
error.stderr = stderr;
|
|
65
|
+
reject(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
resolve({ stdout, stderr });
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function normalizedRunnerResult(result) {
|
|
74
|
+
if (typeof result === 'string') return { stdout: result, stderr: '' };
|
|
75
|
+
return { stdout: String(result?.stdout || ''), stderr: String(result?.stderr || '') };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function runOfficialCli(args, options = {}) {
|
|
79
|
+
const command = safeText(options.command || process.env.XIASHE_ALIPAY_BOT_COMMAND || 'alipay-bot', 200);
|
|
80
|
+
if (!command || /\s/.test(command)) {
|
|
81
|
+
throw new AlipayWalletError('ALIPAY_BOT_COMMAND_INVALID', '支付宝钱包命令配置无效。');
|
|
82
|
+
}
|
|
83
|
+
const runner = options.runFile || defaultRunFile;
|
|
84
|
+
try {
|
|
85
|
+
return normalizedRunnerResult(await runner(command, args, {
|
|
86
|
+
timeoutMs: options.timeoutMs || DEFAULT_TIMEOUT_MS,
|
|
87
|
+
env: options.env || process.env
|
|
88
|
+
}));
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error?.code === 'ENOENT') {
|
|
91
|
+
throw new AlipayWalletError('ALIPAY_BOT_NOT_INSTALLED', '未找到支付宝官方钱包工具。请先在当前 Agent 环境安装并授权 @alipay/agent-payment。');
|
|
92
|
+
}
|
|
93
|
+
if (error?.killed || error?.signal === 'SIGTERM') {
|
|
94
|
+
throw new AlipayWalletError('ALIPAY_WALLET_TIMEOUT', '支付宝钱包操作超时;没有确认付款。');
|
|
95
|
+
}
|
|
96
|
+
throw new AlipayWalletError('ALIPAY_WALLET_COMMAND_FAILED', '支付宝钱包未完成该操作。');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function walletStateFromOutput(stdout, stderr) {
|
|
101
|
+
const output = `${stdout}\n${stderr}`;
|
|
102
|
+
const enabled = /"code"\s*:\s*200|已开启支付宝支付功能|wallet.*(?:ready|enabled|active)/i.test(output);
|
|
103
|
+
const unavailable = /未开启|not.*(?:enabled|authorized)|not.*found|未安装/i.test(output);
|
|
104
|
+
return enabled ? 'ready' : unavailable ? 'unavailable' : 'unknown';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Runs only the official local wallet client. It never returns Payment-Needed,
|
|
109
|
+
* Payment-Proof, or raw wallet output to an Agent caller.
|
|
110
|
+
*/
|
|
111
|
+
export async function checkAlipayWallet(options = {}) {
|
|
112
|
+
const { stdout, stderr } = await runOfficialCli(['check-wallet'], options);
|
|
113
|
+
const state = walletStateFromOutput(stdout, stderr);
|
|
114
|
+
return {
|
|
115
|
+
ok: state === 'ready',
|
|
116
|
+
state,
|
|
117
|
+
provider: 'alipay-agent-payment',
|
|
118
|
+
message: state === 'ready' ? '支付宝钱包已开启。' : '支付宝钱包尚未就绪。',
|
|
119
|
+
diagnostic: safeDiagnostic(stdout || stderr)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Starts one explicit buyer-side 402 payment. The official CLI owns the
|
|
125
|
+
* protocol payload and App confirmation; callers only receive a safe result.
|
|
126
|
+
*/
|
|
127
|
+
export async function payAlipay402Resource(input, options = {}) {
|
|
128
|
+
if (input?.confirm !== true) {
|
|
129
|
+
throw new AlipayWalletError('ALIPAY_CONFIRMATION_REQUIRED', '付款操作必须由用户明确确认。请在展示付款用途后使用 --confirm。');
|
|
130
|
+
}
|
|
131
|
+
const resourceUrl = normalizeResourceUrl(input?.resourceUrl);
|
|
132
|
+
const intentSummary = normalizeIntentSummary(input?.intentSummary);
|
|
133
|
+
const wallet = await checkAlipayWallet(options);
|
|
134
|
+
if (!wallet.ok) {
|
|
135
|
+
throw new AlipayWalletError('ALIPAY_WALLET_NOT_READY', '支付宝钱包未开启;请先完成钱包授权。');
|
|
136
|
+
}
|
|
137
|
+
const { stdout, stderr } = await runOfficialCli([
|
|
138
|
+
'402-buyer-pay',
|
|
139
|
+
'--resource-url', resourceUrl,
|
|
140
|
+
'--intent-summary', intentSummary
|
|
141
|
+
], options);
|
|
142
|
+
return {
|
|
143
|
+
ok: true,
|
|
144
|
+
status: 'submitted',
|
|
145
|
+
provider: 'alipay-agent-payment',
|
|
146
|
+
attemptId: `alipay-402:${digest(`${resourceUrl}\n${intentSummary}`)}`,
|
|
147
|
+
message: '已交给支付宝钱包处理;请在支付宝 App 中确认本次付款。',
|
|
148
|
+
diagnostic: safeDiagnostic(stdout || stderr)
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function queryAlipay402Resource(input, options = {}) {
|
|
153
|
+
const resourceUrl = normalizeResourceUrl(input?.resourceUrl);
|
|
154
|
+
const { stdout, stderr } = await runOfficialCli(['402-query-payment-status', '--resource-url', resourceUrl], options);
|
|
155
|
+
const output = `${stdout}\n${stderr}`;
|
|
156
|
+
const complete = /success|成功|paid|已支付|completed|完成/i.test(output) && !/pending|等待|处理中/i.test(output);
|
|
157
|
+
const pending = /pending|等待|处理中|confirm/i.test(output);
|
|
158
|
+
return {
|
|
159
|
+
ok: true,
|
|
160
|
+
status: complete ? 'completed' : pending ? 'pending_confirmation' : 'unknown',
|
|
161
|
+
provider: 'alipay-agent-payment',
|
|
162
|
+
message: complete ? '支付宝钱包显示付款已完成。' : pending ? '等待用户在支付宝 App 中确认。' : '支付宝钱包尚未返回可确认的付款状态。',
|
|
163
|
+
diagnostic: safeDiagnostic(stdout || stderr)
|
|
164
|
+
};
|
|
165
|
+
}
|
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.10';
|
|
10
10
|
|
|
11
11
|
export const DEFAULTS = {
|
|
12
12
|
cn: {
|
|
@@ -22,9 +22,9 @@ export const DEFAULTS = {
|
|
|
22
22
|
market: 'intl',
|
|
23
23
|
locale: 'en',
|
|
24
24
|
convexUrl: 'https://adept-porcupine-970.convex.cloud',
|
|
25
|
-
actionsUrl: 'https://
|
|
26
|
-
mcpUrl: 'https://
|
|
27
|
-
agentClaimUrl: 'https://
|
|
25
|
+
actionsUrl: 'https://agentpie.app',
|
|
26
|
+
mcpUrl: 'https://agentpie.app/mcp/xiashe',
|
|
27
|
+
agentClaimUrl: 'https://agentpie.app/agent-gateway/claim',
|
|
28
28
|
relayUrl: 'https://relay.agentpie.app'
|
|
29
29
|
}
|
|
30
30
|
};
|
|
@@ -515,8 +515,36 @@ export class XiasheClient {
|
|
|
515
515
|
return this.query(api.skillInstallJobs.listForConnection, this.authArgs({ connectionId, limit }));
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
async createSkillSubmissionDraft(draft = {}) {
|
|
519
|
-
|
|
518
|
+
async createSkillSubmissionDraft(draft = {}, options = {}) {
|
|
519
|
+
const registryPublicToken = options.registryPublicToken || draft.registryPublicToken || draft._registryPublicToken;
|
|
520
|
+
const cleanDraft = { ...draft };
|
|
521
|
+
delete cleanDraft.registryPublicToken;
|
|
522
|
+
delete cleanDraft._registryPublicToken;
|
|
523
|
+
try {
|
|
524
|
+
return await this.mutation(api.skillsCatalog.createSkillSubmissionDraft, this.authArgs({ draft: cleanDraft }));
|
|
525
|
+
} catch (error) {
|
|
526
|
+
if (error?.code !== 'AUTH_REQUIRED' || !registryPublicToken || (!cleanDraft.registryEntryId && !cleanDraft.registryPublicSkillId)) {
|
|
527
|
+
throw error;
|
|
528
|
+
}
|
|
529
|
+
return await this.createSkillSubmissionDraftFromRegistry({
|
|
530
|
+
registryEntryId: cleanDraft.registryEntryId,
|
|
531
|
+
registryPublicSkillId: cleanDraft.registryPublicSkillId,
|
|
532
|
+
publicToken: registryPublicToken,
|
|
533
|
+
draft: cleanDraft
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
async createSkillSubmissionDraftFromRegistry(options = {}) {
|
|
539
|
+
const draft = { ...(options.draft || {}) };
|
|
540
|
+
delete draft.registryPublicToken;
|
|
541
|
+
delete draft._registryPublicToken;
|
|
542
|
+
return this.mutation(api.skillsCatalog.createSkillSubmissionDraftFromRegistry, {
|
|
543
|
+
registryEntryId: options.registryEntryId || draft.registryEntryId || undefined,
|
|
544
|
+
registryPublicSkillId: options.registryPublicSkillId || draft.registryPublicSkillId || undefined,
|
|
545
|
+
publicToken: options.publicToken || options.registryPublicToken,
|
|
546
|
+
draft
|
|
547
|
+
});
|
|
520
548
|
}
|
|
521
549
|
|
|
522
550
|
async updateSkillSubmissionDraft(submissionId, patch = {}) {
|
|
@@ -593,6 +621,388 @@ export class XiasheClient {
|
|
|
593
621
|
);
|
|
594
622
|
}
|
|
595
623
|
|
|
624
|
+
async submitAgentRuntimeListing(options = {}) {
|
|
625
|
+
return this.action(
|
|
626
|
+
api.agentRuntimeMarketplace.submitListing,
|
|
627
|
+
this.authArgs({
|
|
628
|
+
agentCardUrl: options.agentCardUrl,
|
|
629
|
+
registryEntryId: options.registryEntryId || undefined,
|
|
630
|
+
skillCatalogId: options.skillCatalogId || undefined,
|
|
631
|
+
pricingModel: options.pricingModel || undefined,
|
|
632
|
+
priceCredits: options.priceCredits ?? undefined,
|
|
633
|
+
category: options.category || undefined,
|
|
634
|
+
tags: options.tags || undefined,
|
|
635
|
+
reviewState: options.reviewState || undefined,
|
|
636
|
+
listingState: options.listingState || undefined
|
|
637
|
+
})
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
async listAgentRuntimeListings(options = {}) {
|
|
642
|
+
return this.query(
|
|
643
|
+
api.agentRuntimeMarketplace.listListings,
|
|
644
|
+
this.authArgs({
|
|
645
|
+
includeHidden: Boolean(options.includeHidden),
|
|
646
|
+
limit: options.limit || 30
|
|
647
|
+
})
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
async grantAgentRuntimeEntitlement(listingId, options = {}) {
|
|
652
|
+
return this.mutation(
|
|
653
|
+
api.agentRuntimeMarketplace.grantEntitlement,
|
|
654
|
+
this.authArgs({
|
|
655
|
+
listingId,
|
|
656
|
+
source: options.source || undefined,
|
|
657
|
+
expiresAt: options.expiresAt || undefined,
|
|
658
|
+
idempotencyKey: options.idempotencyKey || undefined
|
|
659
|
+
})
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
async adminReviewAgentRuntimeListing(listingId, options = {}) {
|
|
664
|
+
return this.mutation(
|
|
665
|
+
api.agentRuntimeMarketplace.adminReviewListing,
|
|
666
|
+
this.authArgs({
|
|
667
|
+
listingId,
|
|
668
|
+
reviewState: options.reviewState || 'approved',
|
|
669
|
+
listingState: options.listingState || undefined,
|
|
670
|
+
safetyState: options.safetyState || undefined,
|
|
671
|
+
reviewNotes: options.reviewNotes || undefined
|
|
672
|
+
})
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
async invokeAgentRuntimeListing(options = {}) {
|
|
677
|
+
return this.action(
|
|
678
|
+
api.agentRuntimeMarketplace.invokeListing,
|
|
679
|
+
this.authArgs({
|
|
680
|
+
listingId: options.listingId,
|
|
681
|
+
chatId: options.chatId || undefined,
|
|
682
|
+
content: options.content,
|
|
683
|
+
callbackUrl: options.callbackUrl || undefined,
|
|
684
|
+
idempotencyKey: options.idempotencyKey || undefined
|
|
685
|
+
})
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
async getRuntimePurchasePreview(listingId, options = {}) {
|
|
690
|
+
return this.query(
|
|
691
|
+
api.marketplaceBilling.getRuntimePurchasePreview,
|
|
692
|
+
this.authArgs({
|
|
693
|
+
listingId,
|
|
694
|
+
promptBytes: options.promptBytes ?? undefined,
|
|
695
|
+
fileBytes: options.fileBytes ?? undefined
|
|
696
|
+
})
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
async setRuntimeBudgetSettings(options = {}) {
|
|
701
|
+
return this.mutation(
|
|
702
|
+
api.marketplaceBilling.setRuntimeBudgetSettings,
|
|
703
|
+
this.authArgs({
|
|
704
|
+
listingId: options.listingId || undefined,
|
|
705
|
+
singleRunMaxCredits: options.singleRunMaxCredits ?? 0,
|
|
706
|
+
dailyMaxCredits: options.dailyMaxCredits ?? 0,
|
|
707
|
+
allowAutoRetry: Boolean(options.allowAutoRetry)
|
|
708
|
+
})
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
async generateCreatorAlipayAppKeys(options = {}) {
|
|
713
|
+
return this.action(
|
|
714
|
+
api.marketplaceBilling.generateCreatorAlipayAppKeys,
|
|
715
|
+
this.authArgs({
|
|
716
|
+
alipayAppId: options.alipayAppId,
|
|
717
|
+
merchantName: options.merchantName || undefined,
|
|
718
|
+
merchantAccount: options.merchantAccount || options.sellerId || undefined,
|
|
719
|
+
serviceId: options.serviceId || undefined,
|
|
720
|
+
alipayPublicKeyPem: options.alipayPublicKeyPem || undefined
|
|
721
|
+
})
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
async saveCreatorAlipayCollectConfig(options = {}) {
|
|
726
|
+
return this.generateCreatorAlipayAppKeys(options);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
async listCreatorAlipayApps(options = {}) {
|
|
730
|
+
return this.query(
|
|
731
|
+
api.marketplaceBilling.listCreatorAlipayApps,
|
|
732
|
+
this.authArgs({ limit: options.limit || 20 })
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
async verifyCreatorAlipayAppConfig(creatorAlipayAppId, options = {}) {
|
|
737
|
+
return this.mutation(
|
|
738
|
+
api.marketplaceBilling.verifyCreatorAlipayAppConfig,
|
|
739
|
+
this.authArgs({
|
|
740
|
+
creatorAlipayAppId,
|
|
741
|
+
uploadedToAlipay: options.uploadedToAlipay !== false
|
|
742
|
+
})
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
async createSkillPlan(options = {}) {
|
|
747
|
+
return this.mutation(
|
|
748
|
+
api.marketplaceBilling.createSkillPlan,
|
|
749
|
+
this.authArgs({
|
|
750
|
+
skillCatalogId: options.skillCatalogId,
|
|
751
|
+
name: options.name,
|
|
752
|
+
planType: 'one_time',
|
|
753
|
+
monetizationMode: options.monetizationMode || undefined,
|
|
754
|
+
priceCredits: options.priceCredits ?? 0,
|
|
755
|
+
priceCents: options.priceCents ?? undefined,
|
|
756
|
+
currency: options.currency || undefined,
|
|
757
|
+
creatorAlipayAppId: options.creatorAlipayAppId || undefined,
|
|
758
|
+
benefits: options.benefits || undefined,
|
|
759
|
+
status: options.status || undefined
|
|
760
|
+
})
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
async setSkillPrice(skillCatalogId, options = {}) {
|
|
765
|
+
const amount = options.priceAmount ?? options.priceYuan ?? options.price;
|
|
766
|
+
const priceCents = options.priceCents ?? (
|
|
767
|
+
amount === undefined || amount === null || amount === ''
|
|
768
|
+
? 0
|
|
769
|
+
: Math.round(Number(amount) * 100)
|
|
770
|
+
);
|
|
771
|
+
return this.mutation(
|
|
772
|
+
api.marketplaceBilling.setSkillPricing,
|
|
773
|
+
this.authArgs({
|
|
774
|
+
skillCatalogId,
|
|
775
|
+
priceCents,
|
|
776
|
+
currency: options.currency || (options.payableChannel === 'stripe' ? 'USD' : 'CNY'),
|
|
777
|
+
payableChannel: options.payableChannel || 'alipay_ai_collect',
|
|
778
|
+
creatorAlipayAppId: options.creatorAlipayAppId || undefined,
|
|
779
|
+
status: options.status || 'active'
|
|
780
|
+
})
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
async setPaidSkillPrice(skillCatalogId, options = {}) {
|
|
785
|
+
return this.setSkillPrice(skillCatalogId, options);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
async listSkillPlans(skillCatalogId, options = {}) {
|
|
789
|
+
return this.query(
|
|
790
|
+
api.marketplaceBilling.listSkillPlans,
|
|
791
|
+
this.authArgs({
|
|
792
|
+
skillCatalogId,
|
|
793
|
+
includeInactive: Boolean(options.includeInactive)
|
|
794
|
+
})
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
async createPaymentIntent(options = {}) {
|
|
799
|
+
return this.mutation(
|
|
800
|
+
api.marketplaceBilling.createPaymentIntent,
|
|
801
|
+
this.authArgs({
|
|
802
|
+
orderType: options.orderType,
|
|
803
|
+
payableChannel: options.payableChannel,
|
|
804
|
+
sourceSurface: options.sourceSurface || 'web_dashboard',
|
|
805
|
+
amountCents: options.amountCents ?? undefined,
|
|
806
|
+
currency: options.currency || undefined,
|
|
807
|
+
credits: options.credits ?? undefined,
|
|
808
|
+
runtimeListingId: options.runtimeListingId || undefined,
|
|
809
|
+
skillCatalogId: options.skillCatalogId || undefined,
|
|
810
|
+
skillPlanId: options.skillPlanId || undefined,
|
|
811
|
+
creatorAlipayAppId: options.creatorAlipayAppId || undefined,
|
|
812
|
+
description: options.description || undefined,
|
|
813
|
+
idempotencyKey: options.idempotencyKey || createIdempotencyKey('payment-intent', [
|
|
814
|
+
options.orderType,
|
|
815
|
+
options.runtimeListingId,
|
|
816
|
+
options.skillCatalogId,
|
|
817
|
+
options.skillPlanId,
|
|
818
|
+
options.creatorAlipayAppId,
|
|
819
|
+
options.credits,
|
|
820
|
+
options.amountCents
|
|
821
|
+
])
|
|
822
|
+
})
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
async createAlipayAiCollectSkillCheckout(options = {}) {
|
|
827
|
+
return this.action(
|
|
828
|
+
api.marketplaceBilling.createAlipayAiCollectSkillCheckout,
|
|
829
|
+
this.authArgs({
|
|
830
|
+
skillCatalogId: options.skillCatalogId,
|
|
831
|
+
skillPlanId: options.skillPlanId,
|
|
832
|
+
amountCents: options.amountCents,
|
|
833
|
+
currency: options.currency || 'CNY',
|
|
834
|
+
description: options.description || undefined,
|
|
835
|
+
sourceSurface: options.sourceSurface || 'web_dashboard',
|
|
836
|
+
idempotencyKey: options.idempotencyKey || createIdempotencyKey('alipay-ai-collect-skill', [
|
|
837
|
+
options.skillCatalogId,
|
|
838
|
+
options.skillPlanId,
|
|
839
|
+
options.amountCents
|
|
840
|
+
])
|
|
841
|
+
})
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
alipayAiCollectPaymentResourceUrl(orderIdOrUrl, options = {}) {
|
|
846
|
+
const value = String(orderIdOrUrl || options.orderId || options.paymentResourceUrl || '').trim();
|
|
847
|
+
if (!value) {
|
|
848
|
+
throw new XiasheError('Missing Alipay AI Collect order id or payment resource URL.', {
|
|
849
|
+
code: 'ALIPAY_AI_COLLECT_RESOURCE_REQUIRED'
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
if (/^https?:\/\//i.test(value)) {
|
|
853
|
+
return value;
|
|
854
|
+
}
|
|
855
|
+
const actionsUrl = normalizeBaseUrl(options.actionsUrl || this.profile.actionsUrl);
|
|
856
|
+
if (!actionsUrl) {
|
|
857
|
+
throw new XiasheError('Missing actions URL for Alipay AI Collect payment resource.', {
|
|
858
|
+
code: 'ACTIONS_URL_REQUIRED'
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
return `${actionsUrl}/payment/alipay-ai-collect?orderId=${encodeURIComponent(value)}`;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
async getAlipayAiCollectPaymentNeeded(orderIdOrUrl, options = {}) {
|
|
865
|
+
const url = this.alipayAiCollectPaymentResourceUrl(orderIdOrUrl, options);
|
|
866
|
+
const response = await withTimeout(
|
|
867
|
+
(signal) =>
|
|
868
|
+
fetch(url, {
|
|
869
|
+
method: 'GET',
|
|
870
|
+
headers: {
|
|
871
|
+
accept: 'application/json',
|
|
872
|
+
...(options.headers || {})
|
|
873
|
+
},
|
|
874
|
+
signal
|
|
875
|
+
}),
|
|
876
|
+
options.timeoutMs || this.timeoutMs
|
|
877
|
+
);
|
|
878
|
+
const text = await response.text();
|
|
879
|
+
let payload = {};
|
|
880
|
+
try {
|
|
881
|
+
payload = text ? JSON.parse(text) : {};
|
|
882
|
+
} catch {
|
|
883
|
+
payload = { text };
|
|
884
|
+
}
|
|
885
|
+
if (response.status !== 402 && !response.ok) {
|
|
886
|
+
throw new XiasheError(payload.error || payload.message || `HTTP ${response.status}`, {
|
|
887
|
+
code: payload.error || `HTTP_${response.status}`,
|
|
888
|
+
status: response.status,
|
|
889
|
+
details: payload
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
return {
|
|
893
|
+
status: response.status,
|
|
894
|
+
ok: response.ok,
|
|
895
|
+
paymentResourceUrl: url,
|
|
896
|
+
paymentNeededHeader: response.headers.get('Payment-Needed') || response.headers.get('payment-needed') || null,
|
|
897
|
+
payload
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
async completeAlipayAiCollectPayment(orderIdOrUrl, paymentProofHeader, options = {}) {
|
|
902
|
+
const paymentProof = String(paymentProofHeader || options.paymentProof || '').trim();
|
|
903
|
+
if (!paymentProof) {
|
|
904
|
+
throw new XiasheError('Missing Payment-Proof header.', { code: 'PAYMENT_PROOF_REQUIRED' });
|
|
905
|
+
}
|
|
906
|
+
const url = this.alipayAiCollectPaymentResourceUrl(orderIdOrUrl, options);
|
|
907
|
+
const response = await withTimeout(
|
|
908
|
+
(signal) =>
|
|
909
|
+
fetch(url, {
|
|
910
|
+
method: 'GET',
|
|
911
|
+
headers: {
|
|
912
|
+
accept: 'application/json',
|
|
913
|
+
'Payment-Proof': paymentProof,
|
|
914
|
+
...(options.headers || {})
|
|
915
|
+
},
|
|
916
|
+
signal
|
|
917
|
+
}),
|
|
918
|
+
options.timeoutMs || this.timeoutMs
|
|
919
|
+
);
|
|
920
|
+
const text = await response.text();
|
|
921
|
+
let payload = {};
|
|
922
|
+
try {
|
|
923
|
+
payload = text ? JSON.parse(text) : {};
|
|
924
|
+
} catch {
|
|
925
|
+
payload = { text };
|
|
926
|
+
}
|
|
927
|
+
if (!response.ok) {
|
|
928
|
+
throw new XiasheError(payload.error || payload.message || `HTTP ${response.status}`, {
|
|
929
|
+
code: payload.error || `HTTP_${response.status}`,
|
|
930
|
+
status: response.status,
|
|
931
|
+
details: payload
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
return {
|
|
935
|
+
status: response.status,
|
|
936
|
+
paymentResourceUrl: url,
|
|
937
|
+
paymentValidationHeader: response.headers.get('Payment-Validation') || response.headers.get('payment-validation') || null,
|
|
938
|
+
payload
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
async requestOrderRefund(orderId, options = {}) {
|
|
943
|
+
return this.mutation(
|
|
944
|
+
api.marketplaceBilling.requestOrderRefund,
|
|
945
|
+
this.authArgs({
|
|
946
|
+
orderId,
|
|
947
|
+
reason: options.reason || undefined
|
|
948
|
+
})
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
async openOrderDispute(orderId, reason) {
|
|
953
|
+
return this.mutation(
|
|
954
|
+
api.marketplaceBilling.openOrderDispute,
|
|
955
|
+
this.authArgs({ orderId, reason })
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
async adminCompleteOrderRefund(orderId, options = {}) {
|
|
960
|
+
return this.mutation(
|
|
961
|
+
api.marketplaceBilling.completeOrderRefundForAdmin,
|
|
962
|
+
this.authArgs({
|
|
963
|
+
orderId,
|
|
964
|
+
providerRefundNo: options.providerRefundNo || undefined,
|
|
965
|
+
reason: options.reason || undefined
|
|
966
|
+
})
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
async listMyOrders(options = {}) {
|
|
971
|
+
return this.query(
|
|
972
|
+
api.marketplaceBilling.listMyOrders,
|
|
973
|
+
this.authArgs({ limit: options.limit || 30 })
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
async listCreatorEarnings(options = {}) {
|
|
978
|
+
return this.query(
|
|
979
|
+
api.marketplaceBilling.listCreatorEarnings,
|
|
980
|
+
this.authArgs({
|
|
981
|
+
payoutState: options.payoutState || undefined,
|
|
982
|
+
limit: options.limit || 50
|
|
983
|
+
})
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
async adminRecordPaymentReconciliation(options = {}) {
|
|
988
|
+
return this.mutation(
|
|
989
|
+
api.marketplaceBilling.recordPaymentReconciliation,
|
|
990
|
+
this.authArgs({
|
|
991
|
+
provider: options.provider,
|
|
992
|
+
providerOrderId: options.providerOrderId,
|
|
993
|
+
orderId: options.orderId,
|
|
994
|
+
status: options.status || 'paid',
|
|
995
|
+
amountCents: options.amountCents ?? 0,
|
|
996
|
+
idempotencyKey: options.idempotencyKey || createIdempotencyKey('payment-reconcile', [
|
|
997
|
+
options.provider,
|
|
998
|
+
options.providerOrderId,
|
|
999
|
+
options.orderId,
|
|
1000
|
+
options.status
|
|
1001
|
+
])
|
|
1002
|
+
})
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
596
1006
|
async listChats() {
|
|
597
1007
|
return this.query(api.chats.listForUserSidebar, this.authArgs());
|
|
598
1008
|
}
|
|
@@ -947,3 +1357,10 @@ export function printableAgentPrompt(issue) {
|
|
|
947
1357
|
export function stableTaskId() {
|
|
948
1358
|
return `xiashe-cli-${randomUUID()}`;
|
|
949
1359
|
}
|
|
1360
|
+
|
|
1361
|
+
export {
|
|
1362
|
+
AlipayWalletError,
|
|
1363
|
+
checkAlipayWallet,
|
|
1364
|
+
payAlipay402Resource,
|
|
1365
|
+
queryAlipay402Resource
|
|
1366
|
+
} from './alipayWallet.mjs';
|