gpt4 book ai didi

node.js - 无法将金额转移到 Connect Stripe 帐户

转载 作者:行者123 更新时间:2023-12-03 12:14:53 29 4
gpt4 key购买 nike

背景:

我想做的是建立一个市场,客户可以在其中获得卖家的服务,确切地说,该项目是一个 MERN Stack Travel 应用程序。我希望客户在希望获得服务(例如酒店房间)时支​​付平台(与 Stripe 连接的网站)。客户在规定的时间内入住酒店,当他退房时,平台会保留部分客户金额作为申请费,并将其余部分转给服务提供商,在本例中为酒店。

当前努力:

我使用 STRIPE CONNECT 来实现所需的功能。

(注意:你们不需要看到下面的所有代码,只要标题和描述就能让你们了解我做了什么以及我想问什么,但请务必阅读问题部分)

当卖家在我的网站上注册时,我为他创建了一个Connect account

创建连接帐户

const express = require("express");
const router = express.Router();
router.post("/createAccount", async (req, res) => {
const { name, email } = req.body; //Data Passed from the FrontEnd
stripe.accounts.create(
{
type: "custom",
country: "US",
email: email,
requested_capabilities: ["card_payments", "transfers"],
},
function (err, account) {
res.json({ account: account });
}
);
});

当卖家在登录卖家门户后提供所需的其余详细信息(包括银行账户)时,我创建一个bank_account,更新已创建的Connect Account 并将 bank_accountConnect Account 链接(希望这在某种程度上有意义)

创建银行账户

  router.post("/createBankAccount", async (req, res) => {
const { account_holder_name, routing_number, account_number } = req.body;
stripe.tokens.create(
{
bank_account: {
country: "US",
currency: "USD",
account_holder_name,
account_holder_type: "individual",
routing_number,
account_number,
},
},
function (err, token) {
res.send(token);
}
);
});

更新帐户:

  router.post("/updateAccount", async (req, res) => {
const {
AccountID,
Day,
Month,
Year,
first_name,
last_name,
email,
BankAccountID,
} = req.body;

const FrontFilePath = fs.readFileSync("PathToFileHere");
const FrontPhotoIDUpload = await stripe.files.create({
file: {
data: FrontFilePath,
name: "FrontPhotoID.jpg",
type: "application.octet-stream",
},
purpose: "identity_document",
});

const BackFilePath = fs.readFileSync("PathToFileHere");
const BackPhotoIDUpload = await stripe.files.create({
file: {
data: BackFilePath,
name: "BackPhotoID.jpg",
type: "application.octet-stream",
},
purpose: "identity_document",
});

stripe.accounts.update(
AccountID,
{
business_type: "individual",
individual: {
dob: { day: Day, month: Month, year: Year },
first_name: first_name,
last_name: last_name,
id_number: "006-20-8311",
phone: "605-628-6049",
address: {
city: "Half Way",
line1: "2467 Twin House Lane",
postal_code: "65663",
state: "MO",
},
email,
ssn_last_4: "8311",
verification: {
document: {
front: FrontPhotoIDUpload.id,
back: BackPhotoIDUpload.id,
},
},
},
business_profile: {
mcc: "4722",
url: "http://www.baoisne.com",
},
tos_acceptance: {
date: Math.floor(Date.now() / 1000),
ip: req.connection.remoteAddress,
},
},
function (err, account) {
console.log(err);
console.log(account);
}
);
//Connect External Account
stripe.accounts.createExternalAccount(
AccountID,
{
external_account: BankAccountID,
},
function (err, bankAccount) {
console.log(err);
res.send(bankAccount);
}
);
});

然后,当客户提供他的帐户详细信息时,我会向客户收费,保留一些钱作为申请费,并将其余部分转移到 Service Providers Connect 帐户。

