即使检索到 clientSecret,Apple Pay 支付也无法通过

Apple Pay Payment not going through even though clientSecret was retrieved

我们的目标是成功完成 Apple Pay 支付并完成此 API 集成。 我真的快要成功了,但我还有一个我无法解决的错误。

func startApplePayCheckout() {
    let backendUrlForIntent = "https://us-central1-xxxxx-41f12.cloudfunctions.net/createPaymentIntent"
    guard let user = Auth.auth().currentUser else { return }
    getUsersStripeCustomerID { (customerid) in
        if let id = customerid {
            // Create a PaymentIntent as soon as the view loads
            let costAsAnInt = self.actualCostOfEvent.text?.replacingOccurrences(of: "$", with: "").replacingOccurrences(of: ".", with: "")
            let costForStripe = Int(costAsAnInt!)
            let url = URL(string: backendUrlForIntent)!
            let json: [String: Any] = [
                "amount": costForStripe! + (self.gothereFee * Int(self.stepperValue.value)),
                "currency": "CAD",
                "customer": id,
                "setup_future_usage": "on_session",
            ]
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            request.httpBody = try? JSONSerialization.data(withJSONObject: json)
            let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in
                guard let response = response as? HTTPURLResponse,
                      response.statusCode == 200,
                      let data = data,
                      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any],
                      let clientSecret = json["clientSecret"] as? String else {
                    let message = error?.localizedDescription ?? "Failed to decode response from server."
                    self?.displayCancelledAlert(title: "Error Loading Page", message: message)
                    return
                }
                guard let paymentIntentID = json["paymentIntentID"] as? String else { return }
                
                self?.db.document("student_users/\(user.uid)/events_bought/\(self?.nameToUseInAPICall)").setData(["stripePaymentIntentID": paymentIntentID], merge: true, completion: { (error) in
                    if let error = error {
                        print("There was an error setting the paymentIntentID in the document: \(error)")
                    } else {
                        print("PaymentIntentID successfully stored!")
                    }
                })
                print("Created PaymentIntent")
                self?.paymentIntentClientSecret = clientSecret
            })
            task.resume()
        }
    }
    

当 Apple Pay sheet 出现时,我称之为正确。打印语句工作正常,检索到 clientSecret。现在,当我实际尝试付款时,我仍然收到“付款未完成”,这就是我在 didCreatePaymentMethod 函数中的内容:

func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
    guard let paymentIntentClient = paymentIntentClientSecret else {
        print("There is an issue with the clientSecret")
        return
    }
    
    let error = NSError(domain: backendUrl, code: 400, userInfo: [NSLocalizedDescriptionKey: "The payment cannot go through for some reason!"])
    
    let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClient)
    paymentIntentParams.paymentMethodId = paymentMethod.stripeId
    
    let paymentHandler = STPPaymentHandler.shared()
    paymentHandler.confirmPayment(paymentIntentParams, with: self) { (status, intent, error) in
        switch status {
        case .canceled:
            print("Payment Canceled")
            break
        case .failed:
            print("Payment Failed")
            break
        case .succeeded:
            print("Payment Succeeded")
            break
        default:
            break
        }
    }
    
    completion(paymentIntentClient, error)

}

编辑 因此,通过此实施,当我检查日志时付款实际上现在收费,但对于实际的 Apple Pay 本身,它从未在 Apple Pay sheet 中显示成功消息。这是我在 didCompleteWithStatus 方法中的内容:

 func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
    
    guard status == .success else {
        print("Payment couldn't go through")
        return
    }
}

所以奇怪的是,第一种方法最终成功,费用显示在 API 调用日志中,但 didCompleteWith... 方法总是以错误结束状态和 Apple 上的“付款未完成”sheet,对于我来说,我无法理解为什么。

我认为问题在于您在这一行中创建了一个错误:

let error = NSError(domain: backendUrl, code: 400, userInfo: [NSLocalizedDescriptionKey: "The payment cannot go through for some reason!"])

然后将该错误输入此处的 completion 处理程序:

completion(paymentIntentClient, error)

这导致 Apple Pay 中显示“付款未完成”错误 sheet。

completion 处理程序的想法是向其提供支付意向的客户端密码 或者 如果您无法向其提供客户端密码,则会出现错误,而不是两个都。 The documentation 对此进行了解释:

Call this with the PaymentIntent’s client secret, or the error that occurred creating the PaymentIntent.

如果您在没有 error 的情况下调用 completion,您应该已经准备就绪。