PayPal REST API创建发票失败:invalid_token错误求助
解决PayPal发票机器人的invalid_token错误
你的核心问题出在异步函数的调用方式,以及几个细节上的疏漏,以下是分步修复方案:
1. 修复AccessToken的获取与使用
你更新后的getAccessToken是异步函数,但在createInvoice里直接调用getAccessToken()会返回一个Promise对象,而非实际的token值,这会导致Authorization头变成Bearer [object Promise],直接触发invalid_token错误。
同时,获取token的请求需要指定Content-Type为application/x-www-form-urlencoded,否则PayPal服务器无法正确解析请求体。
修改后的getAccessToken:
async function getAccessToken(){ const response = await fetch('https://api-m.sandbox.paypal.com/v1/oauth2/token', { method: "post", body: "grant_type=client_credentials", headers:{ "Content-Type": "application/x-www-form-urlencoded", Authorization: "Basic " + Buffer.from(config.clientId + ":" + config.clientSecret).toString("base64") }, }); const data = await response.json(); // 如果获取token失败,直接抛出错误便于排查 if (data.error) throw new Error(`获取Token失败: ${data.error_description}`); console.log('获取到的Token:', data.access_token); return data.access_token; }
2. 修复createInvoice的异步逻辑
createInvoice需要改为异步函数,等待token获取完成后再发起发票创建请求,同时要确保发票创建成功后再调用sendInvoice,避免因异步时序问题导致发票还未生成就尝试发送。
修改后的createInvoice:
async function createInvoice(item_name, item_description, quantity, cost, payer_email){ try { const accessToken = await getAccessToken(); const invoiceNumber = generateInvoiceNumber(); const response = await fetch('https://api-m.sandbox.paypal.com/v2/invoicing/invoices', { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json', 'Prefer': 'return=representation' }, body: JSON.stringify({ "detail": { "invoice_number": invoiceNumber, // 复用同一个编号,避免重复生成 "currency_code": "USD", }, "invoicer": { "email_address": config.emailAddress, }, "primary_recipients": [ { "billing_info": { "email_address": payer_email, }, } ], "items": [ { "name": item_name, "description": item_description, "quantity": quantity, "unit_amount": { "currency_code": "USD", "value": cost, }, "unit_of_measure": "QUANTITY" }, ], }) }); if (!response.ok) { const errorData = await response.json(); console.error('创建发票失败:', errorData); return; } const invoiceData = await response.json(); console.log('发票创建成功:', invoiceData); // 等待发票创建完成后再发送 await sendInvoice(invoiceNumber); } catch (err) { console.error('流程出错:', err.message); } }
3. 额外排查点
- 确认
config.clientId和config.clientSecret是沙箱环境的凭证,不要混用生产环境的密钥。 - 检查沙箱商家账号的权限,确保该账号拥有创建发票的权限(需为已验证的商家账号)。
- 验证
generateInvoiceNumber生成的编号是否唯一,重复的发票编号会导致创建失败。 - 调用
createInvoice时,也要使用await或者.then()处理异步逻辑,避免调用后直接退出导致请求中断。
内容的提问来源于stack exchange,提问作者KaoDev
相关产品推荐
相关产品推荐

