Cartão de Crédito¶
O que é¶
Pagamento de cartão de crédito/débito alojado com 3D-Secure / OTP. O cliente é redirecionado para a página da eupago para introduzir os dados do cartão e (se o cartão ou o valor o exigirem) completar o desafio 3DS. O resultado chega por webhook.
O mesmo serviço cobre três fluxos:
create_payment— cobrança imediata.authorize+capture— reservar agora, cobrar depois.create_subscription+charge_subscription— registar o cartão uma única vez e cobrar do servidor a qualquer momento.
O valor máximo por transação é 3.999 EUR.
Fluxo¶
sequenceDiagram
participant App
participant eupago
participant Cliente
App->>eupago: create_payment(amount, success_url, error_url, back_url)
eupago-->>App: redirectUrl + transactionID (status PENDING)
App->>Cliente: Redirect para redirectUrl
Cliente->>eupago: Introduz cartão + (opcional) OTP 3DS
eupago->>App: Webhook (PAID / DECLINED)
Exemplo — pagamento único¶
from decimal import Decimal
from eupago import EupagoClient
from eupago.models import Customer
client = EupagoClient(api_key="...", sandbox=True)
payment = client.credit_card.create_payment(
order_id="ORD-CC-001",
amount=Decimal("249.90"),
success_url="https://loja.exemplo.pt/ok",
error_url="https://loja.exemplo.pt/falha",
back_url="https://loja.exemplo.pt/carrinho",
customer=Customer(email="cliente@exemplo.pt"),
)
# Redirecciona o cliente para payment.payment_url e aguarda o webhook
Cartão de teste (sandbox): 4018810000150015 (Visa) — OTP 0101
sucesso, 3333 falha. Valores acima de 500 EUR despoletam o OTP.
Exemplo — authorize + capture¶
auth = client.credit_card.authorize(
order_id="ORD-CC-AUTH-001",
amount=Decimal("100.00"),
success_url="...", error_url="...", back_url="...",
)
# Mais tarde, quando o serviço for prestado — capture exige amount e as
# mesmas URLs (eupago rejeita corpo vazio com AMOUNT_MISSING).
captured = client.credit_card.capture(
transaction_id=auth.transaction_id,
amount=Decimal("100.00"),
success_url="...", error_url="...", back_url="...",
)
Capacidade do canal
authorize + capture exigem que o canal eupago tenha Cartão de
Crédito — Auth & Capture provisionado (uma feature separada do
Cartão de Crédito básico). Num canal demo o formulário redirecciona
para o errorUrl e o capture devolve PAYMENT_NOT_CAPTIVE. Pede ao
suporte da eupago para activar a feature no teu canal.
Exemplo — subscrição¶
sub = client.credit_card.create_subscription(
order_id="SUB-2026-001",
amount=Decimal("19.90"), # valor recorrente
success_url="...", error_url="...", back_url="...",
# Opcionais — defaults equivalem a mensalmente, dia 1, 1 ano:
# periodicity="Mensal",
# collection_day=1,
# auto_process=False, # True = eupago cobra automaticamente
# start_date=date(2026, 6, 1),
# limit_date=date(2027, 6, 1),
)
# sub.transaction_id é o subscriptionID (hex de 32 chars) — guarda-o.
subscription_id = sub.transaction_id
# Cobra depois (server-to-server, sem intervenção do cliente):
client.credit_card.charge_subscription(
recurrent_id=subscription_id,
order_id="SUB-2026-001-M01",
amount=Decimal("19.90"),
success_url="...", error_url="...", back_url="...",
)
Capacidade do canal
Endpoints de subscrição exigem que o canal tenha Cartão de Crédito
— Subscrição provisionado pela eupago. Sem isso, o formulário de
registo redirecciona para o errorUrl e qualquer
charge_subscription é recusado. O SDK envia o body correcto
(verificado contra a spec readme.io); activa a feature no
backoffice ou via suporte.
Gestão de subscrições (Management API)¶
Quatro métodos no mesmo service permitem gerir uma subscrição existente.
Precisam de auth da Management API — passa client_id/client_secret
ou management_bearer ao EupagoClient.
# Listar todas as subscrições do canal
for sub in client.credit_card.list_subscriptions():
print(sub["identifier"], sub["status"], sub["eupagoToken"])
# Obter detalhe (usa o INTEIRO subscription_id — ver nota abaixo)
detail = client.credit_card.get_subscription(4756)
print(detail["nextCollectionDate"])
# Mudar opções de cobrança
client.credit_card.edit_subscription(
4756,
collection_day=15, # dia do mês (1..28)
auto_process=True, # True = eupago cobra sozinha todo o período
)
# Cancelar — só funciona em subscrições activas; em "Pendente" devolve SUBSCRIPTION_NOT_FOUND
client.credit_card.revoke_subscription(4756)
Auto vs. manual
Com auto_process=True a eupago cobra o cartão registado em cada
collection_day da periodicity escolhida — nextCollectionDate
fica visível no detalhe. Com auto_process=False chamas
charge_subscription(recurrent_id=...) quando quiseres cobrar.
Quirk do subscription_id inteiro
Os 4 métodos acima usam o inteiro subscriptionId (ex: 4756).
O hex eupagoToken que vem do create_subscription é o que
charge_subscription espera — é um identificador diferente.
Actualmente o inteiro não vem no list_subscriptions (gap real
de UX no eupago); tens de o ler do URL do backoffice quando editas
uma subscrição. Isto pode melhorar quando o eupago emitir
credenciais OAuth estáveis.
Reembolso¶
Ver Refunds para a configuração OAuth.
Notas¶
- As três URLs de retorno (
success_url,error_url,back_url) são exigidas pelo API emcreate_payment,authorizeecreate_subscription. - As subscrições guardam o token do cartão do lado da eupago; cobranças subsequentes não requerem intervenção do cliente.
- Vê os scripts runnable
07_credit_card_payment.pye08_credit_card_subscription.pypara o ciclo completo.