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

GoCardless生产环境创建Customer报403 Forbidden错误(沙箱正常)

问题

使用GoCardless API创建Customer与Mandate时,sandbox环境运行完全正常,但切换到live生产环境后,在创建Customer环节触发403 Forbidden错误。相关代码如下:

def create_gocardless_customer(self):
    self.ensure_one()
    try:
        print("Inizio processo di associazione/creazione cliente GoCardless")  # Debug

        # Verifica dei campi obbligatori
        if not self.surname:
            raise UserError("Il campo 'Cognome' è obbligatorio.")
        if not self.pec and not self.email:
            raise UserError("Il campo 'Email' è obbligatorio.")
        if (not self.pec and ("@" not in self.email or "." not in self.email)) or (
                self.pec and ("@" not in self.pec or "." not in self.pec)):
            raise UserError("L'indirizzo email fornito non è valido.")
        if not self.iban:
            raise UserError("Il campo 'IBAN' è obbligatorio.")

        print("Campi obbligatori verificati")  # Debug

        # Creazione del client GoCardless
        client = gocardless_pro.Client(
            access_token=token,
            environment='live'
        )
        print("Client GoCardless creato con successo")  # Debug

        # Ricerca del cliente tramite email
        customer = None
        customers_list = client.customers.list()
        print("Lista clienti recuperata:", customers_list.records)  # Stampa la lista dei clienti
        for existing_customer in customers_list.records:
            if existing_customer.email == (self.pec if self.pec else self.email):
                customer = existing_customer
                print(f"Cliente esistente trovato con ID: {customer.id}")  # Debug
                self.id_gocardless = customer.id
                break

        # Creazione del cliente se non esiste
        if not customer:
            customer_data = {
                "given_name": self.name,
                "family_name": self.surname,
                "email": self.pec if self.pec else self.email,
                "address_line1": " ",
                "city": " ",
                "postal_code": " ",
                "country_code": "IT"
            }
            print(f"Creazione nuovo cliente con i seguenti dati: {customer_data}")  # Debug
            customer = client.customers.create(params=customer_data)
            self.id_gocardless = customer.id
            self.env.cr.commit()

        # Verifica se esiste già un account bancario con lo stesso IBAN (utilizzando 'account_number_ending')
        existing_bank_accounts = client.customer_bank_accounts.list(params={"customer": customer.id})
        print("Lista account bancari per il cliente:",
              existing_bank_accounts.records)  # Debug lista account bancari

        for account in existing_bank_accounts.records:
            print(f"Account number ending: {account.attributes['account_number_ending']}")  # Debug

        matching_account = next(
            (account for account in existing_bank_accounts.records if
             account.attributes['account_number_ending'] == self.iban[-2:]),
            None
        )

        if matching_account:
            print(f"Account bancario esistente trovato con ID: {matching_account.attributes['id']}")  # Debug
            self.bank_account_id = matching_account.attributes['id']
            # Verifica se esiste un mandato attivo
            existing_mandates = client.mandates.list(
                params={"customer_bank_account": matching_account.attributes['id']})
            print("Lista mandati per account bancario:", existing_mandates.records)  # Debug lista mandati
            active_mandate = next(
                (mandate for mandate in existing_mandates.records if mandate.status == 'active'),
                None
            )
            if active_mandate:
                print(f"Mandato attivo esistente trovato con ID: {active_mandate.id}")  # Debug
                self.mandato_id = active_mandate.id
            else:
                # Crea un nuovo mandato se non esiste un mandato attivo
                mandate_data = {
                    "scheme": "sepa_core",
                    "links": {
                        "customer_bank_account": matching_account.attributes['id']
                    }
                }
                mandate = client.mandates.create(params=mandate_data)
                print(f"Nuovo mandato creato con ID: {mandate.id}")  # Debug
                self.mandato_id = mandate.id
        else:
            try:
                # Solo se non esiste un account bancario con lo stesso IBAN, creazione nuovo account bancario e mandato
                bank_account_data = {
                    "iban": self.iban,
                    "account_holder_name": f"{self.name} {self.surname}",
                    "country_code": "IT",
                    "links": {
                        "customer": customer.id
                    }
                }
                print(f"Creazione nuovo account bancario con i seguenti dati: {bank_account_data}")  # Debug
                new_bank_account = client.customer_bank_accounts.create(params=bank_account_data)
                print(f"Nuovo account bancario creato con ID: {new_bank_account.id}")  # Debug
                self.bank_account_id = new_bank_account.id
                mandate_data = {
                    "scheme": "sepa_core",
                    "links": {
                        "customer_bank_account": new_bank_account.id
                    }
                }
                mandate = client.mandates.create(params=mandate_data)
                print(f"Nuovo mandato creato con ID: {mandate.id}")  # Debug
                self.mandato_id = mandate.id
            except Exception as e:
                if "Bank account already exists" in str(e):
                    # Se l'account esiste già, recuperalo
                    existing_bank_accounts = client.customer_bank_accounts.list(params={"customer": customer.id})
                    matching_account = next(
                        (account for account in existing_bank_accounts.records if
                         account.attributes['account_number_ending'] == self.iban[-2:] and
                         account.attributes['account_holder_name'] == f"{self.name} {self.surname}"),
                        None
                    )
                    if matching_account:
                        print(
                            f"Account bancario esistente trovato con ID: {matching_account.attributes['id']} dopo errore di creazione")  # Debug
                        self.bank_account_id = matching_account.attributes['id']
                        existing_mandates = client.mandates.list(
                            params={"customer_bank_account": matching_account.attributes['id']})
                        active_mandate = next(
                            (mandate for mandate in existing_mandates.records if mandate.status == 'active'),
                            None
                        )
                        if active_mandate:
                            print(f"Mandato attivo esistente trovato con ID: {active_mandate.id}")  # Debug
                            self.mandato_id = active_mandate.id
                        else:
                            # Crea un nuovo mandato se non esiste un mandato attivo
                            mandate_data = {
                                "scheme": "sepa_core",
                                "links": {
                                    "customer_bank_account": matching_account.attributes['id']
                                }
                            }
                            mandate = client.mandates.create(params=mandate_data)
                            print(f"Nuovo mandato creato con ID: {mandate.id}")  # Debug
                            self.mandato_id = mandate.id
                else:
                    raise

        self.env.cr.commit()
        print("Operazione completata con successo")  # Debug

    except PermissionsError as e:
        print(f"Errore di permessi GoCardless: {e}")  # Debug
        raise UserError(f"Errore di permessi GoCardless: {e}")
    except InvalidApiUsageError as e:
        print(f"Errore di utilizzo API GoCardless: {e}")  # Debug
        raise UserError(f"Errore di utilizzo API GoCardless: {e}")
    except InvalidStateError as e:
        print(f"Errore di stato GoCardless: {e}")  # Debug
        raise UserError(f"Errore di stato GoCardless: {e}")
    except Exception as e:
        print(f"Errore GoCardless generico: {e}")  # Debug
        raise UserError(f"Errore GoCardless: {e}")

