@h-ai/payment 0.1.0-alpha5
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/LICENSE +202 -0
- package/README.md +137 -0
- package/dist/api/index.d.ts +211 -0
- package/dist/api/index.js +96 -0
- package/dist/api/index.js.map +1 -0
- package/dist/chunk-4IUARFWH.js +67 -0
- package/dist/chunk-4IUARFWH.js.map +1 -0
- package/dist/client/index.d.ts +56 -0
- package/dist/client/index.js +90 -0
- package/dist/client/index.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +854 -0
- package/dist/index.js.map +1 -0
- package/dist/payment-types-D1GvLKHg.d.ts +209 -0
- package/package.json +51 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { core } from '@h-ai/core';
|
|
2
|
+
|
|
3
|
+
// src/payment-types.ts
|
|
4
|
+
var PaymentErrorInfo = {
|
|
5
|
+
CREATE_ORDER_FAILED: "001:500",
|
|
6
|
+
QUERY_ORDER_FAILED: "002:500",
|
|
7
|
+
REFUND_FAILED: "003:500",
|
|
8
|
+
CLOSE_ORDER_FAILED: "004:500",
|
|
9
|
+
NOT_INITIALIZED: "010:500",
|
|
10
|
+
SIGN_FAILED: "020:500",
|
|
11
|
+
PROVIDER_NOT_FOUND: "030:404",
|
|
12
|
+
INVALID_AMOUNT: "040:400",
|
|
13
|
+
NOTIFY_VERIFY_FAILED: "050:400",
|
|
14
|
+
NOTIFY_PARSE_FAILED: "051:400",
|
|
15
|
+
INVOKE_WEB_FAILED: "060:500",
|
|
16
|
+
INVOKE_APP_FAILED: "061:500",
|
|
17
|
+
CONFIG_ERROR: "070:500"
|
|
18
|
+
};
|
|
19
|
+
var HaiPaymentError = core.error.buildHaiErrorsDef("payment", PaymentErrorInfo);
|
|
20
|
+
|
|
21
|
+
// messages/en-US.json
|
|
22
|
+
var en_US_default = {
|
|
23
|
+
payment_createOrderFailed: "Failed to create payment order",
|
|
24
|
+
payment_queryOrderFailed: "Failed to query order status",
|
|
25
|
+
payment_refundFailed: "Refund request failed",
|
|
26
|
+
payment_closeOrderFailed: "Failed to close order",
|
|
27
|
+
payment_notifyVerifyFailed: "Payment notification verification failed",
|
|
28
|
+
payment_notifyParseFailed: "Failed to parse payment notification",
|
|
29
|
+
payment_signFailed: "Payment signature generation failed",
|
|
30
|
+
payment_providerNotFound: "Payment provider not found",
|
|
31
|
+
payment_invalidAmount: "Invalid payment amount",
|
|
32
|
+
payment_notInitialized: "Payment module not initialized, call payment.init() first",
|
|
33
|
+
payment_invokeWebFailed: "Failed to invoke web payment",
|
|
34
|
+
payment_invokeAppFailed: "Failed to invoke app payment",
|
|
35
|
+
payment_configError: "Payment config validation failed: {error}",
|
|
36
|
+
payment_initFailed: "Payment module initialization failed: {error}",
|
|
37
|
+
payment_configFieldRequired: "This config field is required"
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// messages/zh-CN.json
|
|
41
|
+
var zh_CN_default = {
|
|
42
|
+
payment_createOrderFailed: "\u521B\u5EFA\u652F\u4ED8\u8BA2\u5355\u5931\u8D25",
|
|
43
|
+
payment_queryOrderFailed: "\u67E5\u8BE2\u8BA2\u5355\u72B6\u6001\u5931\u8D25",
|
|
44
|
+
payment_refundFailed: "\u9000\u6B3E\u8BF7\u6C42\u5931\u8D25",
|
|
45
|
+
payment_closeOrderFailed: "\u5173\u95ED\u8BA2\u5355\u5931\u8D25",
|
|
46
|
+
payment_notifyVerifyFailed: "\u652F\u4ED8\u56DE\u8C03\u9A8C\u7B7E\u5931\u8D25",
|
|
47
|
+
payment_notifyParseFailed: "\u89E3\u6790\u652F\u4ED8\u56DE\u8C03\u5931\u8D25",
|
|
48
|
+
payment_signFailed: "\u652F\u4ED8\u7B7E\u540D\u751F\u6210\u5931\u8D25",
|
|
49
|
+
payment_providerNotFound: "\u672A\u627E\u5230\u652F\u4ED8 Provider",
|
|
50
|
+
payment_invalidAmount: "\u652F\u4ED8\u91D1\u989D\u65E0\u6548",
|
|
51
|
+
payment_notInitialized: "\u652F\u4ED8\u6A21\u5757\u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 payment.init()",
|
|
52
|
+
payment_invokeWebFailed: "\u8C03\u8D77\u7F51\u9875\u652F\u4ED8\u5931\u8D25",
|
|
53
|
+
payment_invokeAppFailed: "\u8C03\u8D77 App \u652F\u4ED8\u5931\u8D25",
|
|
54
|
+
payment_configError: "\u652F\u4ED8\u6A21\u5757\u914D\u7F6E\u6821\u9A8C\u5931\u8D25\uFF1A{error}",
|
|
55
|
+
payment_initFailed: "\u652F\u4ED8\u6A21\u5757\u521D\u59CB\u5316\u5931\u8D25\uFF1A{error}",
|
|
56
|
+
payment_configFieldRequired: "\u6B64\u914D\u7F6E\u5B57\u6BB5\u5FC5\u586B"
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/payment-i18n.ts
|
|
60
|
+
var paymentM = core.i18n.createMessageGetter({
|
|
61
|
+
"zh-CN": zh_CN_default,
|
|
62
|
+
"en-US": en_US_default
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export { HaiPaymentError, paymentM };
|
|
66
|
+
//# sourceMappingURL=chunk-4IUARFWH.js.map
|
|
67
|
+
//# sourceMappingURL=chunk-4IUARFWH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/payment-types.ts","../messages/en-US.json","../messages/zh-CN.json","../src/payment-i18n.ts"],"names":["core"],"mappings":";;;AAaA,IAAM,gBAAA,GAAmB;AAAA,EACvB,mBAAA,EAAqB,SAAA;AAAA,EACrB,kBAAA,EAAoB,SAAA;AAAA,EACpB,aAAA,EAAe,SAAA;AAAA,EACf,kBAAA,EAAoB,SAAA;AAAA,EACpB,eAAA,EAAiB,SAAA;AAAA,EACjB,WAAA,EAAa,SAAA;AAAA,EACb,kBAAA,EAAoB,SAAA;AAAA,EACpB,cAAA,EAAgB,SAAA;AAAA,EAChB,oBAAA,EAAsB,SAAA;AAAA,EACtB,mBAAA,EAAqB,SAAA;AAAA,EACrB,iBAAA,EAAmB,SAAA;AAAA,EACnB,iBAAA,EAAmB,SAAA;AAAA,EACnB,YAAA,EAAc;AAChB,CAAA;AAEO,IAAM,eAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,WAAW,gBAAgB;;;AC7BvF,IAAA,aAAA,GAAA;AAAA,EACE,yBAAA,EAA6B,gCAAA;AAAA,EAC7B,wBAAA,EAA4B,8BAAA;AAAA,EAC5B,oBAAA,EAAwB,uBAAA;AAAA,EACxB,wBAAA,EAA4B,uBAAA;AAAA,EAC5B,0BAAA,EAA8B,0CAAA;AAAA,EAC9B,yBAAA,EAA6B,sCAAA;AAAA,EAC7B,kBAAA,EAAsB,qCAAA;AAAA,EACtB,wBAAA,EAA4B,4BAAA;AAAA,EAC5B,qBAAA,EAAyB,wBAAA;AAAA,EACzB,sBAAA,EAA0B,2DAAA;AAAA,EAC1B,uBAAA,EAA2B,8BAAA;AAAA,EAC3B,uBAAA,EAA2B,8BAAA;AAAA,EAC3B,mBAAA,EAAuB,2CAAA;AAAA,EACvB,kBAAA,EAAsB,+CAAA;AAAA,EACtB,2BAAA,EAA+B;AACjC,CAAA;;;AChBA,IAAA,aAAA,GAAA;AAAA,EACE,yBAAA,EAA6B,kDAAA;AAAA,EAC7B,wBAAA,EAA4B,kDAAA;AAAA,EAC5B,oBAAA,EAAwB,sCAAA;AAAA,EACxB,wBAAA,EAA4B,sCAAA;AAAA,EAC5B,0BAAA,EAA8B,kDAAA;AAAA,EAC9B,yBAAA,EAA6B,kDAAA;AAAA,EAC7B,kBAAA,EAAsB,kDAAA;AAAA,EACtB,wBAAA,EAA4B,yCAAA;AAAA,EAC5B,qBAAA,EAAyB,sCAAA;AAAA,EACzB,sBAAA,EAA0B,+FAAA;AAAA,EAC1B,uBAAA,EAA2B,kDAAA;AAAA,EAC3B,uBAAA,EAA2B,2CAAA;AAAA,EAC3B,mBAAA,EAAuB,2EAAA;AAAA,EACvB,kBAAA,EAAsB,qEAAA;AAAA,EACtB,2BAAA,EAA+B;AACjC,CAAA;;;ACGO,IAAM,QAAA,GAAWA,IAAAA,CAAK,IAAA,CAAK,mBAAA,CAAuC;AAAA,EACvE,OAAA,EAAS,aAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAC","file":"chunk-4IUARFWH.js","sourcesContent":["/**\n * @h-ai/payment — 类型定义\n *\n * 统一支付模块的公共类型、Provider 接口与错误类型。\n * @module payment-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { PaymentConfig, PaymentConfigInput } from './payment-config.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst PaymentErrorInfo = {\n CREATE_ORDER_FAILED: '001:500',\n QUERY_ORDER_FAILED: '002:500',\n REFUND_FAILED: '003:500',\n CLOSE_ORDER_FAILED: '004:500',\n NOT_INITIALIZED: '010:500',\n SIGN_FAILED: '020:500',\n PROVIDER_NOT_FOUND: '030:404',\n INVALID_AMOUNT: '040:400',\n NOTIFY_VERIFY_FAILED: '050:400',\n NOTIFY_PARSE_FAILED: '051:400',\n INVOKE_WEB_FAILED: '060:500',\n INVOKE_APP_FAILED: '061:500',\n CONFIG_ERROR: '070:500',\n} as const satisfies ErrorInfo\n\nexport const HaiPaymentError = core.error.buildHaiErrorsDef('payment', PaymentErrorInfo)\n\n// ─── 支付场景 ───\n\n/** 支付场景(tradeType) */\nexport type TradeType = 'jsapi' | 'h5' | 'app' | 'native' | 'mini_program'\n\n/** 订单状态 */\nexport type OrderStatusValue = 'pending' | 'paid' | 'closed' | 'refunded' | 'failed'\n\n// ─── 创建订单 ───\n\n/** 创建订单入参 */\nexport interface CreateOrderInput {\n /** 商户订单号 */\n orderNo: string\n /** 金额(分) */\n amount: number\n /** 币种(默认 CNY) */\n currency?: string\n /** 商品描述 */\n description: string\n /** 支付场景 */\n tradeType: TradeType\n /** 用户标识(微信 openid 等,jsapi 必填) */\n userId?: string\n /** 异步通知 URL */\n notifyUrl: string\n /** 附加数据(透传) */\n metadata?: Record<string, string>\n}\n\n/** 支付订单(返回给客户端调起支付) */\nexport interface PaymentOrder {\n /** Provider 名称 */\n provider: string\n /** 支付场景 */\n tradeType: TradeType\n /** 客户端调起参数(各平台差异) */\n clientParams: Record<string, unknown>\n /** 预支付 ID(如微信 prepay_id) */\n prepayId?: string\n}\n\n// ─── 回调通知 ───\n\n/** 回调请求(原始 HTTP 数据) */\nexport interface PaymentNotifyRequest {\n /** 请求 body */\n body: string\n /** 请求 headers */\n headers: Record<string, string>\n}\n\n/** 回调解析结果 */\nexport interface PaymentNotifyResult {\n /** 商户订单号 */\n orderNo: string\n /** 支付渠道交易号 */\n transactionId: string\n /** 支付金额(分) */\n amount: number\n /** 支付状态 */\n status: OrderStatusValue\n /** 支付时间 */\n paidAt?: Date\n /** 原始数据 */\n raw?: Record<string, unknown>\n}\n\n// ─── 查询订单 ───\n\n/** 订单状态查询结果 */\nexport interface OrderStatus {\n /** 商户订单号 */\n orderNo: string\n /** 渠道交易号 */\n transactionId?: string\n /** 订单状态 */\n status: OrderStatusValue\n /** 金额(分) */\n amount: number\n /** 支付时间 */\n paidAt?: Date\n}\n\n// ─── 退款 ───\n\n/** 退款入参 */\nexport interface RefundInput {\n /** 商户订单号 */\n orderNo: string\n /** 退款单号 */\n refundNo: string\n /** 退款金额(分) */\n amount: number\n /** 订单总金额(分),微信退款必填 */\n totalAmount?: number\n /** 退款原因 */\n reason?: string\n}\n\n/** 退款结果 */\nexport interface RefundResult {\n /** 退款单号 */\n refundNo: string\n /** 渠道退款 ID */\n refundId: string\n /** 退款状态 */\n status: 'processing' | 'success' | 'failed'\n}\n\n// ─── Provider 接口 ───\n\n/**\n * 支付 Provider 接口\n *\n * 各支付渠道(微信/支付宝/Stripe)实现此接口,\n * 由 payment 模块统一调度。\n */\nexport interface PaymentProvider {\n /** Provider 名称(如 'wechat', 'alipay', 'stripe') */\n readonly name: string\n\n /** 创建支付订单 */\n createOrder: (input: CreateOrderInput) => Promise<HaiResult<PaymentOrder>>\n\n /** 处理异步通知回调(验签 + 解析) */\n handleNotify: (request: PaymentNotifyRequest) => Promise<HaiResult<PaymentNotifyResult>>\n\n /** 查询订单状态 */\n queryOrder: (orderNo: string) => Promise<HaiResult<OrderStatus>>\n\n /** 申请退款 */\n refund: (input: RefundInput) => Promise<HaiResult<RefundResult>>\n\n /** 关闭订单 */\n closeOrder: (orderNo: string) => Promise<HaiResult<void>>\n}\n\n// ─── 函数接口 ───\n\n/** 支付模块函数接口 */\nexport interface PaymentFunctions {\n init: (config: PaymentConfigInput) => Promise<HaiResult<void>>\n close: () => Promise<void>\n readonly config: PaymentConfig | null\n readonly isInitialized: boolean\n createOrder: (providerName: string, input: CreateOrderInput) => Promise<HaiResult<PaymentOrder>>\n handleNotify: (providerName: string, request: PaymentNotifyRequest) => Promise<HaiResult<PaymentNotifyResult>>\n queryOrder: (providerName: string, orderNo: string) => Promise<HaiResult<OrderStatus>>\n refund: (providerName: string, input: RefundInput) => Promise<HaiResult<RefundResult>>\n closeOrder: (providerName: string, orderNo: string) => Promise<HaiResult<void>>\n getProvider: (name: string) => PaymentProvider | undefined\n registerProvider: (provider: PaymentProvider) => void\n}\n","{\n \"payment_createOrderFailed\": \"Failed to create payment order\",\n \"payment_queryOrderFailed\": \"Failed to query order status\",\n \"payment_refundFailed\": \"Refund request failed\",\n \"payment_closeOrderFailed\": \"Failed to close order\",\n \"payment_notifyVerifyFailed\": \"Payment notification verification failed\",\n \"payment_notifyParseFailed\": \"Failed to parse payment notification\",\n \"payment_signFailed\": \"Payment signature generation failed\",\n \"payment_providerNotFound\": \"Payment provider not found\",\n \"payment_invalidAmount\": \"Invalid payment amount\",\n \"payment_notInitialized\": \"Payment module not initialized, call payment.init() first\",\n \"payment_invokeWebFailed\": \"Failed to invoke web payment\",\n \"payment_invokeAppFailed\": \"Failed to invoke app payment\",\n \"payment_configError\": \"Payment config validation failed: {error}\",\n \"payment_initFailed\": \"Payment module initialization failed: {error}\",\n \"payment_configFieldRequired\": \"This config field is required\"\n}\n","{\n \"payment_createOrderFailed\": \"创建支付订单失败\",\n \"payment_queryOrderFailed\": \"查询订单状态失败\",\n \"payment_refundFailed\": \"退款请求失败\",\n \"payment_closeOrderFailed\": \"关闭订单失败\",\n \"payment_notifyVerifyFailed\": \"支付回调验签失败\",\n \"payment_notifyParseFailed\": \"解析支付回调失败\",\n \"payment_signFailed\": \"支付签名生成失败\",\n \"payment_providerNotFound\": \"未找到支付 Provider\",\n \"payment_invalidAmount\": \"支付金额无效\",\n \"payment_notInitialized\": \"支付模块未初始化,请先调用 payment.init()\",\n \"payment_invokeWebFailed\": \"调起网页支付失败\",\n \"payment_invokeAppFailed\": \"调起 App 支付失败\",\n \"payment_configError\": \"支付模块配置校验失败:{error}\",\n \"payment_initFailed\": \"支付模块初始化失败:{error}\",\n \"payment_configFieldRequired\": \"此配置字段必填\"\n}\n","/**\n * @h-ai/payment — i18n\n *\n * 模块 i18n 文案访问入口。\n * @module payment-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\ntype PaymentMessageKey = keyof typeof messagesZhCN\n\n/**\n * payment 模块 i18n 文案获取器\n *\n * @param key - 文案 Key\n * @returns 本地化后的文案字符串\n */\nexport const paymentM = core.i18n.createMessageGetter<PaymentMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { h as PaymentOrder } from '../payment-types-D1GvLKHg.js';
|
|
2
|
+
import { HaiResult } from '@h-ai/core';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @h-ai/payment/client — 客户端类型
|
|
7
|
+
*
|
|
8
|
+
* 客户端支付调起相关类型。
|
|
9
|
+
* @module payment-client-types
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** 支付调起结果 */
|
|
13
|
+
interface InvokePaymentResult {
|
|
14
|
+
/** 是否成功调起 */
|
|
15
|
+
invoked: boolean;
|
|
16
|
+
/** 额外信息 */
|
|
17
|
+
message?: string;
|
|
18
|
+
}
|
|
19
|
+
/** 支付调起选项 */
|
|
20
|
+
interface InvokePaymentOptions {
|
|
21
|
+
/** 支付订单(来自后端 createOrder 返回) */
|
|
22
|
+
order: PaymentOrder;
|
|
23
|
+
/** 成功回调 URL(Web 跳转场景) */
|
|
24
|
+
successUrl?: string;
|
|
25
|
+
/** 取消回调 URL */
|
|
26
|
+
cancelUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @h-ai/payment/client — Web/H5 支付调起
|
|
31
|
+
*
|
|
32
|
+
* 在浏览器或 H5 环境中调起微信/支付宝支付。
|
|
33
|
+
* @module payment-client-web
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 调起支付(Web / H5 通用入口)
|
|
38
|
+
*
|
|
39
|
+
* 根据 PaymentOrder 中的 provider 和 tradeType 自动选择调起方式。
|
|
40
|
+
*
|
|
41
|
+
* @param order - 后端返回的支付订单
|
|
42
|
+
* @returns 调起结果
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { invokePayment } from '@h-ai/payment/client'
|
|
47
|
+
*
|
|
48
|
+
* const orderResult = await api.call(paymentEndpoints.create, { ... })
|
|
49
|
+
* if (orderResult.success) {
|
|
50
|
+
* const result = await invokePayment(orderResult.data)
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function invokePayment(order: PaymentOrder): Promise<HaiResult<InvokePaymentResult>>;
|
|
55
|
+
|
|
56
|
+
export { type InvokePaymentOptions, type InvokePaymentResult, invokePayment };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { HaiPaymentError, paymentM } from '../chunk-4IUARFWH.js';
|
|
2
|
+
import { err, ok } from '@h-ai/core';
|
|
3
|
+
|
|
4
|
+
function invokeWechatJsapi(clientParams) {
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
const WeixinJSBridge = window.WeixinJSBridge;
|
|
7
|
+
if (!WeixinJSBridge) {
|
|
8
|
+
resolve({ invoked: false, message: "WeixinJSBridge not available" });
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
WeixinJSBridge.invoke("getBrandWCPayRequest", clientParams, (res) => {
|
|
12
|
+
resolve({
|
|
13
|
+
invoked: true,
|
|
14
|
+
message: res.err_msg
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function invokeWechatH5(clientParams) {
|
|
20
|
+
const h5Url = clientParams.h5Url;
|
|
21
|
+
if (h5Url) {
|
|
22
|
+
window.location.href = h5Url;
|
|
23
|
+
return { invoked: true };
|
|
24
|
+
}
|
|
25
|
+
return { invoked: false, message: "Missing h5Url" };
|
|
26
|
+
}
|
|
27
|
+
function invokeAlipayH5(clientParams) {
|
|
28
|
+
const formHtml = clientParams.form;
|
|
29
|
+
const payUrl = clientParams.pay_url;
|
|
30
|
+
if (formHtml) {
|
|
31
|
+
const parser = new DOMParser();
|
|
32
|
+
const doc = parser.parseFromString(formHtml, "text/html");
|
|
33
|
+
const form = doc.querySelector("form");
|
|
34
|
+
if (form) {
|
|
35
|
+
document.body.appendChild(document.adoptNode(form));
|
|
36
|
+
form.submit();
|
|
37
|
+
return { invoked: true };
|
|
38
|
+
}
|
|
39
|
+
return { invoked: false, message: "No form element found in response" };
|
|
40
|
+
}
|
|
41
|
+
if (payUrl) {
|
|
42
|
+
window.location.href = payUrl;
|
|
43
|
+
return { invoked: true };
|
|
44
|
+
}
|
|
45
|
+
return { invoked: false, message: "Missing alipay form or pay_url" };
|
|
46
|
+
}
|
|
47
|
+
function invokeStripeCheckout(clientParams) {
|
|
48
|
+
const checkoutUrl = clientParams.checkoutUrl;
|
|
49
|
+
if (checkoutUrl) {
|
|
50
|
+
window.location.href = checkoutUrl;
|
|
51
|
+
return { invoked: true };
|
|
52
|
+
}
|
|
53
|
+
return { invoked: false, message: "Missing checkoutUrl" };
|
|
54
|
+
}
|
|
55
|
+
async function invokePayment(order) {
|
|
56
|
+
try {
|
|
57
|
+
let result;
|
|
58
|
+
switch (order.provider) {
|
|
59
|
+
case "wechat":
|
|
60
|
+
if (order.tradeType === "jsapi") {
|
|
61
|
+
result = await invokeWechatJsapi(order.clientParams);
|
|
62
|
+
} else {
|
|
63
|
+
result = invokeWechatH5(order.clientParams);
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
case "alipay":
|
|
67
|
+
result = invokeAlipayH5(order.clientParams);
|
|
68
|
+
break;
|
|
69
|
+
case "stripe":
|
|
70
|
+
result = invokeStripeCheckout(order.clientParams);
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
return err(
|
|
74
|
+
HaiPaymentError.INVOKE_WEB_FAILED,
|
|
75
|
+
paymentM("payment_invokeWebFailed")
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return ok(result);
|
|
79
|
+
} catch (cause) {
|
|
80
|
+
return err(
|
|
81
|
+
HaiPaymentError.INVOKE_WEB_FAILED,
|
|
82
|
+
paymentM("payment_invokeWebFailed"),
|
|
83
|
+
cause
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { invokePayment };
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
90
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/payment-client-web.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/payment/client — Web/H5 支付调起\n *\n * 在浏览器或 H5 环境中调起微信/支付宝支付。\n * @module payment-client-web\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { PaymentOrder } from '../payment-types.js'\nimport type { InvokePaymentResult } from './payment-client-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { paymentM } from '../payment-i18n.js'\nimport { HaiPaymentError } from '../payment-types.js'\n\n/**\n * Web/H5 环境调起微信支付(JSAPI)\n *\n * 需要在微信内置浏览器中使用,依赖 WeixinJSBridge。\n */\nfunction invokeWechatJsapi(clientParams: Record<string, unknown>): Promise<InvokePaymentResult> {\n return new Promise((resolve) => {\n const WeixinJSBridge = (window as unknown as Record<string, unknown>).WeixinJSBridge as {\n invoke: (api: string, params: unknown, callback: (res: { err_msg: string }) => void) => void\n } | undefined\n\n if (!WeixinJSBridge) {\n resolve({ invoked: false, message: 'WeixinJSBridge not available' })\n return\n }\n\n WeixinJSBridge.invoke('getBrandWCPayRequest', clientParams, (res) => {\n resolve({\n invoked: true,\n message: res.err_msg,\n })\n })\n })\n}\n\n/**\n * Web/H5 环境调起微信 H5 支付\n *\n * 通过跳转 URL 唤起微信客户端支付。\n */\nfunction invokeWechatH5(clientParams: Record<string, unknown>): InvokePaymentResult {\n const h5Url = clientParams.h5Url as string | undefined\n if (h5Url) {\n window.location.href = h5Url\n return { invoked: true }\n }\n return { invoked: false, message: 'Missing h5Url' }\n}\n\n/**\n * Web 环境调起支付宝(H5 跳转)\n */\nfunction invokeAlipayH5(clientParams: Record<string, unknown>): InvokePaymentResult {\n const formHtml = clientParams.form as string | undefined\n const payUrl = clientParams.pay_url as string | undefined\n\n if (formHtml) {\n // 支付宝返回的 HTML form,使用 DOMParser 安全解析后提交\n const parser = new DOMParser()\n const doc = parser.parseFromString(formHtml, 'text/html')\n const form = doc.querySelector('form')\n if (form) {\n document.body.appendChild(document.adoptNode(form))\n form.submit()\n return { invoked: true }\n }\n return { invoked: false, message: 'No form element found in response' }\n }\n\n if (payUrl) {\n window.location.href = payUrl\n return { invoked: true }\n }\n\n return { invoked: false, message: 'Missing alipay form or pay_url' }\n}\n\n/**\n * Web 环境调起 Stripe Checkout\n */\nfunction invokeStripeCheckout(clientParams: Record<string, unknown>): InvokePaymentResult {\n const checkoutUrl = clientParams.checkoutUrl as string | undefined\n if (checkoutUrl) {\n window.location.href = checkoutUrl\n return { invoked: true }\n }\n return { invoked: false, message: 'Missing checkoutUrl' }\n}\n\n/**\n * 调起支付(Web / H5 通用入口)\n *\n * 根据 PaymentOrder 中的 provider 和 tradeType 自动选择调起方式。\n *\n * @param order - 后端返回的支付订单\n * @returns 调起结果\n *\n * @example\n * ```ts\n * import { invokePayment } from '@h-ai/payment/client'\n *\n * const orderResult = await api.call(paymentEndpoints.create, { ... })\n * if (orderResult.success) {\n * const result = await invokePayment(orderResult.data)\n * }\n * ```\n */\nexport async function invokePayment(order: PaymentOrder): Promise<HaiResult<InvokePaymentResult>> {\n try {\n let result: InvokePaymentResult\n\n switch (order.provider) {\n case 'wechat':\n if (order.tradeType === 'jsapi') {\n result = await invokeWechatJsapi(order.clientParams)\n }\n else {\n result = invokeWechatH5(order.clientParams)\n }\n break\n case 'alipay':\n result = invokeAlipayH5(order.clientParams)\n break\n case 'stripe':\n result = invokeStripeCheckout(order.clientParams)\n break\n default:\n return err(\n HaiPaymentError.INVOKE_WEB_FAILED,\n paymentM('payment_invokeWebFailed'),\n )\n }\n\n return ok(result)\n }\n catch (cause) {\n return err(\n HaiPaymentError.INVOKE_WEB_FAILED,\n paymentM('payment_invokeWebFailed'),\n cause,\n )\n }\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { P as PaymentFunctions } from './payment-types-D1GvLKHg.js';
|
|
2
|
+
export { A as AlipayConfig, a as AlipayConfigSchema, C as CreateOrderInput, H as HaiPaymentError, O as OrderStatus, b as OrderStatusValue, c as PaymentConfig, d as PaymentConfigInput, e as PaymentConfigSchema, f as PaymentNotifyRequest, g as PaymentNotifyResult, h as PaymentOrder, i as PaymentProvider, R as RefundInput, j as RefundResult, S as StripeConfig, k as StripeConfigSchema, T as TradeType, W as WechatPayConfig, l as WechatPayConfigSchema } from './payment-types-D1GvLKHg.js';
|
|
3
|
+
import '@h-ai/core';
|
|
4
|
+
import 'zod';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @h-ai/payment — 模块入口(生命周期管理)
|
|
8
|
+
*
|
|
9
|
+
* 提供支付模块的初始化、Provider 注册与统一支付操作 API。
|
|
10
|
+
* `payment.init(config)` 负责根据配置自动注册可用的 Provider。
|
|
11
|
+
*
|
|
12
|
+
* @module payment-main
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 支付模块服务对象
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { payment } from '@h-ai/payment'
|
|
21
|
+
*
|
|
22
|
+
* await payment.init({
|
|
23
|
+
* wechat: { mchId: '...', apiV3Key: '...', ... },
|
|
24
|
+
* alipay: { appId: '...', privateKey: '...' , ... },
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* const result = await payment.createOrder('wechat', {
|
|
28
|
+
* orderNo: 'ORD001',
|
|
29
|
+
* amount: 100,
|
|
30
|
+
* description: '测试商品',
|
|
31
|
+
* tradeType: 'jsapi',
|
|
32
|
+
* userId: 'openid-xxx',
|
|
33
|
+
* notifyUrl: 'https://api.example.com/payment/notify/wechat',
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare const payment: PaymentFunctions;
|
|
38
|
+
|
|
39
|
+
export { PaymentFunctions, payment };
|