概览

它是什么

通过MONDO接受Apple Pay支付

您需要的

MONDO 账户 ID + 密钥

您发送的内容

Apple Pay 令牌 + 金额 + 货币

您获得的内容

已完成或已拒绝状态

如何使用

客户
Apple Pay
MONDO
完成

选项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 解密并处理支付令牌
不需要的: 无苹果开发者账号,无苹果商户ID,无需管理证书。

令牌处理 — 谁来做什么?

Apple Pay 使用端到端加密来保护持卡人数据。以下是责任分配方式:

苹果(客户的设备) 生成包含卡信息、加密图案和认证详情的加密支付令牌
您 (商家) 加密令牌直接通过apple_pay_token参数传递给MONDO — 不要尝试解密
MONDO (PSP) 使用我们的Apple Pay支付处理证书解密令牌并通过CardCorp处理支付
重要: 您永远不会看到或处理原始卡号。您从苹果收到的令牌已加密,只能由MONDO使用我们的商户证书解密。

选择集成方式

最适合: 完全控制您自己结账页面上的Apple Pay按钮外观和用户体验。

📋 先决条件

  • 合作伙伴账户 ID - 您的独特MONDO账户标识
  • 合作伙伴密钥 - 您的API认证密钥
  • HTTPS - 您的网站必须使用 HTTPS

⚠️ 域名验证需要

您的域名必须通过MONDO在Apple注册。这是一次性设置。

  1. 前往 GETMONDO.CO
  2. LoginDeveloperApple PayAdd Apple Pay Domain

🔄 支付流程

1
用户点击Apple Pay按钮
在您的网站上
2
Apple Pay 界面打开
原生 Apple Pay 界面
3
商户验证
您的 JS 调用 MONDO 的验证端点
4
用户验证
Face ID / Touch ID
5
令牌已发送至MONDO
POST to /payment/ with apple_pay_token
6
3D 安全 & 重定向
用户重定向到成功/失败网址

🔗 API 端点

POST https://server-to-server.getmondo.co/payment/

商户验证端点

POST https://server-to-server.getmondo.co/payment/apple_pay_validate_merchant.php

商户验证参数

参数类型需要描述
validationURLstring✓ 是Apple 提供的 URL onvalidatemerchant 事件
company_account_idstring✓ 是您的MONDO合作伙伴账户ID
gateway_secret_keystring✓ 是您的MONDO合作伙伴密钥
domain_namestring○ 条件的您的Apple Pay域名(例如 paynow.yoursite.com). 用于服务器到服务器的调用,当浏览器的 Origin 头不可用时需要。如果直接从浏览器调用,则不需要。
服务器对服务器集成注意事项:
如果您的后端代理商户验证调用(即您的服务器调用MONDO而不是浏览器直接调用),您必须包括 domain_name 设置到显示您的 Apple Pay 按钮的域。这确保 Apple Pay 会话与您的支付页面域相匹配。

📝 所需参数 (支付处理)

参数类型描述
company_account_idstring您的MONDO合作伙伴账户ID
gateway_secret_keystring您的MONDO合作伙伴密钥
apple_pay_tokenobject加密 来自 event.payment.token — pass directly to MONDO as-is (不要解密)
transaction_amountdecimal支付金额(例如,99.99)
transaction_currency_iso3string货币代码(EUR, USD, GBP)
cardholder_email_addressstring客户的电子邮件

可选参数

参数描述
partner_return_url_completed支付成功重定向网址
partner_return_url_rejected拒绝付款重定向的 URL
partner_webhook_urlWebhook 通知的 URL
live_or_sandboxlive 或者 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"
}

响应字段

字段描述
statussuccess 或者 error
transaction_statusCOMPLETED 或者 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支持两种测试模式。理解差异对于成功集成至关重要。

SANDBOX 用于测试

发生了什么

  • ✅ 令牌结构已验证
  • ✅ 所有必填字段已检查
  • ⏭️ 解密已跳过(返回模拟数据)
  • ⏭️ CardCorp API 调用已跳过
  • ✅ 全额支付流程已执行
💡
关键点: 您必须发送正确格式的令牌 - 与LIVE模式所需的格式相同。
LIVE 用于生产

发生了什么

  • ✅ 令牌结构已验证
  • ✅ 所有必填字段已检查
  • ✅ 真实解密
  • ✅ 真实卡片公司API处理
  • ✅ 真实货币已收费
🔒
关键点: 仅使用来自实际设备的真实Apple Pay令牌的LIVE模式。

🎯 为什么SANDBOX需要相同的令牌结构

此设计确保您从沙盒切换到实时时,无需更改代码即可立即工作。

🧪
SANDBOX
测试有效结构
已验证
结构确认
🚀
LIVE
立即生效

⚙️ 设置模式

包括 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.dataApple 加密的 Base64 支付数据
paymentData.signatureBase64 签名验证
paymentData.header.ephemeralPublicKeyBase64 临时公钥
paymentData.header.publicKeyHash商户公钥的Base64哈希
paymentData.header.transactionId独特交易标识符
paymentMethod.network卡网络(Visa,Mastercard,Amex)
paymentMethod.displayNameApple 钱包显示名称

= 需要  |  = 推荐

沙盒测试令牌

复制此令牌进行沙盒测试。加密值不需要是真实的 - 只验证结构。

{
    "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 端点时可能收到的最终状态:

COMPLETED
支付成功
REJECTED
处理器拒绝付款
CANCELED
用户取消支付
FAILED
技术错误发生了

中级状态

INITIATED

交易已创建但仍在处理中。这可能发生在以下情况:

  • 用户正在完成3D安全认证
  • 卡网络正在处理付款
  • 用户放弃了支付流程

何时查询交易状态?

最佳实践: 始终将 Webhooks 作为您的主要通知方法。仅在以下情况下将查询 /details 端点作为后备方法:
  • 您在预期时间内未收到 webhook(例如,5分钟)
  • 您需要手动验证交易状态
  • 您的 Webhook 端点暂时不可用

查询交易状态

要检查交易状态,请向详情端点发出 POST 请求:

POST https://server-to-server.getmondo.co/details/

请求参数

参数 需要 描述
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 状态。