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

Swift向Node.js Firebase函数传递Stripe金额及数据交互咨询

Swift与Node.js Firebase云函数的数据传递指导(针对Stripe支付场景)

核心传递机制

Swift和Node.js云函数之间通过HTTP请求传递数据,最常用的格式是JSON:

  • Swift端构造包含所需参数的JSON对象,转为Data后作为请求体发送
  • Node.js云函数通过req.body解析请求体中的JSON数据(Firebase的HTTPS函数默认支持解析JSON,只要请求头设置正确)

当前代码的问题

  1. Swift端请求体格式错误:直接把stripeTotalAmount.description作为请求体,这只是纯数字字符串,不是Node.js期望的JSON格式,而且没传递Node.js代码里依赖的email参数
  2. Node.js端存在小bug:创建新客户时,customer.data.id应该改为customer.id(Stripe的customers.create返回的对象直接包含id字段,不存在data子属性)

修正后的代码实现

1. Swift端HTTP请求代码

func callStripeCheckOut() {
    // MARK: Fetch the PaymentIntent and Customer information from the backend
    let stripeTotalAmount = StripeCart.total // 确保这个值是分单位的整数(比如100代表1美元)
    let userEmail = "user@example.com" // 替换为实际用户邮箱
    
    // 构造请求参数JSON
    let params: [String: Any] = [
        "amount": stripeTotalAmount,
        "email": userEmail
    ]
    
    var request = URLRequest(url: backendCheckoutUrl)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 必须设置这个请求头
    
    // 将JSON转为Data作为请求体
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
    } catch {
        print("构造请求体失败:\(error)")
        return
    }
    
    let task = URLSession.shared.dataTask(
        with: request,
        completionHandler: { [weak self] (data, response, error) in
            guard let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data, options: [])
                    as? [String: Any],
                  let customerId = json["customer"] as? String,
                  let customerEphemeralKeySecret = json["ephemeralKey"] as? String,
                  let paymentIntentClientSecret = json["paymentIntent"] as? String,
                  let publishableKey = json["publishableKey"] as? String,
                  let self = self
            else {
                // Handle error
                print("请求出错:\(error?.localizedDescription ?? "未知错误")")
                return
            }
            // MARK: Set your Stripe publishable key - this allows the SDK to make requests to Stripe for your account
            STPAPIClient.shared.publishableKey = publishableKey
            // MARK: Create a PaymentSheet instance
            var configuration = PaymentSheet.Configuration()
            configuration.merchantDisplayName = "Example, Inc."
            configuration.applePay = .init(
                merchantId: "com.foo.example", merchantCountryCode: "US")
            configuration.customer = .init(
                id: customerId, ephemeralKeySecret: customerEphemeralKeySecret)
            configuration.returnURL = "payments-example://stripe-redirect"
            // Set allowsDelayedPaymentMethods to true if your business can handle payment methods that complete payment after a delay, like SEPA Debit and Sofort.
            configuration.allowsDelayedPaymentMethods = true
            self.paymentSheet = PaymentSheet(
                paymentIntentClientSecret: paymentIntentClientSecret,
                configuration: configuration)
            
            DispatchQueue.main.async {
                self.checkoutButton.isEnabled = true
            }
        })
    task.resume()
}

2. Node.js Firebase云函数代码

exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => {
try {
  let customerId;
  const { email, amount } = req.body; // 解构获取请求参数

  // 校验必填参数
  if (!email || !amount) {
    return res.status(400).send({ success: false, error: "缺少必填参数:email或amount" });
  }

  //Gets the customer who's email id matches the one sent by the client
  const customerList = await stripe.customers.list({
      email: email,
      limit: 1
  });
          
  //Checks the if the customer exists, if not creates a new customer
  if (customerList.data.length !== 0) {
      customerId = customerList.data[0].id;
  }
  else {
      const customer = await stripe.customers.create({
          email: email
      });
      customerId = customer.id; // 修正:这里直接取customer.id
  }

  //Creates a temporary secret key linked with the customer 
  const ephemeralKey = await stripe.ephemeralKeys.create(
      { customer: customerId },
      { apiVersion: '2022-11-15'}
  );

  //Creates a new payment intent with amount passed in from the client
  const paymentIntent = await stripe.paymentIntents.create({
      amount: parseInt(amount), // 确保转为整数(Stripe要求金额为分单位的整数)
      currency: 'usd',
      customer: customerId,
      automatic_payment_methods: {
        enabled: true,
      }
  })

  res.status(200).send({
      paymentIntent: paymentIntent.client_secret,
      ephemeralKey: ephemeralKey.secret,
      customer: customerId,
      publishableKey: 'pk_test_51I8zoILw87X7i4vz3Wxu4EAmmNxKKtgKNpwwMwpsbUHZ1Pe8La4CDiVyNao1bYQULFT9mfNV1Ys22PzeyndpWNUP00YIzK6Mji',
      success: true,
  })
  
} catch (error) {
  res.status(500).send({ success: false, error: error.message }) // 这里用500表示服务器内部错误更合适
}
});

关键要点说明

  • 请求头必须设置Content-Type: application/json:告诉Node.js云函数请求体是JSON格式,这样Firebase会自动解析到req.body中
  • 参数完整性:确保Swift端传递Node.js端需要的所有参数(比如这里的email和amount)
  • Stripe金额单位:Stripe要求金额以分为单位(比如1美元传100),所以Swift里的stripeTotalAmount必须是对应分的整数
  • 错误处理:两端都要增加参数校验和错误捕获,方便排查问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 03:45:11