本次新增的是买家端 PayPal 支付能力。
前端需要理解的业务边界:
PayPal 只作为支付渠道,不是 artist 入驻方式。CNY 的场景。PayPal 支付时,后端会把外部支付金额换算成 USD 发起支付。Alipay 钱包和提现账户。前端对接时,可以把 PayPal 理解成“和 Alipay 一样需要跳转到外部页面支付”的渠道。
POST /api/user/pay/work_task/pre_calc
用途:
pay_channel 现在支持 paypal。请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
work_task_id | number | 是 | work task id |
type | string | 是 | stage_pay / full_pay / price_change |
pay_channel | string | 是 | stripe / alipay / paypal |
wallets | number[] | 否 | 参与抵扣的 credit wallet id 列表 |
请求示例:
响应要点:
data.before_amount、data.after_amount、data.process。CNY 且 pay_channel=paypal 时,after_amount.currency.code 会变成 USD。USD 发起,不表示 artist 收款币种变更。响应示例:
POST /api/user/pay/work_task/create_checkout_session
用途:
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
work_task_id | number | 是 | work task id |
type | string | 是 | stage_pay / full_pay / price_change |
pay_channel | string | 是 | stripe / alipay / paypal |
wallets | number[] | 否 | 参与抵扣的 credit wallet id 列表 |
callback | string | 否 | 外部支付完成后回跳前端页面地址。alipay/paypal 场景建议传当前页面 URL |
前端处理规则:
pay_channel=stripe
pay_data.client_secret 和 pay_data.checkout_session_id 打开现有 Stripe 支付弹窗。pay_channel=alipay
pay_data.pay_url 打开新标签页或新窗口。pay_channel=paypal
pay_data.pay_url 打开新标签页或新窗口。amount=0
响应示例:
说明:
pay_url / paypal_order_id 是兼容字段。pay_channel + pay_data 即可,不要依赖顶层兼容字段。POST /api/user/pay/work_task/confirm_zero
用途:
create_checkout_session 返回 amount = 0 时,前端调用此接口完成支付确认。请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
out_trade_no | string | 是 | 订单号 |
说明:
out_trade_no 来自零金额场景的 pay_data.out_trade_no。paypal 非零金额支付不调用这个接口。POST /api/orders/continue
用途:
paying 订单时,继续支付未完成订单。请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | number | 是 | order id |
前端处理规则:
data.pay_channel == stripe
data.pay_data.client_secret 和 data.pay_data.checkout_session_id。data.pay_channel == paypal
data.pay_data.pay_url 打开新标签页或新窗口。alipay 继续支付返回分支,前端不需要为这个接口补 alipay 处理。响应示例:
说明:
client_secret / checkout_session_id / pay_url。pay_channel + pay_data。POST /api/user/pay/product/pre_calc
用途:
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
product_option_id | number | 是 | product option id |
pay_channel | string | 是 | stripe / alipay / paypal |
wallets | number[] | 否 | 参与抵扣的 credit wallet id 列表 |
响应规则与 work task 相同:
CNY + paypal 时,after_amount.currency.code 会是 USD。POST /api/user/pay/product/create_checkout_session
用途:
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
product_option_id | number | 是 | product option id |
pay_channel | string | 是 | stripe / alipay / paypal |
wallets | number[] | 否 | 参与抵扣的 credit wallet id 列表 |
前端处理规则:
pay_channel=stripe
pay_data.client_secret 和 pay_data.checkout_session_id 打开 Stripe 弹窗。pay_channel=alipay
pay_data.pay_url 打开新标签页或新窗口。pay_channel=paypal
pay_data.pay_url 打开新标签页或新窗口。amount=0
响应示例:
POST /api/user/pay/product/confirm_zero
用途:
0 时,前端调用此接口完成支付确认。请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
license_id | number | 是 | product license id |
说明:
license_id 来自零金额场景的 pay_data.license_id。POST /api/product_licenses/continue_payment
用途:
paying 状态时继续支付。请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
license_id | number | 是 | product license id |
前端处理规则:
data.pay_channel == stripe
data.pay_data.client_secret 和 data.pay_data.checkout_session_id。data.pay_channel == alipay
data.pay_data.pay_url 打开新标签页或新窗口。data.pay_channel == paypal
data.pay_data.pay_url 打开新标签页或新窗口。amount = 0
响应示例:
建议前端统一按下面的方式分支,不再为不同页面写多套判断:
建议:
pay_channel + pay_data。PayPal 交互按 Alipay 的外跳模式处理,不要走 Stripe 弹窗。前端展示 PayPal 支付入口时,应限制在原始币种为 CNY 的场景。
如果前端仍把 paypal 提交给非 CNY 订单,后端会返回:
或:
对于 CNY + paypal:
CNY。USD。amount/currency 可能是 USD。前端不要把这理解成 artist 改为美元结算。
work task 的 alipay/paypal 外部支付,建议在 create_checkout_session 时传当前页面 URL 作为 callback。
这样用户在 PayPal 页面支付完成或取消后,后端可以回跳到原页面。
当前前端商品续付页如果只判断 stripe/alipay,会漏掉 paypal。
需要按 data.pay_channel === 'paypal' 增加外跳处理。
下面这些接口是后端内部支付回调使用,前端不需要主动调用:
GET /api/user/paypal/returnGET /api/user/paypal/cancelPOST /api/user/paypal/notify前端只需要:
pay_url如果前端只做最小改动,至少需要补这几处:
paypalpaypal 分支,行为与 alipay 类似:外跳 pay_urlpaypal 分支,行为与 alipay 类似:外跳 pay_urlpaypal 分支pay_channel + pay_data 处理支付结果