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
相关产品推荐
相关产品推荐

