【问题标题】:Could not parse the ephemeral key response following protocol无法按照协议解析临时密钥响应
【发布时间】:2021-01-29 07:56:37
【问题描述】:

我正在尝试在我的 IOS 应用程序中创建一个临时密钥。我可以成功地创建一个保存在我的 firebase 控制台和我的条带仪表板上的条带客户。但是,当我尝试创建临时密钥时,在尝试查看结帐控制器后,我在 ios 控制台中收到错误消息。

'无法解析遵循协议 STPCustomerEphemeralKeyProvider 的临时密钥响应。确保您的后端将临时密钥的未修改 JSON 发送到您的应用。

在我看到的 Firebase 函数日志中,

创建临时密钥 请求的 Content-Type 不正确。

创建临时密钥 请求无效,无法处理。

在我的 index.js 文件中,我使用的代码是

exports.createEphemeralKey = functions.https.onCall(async(data, context) => {
  var stripeVersion = data.api_version;
  const customerId = data.customer_id;

  return stripe.ephemeralKeys.create(
    {customer: customerId},
    {stripe_version: stripeVersion}
  ).then((key) => {
    return key
  }).catch((err) => {
    console.log(err)
  })
})

下面是我如何创建我的条纹客户。

    exports.createStripeCustomer = functions.auth.user().onCreate((user) => {
  return stripe.customers.create({
    email: user.email,
  }).then((customer) => {
    return admin.database().ref(`/stripe_customers/${user.uid}/customer_id`).set(customer.id);
  });
});

然后 myAPIClient 看起来像。

    enum APIError: Error {
     case unknown

     var localizedDescription: String {
         switch self {
         case .unknown:
             return "Unknown error"
         }
     }
 }

static let sharedClient = MyAPIClient()
var baseURLString: String? = "https://myProject.cloudfunctions.net/"
var baseURL: URL {
    if let urlString = self.baseURLString, let url = URL(string: urlString) {
        return url
    } else {
        fatalError()
    }
}

   func createCustomerKey(withAPIVersion apiVersion: String, completion: @escaping STPJSONResponseCompletionBlock) {
    let url = self.baseURL.appendingPathComponent("ephemeral_keys")
    Alamofire.request(url, method: .post, parameters: [
        "api_version": apiVersion,
        ])
        .validate(statusCode: 200..<300)
        .responseJSON { responseJSON in
            switch responseJSON.result {
            case .success(let json):
                completion(json as? [String: AnyObject], nil)
            case .failure(let error):
                completion(nil, error)
            }
    }
}

在我的 checkOutVC 上,我有

var stripePublishableKey = "pk_test_testProjectKey"
var backendBaseURL: String? = "https://myProject.cloudfunctions.net"

        let customerContext = STPCustomerContext(keyProvider: MyAPIClient())

    init(price: Int, settings: Settings) {
        
        if let stripePublishableKey = UserDefaults.standard.string(forKey: "StripePublishableKey") {
            self.stripePublishableKey = stripePublishableKey
        }
        if let backendBaseURL = UserDefaults.standard.string(forKey: "StripeBackendBaseURL") {
            self.backendBaseURL = backendBaseURL
        }
        let stripePublishableKey = self.stripePublishableKey
        let backendBaseURL = self.backendBaseURL
        
        assert(stripePublishableKey.hasPrefix("pk_"), "You must set your Stripe publishable key at the top of acceptWorker.swift to run this app.")
        assert(backendBaseURL != nil, "You must set your backend base url at the top of acceptWorker.swift to run this app.")
        
        Stripe.setDefaultPublishableKey(self.stripePublishableKey)
        let config = STPPaymentConfiguration.shared()
        config.appleMerchantIdentifier = self.appleMerchantID
        config.companyName = self.companyName
        config.requiredBillingAddressFields = settings.requiredBillingAddressFields
        config.requiredShippingAddressFields = settings.requiredShippingAddressFields
        config.shippingType = settings.shippingType
        config.additionalPaymentOptions = settings.additionalPaymentOptions
        config.cardScanningEnabled = true
        self.country = settings.country
        self.paymentCurrency = settings.currency
        
        self.theme = settings.theme
        MyAPIClient.sharedClient.baseURLString = self.backendBaseURL
  
        let paymentContext = STPPaymentContext(customerContext: customerContext, configuration: config, theme: settings.theme)
        self.paymentContext = STPPaymentContext(customerContext: customerContext)
        super.init(nibName: nil, bundle: nil)
        self.paymentContext.delegate = self
        self.paymentContext.hostViewController = self
        self.paymentContext.paymentAmount = 5000 // This is in cents, i.e. $50 USD

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

我为冗长的代码行道歉,但我真的遇到了一堵砖墙。为什么后端不为客户创建 ephemeralKey?

【问题讨论】:

    标签: node.js swift google-cloud-functions stripe-payments


    【解决方案1】:

    有两件事在我身上跳出来:

    • 您已经编写了一个可调用类型函数(使用 onCall),但是您正在 尝试使用正常的 HTTP 请求调用它。这些功能需要 使用 Firebase 的客户端库调用 (https://firebase.google.com/docs/functions/callable#call_the_function)。 这个堆栈溢出答案提供了一些很好的链接: Firebase Cloud Function to delete user
    • 您的 firebase 函数正在解析 stripe_versioncustomer_id 来自 data,但您的请求仅发送 api_version。在你的什么地方 代码是发送stripe_versioncustomer_id 吗?

    【讨论】:

    • 感谢您的回答!我已更新以显示我如何发送 customer_id。那是我调用exports.createStripeCustomer 的时候。我是否也应该发送 stripe_version 和临时密钥?
    • 啊,那么您不应该尝试从data 中解析出customer_id。由于您在数据库中设置了它,因此您必须在需要时从数据库中检索它。
    • 但是条纹客户还好吗?
    • 另外,我应该在最初创建客户时创建 stripe_version 吗?
    • 您可以只使用 api_version 作为 stripe_version,因为您在创建临时密钥时将其作为请求的一部分发送
    猜你喜欢
    • 2019-11-07
    • 1970-01-01
    • 2021-04-14
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多