@trustbaseai/protocol 0.1.0

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.
Files changed (42) hide show
  1. package/README.md +348 -0
  2. package/dist/bundle-hash.d.ts +54 -0
  3. package/dist/bundle-hash.d.ts.map +1 -0
  4. package/dist/bundle-hash.js +105 -0
  5. package/dist/bundle-hash.js.map +1 -0
  6. package/dist/canonical.d.ts +65 -0
  7. package/dist/canonical.d.ts.map +1 -0
  8. package/dist/canonical.js +215 -0
  9. package/dist/canonical.js.map +1 -0
  10. package/dist/constants.d.ts +200 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/constants.js +216 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/endpoint-protocol.d.ts +143 -0
  15. package/dist/endpoint-protocol.d.ts.map +1 -0
  16. package/dist/endpoint-protocol.js +236 -0
  17. package/dist/endpoint-protocol.js.map +1 -0
  18. package/dist/errors.d.ts +13 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +21 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/index.d.ts +24 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +121 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/registry.d.ts +116 -0
  27. package/dist/registry.d.ts.map +1 -0
  28. package/dist/registry.js +637 -0
  29. package/dist/registry.js.map +1 -0
  30. package/dist/sp-framework.d.ts +686 -0
  31. package/dist/sp-framework.d.ts.map +1 -0
  32. package/dist/sp-framework.js +187 -0
  33. package/dist/sp-framework.js.map +1 -0
  34. package/dist/validation.d.ts +37 -0
  35. package/dist/validation.d.ts.map +1 -0
  36. package/dist/validation.js +85 -0
  37. package/dist/validation.js.map +1 -0
  38. package/dist/ws-protocol.d.ts +242 -0
  39. package/dist/ws-protocol.d.ts.map +1 -0
  40. package/dist/ws-protocol.js +289 -0
  41. package/dist/ws-protocol.js.map +1 -0
  42. package/package.json +34 -0