环境情况:

  • Sandbox环境:Customer与Mandate创建流程完全正常,无任何问题。
  • Live生产环境:创建Customer时触发403 Forbidden错误。

排查与解决方案

1. 校验Live环境的Access Token

  • 确认使用的live环境token是独立生成的,不能复用sandbox的token。
  • 登录GoCardless后台,检查该token对应的API密钥是否开启了*customers:write*权限,live环境的权限配置和sandbox不共享。

2. 检查账号激活状态

  • 确认你的GoCardless live账号已经完成所有激活步骤(身份验证、合规审核),未激活账号会被限制API写操作。

3. 修正Customer数据的必填字段

  • 代码中address_line1、city、postal_code填的是空格,live环境对地址字段的合法性要求严格,必须提供真实有效的地址信息,空或无效地址会触发权限或参数校验错误。

4. 查看详细错误响应

  • 修改异常捕获逻辑,打印403错误的完整响应内容(包括error.code和error.message),GoCardless API会返回具体的拒绝原因,比如权限不足、字段非法等,这是定位问题最快的方式。

5. 排查速率限制

  • 检查是否触发了live环境的API速率限制,虽然403通常不是速率限制的错误码,但短时间内大量调用可能导致临时封禁,可通过GoCardless后台的API日志确认。

内容的提问来源于stack exchange,提问作者Luca Marcone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:23:11