You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用PayPal REST API发送发票遇AUTHORIZATION_ERROR问题排查

问题:PayPal发票创建成功但发送时出现AUTHORIZATION_ERROR

我正在开发一款桌面应用,计划使用Python通过PayPal REST API批量创建并发送发票。最初使用paypalrestsdk库,通过正式环境(非沙箱)的Client ID和Client Secret创建发票,但调用send()方法发送时应用持续加载,PayPal开发者API调用界面显示401权限错误。

因该库已废弃,我采用混合方案:用paypalrestsdk创建发票,自行编写基于requests库的代码发送发票,代码如下:

def send_invoices_batch(self, email_list):
        paypalrestsdk.configure({
            "mode": "live", # sandbox or live
            "client_id": str(self.clientIdInput.text()),
            "client_secret": str(self.clientSecretInput.text())
        })

        invoices = []  # Store Invoice objects for each email

        # Construct and store Invoice objects for each email
        # for email in email_list:
        invoice = self.construct_invoice(email_list)
        invoices.append(invoice)

        # Create and send invoices using the paypalrestsdk library
        for invoice in invoices:
            invoice_created = invoice.create()
            if invoice_created:
                print("INVOICE CREATED:", invoice_created)
                self.responseDisplay.append(f"Invoice {invoice.id} created successfully!")
            else:
                self.responseDisplay.append(f"Failed to create invoice {invoice.id}: {invoice.error}")

            paypalrestsdk.configure({
                "mode": "live", # sandbox or live
                "client_id": str(self.clientIdInput.text()),
                "client_secret": str(self.clientSecretInput.text())
            })

            send_url = f"https://api.paypal.com/v1/invoicing/invoices/{invoice.id}/send"
            headers = {
                "Authorization": f"Bearer {self.get_access_token()}",
                "Content-Type": "application/json"
            }
            response = requests.post(send_url, headers=headers)

            if response.status_code == 202:
                self.responseDisplay.append(f"Invoice {invoice.id} sent successfully!")
            else:
                self.responseDisplay.append(f"Failed to send invoice {invoice.id}: {response.text}")

def get_access_token(self):
        auth_url = "https://api.paypal.com/v1/oauth2/token"
        headers = {
            "Accept": "application/json",
            "Accept-Language": "en_US"
        }
        data = {
            "grant_type": "client_credentials"
        }
        auth = (self.clientIdInput.text(), self.clientSecretInput.text())
        
        response = requests.post(auth_url, headers=headers, data=data, auth=auth)
        if response.status_code == 200:
            access_token = response.json().get("access_token")
            return access_token
        else:
            raise Exception(f"Failed to obtain access token: {response.text}")

运行应用后,发票创建成功,但发送时出现错误:

Failed to send invoice [INVOICE-ID]: {"name":"AUTHORIZATION_ERROR","message":"Authorization error occurred.","information_link":"https://developer.paypal.com/docs/api/invoicing/#errors","debug_id":"48832993cf8a2"}

已确认以下信息:

  • 使用正式账户的Client ID和Client Secret
  • 账户拥有创建和发送发票的权限
  • 发送请求为POST而非GET

请问我哪里操作有误?


解决思路与方案

1. 补充Access Token的权限范围

client_credentials模式获取的token默认仅拥有应用级基础权限,发送发票需要明确的invoicing:send权限。修改get_access_token方法,在请求参数中添加权限范围:

data = {
    "grant_type": "client_credentials",
    "scope": "invoicing:send invoicing:create"
}

2. 修复POST请求的空Body问题

根据PayPal API规范,发送发票的POST请求需要携带空的JSON请求体,否则会触发权限校验异常。修改发送请求的代码:

response = requests.post(send_url, headers=headers, json={})

3. 移除冗余配置

循环内重复调用paypalrestsdk.configure属于无效操作,会增加不必要的状态开销,直接删除该重复配置代码即可。

4. 验证Token权限有效性

打印获取到的access_token,通过PayPal开发者后台的token验证工具检查其权限列表,确认是否包含invoicing:send。如果没有,需在PayPal开发者后台为当前应用启用发票发送权限。


内容的提问来源于stack exchange,提问作者Khubaib Khawar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:35:19