You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift集成Apple Pay:如何实现3DS验证后的支付成功回调?

问题解答

一、打开redirect_url的方式是否正确?

你当前使用UIApplication.shared.open的方式基本正确,但有几个细节需要优化:

  1. 必须保证url是合法解析后的URL类型,避免字符串转URL失败:
    guard let redirectUrlStr = response["redirect_url"] as? String,
          let redirectUrl = URL(string: redirectUrlStr) else {
        // 处理URL解析失败逻辑
        return
    }
    
  2. UI操作需在主线程执行,建议包裹在DispatchQueue.main.async中:
    DispatchQueue.main.async {
        UIApplication.shared.open(redirectUrl, options: [:]) { success in
            print("Open url : \(success)")
        }
    }
    
  3. 针对3DS支付验证场景,更推荐使用ASWebAuthenticationSession(iOS 12+),它能更好地管理网页会话,且支持验证完成后自动回调回APP:
    import AuthenticationServices
    
    let session = ASWebAuthenticationSession(url: redirectUrl, callbackURLScheme: "your-app-scheme") { callbackUrl, error in
        if let callbackUrl = callbackUrl {
            // 解析回调URL中的交易结果参数
            let components = URLComponents(url: callbackUrl, resolvingAgainstBaseURL: false)
            let status = components?.queryItems?.first(where: { $0.name == "status" })?.value
            let transId = components?.queryItems?.first(where: { $0.name == "trans_id" })?.value
            // 根据参数更新本地订单状态
        }
    }
    session.presentationContextProvider = self
    session.start()
    
    需额外实现ASWebAuthenticationPresentationContextProviding协议提供展示上下文。

二、如何获取支付回调?

根据支付系统说明,回调分为两种常见类型,以下是对应处理方案及伪代码:

1. 服务器端回调(推荐)

支付系统会在交易完成后主动调用你预先提供的后端接口,传递交易状态、订单ID等核心信息。你需要在后端实现一个接收回调的接口:

Swift Vapor后端伪代码:

import Vapor

struct PaymentCallbackRequest: Content {
    let order_id: String
    let trans_id: String
    let status: String // 例如SUCCESS/FAILED
    let trans_date: String
}

func routes(_ app: Application) throws {
    app.post("payment", "callback") { req async throws -> HTTPStatus in
        let callbackData = try req.content.decode(PaymentCallbackRequest.self)
        // 关键:验证回调签名,防止伪造请求
        guard verifyCallbackSignature(req.headers, callbackData) else {
            return .badRequest
        }
        // 更新数据库中对应订单的状态
        if let order = try await Order.query(on: req.db).filter(\.$id == callbackData.order_id).first() {
            order.status = callbackData.status
            try await order.save(on: req.db)
        }
        // 返回成功响应给支付系统
        return .ok
    }
}

// 签名验证逻辑(需按支付系统提供的规则实现)
func verifyCallbackSignature(_ headers: HTTPHeaders, _ data: PaymentCallbackRequest) -> Bool {
    let receivedSignature = headers.first(name: "X-Payment-Signature") ?? ""
    let generatedSignature = generateSignature(from: data, secret: "your-payment-secret")
    return receivedSignature == generatedSignature
}

2. APP端跳转回调

若支付系统配置的是APP端回调(通过URL Scheme或Universal Links),需先配置APP的跳转能力:

步骤1:配置URL Scheme

在Xcode的Info.plist中添加:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>your-app-scheme</string> <!-- 例如:myapp-pay -->
        </array>
    </dict>
</array>

步骤2:处理跳转回调

在SceneDelegate(iOS 13+)中实现回调方法:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else { return }
    // 解析回调URL中的参数
    let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
    guard let status = components?.queryItems?.first(where: { $0.name == "status" })?.value,
          let orderId = components?.queryItems?.first(where: { $0.name == "order_id" })?.value else {
        return
    }
    // 更新本地订单状态,或请求后端确认交易真实性
    updateLocalOrderStatus(orderId: orderId, status: status)
}

// 本地更新订单状态示例
func updateLocalOrderStatus(orderId: String, status: String) {
    if let order = LocalDB.shared.getOrder(by: orderId) {
        order.status = status
        LocalDB.shared.saveOrder(order)
        // 通知UI更新
        NotificationCenter.default.post(name: .orderStatusUpdated, object: order)
    }
}

注意:无论哪种回调方式,都必须做合法性验证(如签名校验),避免恶意请求伪造交易状态。

内容的提问来源于stack exchange,提问作者imjohnnotsina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:34:53