概览
它是什么
通过MONDO接受Apple Pay支付
您需要的
MONDO 账户 ID + 密钥
您发送的内容
Apple Pay 令牌 + 金额 + 货币
您获得的内容
已完成或已拒绝状态
如何使用
选项A:自托管
您在您的网站上显示Apple Pay按钮并发送令牌给我们
选项B:MONDO托管
我们处理一切 - 只需将您的客户重定向给我们
快速启动(自托管)
POST https://server-to-server.getmondo.co/payment/
{
"company_account_id": "your_id",
"gateway_secret_key": "your_key",
"apple_pay_token": { /* from Apple Pay JS */ },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox"
}
关于Apple Pay
Apple Pay 提供了一种快速、安全且私密的支付方式。使用 MONDO 作为您的支付服务提供商(PSP),您可以接受 Apple Pay,无需自己的苹果开发者账户。
MONDO 作为您的 PSP
- ✓ MONDO拥有苹果商户ID
- ✓ MONDO 管理 Apple Pay 证书
- ✓ MONDO 处理商户验证
- ✓ MONDO 解密并处理支付令牌
令牌处理 — 谁来做什么?
Apple Pay 使用端到端加密来保护持卡人数据。以下是责任分配方式:
| 苹果(客户的设备) | 生成包含卡信息、加密图案和认证详情的加密支付令牌 |
| 您 (商家) | 将加密令牌直接通过apple_pay_token参数传递给MONDO — 不要尝试解密 |
| MONDO (PSP) | 使用我们的Apple Pay支付处理证书解密令牌并通过CardCorp处理支付 |
选择集成方式
📋 先决条件
- ✓ 合作伙伴账户 ID - 您的独特MONDO账户标识
- ✓ 合作伙伴密钥 - 您的API认证密钥
- ✓ HTTPS - 您的网站必须使用 HTTPS
⚠️ 域名验证需要
您的域名必须通过MONDO在Apple注册。这是一次性设置。
- 前往 GETMONDO.CO
- Login → Developer → Apple Pay → Add Apple Pay Domain
🔄 支付流程
在您的网站上
原生 Apple Pay 界面
您的 JS 调用 MONDO 的验证端点
Face ID / Touch ID
POST to /payment/ with apple_pay_token
用户重定向到成功/失败网址
🔗 API 端点
商户验证端点
商户验证参数
| 参数 | 类型 | 需要 | 描述 |
|---|---|---|---|
| validationURL | string | ✓ 是 | Apple 提供的 URL onvalidatemerchant 事件 |
| company_account_id | string | ✓ 是 | 您的MONDO合作伙伴账户ID |
| gateway_secret_key | string | ✓ 是 | 您的MONDO合作伙伴密钥 |
| domain_name | string | ○ 条件的 | 您的Apple Pay域名(例如 paynow.yoursite.com). 用于服务器到服务器的调用,当浏览器的 Origin 头不可用时需要。如果直接从浏览器调用,则不需要。 |
如果您的后端代理商户验证调用(即您的服务器调用MONDO而不是浏览器直接调用),您必须包括
domain_name 设置到显示您的 Apple Pay 按钮的域。这确保 Apple Pay 会话与您的支付页面域相匹配。 📝 所需参数 (支付处理)
| 参数 | 类型 | 描述 |
|---|---|---|
| company_account_id | string | 您的MONDO合作伙伴账户ID |
| gateway_secret_key | string | 您的MONDO合作伙伴密钥 |
| apple_pay_token | object | 加密 来自event.payment.token — pass directly to MONDO as-is (不要解密) |
| transaction_amount | decimal | 支付金额(例如,99.99) |
| transaction_currency_iso3 | string | 货币代码(EUR, USD, GBP) |
| cardholder_email_address | string | 客户的电子邮件 |
可选参数
| 参数 | 描述 |
|---|---|
| partner_return_url_completed | 支付成功重定向网址 |
| partner_return_url_rejected | 拒绝付款重定向的 URL |
| partner_webhook_url | Webhook 通知的 URL |
| live_or_sandbox | live 或者 sandbox |
📤 API 响应
Apple Pay 支付立即处理。响应包含最终交易状态:
{
"status": "success",
"transaction_status": "COMPLETED",
"gateway_session_id": "73d68b79579eeaa4a1f35f667509ba19",
"transaction_id": "37819a4707f3736b6fb42148d98f05ab",
"gateway_message": "Transaction succeeded",
"redirect_url": "https://yoursite.com/success?gateway_session_id=...&payment_status=COMPLETED"
}
响应字段
| 字段 | 描述 |
|---|---|
| status | success 或者 error |
| transaction_status | COMPLETED 或者 REJECTED |
| gateway_session_id | 此次交易的唯一会话标识符 |
| transaction_id | 唯一交易标识符 - 使用此标识符与回调关联 |
| gateway_message | 人类可读状态消息 |
| redirect_url | 支付后重定向用户的网址(可选 - 仅限用户体验) |
与需要3D Secure重定向的卡支付不同,Apple Pay交易可以即时处理。当您收到响应时,支付已经完成。
🍎 Apple Pay JS 集成
步骤1:添加Apple Pay按钮
<apple-pay-button buttonstyle="black" type="plain" locale="en" onclick="startApplePayPayment()"></apple-pay-button>
步骤2:检查可用性
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
document.getElementById('apple-pay-button').style.display = 'block';
}
步骤3:完成实施
async function startApplePayPayment() {
const paymentRequest = {
countryCode: 'US',
currencyCode: 'EUR',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
total: { label: 'Your Company', amount: '99.99', type: 'final' }
};
const session = new ApplePaySession(3, paymentRequest);
// Merchant Validation
session.onvalidatemerchant = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/apple_pay_validate_merchant.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
validationURL: event.validationURL,
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
domain_name: 'your-domain.com' // Required for server-to-server; optional if browser calls directly
})
});
session.completeMerchantValidation(await resp.json());
};
// Payment Authorization - Apple provides ENCRYPTED token in event.payment.token
// IMPORTANT: Pass the token directly to MONDO - do NOT attempt to decrypt it
session.onpaymentauthorized = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
apple_pay_token: event.payment.token, // Encrypted token - MONDO decrypts
transaction_amount: '99.99',
transaction_currency_iso3: 'EUR',
cardholder_email_address: 'customer@example.com',
partner_return_url_completed: 'https://yoursite.com/success',
partner_return_url_rejected: 'https://yoursite.com/failed',
live_or_sandbox: 'live'
})
});
const result = await resp.json();
if (result.transaction_status === 'COMPLETED') {
session.completePayment(ApplePaySession.STATUS_SUCCESS);
// Payment already processed - redirect is optional for user experience
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
} else {
session.completePayment(ApplePaySession.STATUS_FAILURE);
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
}
};
session.begin();
}
测试模式
MONDO支持两种测试模式。理解差异对于成功集成至关重要。
发生了什么
- ✅ 令牌结构已验证
- ✅ 所有必填字段已检查
- ⏭️ 解密已跳过(返回模拟数据)
- ⏭️ CardCorp API 调用已跳过
- ✅ 全额支付流程已执行
发生了什么
- ✅ 令牌结构已验证
- ✅ 所有必填字段已检查
- ✅ 真实解密
- ✅ 真实卡片公司API处理
- ✅ 真实货币已收费
🎯 为什么SANDBOX需要相同的令牌结构
此设计确保您从沙盒切换到实时时,无需更改代码即可立即工作。
⚙️ 设置模式
包括 live_or_sandbox API 请求中的参数:
{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"apple_pay_token": { ... },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox" // or "live" for production
}
🎭 沙盒:强制交易结果
在沙盒模式中,您可以强制特定的交易结果以进行测试:
| 参数 | 价值 | 结果 |
|---|---|---|
| sandbox_force_transaction_status | COMPLETED |
✅ 支付成功 |
| sandbox_force_transaction_status | REJECTED |
❌ 支付失败 |
Apple Pay 令牌结构
Apple Pay 令牌必须具有以下结构。这适用于 SANDBOX 和 LIVE 模式。
"***") 将导致错误,即使在沙盒模式下。 所需令牌结构
{
"paymentData": {
"version": "EC_v1",
"data": "BASE64_ENCRYPTED_PAYMENT_DATA",
"signature": "BASE64_SIGNATURE",
"header": {
"ephemeralPublicKey": "BASE64_EPHEMERAL_KEY",
"publicKeyHash": "BASE64_PUBLIC_KEY_HASH",
"transactionId": "UNIQUE_TRANSACTION_ID"
}
},
"paymentMethod": {
"displayName": "Visa 1234",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "APPLE_TRANSACTION_ID"
}
字段描述
| 字段 | 需要 | 描述 |
|---|---|---|
| paymentData.version | ✓ | 始终 EC_v1 |
| paymentData.data | ✓ | Apple 加密的 Base64 支付数据 |
| paymentData.signature | ✓ | Base64 签名验证 |
| paymentData.header.ephemeralPublicKey | ✓ | Base64 临时公钥 |
| paymentData.header.publicKeyHash | ✓ | 商户公钥的Base64哈希 |
| paymentData.header.transactionId | ✓ | 独特交易标识符 |
| paymentMethod.network | ○ | 卡网络(Visa,Mastercard,Amex) |
| paymentMethod.displayName | ○ | Apple 钱包显示名称 |
✓ = 需要 | ○ = 推荐
沙盒测试令牌
复制此令牌进行沙盒测试。加密值不需要是真实的 - 只验证结构。
{
"paymentData": {
"version": "EC_v1",
"data": "c2FuZGJveF9lbmNyeXB0ZWRfZGF0YV8xNzAyMjU2MDAwMDAw",
"signature": "c2FuZGJveF9zaWduYXR1cmVfMTcwMjI1NjAwMDAwMA==",
"header": {
"ephemeralPublicKey": "c2FuZGJveF9lcGhlbWVyYWxfa2V5XzE3MDIyNTYwMDAwMDA=",
"publicKeyHash": "c2FuZGJveF9wdWJsaWNfa2V5X2hhc2g=",
"transactionId": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
},
"paymentMethod": {
"displayName": "Visa 4242",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
常见令牌错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
| Invalid token format | 令牌不是JSON对象 | 发送令牌作为对象,而不是字符串 |
| Missing paymentData | 令牌没有 paymentData 属性 | 包括完整的 Apple Pay JS 令牌 |
| Missing header fields | 临时公钥、公钥哈希或交易ID缺失 | 确保所有标题字段都存在 |
令牌从哪里来?
在LIVE模式下,当用户授权支付时,令牌来自Apple Pay JS:
session.onpaymentauthorized = (event) => {
// This is the token you send to MONDO
const token = event.payment.token;
// Send to MONDO API
fetch('/payment/', {
body: JSON.stringify({
apple_pay_token: token, // Pass the entire token object
...
})
});
};
交易状态
了解交易状态及如何查询对完整集成至关重要。
最终交易状态
以下是您通过 webhook 或查询 /details 端点时可能收到的最终状态:
中级状态
交易已创建但仍在处理中。这可能发生在以下情况:
- 用户正在完成3D安全认证
- 卡网络正在处理付款
- 用户放弃了支付流程
何时查询交易状态?
- 您在预期时间内未收到 webhook(例如,5分钟)
- 您需要手动验证交易状态
- 您的 Webhook 端点暂时不可用
查询交易状态
要检查交易状态,请向详情端点发出 POST 请求:
请求参数
| 参数 | 需要 | 描述 |
|---|---|---|
| company_account_id | ✓ | 您的MONDO合作伙伴账户ID |
| gateway_secret_key | ✓ | 您的MONDO合作伙伴密钥 |
| gateway_session_id | ✓ | 初始支付请求返回的会话 ID |
示例请求
curl -X POST https://server-to-server.getmondo.co/details/ \
-H "Content-Type: application/json" \
-d '{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"gateway_session_id": "sess_abc123xyz"
}'
示例响应
{
"success": true,
"transaction_status": "COMPLETED",
"gateway_session_id": "sess_abc123xyz",
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"card_last_4_digits": "4242",
"card_brand": "VISA",
"gateway_result_code": "000.000.000",
"gateway_result_description": "Transaction succeeded",
"created_at": "2024-12-10T22:30:00Z",
"completed_at": "2024-12-10T22:31:15Z"
}
接收状态更新
有两种方式接收最终交易状态:
| 方法 | 如何使用 | 何时使用 |
|---|---|---|
| Webhook 推荐 | MONDO 发送 POST 请求给您 partner_webhook_url |
主要方式 - 自动,实时 |
| Redirect URL | 用户被重定向到您的 partner_return_url_completed 或者 partner_return_url_rejected |
用于用户确认 |
| Query /details | 您发起POST请求以检查状态 | 如果未收到网络钩子 |
如果交易保持已启动
如果交易状态超过15分钟仍为已启动,这可能意味着:
- 用户放弃了3D Secure挑战
- 用户在付款时关闭了浏览器
- 处理期间出现网络问题
操作: 查询 /details 端点以获取当前状态。这些交易最终将超时并转移到 FAILED 或 CANCELED 状态。