HarmonyOS NEXT 如何对接支付宝代扣并拉起免密支付签约页
结论
支付宝代扣(周期扣款/免密代扣)的签约请求应由服务端创建。HarmonyOS NEXT 应用负责打开支付宝签约收银台,并在用户返回后查询最终签约状态。
服务端通常可以通过支付宝开放平台接口 alipay.user.agreement.page.sign 创建签约页面。能否直接使用 HarmonyOS NEXT 官方 Demo,以及支付宝客户端 SDK 是否支持原生拉起,要看支付宝开放平台当前发布的 HarmonyOS SDK 和商户已有的产品权限,不能直接套用 Android 或 iOS SDK。
如果没有适用的 HarmonyOS SDK,可以由服务端生成签约表单,再通过 HarmonyOS Web 组件加载中转页。
推荐的对接流程
对接流程可以按以下步骤完成:
- 在支付宝开放平台申请代扣类产品并完成签约。
- 服务端调用
alipay.user.agreement.page.sign。 - 服务端返回一个 HTTPS 中转页地址。
- HarmonyOS NEXT 使用
Web组件打开该地址。 - 中转页自动提交支付宝返回的 HTML Form,进入签约页面。
- 支付宝通过
notify_url异步通知服务端。 - 应用回到前台后,向业务服务端查询签约结果。
- 后续扣款由服务端发起。客户端不能保存商户私钥,也不能直接构造扣款请求。
产品码、签约场景和必填参数应以商户实际开通的代扣产品文档为准,不同代扣产品之间不能直接复用这些配置。
服务端创建签约请求
下面使用 Java 和支付宝开放平台 SDK 的常见调用形式进行说明。示例中的产品码和场景值都是占位符,接入时需要替换为开放平台给当前商户产品配置的真实值。
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayUserAgreementPageSignRequest request =
new AlipayUserAgreementPageSignRequest();
request.setNotifyUrl("https://api.example.com/alipay/agreement/notify");
request.setReturnUrl("https://m.example.com/alipay/agreement/return");
JSONObject bizContent = new JSONObject();
bizContent.put("personal_product_code", "请填写实际开通产品的产品码");
bizContent.put("sign_scene", "请填写实际签约场景");
bizContent.put("external_agreement_no", createUniqueAgreementNo());
bizContent.put("access_params", new JSONObject()
.fluentPut("channel", "ALIPAYAPP"));
request.setBizContent(bizContent.toJSONString());
AlipayUserAgreementPageSignResponse response =
alipayClient.pageExecute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
"创建支付宝签约请求失败:" +
response.getCode() + " " +
response.getSubMsg()
);
}
// pageExecute 通常返回需要提交到支付宝网关的 HTML Form。
// 建议将其保存在一次性中转页中,不要把商户私钥或签名逻辑放到客户端。
String formHtml = response.getBody();
external_agreement_no 由商户生成,并且需要在业务范围内保持唯一。不要直接用用户手机号等敏感信息作为协议号。
构造 HTTPS 中转页
支付宝页面类接口通常返回一段自动提交的 HTML Form,并不是可以直接拼接参数的普通 URL。因此,服务端可以提供一个短时有效的签约中转地址,例如:
https://m.example.com/alipay/agreement/start?token=一次性随机令牌
服务端收到请求后,根据令牌取出对应的支付宝 Form,并以 HTML 形式返回:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1"
>
<title>正在跳转到支付宝</title>
</head>
<body>
<!-- 服务端在此输出支付宝 SDK pageExecute 返回的完整 Form -->
</body>
</html>
令牌的有效期应尽量短,最好只能使用一次。商户私钥、完整签名参数和可重复使用的业务凭证都不能下发给应用。
HarmonyOS NEXT 端打开签约页
如果没有适用的支付宝 HarmonyOS 原生 SDK,可以使用 ArkUI 的 Web 组件加载服务端中转页。
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct AgreementPage {
controller: webview.WebviewController = new webview.WebviewController();
private agreementUrl: string =
'https://m.example.com/alipay/agreement/start?token=ONE_TIME_TOKEN';
build() {
Column() {
Web({
src: this.agreementUrl,
controller: this.controller
})
.width('100%')
.height('100%')
.javaScriptAccess(true)
.domStorageAccess(true)
.onPageEnd(() => {
// 页面结束加载不代表签约成功。
// 可在应用回到前台后向业务服务端查询签约状态。
})
}
}
}
如果页面需要跳转到支付宝客户端,应优先采用支付宝官方 SDK 或官方文档指定的跳转方式。不要自行猜测或硬编码支付宝私有 URL Scheme。客户端版本、系统能力和安全策略的差异都可能造成拉起失败。
使用 Web 组件时,还需要确认以下事项:
- 应用已经声明网络访问权限。
- 中转页和回跳地址都使用可信的 HTTPS 域名。
- Web 页面跳转策略允许访问支付宝官方域名。
- 对非 HTTPS 地址、未知域名和自定义 Scheme 进行拦截及白名单校验。
- 日志中不记录签约表单、令牌或用户身份参数。
获取签约结果
return_url 只能说明用户的浏览器发生了回跳,不能用来判定签约成功。用户可能取消操作,也可能在回跳前关闭页面。
签约结果应按以下方式处理:
- 服务端接收支付宝发送到
notify_url的异步通知。 - 严格验证支付宝签名。
- 校验通知中的商户应用、协议号和业务状态。
- 通过
external_agreement_no更新本地签约记录。 - HarmonyOS 应用向自己的服务端查询签约状态。
客户端查询接口可以设计为:
GET /api/payment/agreement/status?agreementNo=AGREEMENT_202609090001
Authorization: Bearer <access-token>
示例响应:
{
"agreementNo": "AGREEMENT_202609090001",
"status": "SIGNED",
"alipayAgreementNo": "支付宝返回的协议号"
}
服务端可以自行定义 INIT、SIGNING、SIGNED、CANCELLED、FAILED 等状态,避免客户端直接依赖支付宝的原始状态值。
关于 HarmonyOS Demo
HarmonyOS 提供 Web 组件、应用跳转和网络请求等基础能力。支付宝代扣则属于支付宝开放平台业务,使用的核心接口、SDK 和示例需要以支付宝开放平台相应产品的文档为准。
接入时需要区分以下情况:
- HarmonyOS 通用支付示例不是代扣签约示例。
- 支付宝 App 支付 SDK 支持 HarmonyOS,不代表该 SDK 一定包含代扣签约接口。
- Android 的 AAR、Activity、Intent 和
alipays://示例不能直接移植到 HarmonyOS NEXT。 - 如果支付宝提供 HarmonyOS NEXT 专用 SDK,应优先使用官方包、API 和示例工程。
- 如果官方只提供服务端页面签约接口,可以使用 HTTPS 中转页配合 ArkUI
Web组件。
接入前,需要在支付宝开放平台确认商户是否已经开通相应的代扣产品,并核对 personal_product_code、sign_scene、签约参数、回调验签规则和 HarmonyOS SDK 的支持范围。如果商户没有对应的产品权限,即使成功拉起页面,也无法完成有效签约。
备注:内容仅供参考。
