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,只要请求头设置正确)
当前代码的问题
- Swift端请求体格式错误:直接把
stripeTotalAmount.description作为请求体,这只是纯数字字符串,不是Node.js期望的JSON格式,而且没传递Node.js代码里依赖的email参数 - 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
相关产品推荐
相关产品推荐

