【问题标题】:Android Firestore Stripe - Add Payment SourceAndroid Firestore Stripe - 添加付款来源
【发布时间】:2020-08-16 06:32:40
【问题描述】:

底部更新

我正在尝试在我的 Android 应用中构建一个注册页面,让用户通过 Stripe 注册订阅。我坚持的是通过云功能从 Android 添加支付源,并从 Stripe 接收令牌。

我目前已经解决了,自动将新创建的用户添加到 Stripe。在写入或更改 (/users/{userId}/membership/token) 时创建订阅。

在 Android 上,我可以通过输入获取信用卡数据..

PaymentMethodCreateParams.Card card = cardInputWidget.getPaymentMethodCard();

接下来我需要使用.. 将其提交到我的云功能。

mFunctions = FirebaseFunctions.getInstance();
mFunctions.getHttpsCallable("addPaymentSource")
          .call()
          .addOnCompleteListener(task -> {
          ...

由于我无法找到这方面的信息,这就是我对这个云功能 (Javascript) 的全部了解

exports.addPaymentSource = functions.https.onCall((data, context) =>{

      const pm = await stripe.paymentMethods.attach('pm_678', {customer: 'cus_123'});
      return admin.firestore().collection('users').doc(user.uid).get('membership').set({token: token});

}

我需要获取保存在 - /users/{user.uid}/customerId' 的客户编号。以及通过我的 http 数据调用传递付款方式,并传递/获取 user_id(在这之前很久就已经创建了)。

到目前为止,我观看了这个 youtube 视频并转换了我的代码。 Subscription Payments with Stripe, Angular, and Firebase

我还大量引用了 Stripe 的 Cloud Function 示例。一个问题是每个人似乎都在使用这段代码(如下),这在我的实现中不起作用。大多数指南/示例未用于订阅。

// Add a payment source (card) for a user by writing a stripe payment source token to Cloud Firestore
exports.addPaymentSource = functions.firestore.document('/stripe_customers/{userId}/tokens/{pushId}').onCreate(async (snap, context) => {
  const source = snap.data();
  const token = source.token;
  if (source === null){
    return null;
  }

  try {
    const snapshot = await admin.firestore().collection('stripe_customers').doc(context.params.userId).get();
    const customer =  snapshot.data().customer_id;
    const response = await stripe.customers.createSource(customer, {source: token});
    return admin.firestore().collection('stripe_customers').doc(context.params.userId).collection("sources").doc(response.fingerprint).set(response, {merge: true});
  } catch (error) {
    await snap.ref.set({'error':userFacingMessage(error)},{merge:true});
    return reportError(error, {user: context.params.userId});
  }
});

更新:


做了一些小的改动来尝试让它工作..

exports.addPaymentSource = functions.https.onCall((data, context) =>{
    ///users/{userId}/membership/token

    // Create Payment Method
    const paymentMethod = stripe.paymentMethods.create(
        {
            type: 'card',
            card: {
              number: '4242424242424242',
              exp_month: 5,
              exp_year: 2021,
              cvc: '314',
            },
    }).then(pm => {

        console.log('paymentMethod: ', paymentMethod.id);

        return stripe.paymentMethods.attach(paymentMethod.id, { customer: 'cus_HCQNxmI5CSlIV5' })
        .then(pm => {

        return admin.firestore().collection('users').doc(user.uid).get('membership').set({token: pm.id});

        });
    });
});

我快接近了,问题是 paymentMethod.id 是 'undefined'

【问题讨论】:

  • 你的回调有pm作为参数但是你正在访问一个名为paymentMethod的变量,你应该将(pm => {更改为(paymentMethod => {
  • 另外,您不应该在 Firestore 函数中对 PaymentMethod 进行标记化,标记化应该在您的移动应用上进行

标签: android firebase google-cloud-firestore google-cloud-functions stripe-payments


【解决方案1】:

虽然我不是 Firebase 专家,但在您的 Android 端,您希望使用 Customer ID 和 PaymentMethod ID 的参数调用您的云函数,以便将它们传递给您的云函数。

此处显示的传递参数:https://stackoverflow.com/a/56298213/10654456

然后在您的云函数中,您希望将 PaymentMethod 附加到客户(就像您使用条带节点所做的那样)并将其设置为客户的默认订阅,如下所示:https://stripe.com/docs/billing/subscriptions/payment#signup-3

然后,您应该为特定计划在客户上创建订阅,再次使用条带节点,如此处所示https://stripe.com/docs/billing/subscriptions/payment#signup-4

【讨论】:

  • 这是最难的部分。我知道我可以使用“.call()”来传递参数。虽然同时获得我的 CustomerID 并用我看不到的卡传递它。除非分解卡片信息并构建我自己的地图对象会起作用吗?第二个链接未显示将数据传递到“stripe.paymentMethods.attach('pm_678', {customer: 'cus_123'});” (替换 pm 和 cus 字段)。最后,我不需要第三个链接,因为我将返回的令牌保存到 firestore,然后在不同的云功能中自动处理。谢谢你的回复!
  • 我在底部添加了一个更新部分,它要么有帮助,要么让我走得更远哈哈
  • > 虽然同时获取我的CustomerID并用卡传递它我看不到你能解释一下这部分吗?你想在这里做什么?是不是您的移动应用不知道您的客户 ID?
  • 我将发布我的问题的答案,因为我能够让它的核心工作。感谢您的帮助!
【解决方案2】:

这里有我的功能代码。 (我使用了一些占位符数据来填充变量)

exports.addPaymentSource = functions.https.onCall((data, context) =>{

    // Create Payment Method
    stripe.paymentMethods.create( {

        type: 'card',
        card: {
          number: '4242424242424242',
          exp_month: 5,
          exp_year: 2021,
          cvc: '314',
        },
    }) 
    .then(pm => {

         return stripe.paymentMethods.attach(pm.id, { customer: 'cus_HCCNMAAwRhNM3c' })

    })
    .then(pm => {

        console.log('final step');
        console.log('paymentMethod: ', pm.id);
        admin.firestore().collection('users').doc('LzgbQBtk0QSZi7QISIbV').set({token: pm.id});
        return admin.firestore().collection('users').doc(user.uid).collection('membership').set({token: pm.id});

        })
    .catch(error => { return null });
});

所以我手动粘贴了一些变量以确认我的功能正常运行。 CustomerID 和卡详细信息需要从 Android 应用程序传入。这些卡详细信息是我订阅时唯一需要的信息

'pm'是返回的Payment Method对象,其中id是需要附加给用户的变量。

最后,pm.id 是必须保存在 Firestore 中的令牌。这样做会触发我的订阅设置云功能(未显示)。

显示的代码显示了如何避免嵌套 then 语句和 Android firestore 直接函数调用。虽然也没有显示,但数据字段可以调用任何变量的关键字“data.cardnbr”。

该方法避免使用任何SetupIntents。虽然这对于基于订阅的收费非常有效,但对于直接收费可能不是最佳做法。

【讨论】:

  • 太好了,你让它工作了!我要指出的一件事是,这种方法意味着您将卡详细信息从客户端传递到服务器并从服务器进行标记。这意味着您的集成具有更高的 PCI 合规性负担。您应该在 Android 应用上创建一个 PaymentMethod,然后将客户 ID 和 PM ID 从 Android 应用传递到您的服务器。
  • 我听到你在说什么 hmunoz,原始教程能够轻松地从网站使用 PaymentMethod。这个月我会看看并考虑转换,因为这听起来可能是最佳实践
猜你喜欢
  • 2019-06-28
  • 2018-12-13
  • 2016-05-22
  • 1970-01-01
  • 2021-01-10
  • 2017-03-13
  • 1970-01-01
  • 2018-06-17
  • 1970-01-01
相关资源
最近更新 更多