StripeInvalidRequestError: No such setupintent: 'seti_...'

StripeInvalidRequestError: No such setupintent: 'seti_...'

用户在我的应用程序上注册后,我希望他们添加付款方式。他们的条纹客户帐户在他们注册后立即创建,并从那里转移到 'AddPaymentMethod' 屏幕。 “AddPaymentMethod”屏幕一出现,我就向我的服务器发送一个创建 setupIntent 的请求。

正在创建设置意图:

exports.createSetupIntent = functions.https.onCall(async (data, context) => {
  const userId = data.userId;
  const snapshot = await db
      .collection("development")
      .doc("development")
      .collection("users")
      .doc(userId).get();
  const customerId = snapshot.data().customer_id;
  const setupIntent = await stripe.setupIntents.create({
    customer: customerId,
  });
  const clientSecret = setupIntent.client_secret;
  return {
    clientsecret: clientSecret,
  };
});

当屏幕出现在我的客户端上时调用该函数(这成功创建了客户端密钥并将其存储在前端的变量中):

FirebaseReferenceManager.functions.httpsCallable("createSetupIntent").call(["userId": Auth.auth().currentUser?.uid]) { (response, error) in
    if let error = error {
        print(error.localizedDescription)
    }

    if let response = (response?.data as? [String: Any]) {
        let clientSecretKey = response["clientsecret"] as! String?
        self.clientSecret = clientSecretKey ?? "-"
        print("created client secret key: \(clientSecretKey!)")
    }
}

接下来,用户输入他们的信用卡信息并创建付款方式。这是我服务器上的函数:

exports.createPaymentMethod = functions.https.onCall(async (data, context) => {
  const number = data.number;
  const expMonth = data.expMonth;
  const expYear = data.expYear;
  const cvc = data.cvc;

  const paymentMethod = await stripe.paymentMethods.create({
    type: "card",
    card: {
      number: number,
      exp_month: expMonth,
      exp_year: expYear,
      cvc: cvc,
    },
  });
  const pmId = paymentMethod.id;
  return {
    paymentMethodId: pmId,
  };
});

当用户按下“保存付款方式”按钮时,我从前端调用此函数。这成功地创建了一个支付方式和 returns 存储在前端变量中的支付方式 ID。

最后,我使用从前面的函数返回的客户端密码 ID 和支付方式 ID,调用最后一个函数来确认 setupIntent。

支付方式创建成功后调用此函数:

exports.confirmSetupIntent = functions.https.onCall(async (data, context) => {
  const clientSecretKey = data.clientSecretKey;
  const paymentMethodId = data.paymentMethodId;

  const setupIntent = await stripe.setupIntents.confirm(
      clientSecretKey,
      {payment_method: paymentMethodId}
  );
});

这是从前端调用 createPaymentMethod 和 confirmSetupIntent 函数的方式:

FirebaseReferenceManager.functions.httpsCallable("createPaymentMethod").call(["number": self.cardNumber, "expMonth": self.expMonth, "expYear": "20\(self.expYear)", "cvc": self.cvvCode]) { (response, error) in

if let error = error {
    print("error occured when creating payment method: \(error.localizedDescription)")
}

if let response = response?.data as? [String: Any] {
    let paymentMethodId = response["paymentMethodId"] as! String?
    self.paymentMethodID = paymentMethodId ?? "-"
    print(paymentMethodId!)
    
    FirebaseReferenceManager.functions.httpsCallable("confirmSetupIntent").call(["clientSecretKey": self.clientSecret, "paymentMethodId": self.paymentMethodID]) { (response, error) in
        if let error = error {
            print("error occured when confirming setup intent: \(error.localizedDescription)")
        }
        print("setup intent confirmed")
    }
    
}

}

在前端的调试控制台中,它表示确认 setupIntent 的错误是内部错误。当我检查服务器上的日志时,我说: StripeInvalidRequestError:没有这样的设置意图:'seti_...'

请注意,我使用 SwiftUI 和自定义 screens/textfields 进行条带集成。

感谢任何帮助!

No such setupintent 错误表明您的 API 密钥不匹配,您应该仔细检查您的服务器密钥和客户端可发布密钥是否是同一帐户的匹配对,并且都用于测试模式,例如

更令人担忧的是,您似乎正在将付款详细信息传递到您的服务器以创建付款方式。这是不推荐的,并且有显着的PCI Compliance implications. Instead of creating the payment method like this on your server, you should use Elements and provide a reference to the Card Element when you use confirmCardSetup (docs):

stripe.confirmCardSetup(
  clientSecret,
  {
    payment_method: {
      card: cardElement,
    },
  }
)