【问题标题】:Stripe Connect transfer: Insufficient fundsStripe Connect 转账:资金不足
【发布时间】:2020-04-14 01:22:55
【问题描述】:

我正在尝试在我的应用程序中实现 Stripe 的 Connect。我已经进行了数小时的研究和试错法调试,现在我没有遇到技术错误但错误提示:

Stripe 帐户中的资金不足。在测试模式下,您可以添加资金 通过创建您的可用余额(绕过您的未结余额) 以 4000 0000 0000 0077 作为卡号的收费。您可以使用 /v1/balance 端点来查看您的 Stripe 余额(更多 详细信息,请参阅 stripe.com/docs/api#balance)。

Stripe Dashboar 中的 paymentIntent 显示 PaymentIntent status: requires_confirmation

这个错误对我来说似乎很奇怪,因为我正在测试的卡正是他们建议我使用的卡。请注意,我也尝试过使用其他卡。

我正在使用 Google Cloud Functions 作为我的 Stipe API 的后端。

这是创建accountcustomer 的函数。我正在创建它们,只是为了确保一切正常。

// When a user is created in firebase auth, register them with Stripe
exports.createStripeUser = functions.auth.user().onCreate(async (user) => {
  const account = await stripe.accounts.create({type: 'custom', business_type: 'individual', individual: {email: user.email}, requested_capabilities: ['card_payments', 'transfers'], email: user.email});
  const customer = await stripe.customers.create({email: user.email});
  return admin.firestore().collection('stripe_customers').doc(user.uid).set({account_id: account.id, customer_id: customer.id});
});

现在我正在添加卡信息:

// 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});
  }
});

这就是我创建paymentIntent 的方式:

// Create Stripe paymentIntent whenever an amount is created in Cloud Firestore
exports.createStripePaymentIntent = functions.firestore.document('stripe_customers/{userId}/charges/{id}').onCreate(async (snap, context) => {
      const val = snap.data();
      try {
        // Look up the Stripe customer id written in createStripeUser
        const snapshot = await admin.firestore().collection(`stripe_customers`).doc(context.params.userId).get()
        const snapval = snapshot.data();
        const customer = snapval.customer_id
        const amount = val.amount;
        const charge = {amount, currency, customer, transfer_group: val.transfer_group, payment_method: val.payment_method};
        if (val.source !== null) {
          charge.source = val.source;
        }
        const response = await stripe.paymentIntents.create(charge);
        // If the result is successful, write it back to the database
        return snap.ref.set(response, { merge: true });
      } catch(error) {
        // We want to capture errors and render them in a user-friendly way, while
        // still logging an exception with StackDriver
        console.log(error);
        await snap.ref.set({error: userFacingMessage(error)}, { merge: true });
        return reportError(error, {user: context.params.userId});
      }
    });

现在一切似乎都按预期进行,现在进入有趣的部分,即转移。由于上述错误,我无法做到这一点。这就是我创建费用的方式:

exports.createStripeTransfer = functions.firestore.document('stripe_customers/{userId}/transfers/{id}').onCreate(async (snap, context) => {
  const val = snap.data();
  try {
    // Look up the Stripe account id written in createStripeUser
    const snapshot = await admin.firestore().collection(`stripe_customers`).doc(context.params.userId).get()
    const snapval = snapshot.data();

    const destinationAccount = val.destination
    const amount = val.amount;
    const charge = {amount, currency, destination: destinationAccount, transfer_group: val.transfer_group};
    if (val.source !== null) {
      charge.source = val.source;
    }
    const response = await stripe.transfers.create(charge);
    stripe.paymentIntents.confirm(response.id, {payment_method: response.payment_method})
    // If the result is successful, write it back to the database
    return snap.ref.set(response, { merge: true });
  } catch(error) {
    // We want to capture errors and render them in a user-friendly way, while
    // still logging an exception with StackDriver
    console.log(error);
    await snap.ref.set({error: userFacingMessage(error)}, { merge: true });
    return reportError(error, {user: context.params.userId});
  }
});

谁能解释一下我在这里缺少什么?为什么我会收到错误消息?我尝试手动充值也无济于事。

更新 1:根据 Sergio Tulentsev 的评论,看来我必须确认转移才能成功。所以我在成功传输后确实实现了以下行,但错误仍然存​​在:

stripe.paymentIntents.confirm(response.id, {payment_method: response.payment_method})

stripe.paymentIntent.confirmstripe.confirmCardPayment 有什么区别?

【问题讨论】:

  • 创建一个 PaymentIntent 是不够的。要执行转移,您必须 confirm 它。 stripe.com/docs/js/payment_intents/confirm_card_payment
  • @SergioTulentsev 哇......当你写评论时,我刚刚发现一些链接也在讨论关于 Stripe 文档的确认。但是没有提到这必须是创建转移后的下一步,也没有提到这对于转移成功是强制性的。我希望 PaymentIntent 或 transfer 部分中有一个链接来讨论这个问题。我很高兴隧道尽头似乎有光 :D 非常感谢。现在要实现这个功能了。
  • @SergioTulentsev 我确实实现了stripe.confirm 端点,但由于某种原因它没有确认它但返回相同的错误。
  • 从客户端(JS),你应该使用stripe.confirmCardPayment(如果支付是通过卡)。例如,它处理 3DS 步骤。看看这个指南:stripe.com/docs/payments/accept-a-payment#web
  • @SergioTulentsev 我确实在单独的流程中询问信用卡信息,而不是在意图/转移中进行。在设置中,用户正在添加他/她的卡/来源并且我存储令牌。现在在支付视图中,只有用户可以选择和支付按钮的来源列表。单击付款按钮后,我创建了意图,然后立即想将钱从帐户 A 转移到 B。这不是我正在构建的结帐..但似乎它现在正在工作.. 要做更多的测试和更新问题或将添加答案。

标签: javascript google-cloud-firestore stripe-payments


【解决方案1】:

您似乎可以访问仪表板并且您拥有测试帐户。在这种情况下,您可以从 Payments -> New 手动添加资金,然后提供测试卡详细信息,如附图所示,此处使用的卡号为 4000 0000 0000 0077。

正如您提到的,您正在生成付款意向,只有在您添加了有效的真实账户之后,这只会将费用金额记入您的可用资金,直到那时资金将始终处于暂停状态。

所以为了测试你可以手动添加资金,如链接pic of generating new payment manually所示

【讨论】:

    猜你喜欢
    • 2022-11-28
    • 2018-08-30
    • 2016-11-30
    • 2017-01-19
    • 2023-01-27
    • 1970-01-01
    • 2021-04-24
    • 2020-06-04
    • 2021-07-24
    相关资源
    最近更新 更多