@@ -0,0 +1,686 @@
1
+ /**
2
+ * sp-framework.ts —— TrustBase 服务商抽象层 (Service Provider Framework)
3
+ *
4
+ * ## 这是什么
5
+ *
6
+ * TrustBase 的服务商 (SP) 是商户与主链/支付通道之间的网关角色:帮商户进件
7
+ * (微信支付特约商户)、接收并验证支付回调、把支付事实上链、按登记比例抽佣分账、
8
+ * 支持商户自由迁出迁入。服务商行业形态多样(附近商圈/国内电商/垂直私域/网课/
9
+ * 订阅/技术服务),本文件把它们收敛成**一组必须实现的接口 + 每行业一个扩展点**。
10
+ *
11
+ * **成为 TrustBase 服务商 = 实现本文件里的 `ServiceProviderGateway`。**
12
+ *
13
+ * ## 本文件的纪律(与 @trustbase/protocol 全包一致)
14
+ *
15
+ * - **纯类型 + 接口 + 常量**:零实现、零依赖、零副作用,Node/浏览器通用。
16
+ * - 私钥、签名、网络、存储都不在这里(实现参考 trustbase-seller-backend)。
17
+ *
18
+ * ## 三层映射(每个接口方法都用 JSDoc 标注)
19
+ *
20
+ * | 层 | 含义 | 出处 |
21
+ * |---|---|---|
22
+ * | `@chain` | 链上对应 Msg / Query | trustchain-relmerge `proto/trustchain/serviceprovider/v1/*.proto` |
23
+ * | `@backend` | 后端对应路由/实现文件 | trustbase-seller-backend `routes/sp-*.js`、`payments/wechat/profitsharing.js` |
24
+ * | `@wechat` | 微信对应 APIv3 接口 | pay.weixin.qq.com 服务商/特约商户文档 |
25
+ *
26
+ * ## 设计依据(口径冲突以这些文档为准)
27
+ *
28
+ * - 《商户经济模型最终方案-2026-09-24》§六 迁移协议、§七之二 抽佣(30% 硬顶)
29
+ * - 《支付服务商子链实现规划-2026-09-21》(x/serviceprovider 模块落地口径)
30
+ * - 《行业扩展图景与国内合规红线-2026-09-23》(六行业判定 + 合规红线)
31
+ *
32
+ * ## 红线(实现者不可违反)
33
+ *
34
+ * 1. 商户私钥永不出商户设备;服务商只持有自己的 SP 签名 key。
35
+ * 2. 进件敏感资料本地加密留存,链上零 PII(只上 evidence_hash)。
36
+ * 3. 商户迁移不可阻拦:迁出导出是义务,不是功能选项。
37
+ * 4. 抽佣比例 ≤ 30% 硬顶(`SP_COMMISSION_HARD_CAP_BP`),登记公开、商户可查。
38
+ * 5. devreward 是链上奖励池发给服务商的,不挪用、不从商户扣。
39
+ */
40
+ /** 链上 Msg type URL(逐条核对 trustchain/serviceprovider/v1/tx.proto) */
41
+ export declare const SP_MSG_TYPE_URLS: {
42
+ /** 服务商注册:质押 + 绑定微信商户号(唯一性约束)。signer = provider 自己 */
43
+ readonly RegisterServiceProvider: "/trustchain.serviceprovider.v1.MsgRegisterServiceProvider";
44
+ /** 提交支付事实:仅 ACTIVE 服务商可提交,psp_txn_id 幂等防重 */
45
+ readonly SubmitPaymentFact: "/trustchain.serviceprovider.v1.MsgSubmitPaymentFact";
46
+ /** 踢出服务商 + 全额罚没。signer = authority(gov/emergency 双轨) */
47
+ readonly KickOutServiceProvider: "/trustchain.serviceprovider.v1.MsgKickOutServiceProvider";
48
+ /** 罚没质押但不踢出(惩罚性)。signer = authority */
49
+ readonly SlashServiceProvider: "/trustchain.serviceprovider.v1.MsgSlashServiceProvider";
50
+ /** 领取累计贡献奖励(credits)。signer = provider 自己 */
51
+ readonly ClaimProviderReward: "/trustchain.serviceprovider.v1.MsgClaimProviderReward";
52
+ /** 保障链 C5 确认支付事实 → 贡献分。signer = authority 或 params 白名单 */
53
+ readonly ConfirmPaymentFact: "/trustchain.serviceprovider.v1.MsgConfirmPaymentFact";
54
+ };
55
+ /** 链上 Query 端点(LCD REST,proto query.proto 的 google.api.http 注解) */
56
+ export declare const SP_QUERY_ENDPOINTS: {
57
+ readonly Params: "/oxiaom/trustchain/serviceprovider/v1/params";
58
+ readonly ServiceProviders: "/oxiaom/trustchain/serviceprovider/v1/providers";
59
+ readonly ServiceProvider: "/oxiaom/trustchain/serviceprovider/v1/provider/{address}";
60
+ readonly PaymentFacts: "/oxiaom/trustchain/serviceprovider/v1/facts/{provider}";
61
+ };
62
+ /** 后端路由(trustbase-seller-backend 已实现,参考实现即官方服务商"无锡小播鼠") */
63
+ export declare const SP_BACKEND_ROUTES: {
64
+ /** 支付回调统一入口:验签→解密→幂等落账→上链→转发商户→分账。routes/sp-notify.js */
65
+ readonly NotifyWechat: "POST /api/sp/notify/wechat";
66
+ /** 进件资料上传(证件照 → 微信 media/upload)。routes/sp-applyment.js */
67
+ readonly ApplymentUpload: "POST /api/sp/applyment/upload";
68
+ /** 进件提交(→ 微信 applyment4sub)。routes/sp-applyment.js */
69
+ readonly ApplymentSubmit: "POST /api/sp/applyment/submit";
70
+ /** 进件状态查询(含 sign_url / sub_mchid / 驳回明细)。routes/sp-applyment.js */
71
+ readonly ApplymentStatus: "GET /api/sp/applyment/status/:business_code";
72
+ /** 抽佣比例登记/更新(admin,x-sp-admin-key)。routes/sp-commission.js */
73
+ readonly CommissionRatePut: "PUT /api/sp/commission-rate";
74
+ /** 抽佣比例商户自查(公开只读)。routes/sp-commission.js */
75
+ readonly CommissionRateGet: "GET /api/sp/commission-rate/:sub_mchid";
76
+ };
77
+ /** 微信支付 APIv3(服务商模式;网关 = https://api.mch.weixin.qq.com) */
78
+ export declare const WECHAT_APIS: {
79
+ /** 图片/证件上传 → media_id */
80
+ readonly MediaUpload: "POST /v3/merchant/media/upload";
81
+ /** 特约商户进件提交 → applyment_id */
82
+ readonly ApplymentSubmit: "POST /v3/applyment4sub/applyment/";
83
+ /** 进件状态查询(按 business_code)→ applyment_state / sign_url / sub_mchid */
84
+ readonly ApplymentStatus: "GET /v3/applyment4sub/applyment/business_code/{business_code}";
85
+ /** 添加分账接收方 */
86
+ readonly ProfitsharingAddReceiver: "POST /v3/profitsharing/receivers/add";
87
+ /** 请求分账(out_order_no 幂等键) */
88
+ readonly ProfitsharingOrders: "POST /v3/profitsharing/orders";
89
+ /** 查询分账结果 */
90
+ readonly ProfitsharingQuery: "GET /v3/profitsharing/orders/{out_order_no}";
91
+ };
92
+ /**
93
+ * 服务商行业类型(决定商品模型 / 履约方式 / 结算周期的扩展点选择)。
94
+ * 依据《行业扩展图景与国内合规红线》六行业判定,映射为本框架六类:
95
+ * 外卖/打车等参数敏感行业归入 LOCAL_LIFE 并建议走服务包子链(x/subchain)。
96
+ */
97
+ export declare enum SpIndustry {
98
+ /** 附近商圈/本地生活:核销码履约,即时或 T+1 结算,争议窗口短(可走子链独立参数) */
99
+ LOCAL_LIFE = "LOCAL_LIFE",
100
+ /** 国内电商实物:SKU 商品模型,物流履约,T+1 结算(v0 原生主战场) */
101
+ ECOMMERCE = "ECOMMERCE",
102
+ /** 垂直私域:社群/会员制实物或虚拟混合,履约按商户自定义 */
103
+ PRIVATE_DOMAIN = "PRIVATE_DOMAIN",
104
+ /** 网课/知识付费:章节商品模型,自动交付(license/兑换码上链防复制),一次性结算 */
105
+ COURSE = "COURSE",
106
+ /** 订阅制:周期扣款授权 + 按周期结算(国内注意:委托代扣本身要牌照,合规前置) */
107
+ SUBSCRIPTION = "SUBSCRIPTION",
108
+ /** 技术服务/软件:工时或许可证商品模型,API 交付 */
109
+ TECH_SERVICE = "TECH_SERVICE",
110
+ /** 其他:兜底类型,扩展点全自定义 */
111
+ OTHER = "OTHER"
112
+ }
113
+ /** 链上金额(utct 字符串,proto 口径;1 TCT = 1,000,000 utct) */
114
+ export type UtctAmount = string;
115
+ /** 微信侧金额(分,整数) */
116
+ export type FenAmount = number;
117
+ /** 商户/服务商链上地址(tct1... bech32) */
118
+ export type TctAddress = string;
119
+ /** 微信支付交易号(transaction_id) */
120
+ export type PspTxnId = string;
121
+ /** 订单引用(tb-xxxx 形态,与 seller-backend agent-pay 会话关联) */
122
+ export type OrderRef = string;
123
+ /** 微信特约商户号(sub_mchid) */
124
+ export type SubMchId = string;
125
+ /** 服务商链上状态(proto serviceprovider.proto:24 status 字段口径) */
126
+ export declare enum SpStatus {
127
+ ACTIVE = "ACTIVE",
128
+ KICKED = "KICKED",
129
+ SLASHED = "SLASHED"
130
+ }
131
+ /** 支付事实链上状态(proto paymentfact.proto:30) */
132
+ export declare enum PaymentFactStatus {
133
+ PENDING = "PENDING",
134
+ CONFIRMED = "CONFIRMED",
135
+ REJECTED = "REJECTED"
136
+ }
137
+ /**
138
+ * 服务商链上身份。镜像 proto `ServiceProvider`(serviceprovider.proto),
139
+ * 一个微信服务商商户号全链只能绑定一个服务商(唯一性约束)。
140
+ */
141
+ export interface ServiceProviderIdentity {
142
+ /** 服务商链上地址(tct1...) */
143
+ readonly address: TctAddress;
144
+ /** 服务商名称(如"无锡小播鼠服务商") */
145
+ readonly name: string;
146
+ /** 绑定的微信支付服务商商户号(唯一) */
147
+ readonly wechatMchid: string;
148
+ /** 质押 TCT(utct;作恶时按 params.slash_ratio 罚没,踢出默认 100%) */
149
+ readonly stake: UtctAmount;
150
+ /** 链上状态 */
151
+ readonly status: SpStatus;
152
+ /** 累计赚取 credits(ConfirmPaymentFact 每笔 +params.reward_per_fact) */
153
+ readonly creditsEarned: string;
154
+ /** 注册时间(unix 秒) */
155
+ readonly registeredAt: number;
156
+ /** 踢出时间(0 = 未踢出) */
157
+ readonly kickedAt: number;
158
+ /** 踢出原因 */
159
+ readonly kickReason: string;
160
+ }
161
+ /** 链上模块参数(proto params.proto;治理可写,MsgUpdateParams 双轨) */
162
+ export interface ServiceProviderParams {
163
+ /** 注册最低质押(utct;初始 1,000,000,000 = 1000 TCT) */
164
+ minStake: UtctAmount;
165
+ /** 踢出罚没比例(per-10000,10000 = 100%) */
166
+ slashRatio: string;
167
+ /** 每笔确认支付事实的奖励积分(credits;初始 5) */
168
+ rewardPerFact: string;
169
+ /** 单服务商每日最大提交量(防刷) */
170
+ maxFactPerDay: string;
171
+ /** 单服务商同时在线最大子商户数 */
172
+ maxSubMerchants: string;
173
+ /** C5 确认人白名单(逗号分隔地址;gov/emergency 始终有权) */
174
+ confirmerAddresses: string;
175
+ }
176
+ export interface IdentityRegistry {
177
+ /**
178
+ * 链上注册服务商(质押真实托管进 x/serviceprovider 模块账户)。
179
+ * @chain MsgRegisterServiceProvider(tx.proto:50,signer = provider)
180
+ * @backend routes/agent-serviceprovider.js POST /api/agent/serviceprovider/register
181
+ * @wechat 前置条件:先拿到微信支付服务商资质(sp_mchid),本方法只绑不定资质
182
+ */
183
+ register(input: {
184
+ name: string;
185
+ wechatMchid: string;
186
+ stake: UtctAmount;
187
+ }): Promise<{
188
+ address: TctAddress;
189
+ txhash: string;
190
+ }>;
191
+ /**
192
+ * 查询自己/他人的链上身份与状态。
193
+ * @chain Query ServiceProvider(query.proto:23)
194
+ * @backend 无(直读 LCD)
195
+ * @wechat 无
196
+ */
197
+ getIdentity(address: TctAddress): Promise<ServiceProviderIdentity | null>;
198
+ /**
199
+ * 读取模块参数(最低质押/罚没比例/每日上限……实现前必读,别硬编码)。
200
+ * @chain Query Params(query.proto:14)
201
+ * @backend 无
202
+ * @wechat 无
203
+ */
204
+ getParams(): Promise<ServiceProviderParams>;
205
+ /**
206
+ * 领取累计贡献奖励(credits 清零入账)。
207
+ * @chain MsgClaimProviderReward(tx.proto:102,signer = provider)
208
+ * @backend 无(服务商自己的运营台发起)
209
+ * @wechat 无
210
+ */
211
+ claimReward(): Promise<{
212
+ claimed: string;
213
+ txhash: string;
214
+ }>;
215
+ }
216
+ /** 进件状态(微信 applyment_state 原样透传) */
217
+ export declare enum ApplymentState {
218
+ EDITTING = "APPLYMENT_STATE_EDITTING",
219
+ AUDITING = "APPLYMENT_STATE_AUDITING",
220
+ REJECTED = "APPLYMENT_STATE_REJECTED",
221
+ TO_BE_CONFIRMED = "APPLYMENT_STATE_TO_BE_CONFIRMED",
222
+ TO_BE_SIGNED = "APPLYMENT_STATE_TO_BE_SIGNED",
223
+ SIGNING = "APPLYMENT_STATE_SIGNING",
224
+ FINISHED = "APPLYMENT_STATE_FINISHED",
225
+ CANCELED = "APPLYMENT_STATE_CANCELED"
226
+ }
227
+ /** 经营场景(微信 sales_scenes_type 三选一) */
228
+ export declare enum SalesScene {
229
+ /** 线下门店(默认,需门头/店内照片) */
230
+ STORE = "SALES_SCENES_STORE",
231
+ /** 互联网网站(需已上线 + ICP 备案域名) */
232
+ WEB = "SALES_SCENES_WEB",
233
+ /** 公众号/小程序 */
234
+ MP = "SALES_SCENES_MP"
235
+ }
236
+ /**
237
+ * 进件表单(脱敏视角;敏感字段实现层用微信支付公钥 RSA-OAEP-SHA256 加密后上送)。
238
+ * 完整字段口径见 trustbase-seller-backend routes/sp-applyment.js buildApplymentBody()。
239
+ */
240
+ export interface ApplymentForm {
241
+ /** 幂等键(TB{毫秒}{6位随机},重复提交带同码直接返回已有 applyment_id) */
242
+ businessCode?: string;
243
+ subjectType: 'SUBJECT_TYPE_INDIVIDUAL' | 'SUBJECT_TYPE_ENTERPRISE';
244
+ salesScene: SalesScene;
245
+ merchantName: string;
246
+ merchantShortname: string;
247
+ licenseNumber: string;
248
+ legalName: string;
249
+ /** 敏感字段(contact/id_card/account 系列)在实现层加密,本类型不展开 */
250
+ sensitiveFieldsEncrypted: boolean;
251
+ /** 必备照片 media_id(执照/身份证正反面;STORE 场景另需门头+店内) */
252
+ mediaIds: Record<string, string>;
253
+ /** 结算类目(微信 settlement_id,如通用类目 716/719/727) */
254
+ settlementId: string;
255
+ }
256
+ export interface ApplymentResult {
257
+ businessCode: string;
258
+ applymentId: string;
259
+ state: ApplymentState;
260
+ /** 超管签约链接(TO_BE_SIGNED/SIGNING 态返回,发给商户扫码签约) */
261
+ signUrl: string;
262
+ /** 审核通过后微信分配的特约商户号 */
263
+ subMchid: SubMchId;
264
+ /** 驳回明细(field / field_name / reject_reason,必须原样展示给商户) */
265
+ auditDetail: ReadonlyArray<{
266
+ field: string;
267
+ fieldName: string;
268
+ rejectReason: string;
269
+ }>;
270
+ }
271
+ export interface OnboardingChannel {
272
+ /**
273
+ * 上传证件/门店照片拿 media_id(multipart,meta JSON 串参与签名)。
274
+ * @chain 无
275
+ * @backend POST /api/sp/applyment/upload(routes/sp-applyment.js)
276
+ * @wechat POST /v3/merchant/media/upload
277
+ */
278
+ uploadCredential(file: {
279
+ filename: string;
280
+ content: Uint8Array;
281
+ }): Promise<{
282
+ mediaId: string;
283
+ }>;
284
+ /**
285
+ * 提交进件申请(敏感字段本机/服务商侧公钥加密,HTTP 头带 Wechatpay-Serial=公钥ID)。
286
+ * @chain 无(进件是微信侧动作;商户链上注册另走卖家自己的 onboarding)
287
+ * @backend POST /api/sp/applyment/submit(routes/sp-applyment.js;mock: SP_APPLYMENT_MOCK=1)
288
+ * @wechat POST /v3/applyment4sub/applyment/
289
+ */
290
+ submitApplication(form: ApplymentForm): Promise<{
291
+ businessCode: string;
292
+ applymentId: string;
293
+ }>;
294
+ /**
295
+ * 查询进件状态(驳回原因必须透传给商户,不许吞)。
296
+ * @chain 无
297
+ * @backend GET /api/sp/applyment/status/:business_code
298
+ * @wechat GET /v3/applyment4sub/applyment/business_code/{business_code}
299
+ */
300
+ queryApplication(businessCode: string): Promise<ApplymentResult>;
301
+ /**
302
+ * sub_mchid 分配回调/轮询落定后,登记商户路由(链上地址 ↔ sub_mchid ↔ webhook)。
303
+ * @chain 无(台账动作;商户链上卖家注册由商户自己设备完成)
304
+ * @backend sp_sub_merchants 台账(routes/sp-notify.js ensureTables)
305
+ * @wechat 签约完成后微信侧生效
306
+ */
307
+ bindSubMerchant(binding: {
308
+ subMchid: SubMchId;
309
+ sellerAddress: TctAddress;
310
+ shopName: string;
311
+ /** 空 = 不转发支付结果(商户查单模式) */
312
+ webhookUrl?: string;
313
+ }): Promise<void>;
314
+ }
315
+ /**
316
+ * 下单请求的商品载荷按行业不同(见第 8 节行业扩展点),此处只约束公共字段。
317
+ * `payload` 的具体形态由 `IndustryExtension['product']` 决定。
318
+ */
319
+ export interface CreateOrderInput<TProduct = unknown> {
320
+ industry: SpIndustry;
321
+ /** 商户侧订单号(幂等键) */
322
+ outTradeNo: string;
323
+ /** 金额(分) */
324
+ amountFen: FenAmount;
325
+ /** 行业商品载荷(SKU/章节/订阅计划/工时……) */
326
+ product: TProduct;
327
+ /** 买家标识(设备伪名,非实名) */
328
+ buyerHint?: string;
329
+ }
330
+ /** 解密后的支付事实(微信回调明文的最小必要子集,零 PII) */
331
+ export interface VerifiedPayment {
332
+ txnId: PspTxnId;
333
+ outTradeNo: string;
334
+ /** 实付金额(分) */
335
+ amountFen: FenAmount;
336
+ subMchid: SubMchId;
337
+ tradeState: 'SUCCESS' | string;
338
+ /** 证据哈希口径(与 ShopXO 插件/agent-serviceprovider 一致):sha256(order_ref + psp_txn_id + amount) */
339
+ evidenceHash: string;
340
+ }
341
+ export interface PaymentRail {
342
+ /**
343
+ * 按行业商品模型创建支付单(返回微信支付参数/二维码/调起串)。
344
+ * @chain 无(链上订单另由卖家设备 MsgCreateOrder,本接口只产生支付单)
345
+ * @backend agent-pay 下单通道(routes/agent-pay.js)
346
+ * @wechat JSAPI/Native/小程序下单(服务商模式带 sp_mchid + sub_mchid)
347
+ */
348
+ createPayment<TProduct>(input: CreateOrderInput<TProduct>): Promise<{
349
+ outTradeNo: string;
350
+ /** 支付调起参数(形态随支付产品而定) */
351
+ payPayload: Record<string, string>;
352
+ }>;
353
+ /**
354
+ * 支付回调处理:平台证书验签 → AES-256-GCM 解密 → 幂等(txn_id 主键)→
355
+ * 非 SUCCESS 不落账。验签/解密失败回 4xx/5xx 让微信重试,后续步骤失败一律回 200。
356
+ * @chain 间接产生 MsgSubmitPaymentFact(见 submitPaymentFact)
357
+ * @backend POST /api/sp/notify/wechat(routes/sp-notify.js:145)
358
+ * @wechat 支付结果通知(平台证书验签 + APIv3 key 解密 resource)
359
+ */
360
+ handleNotify(rawBody: string, headers: {
361
+ signature: string;
362
+ serial: string;
363
+ timestamp: string;
364
+ nonce: string;
365
+ }): Promise<{
366
+ accepted: boolean;
367
+ payment?: VerifiedPayment;
368
+ ignoredReason?: string;
369
+ }>;
370
+ /**
371
+ * 支付事实上链(失败 warn 不阻塞商户回调,台账留空由 retryPending 定时补链)。
372
+ * @chain MsgSubmitPaymentFact(tx.proto:63,signer = provider;仅 ACTIVE 可提交)
373
+ * @backend routes/sp-notify.js submitPaymentFactToChain() + retryPending()
374
+ * @wechat 无(数据源是回调明文,链上零 PII 只存 evidence_hash)
375
+ */
376
+ submitPaymentFact(payment: VerifiedPayment): Promise<{
377
+ txhash: string;
378
+ } | {
379
+ deferred: true;
380
+ }>;
381
+ /**
382
+ * 查单(回调不可达场景的兜底,每 2 分钟主动查单模式同样走本接口语义)。
383
+ * @chain 无
384
+ * @backend agent-pay 查单通道(routes/agent-pay.js)
385
+ * @wechat 微信支付订单查询(by out_trade_no / transaction_id)
386
+ */
387
+ queryPayment(outTradeNo: string): Promise<VerifiedPayment | null>;
388
+ /**
389
+ * 支付结果转发商户 webhook(3s 超时,结果记台账 forward_status)。
390
+ * @chain 无
391
+ * @backend routes/sp-notify.js 第 7 步转发
392
+ * @wechat 无
393
+ */
394
+ forwardToMerchant(merchant: {
395
+ webhookUrl: string;
396
+ }, payment: VerifiedPayment): Promise<'ok' | 'failed' | 'none'>;
397
+ }
398
+ /**
399
+ * 抽佣硬顶:万分比 3000 = 30%(微信平台分账上限,《商户经济模型最终方案》§七之二 定稿)。
400
+ * 链上 params 对齐同值;超出必须拒绝(422),mock 模式护栏同样生效。
401
+ */
402
+ export declare const SP_COMMISSION_HARD_CAP_BP = 3000;
403
+ /** 抽佣比例登记(rate_bp 万分比:150 = 1.50%) */
404
+ export interface CommissionRate {
405
+ subMchid: SubMchId;
406
+ /** 万分比整数,0..3000 */
407
+ rateBp: number;
408
+ /** 人性化展示("1.50%"),商户后台可见 */
409
+ ratePct: string;
410
+ updatedAt: number;
411
+ }
412
+ /** 分账回单(微信分账是执行通道:自动、实时、有回单可证;不做线下私下结算) */
413
+ export interface ProfitsharingReceipt {
414
+ /** 分账单号(out_order_no,幂等键,建议 "ps-" + txn_id) */
415
+ outOrderNo: string;
416
+ transactionId: PspTxnId;
417
+ /** 分账金额(分),护栏:≤ 交易金额 × 30% */
418
+ amountFen: FenAmount;
419
+ receiverAccount: string;
420
+ /** mock=true 表示 WXPAY_PROFITSHARING_ENABLED 未开,未真调微信 */
421
+ mock: boolean;
422
+ }
423
+ export interface CommissionPolicy {
424
+ /**
425
+ * 登记/更新抽佣比例(admin 鉴权;比例登记公开是商户比价的权利)。
426
+ * @chain v3.9.6 计划:ServiceProvider proto 加 commission_rate 字段上链;v0 先 indexer/台账登记
427
+ * @backend PUT /api/sp/commission-rate(routes/sp-commission.js,x-sp-admin-key)
428
+ * @wechat 无
429
+ */
430
+ registerRate(subMchid: SubMchId, rateBp: number): Promise<CommissionRate>;
431
+ /**
432
+ * 商户自查当前比例(公开只读,未登记 404)。
433
+ * @chain 同上(v3.9.6 后链上可查)
434
+ * @backend GET /api/sp/commission-rate/:sub_mchid
435
+ * @wechat 无
436
+ */
437
+ getRate(subMchid: SubMchId): Promise<CommissionRate | null>;
438
+ /**
439
+ * 支付成功后按登记比例触发分账(fire-and-forget,失败只 warn 不阻塞回调)。
440
+ * @chain 分账结果(分账单号+比例)随支付事实证据留存,商户可对账
441
+ * @backend routes/sp-notify.js maybeTriggerProfitsharing() → payments/wechat/profitsharing.js
442
+ * @wechat POST /v3/profitsharing/receivers/add + POST /v3/profitsharing/orders
443
+ */
444
+ executeProfitsharing(payment: VerifiedPayment, rate: CommissionRate): Promise<ProfitsharingReceipt>;
445
+ }
446
+ /**
447
+ * 标准迁移包(《商户经济模型最终方案》§六 迁移协议):
448
+ * 换服务商 = 换供应商,不是搬家。链上状态(商品/订单/信誉/KYC 标记)自动跟随商户地址,
449
+ * 本包只承载 off-chain 内容;content_hash 供新服务商校验完整性。
450
+ */
451
+ export interface SpMigrationPackage {
452
+ version: string;
453
+ sellerAddress: TctAddress;
454
+ /** 旧服务商地址(信息性,不构成任何审批权) */
455
+ fromProvider: TctAddress;
456
+ exportedAt: number;
457
+ /** off-chain 内容(结构化 JSON:店铺配置/商品详情页素材/物流模板……) */
458
+ offChainContent: Record<string, unknown>;
459
+ /** 内容哈希(canonical JSON → sha256,口径同 @trustbase/protocol bundle-hash) */
460
+ contentHash: string;
461
+ /** KYC 原件转交凭据(跟人不跟服务商;按商户授权转交,链上只记 evidence_hash + level) */
462
+ kycTransferEvidence?: string;
463
+ }
464
+ export interface MigrationSupport {
465
+ /**
466
+ * 迁出导出(义务接口):商户要包必须给,不可阻拦、不可扣留。
467
+ * @chain 链上状态零迁移(锚定商户地址天然可携带)
468
+ * @backend SDK tb-migrate 导出侧(S4;参考 config/export-import.js 的配置导出形态)
469
+ * @wechat 无
470
+ */
471
+ exportMigrationPackage(sellerAddress: TctAddress): Promise<SpMigrationPackage>;
472
+ /**
473
+ * 迁入导入:校验 content_hash → 落库 → 商户在新服务商重新进件(sub_mchid 会换)。
474
+ * @chain 同上
475
+ * @backend SDK tb-migrate 导入侧
476
+ * @wechat 迁入后重新走 OnboardingChannel(新服务商主体下重新进件)
477
+ */
478
+ importMigrationPackage(pkg: SpMigrationPackage): Promise<{
479
+ imported: true;
480
+ }>;
481
+ /**
482
+ * feegrant 切换:旧服务商 revoke + 新服务商新发(AllowedMsgAllowance 白名单 + 双限额)。
483
+ * 质押切换走链上 redelegate:即时生效,资金不解锁、不等 21 天。
484
+ * @chain MsgRevokeAllowance + MsgGrantAllowance(cosmos feegrant);redelegate(staking)
485
+ * @backend 冷启动 feegrant 三道闸实现(seller-backend feegrant 模块)
486
+ * @wechat 无
487
+ */
488
+ switchFeegrant(input: {
489
+ sellerAddress: TctAddress;
490
+ newProvider: TctAddress;
491
+ }): Promise<{
492
+ revoked: string;
493
+ granted: string;
494
+ }>;
495
+ }
496
+ /** 结算周期形态(按行业不同) */
497
+ export declare enum SettlementCycleKind {
498
+ /** 实物电商:确认收货后 T+N(默认 T+1) */
499
+ T_PLUS_N = "T_PLUS_N",
500
+ /** 订阅制:按订阅周期结算 */
501
+ PERIODIC = "PERIODIC",
502
+ /** 课程/虚拟商品:交付即结算(一次性) */
503
+ ONE_SHOT = "ONE_SHOT",
504
+ /** 本地生活:核销即结算(即时或当日) */
505
+ ON_REDEMPTION = "ON_REDEMPTION",
506
+ /** 技术服务:里程碑/验收结算 */
507
+ MILESTONE = "MILESTONE"
508
+ }
509
+ export interface SettlementRule {
510
+ kind: SettlementCycleKind;
511
+ /** T_PLUS_N 的 N(天);其他形态忽略 */
512
+ delayDays?: number;
513
+ /** PERIODIC 的周期(天) */
514
+ periodDays?: number;
515
+ /** 争议窗口(小时):窗口内资金冻结;外卖等即时行业必须显著短于默认 3 天(→ 服务包子链独立参数) */
516
+ disputeWindowHours: number;
517
+ /** 行业特定的补充说明(实现层自由文本,进商户协议) */
518
+ notes?: string;
519
+ }
520
+ export interface SettlementPolicy {
521
+ /**
522
+ * 给出某行业某商户的结算规则(进件时明示,写进商户协议)。
523
+ * @chain 结算锚定走 escrow/订单状态机(x/order);参数敏感行业走 x/subchain 子链参数
524
+ * @backend 无独立路由(随订单/回调流程生效)
525
+ * @wechat 微信侧实际结算周期以微信支付协议为准,本规则是链上 escrow 释放口径
526
+ */
527
+ ruleFor(industry: SpIndustry, subMchid?: SubMchId): SettlementRule;
528
+ }
529
+ /** 退款规则(行业差异:实物有退货物流,虚拟/课程交付后原则上不退,订阅按剩余周期折算) */
530
+ export interface RefundPolicy {
531
+ /** 交付后是否可退 */
532
+ refundableAfterDelivery: boolean;
533
+ /** 退款窗口(小时,自支付/交付起算,口径自选并写进 notes) */
534
+ windowHours: number;
535
+ /** 部分退款支持(按比例/按章节/按剩余周期……) */
536
+ partialRefund: boolean;
537
+ notes?: string;
538
+ }
539
+ /** 附近商圈/本地生活扩展 */
540
+ export interface LocalLifeExtension {
541
+ /** 商品模型:券/套餐(核销次数、有效期、适用门店) */
542
+ product: {
543
+ voucherSkuId: string;
544
+ redemptionCount: number;
545
+ validDays: number;
546
+ storeIds: string[];
547
+ };
548
+ /** 履约:核销码(买家出示 → 商户扫码核销 → 链上确认) */
549
+ fulfillment: {
550
+ kind: 'REDEMPTION_CODE';
551
+ codeTtlMinutes: number;
552
+ };
553
+ refund: RefundPolicy;
554
+ }
555
+ /** 国内电商实物扩展(v0 原生主战场) */
556
+ export interface EcommerceExtension {
557
+ /** 商品模型:多规格 SKU(spu + sku 列表,单件质押 CHAIN_STAKE_PER_UNIT) */
558
+ product: {
559
+ spuId: string;
560
+ skus: ReadonlyArray<{
561
+ skuId: string;
562
+ attrs: Record<string, string>;
563
+ priceFen: FenAmount;
564
+ stock: number;
565
+ }>;
566
+ };
567
+ /** 履约:物流(物流事实卖家推送,保障链 C5 结合支付事实判 NORMAL/WASH) */
568
+ fulfillment: {
569
+ kind: 'LOGISTICS';
570
+ carrier?: string;
571
+ trackingNo?: string;
572
+ };
573
+ refund: RefundPolicy;
574
+ }
575
+ /** 垂直私域扩展(社群/会员制,实物虚拟混合) */
576
+ export interface PrivateDomainExtension {
577
+ /** 商品模型:任意(引用实物或虚拟模型之一) */
578
+ product: {
579
+ ref: 'ECOMMERCE' | 'COURSE' | 'CUSTOM';
580
+ customSchema?: Record<string, unknown>;
581
+ };
582
+ /** 履约:按引用模型;私域特有的是触达通道(群/私信),不进本框架 */
583
+ fulfillment: {
584
+ kind: 'LOGISTICS' | 'AUTO_DELIVERY' | 'CUSTOM';
585
+ };
586
+ refund: RefundPolicy;
587
+ }
588
+ /** 网课/知识付费扩展 */
589
+ export interface CourseExtension {
590
+ /** 商品模型:课程 → 章节(试看章节标记、时长、资料附件哈希) */
591
+ product: {
592
+ courseId: string;
593
+ chapters: ReadonlyArray<{
594
+ chapterId: string;
595
+ title: string;
596
+ preview: boolean;
597
+ durationSec?: number;
598
+ }>;
599
+ };
600
+ /** 履约:自动交付(license/兑换码;交付凭据上链防复制);结业证书链上凭证可选 */
601
+ fulfillment: {
602
+ kind: 'AUTO_DELIVERY';
603
+ licenseKey?: string;
604
+ certificateOnChain?: boolean;
605
+ };
606
+ refund: RefundPolicy;
607
+ }
608
+ /** 订阅制扩展 */
609
+ export interface SubscriptionExtension {
610
+ /** 商品模型:订阅计划(周期、档位、首期优惠) */
611
+ product: {
612
+ planId: string;
613
+ intervalDays: number;
614
+ tier?: string;
615
+ trialDays?: number;
616
+ };
617
+ /** 履约:周期开通权益;扣款授权上链(周期扣款授权 msg)
618
+ * ⚠️ 合规前置:国内微信"委托代扣"本身要牌照,未取得前不得上线扣款 */
619
+ fulfillment: {
620
+ kind: 'RECURRING_ENTITLEMENT';
621
+ deductionAuthMsg?: string;
622
+ };
623
+ refund: RefundPolicy;
624
+ }
625
+ /** 技术服务/软件扩展 */
626
+ export interface TechServiceExtension {
627
+ /** 商品模型:工时包/许可证/里程碑 */
628
+ product: {
629
+ offeringId: string;
630
+ unit: 'HOUR' | 'LICENSE' | 'MILESTONE';
631
+ quantity: number;
632
+ };
633
+ /** 履约:API 交付(key 签发/额度开通/工单验收) */
634
+ fulfillment: {
635
+ kind: 'API_DELIVERY';
636
+ deliveryEndpoint?: string;
637
+ acceptanceRequired?: boolean;
638
+ };
639
+ refund: RefundPolicy;
640
+ }
641
+ /** 兜底:自定义扩展 */
642
+ export interface OtherExtension {
643
+ product: Record<string, unknown>;
644
+ fulfillment: {
645
+ kind: 'CUSTOM';
646
+ description: string;
647
+ };
648
+ refund: RefundPolicy;
649
+ }
650
+ /** SpIndustry → 扩展接口映射(实现网关时用本类型约束扩展载荷) */
651
+ export interface IndustryExtensionMap {
652
+ [SpIndustry.LOCAL_LIFE]: LocalLifeExtension;
653
+ [SpIndustry.ECOMMERCE]: EcommerceExtension;
654
+ [SpIndustry.PRIVATE_DOMAIN]: PrivateDomainExtension;
655
+ [SpIndustry.COURSE]: CourseExtension;
656
+ [SpIndustry.SUBSCRIPTION]: SubscriptionExtension;
657
+ [SpIndustry.TECH_SERVICE]: TechServiceExtension;
658
+ [SpIndustry.OTHER]: OtherExtension;
659
+ }
660
+ /**
661
+ * 服务商网关聚合接口。六个核心接口全部必须实现(迁移支持是义务不是选项),
662
+ * 行业扩展点按自己服务的行业至少实现一个。
663
+ *
664
+ * 参考实现(官方服务商"无锡小播鼠"):trustbase-seller-backend 的
665
+ * routes/sp-notify.js / sp-applyment.js / sp-commission.js / payments/wechat/profitsharing.js。
666
+ */
667
+ export interface ServiceProviderGateway {
668
+ /** ① 链上身份:注册/质押/参数/领奖 */
669
+ readonly identity: IdentityRegistry;
670
+ /** ② 进件通道:资料上传/提交/状态/sub_mchid 绑定 */
671
+ readonly onboarding: OnboardingChannel;
672
+ /** ③ 支付通道:下单/回调验签解密/支付事实上链/查单/转发 */
673
+ readonly payment: PaymentRail;
674
+ /** ④ 抽佣分账:比例登记公开 + 微信分账执行(≤30% 硬顶) */
675
+ readonly commission: CommissionPolicy;
676
+ /** ⑤ 迁移支持:迁出导出/迁入导入/feegrant 切换(不可阻拦) */
677
+ readonly migration: MigrationSupport;
678
+ /** ⑥ 结算规则:按行业给出结算周期与争议窗口 */
679
+ readonly settlement: SettlementPolicy;
680
+ }
681
+ /** 行业化网关 = 通用网关 + 某行业的扩展点实现 */
682
+ export interface IndustryGateway<I extends SpIndustry> extends ServiceProviderGateway {
683
+ readonly industry: I;
684
+ readonly extension: IndustryExtensionMap[I];
685
+ }
686
+ //# sourceMappingURL=sp-framework.d.ts.map