Apple Pay
Apple Pay 是一款全球消费者广泛使用的数字钱包,用于电子商务购物,通过提供更快速、更安全的结账体验来提高支付转化率。Apple Pay 占据了全球数字钱包市场份额的 30%,消费者可以无缝访问已保存的卡信息,并在无需手动输入的情况下完成支付。

支付方式属性
| 属性 | 内容 |
|---|---|
| 可用国家代码 | 香港(HK)、美国 (US)、英国(EU)、欧洲(UK) |
| 消费者货币 | AUD, CAD, CHF, CZK, DKK, EUR, GBP, HKD, HUF, IDR, JPY, MXN, NOK, NZD, PEN, PLN, SEK, SGD, THB, USD, ZAR |
| 处理货币 | 美元 (USD) |
| 结算货币 | 美元 (USD) |
| 类型 I | 信用卡及借记卡(Cards) |
| 类型 II | applepayus |
| 最小交易金额 | 币种的最小单位乘以 2 (即如果币种为 USD,基于最小单位是 1 美分,则最小支付金额为 2 美分) |
| 最大交易金额 | 无限制 |
| 会话超时 | 1 小时,取决于流程 |
| 退款 | 支持全额退款、部分退款和多次部分退款 |
| 退款有效期 | 360 天 |
| 拒付 | 180 天 |
当国家代码与处理货币不一致时,FuturePay会按照国际卡费率处理交易。
1. 概述
Apple Pay 是 Apple 提供的安全支付方式,用户使用绑定在 Apple 钱包中的银行卡,通过 Face ID / Touch ID 快速完成付款。FuturePay 支持以下三种集成方式:
| 集成方式 | 适用场景 | 域名报备 | 商户开发量 |
|---|---|---|---|
| 收银台链接 | 跳转到 FuturePay 收银台付款 | 不需要 | 最少 |
| SDK 弹窗 | 在商户网页中嵌入 FuturePay SDK 弹窗 | 需要 | 少 |
| API 直连(新增) | 商户在自己的页面中自行渲染 Apple Pay 按钮、完全控制交互 | 需要 | 较多 |
- Apple Pay 只能在 HTTPS 网页 中使用,需在 Safari 或其他支持 Apple Pay 的浏览器、且用户设备已绑卡时才会展示。
- 三种方式均不支持原生 iOS App 内直接调起 Apple Pay。
- API 直连目前按白名单开通,如需使用请联系 FuturePay 商务或技术支持。
2. 收银台链接方式
商户通过 FuturePay 创建订单接口获取收银台 URL,用户跳转到收银台完成 Apple Pay 付款。
- 特点:无需域名报备,开箱即用
- 流程:
- 商户调用创建支付订单接口
- FuturePay 返回收银台链接
- 用户跳转收银台完成付款
- FuturePay 通过 Webhook 异步通知商户支付结果
3. SDK 弹窗方式
商户在自己的网页中嵌入 FuturePay SDK,用户在 SDK 弹窗中直接选择 Apple Pay 付款。
- 特点:Apple 要求调起 Apple Pay 的域名必须事先报备并验证,流程见 第 5 节 域名报备。
4. API 直连方式(新增)
商户在自己的页面中使用 Apple Pay JS 渲染按钮、调起支付面板,通过 FuturePay 接口完成商户验证与扣款。商户对按钮位置、页面交互拥有完全控制权。
4.1 整体流程
用户浏览器(商户页面) 商户后端 FuturePay
│ │ │
①点击 Apple Pay 按钮 │ │
new ApplePaySession(...) │ │
session.begin() │ │
│ │ │
②onvalidatemerchant ────────► │ ③POST /payin/applePaySession ►│ 向 Apple 申请 merchant session
│ │ ◄──────────── data ──────────│
completeMerchantValidation ◄──│ │
(data) │ │
│ │ │
④用户在面板中授权付款 │ │
onpaymentauthorized ────────► │ ⑤POST /payin/paymentOrder ──►│ 解密 token 并扣款
│ │ ◄────────── 支付结果 ─────────│
completePayment(status) ◄─────│ │
│ │ ◄──── ⑥Webhook 异步通知 ──────│
关键要求:
- 步骤 ③、⑤ 必须由商户后端调用,签名密钥不能放在前端。
- 调起 Apple Pay 的页面域名必须已完成报备(见第 5 节),否则步骤 ③ 会被拒绝。
- 每次付款都要重新申请 merchant session,session 只能使用一次,且有效期很短(约 5 分钟),不要缓存。
4.2 前端唤起 Apple Pay
<script src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script>
<apple-pay-button buttonstyle="black" type="buy" locale="zh-CN" onclick="onApplePayClicked()"></apple-pay-button>function onApplePayClicked() {
// 必须在用户点击事件中【同步】创建并 begin,不能先 await 其他请求
const session = new ApplePaySession(3, {
countryCode: 'US', // 收单国家,开通时由 FuturePay 告知(如 US / HK)
currencyCode: 'USD', // 与下单币种一致
supportedNetworks: ['visa', 'masterCard'],
merchantCapabilities: ['supports3DS'],
total: { label: 'Example Shop', amount: '10.00' } // 与下单金额一致
});
// ② 商户验证:调用商户自己的后端,由后端转调 FuturePay /payin/applePaySession
session.onvalidatemerchant = async () => {
try {
const merchantSession = await fetch('/your-api/apple-pay/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ domain: window.location.hostname })
}).then(r => r.json());
// 传入 FuturePay 响应中的 data 字段,而不是整个响应体
session.completeMerchantValidation(merchantSession);
} catch (e) {
session.abort();
}
};
// ④ 用户授权后,把 token 交给商户后端,由后端调用 FuturePay /payin/paymentOrder
session.onpaymentauthorized = async (event) => {
const result = await fetch('/your-api/apple-pay/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: event.payment.token })
}).then(r => r.json());
session.completePayment(result.success
? ApplePaySession.STATUS_SUCCESS
: ApplePaySession.STATUS_FAILURE);
};
session.begin();
}页面通过 iframe 嵌入时:iframe 需要加
allow="payment"属性,申请 session 时domain填顶层页面的域名,且顶层页面域名需完成报备。
4.3 接口一:申请 Merchant Session
商户后端在前端触发 onvalidatemerchant 时调用,返回 Apple 签发的 merchant session。
端点
| 环境 | 地址 |
|---|---|
| 生产 | POST https://api.futurepay.global/payin/applePaySession |
| 沙箱 | POST https://api.futurepay-develop.com/payin/applePaySession |
鉴权:与创建支付订单接口 /payin/paymentOrder 完全一致——请求头携带 merchantId、appId、Authorization(签名),Content-Type: application/json;开启了 IP 白名单的商户需从白名单 IP 调用。
请求参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
domain | 是 | String | 调起 Apple Pay 的页面域名,即前端的 window.location.hostname。只填域名,不带协议、端口和路径,例如 shop.example.com。必须已完成报备 |
displayName | 否 | String | 支付面板上显示的商户名,最长 64 个字符。不传时使用商户在 FuturePay 登记的名称 |
请求示例
{
"domain": "shop.example.com",
"displayName": "Example Shop"
}响应参数
| 字段 | 类型 | 说明 |
|---|---|---|
code | String | 0 表示成功,其他见 4.5 错误码 |
msg | String | 结果说明 |
data | Object | Apple merchant session。原样传给前端 session.completeMerchantValidation(data),不要修改其中任何字段 |
响应示例
{
"code": "0",
"msg": "succeeded",
"data": {
"epochTimestamp": 1761100000000,
"expiresAt": 1761103600000,
"merchantSessionIdentifier": "SSH1A2B3C4D5E6F...",
"nonce": "8a1b2c3d",
"merchantIdentifier": "4F1E2D3C...",
"domainName": "shop.example.com",
"displayName": "Example Shop",
"signature": "308006092a864886f70d0107...",
"operationalAnalyticsIdentifier": "...",
"retries": 0
}
}4.4 接口二:提交 Apple Pay 支付
用户在面板中授权付款后,前端在 onpaymentauthorized 中拿到 event.payment.token,交由商户后端调用创建支付订单接口完成扣款。
端点:POST /payin/paymentOrder(与常规 API 下单为同一接口,鉴权方式相同)
Apple Pay 相关参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
paymentMethod.type | 是 | String | 固定 applepayus |
paymentMethod.applePayToken | 是 | String | event.payment.token 整个对象序列化成的 JSON 字符串(包含 paymentData、paymentMethod、transactionIdentifier)。注意是字符串,不是对象 |
amount.value | 是 | Long | 支付金额,最小货币单位,必须与前端 total.amount 一致 |
amount.currency | 是 | String | 支付币种,ISO 4217,必须与前端 currencyCode 一致 |
其余字段(reference、shopperIP、returnUrl、Webhook 地址等)与常规 API 下单相同,请参考《创建支付订单》接口文档。
请求示例
{
"reference": "ORDER-20261022-0001",
"amount": { "value": 1000, "currency": "USD" },
"shopperIP": "203.0.113.10",
"paymentMethod": {
"type": "applepayus",
"applePayToken": "{\"paymentData\":{\"data\":\"...\",\"signature\":\"...\",\"header\":{\"publicKeyHash\":\"...\",\"ephemeralPublicKey\":\"...\",\"transactionId\":\"...\"},\"version\":\"EC_v1\"},\"paymentMethod\":{\"displayName\":\"Visa 1234\",\"network\":\"Visa\",\"type\":\"debit\"},\"transactionIdentifier\":\"...\"}"
}
}响应与结果通知:与常规 API 下单一致。商户后端根据同步响应决定前端调用 STATUS_SUCCESS 还是 STATUS_FAILURE,最终支付结果以 Webhook 通知或订单查询为准。
4.5 错误码
申请 Merchant Session 接口的错误码:
| code | 含义 | 处理建议 |
|---|---|---|
0 | 成功 | 把 data 传给 completeMerchantValidation |
40001 | 缺少参数(domain 为空,或未传 displayName 且商户名称未登记) | 补齐参数 |
40000 | 参数错误(domain 不是合法域名或带了协议/端口/路径;displayName 超过 64 个字符) | 按说明修正参数 |
40026 | 域名未报备,或该域名不属于当前商户 | 按第 5 节完成报备;确认 domain 填的是顶层页面域名 |
40025 | Apple 返回错误或请求超时 | 可提示用户稍后重试;持续出现请联系 FuturePay,常见原因是域名验证文件被删除或失效 |
40007 | 签名无效 | 检查签名算法和密钥 |
40011 | IP 不在白名单 | 从已登记的服务器 IP 调用 |
429 | 请求过于频繁 | 降低调用频率 |
提交支付接口的错误码与常规 API 下单一致。
5. 域名报备(SDK 弹窗 / API 直连通用)
Apple 要求每一个调起 Apple Pay 的域名都必须事先报备并验证。主域名和子域名需要分别报备,例如 example.com 与 www.example.com、shop.example.com 是三个不同的域名。
流程:
-
商户提交域名
将需要调起 Apple Pay 的完整域名列表提供给 FuturePay 技术支持,并说明使用 SDK 弹窗还是 API 直连。 -
FuturePay 提供验证文件
FuturePay 向商户提供域名验证文件apple-developer-merchantid-domain-association.txt。 -
商户部署验证文件
将文件放到每个报备域名的以下路径,保证公网可以通过 HTTPS 直接访问:https://{你的域名}/.well-known/apple-developer-merchantid-domain-association.txt- 文件名保留
.txt扩展名,内容不得修改; - 必须返回 HTTP 200,不能重定向、不能需要登录、不能被 WAF / CDN 拦截;
- 验证通过后请勿删除该文件,Apple 会不定期复核,文件失效会导致 Apple Pay 不可用。
- 文件名保留
-
FuturePay 向 Apple 报备并验证
商户告知部署完成后,FuturePay 向 Apple 提交该域名并完成验证。 -
开通完成
FuturePay 通知商户开通结果,之后即可在该域名下使用 Apple Pay。
6. 注意事项
- 收银台链接方式无需域名报备,可直接使用;SDK 弹窗与 API 直连必须先完成域名报备。
- API 直连中,申请 session 与提交支付都必须由商户后端调用,切勿在前端暴露签名密钥。
- 前端
total.amount/currencyCode必须与下单的amount一致,否则用户看到的金额与实际扣款不符。 new ApplePaySession(...)和session.begin()必须在用户点击事件中同步执行,否则浏览器会拒绝调起。- 新增、变更或下线域名请提前联系 FuturePay;域名验证文件需长期保留。
- Apple Pay 支付的退款、查询、拒付处理与卡支付一致,使用相同接口。
Updated 10 days ago