Stripe API调用报错求助:密钥无法访问指定cus账户
Stripe API付款错误:无权限访问Customer账户
错误信息
The provided key 'sk_test_***********************************************************************************************JQQa' does not have access to account 'cus_PN***' (or that account does not exist). Application access may have been revoked
代码实现
const stripe = require('stripe')( process.env.STRIPE_REAL_API_SECRET_KEY || process.env.STRIPE_TEST_API_SECRET_KEY ); const eligibleBalanceDueData = res[1].rows.map((row) => ({ balanceDueId: row.balance_due_id, affiliateStripeId: row.stripe_customer_id?.trim(), totalAmount: parseFloat(row.total_amount), })); for (const item of eligibleBalanceDueData) { // Retrieve the Connected Account ID associated with the Customer ID const connectedAccountId = await stripe.accounts.listExternalAccounts( item.affiliateStripeId, { limit: 1, type: 'custom_account' } ); const transfer = await stripe.transfers.create( { amount: 2, // item.totalAmount * 100, // Amount in cents currency: 'usd', destination: connectedAccountId.data[0].id, transfer_group: 'affiliate_payout', }, { idempotencyKey: 'unique_key_here' } ); }
调用stripe.accounts.listExternalAccounts或stripe.transfers.create时均会触发错误。我认为应使用transfers而非payouts或paymentIntents进行付款,且transfer的destination应为Stripe客户的账户ID。
已确认信息
- 测试模式下使用的是标准API密钥,具备认证权限;
- 错误中提及的
cus_PN***账户真实存在,与item.affiliateStripeId的值一致; - 仅需生成测试付款。
错误详情
{ type: 'StripePermissionError', raw: { message: "The provided key 'sk_test_***********************************************************************************************JQQa' does not have access to account 'cus_PNaqkPyNm7hjp4' (or that account does not exist). Application access may have been revoked.", type: 'invalid_request_error', code: 'account_invalid', doc_url: 'https://stripe.com/docs/error-codes/account-invalid', headers: { server: 'nginx', date: 'Tue, 16 Jan 2024 09:11:48 GMT', 'content-type': 'application/json', 'content-length': '432', connection: 'keep-alive', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', vary: 'Origin', 'strict-transport-security': 'max-age=63072000; includeSubDomains; preload' }, statusCode: 403, requestId: undefined }, rawType: 'invalid_request_error', code: 'account_invalid', doc_url: 'https://stripe.com/docs/error-codes/account-invalid', param: undefined, detail: undefined, headers: { server: 'nginx', date: 'Tue, 16 Jan 2024 09:11:48 GMT', 'content-type': 'application/json', 'content-length': '432', connection: 'keep-alive', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', vary: 'Origin', 'strict-transport-security': 'max-age=63072000; includeSubDomains; preload' }, requestId: undefined, statusCode: 403, charge: undefined, decline_code: undefined, payment_intent: undefined, payment_method: undefined, payment_method_type: undefined, setup_intent: undefined, source: undefined }
错误代码account_invalid的官方描述为:Stripe-Account请求头中的账户ID无效,请检查请求是否指定了有效的账户ID。
已查阅文档和相关帖子仍无法解决,寻求帮助。
解决方案
核心问题定位
你的代码存在两个关键错误:
- API误用:
stripe.accounts.listExternalAccounts是用于查询Connected Account(前缀acct_)的外部账户,而非Customer(前缀cus_)。传入Customer ID直接触发权限校验失败。 - 概念混淆:Transfers API用于平台与Connected Account之间的资金转移,若你的联盟伙伴是Customer身份,不能直接用Transfers到Customer ID,需改为付款到其绑定的支付方式。
修正方案
方案1:给Customer付款到绑定的支付方式
如果联盟伙伴是Customer且已绑定支付方式(银行卡/信用卡),直接创建Transfer到支付方式ID:
for (const item of eligibleBalanceDueData) { // 获取Customer的支付方式 const paymentMethods = await stripe.paymentMethods.list({ customer: item.affiliateStripeId, type: 'card' // 若为银行账户则改为'us_bank_account' }); if (paymentMethods.data.length === 0) { throw new Error(`Customer ${item.affiliateStripeId} 未绑定支付方式`); } // 创建Transfer到支付方式 const transfer = await stripe.transfers.create({ amount: Math.round(item.totalAmount * 100), // 转换为分 currency: 'usd', destination: paymentMethods.data[0].id, transfer_group: 'affiliate_payout', }, { idempotencyKey: `payout_${item.balanceDueId}` // 用唯一ID避免重复请求 }); }
方案2:将联盟伙伴转为Connected Account(适合长期合作场景)
若联盟伙伴是长期合作的商家,建议将其创建为Connected Account,后续用Transfers直接打款:
// 假设已通过OAuth或平台创建流程获取到Connected Account ID(acct_前缀) for (const item of eligibleBalanceDueData) { const transfer = await stripe.transfers.create({ amount: Math.round(item.totalAmount * 100), currency: 'usd', destination: item.affiliateConnectedAccountId, // 替换为acct_开头的ID transfer_group: 'affiliate_payout', }, { idempotencyKey: `payout_${item.balanceDueId}` }); }
额外检查点
- 确认API密钥权限:标准密钥默认具备Transfers创建权限,若使用Restricted密钥,需开启
transfers:create和payment_methods:read权限; - 若使用Connected Account,需确保平台已获得该账户的授权(未被撤销);
- 测试模式下使用Stripe官方测试支付方式(如卡号
4242 4242 4242 4242)。
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