向客户收费

  router.post("/charge", async (req, res) => {
const { TokenID, CustomerID, Amount, AccountID } = req.body;
let PaymentAmount = Amount * 100;
let application_fee_amount = 400;
try {
const payment = await stripe.paymentIntents.create({
amount: PaymentAmount,
currency: "USD",
description: "We did it boss",
payment_method_data: {
type: "card",
card: {
token: TokenID,
},
},
receipt_email: "abdullahabid427@gmail.com",
customer: CustomerID,
application_fee_amount,
transfer_data: {
destination: AccountID,
},
confirm: true,
});
return res.status(200).json({
confirm: "Payment Succeeded",
});
} catch (error) {
console.log(error);
return res.status(400).json({
message: error.message,
});
}
});

通过执行上述程序,创建连接账户并将金额转入连接账户。

Issue

上述程序虽然工作正常,但它会在客户收费后直接将金额转移到连接的服务提供商帐户中,我希望客户向平台付款,在服务提供商提供服务后,平台支付给服务提供商,我考虑删除

  application_fee_amount,
transfer_data: {
destination: AccountID,
}

ChargeStripe.paymentIntents.create 端点中的上述参数,在服务提供商完成其服务后,我使用 Stripe Transfer API 转账金额

router.post("/transfer", async (req, res) => {
try {
console.log("TRANSFER=");
const { AccountID, amount } = req.body;
const transfer = await stripe.transfers.create({
amount,
currency: "USD",
destination: AccountID,
});
res.send(transfer);
} catch (error) {
res.send(error);
}
});

这里的问题是传输端点返回“您的目标帐户需要至少启用以下功能之一:传输、legacy_payments”,我已经在 Stripe 仪表板和功能部分 Card_PaymentTransfers 都设置为 Active,而且 Payments 和 Payouts 都已启用并且连接帐户的状态为“Complete”

因此,如果有人能指出正确的方向,我将不胜感激,干杯 :)

最佳答案

好的 - 我们同意 Stripe 按预期工作。您收到错误消息是因为您从付款意向创建函数中删除了目标账户 ID。这就是问题所在,在您的标题Charge Customer 下。

让我们看一下:(简化版)

const payment = await stripe.paymentIntents.create({
amount: PaymentAmount,
currency: "USD",
...
customer: CustomerID,
application_fee_amount,
transfer_data: {
destination: AccountID,
},
confirm: true,
});

最后一个属性confirm: true 相当于在同一个调用中创建和确认支付意图。默认值为 false - 使用新创建的支付意向的状态将为 requires_confirmation。准备就绪后,您可以按照以下方式确认付款意向:

const confirmedPayment = await stripe.paymentIntents.confirm(
'payment_intent_id',
{payment_method: 'card'},
function(err, paymentIntent) {

}
});

对出错的一些一般性评论

当付款人在线为某些商品付款时,应用程序开发人员有责任实现发送和接收金钱和商品的逻辑:可以是预付费、后付费或部分两者。没有逻辑是万无一失的。一般来说,如果我们担心客户利用我们的付款政策,我们可以要求所有付款方预付所有费用,并包括公平的退款政策。在这种情况下,Stripe 支持付款意向的退款,但更重要的是:它会跟踪付款状态。

当支付意向创建但未确认时,状态为requires_confirmation。那里不会出错。但在付款意向得到确认后,状态将为processing - 这可能需要几天时间。您可以随时决定取消付款。但如果一切顺利,状态将更改为 成功,这意味着资金已到达目标帐户。但如果由于某种原因支付失败,状态将返回到requires_payment_method。即使在这种情况下,也无需创建新的付款或转帐对象。您可以随时通过调用 stripe.retrievePaymentIntent(clientSecret) 检索支付意向并检查状态。但在我看来,使用配置为接收状态更改事件的 webhook 监视状态更改要容易得多。即使在状态更改时没有立即采取任何操作,我们也可以将状态存储在可用的数据库中。

根据经验,我发现付款失败是多么普遍。这并不意味着任何一方都在进行欺诈,但这确实意味着该应用程序应该准备好处理这两种情况。添加到 webhook 配置的事件是 payment_intent.succeededpayment_intent.payment_failed。这些事件的处理方式因每个应用程序而异。

关于node.js - 无法将金额转移到 Connect Stripe 帐户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62095187/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com