"""Read-only look at the Mercado Pago account behind MP_ACCESS_TOKEN. python -m app.mercadopago_probe [--bin 503143] [--valor 50] Run from the api container's console (Portainer > Containers > api > Console). It creates nothing and charges nothing: it asks Mercado Pago which account the token belongs to, which card methods the account accepts, and how it classifies a card number's first digits (type, issuer, instalments). That is what payment errors such as 10111 (issuer) and 10113 (method excluded by a rule) depend on. """ import argparse import os import sys import httpx from .core.secrets import load as load_secret_files API = 'https://api.mercadopago.com' def main(argv=None): parser = argparse.ArgumentParser(prog='python -m app.mercadopago_probe') parser.add_argument('--bin', default='503143', help="the card's first six digits (default: the Mastercard test card)") parser.add_argument('--valor', default='50', help='amount in reais for the instalment lookup') args = parser.parse_args(argv) load_secret_files() token = os.environ.get('MP_ACCESS_TOKEN', '') if not token: print('MP_ACCESS_TOKEN is not set in this container.') return 1 http = httpx.Client(base_url=API, timeout=15, headers={'Authorization': f'Bearer {token}'}) print(f"Token: {'TEST' if token.startswith('TEST-') else 'produção'}") me = http.get('/users/me') if me.status_code == 200: user = me.json() tags = user.get('tags') or [] print(f"Conta: id {user.get('id')} · {user.get('nickname')} · site {user.get('site_id')} · " f"usuário de teste: {'sim' if 'test_user' in tags else 'não'} · tags {tags}") else: print(f'Conta: HTTP {me.status_code} {me.text[:200]}') methods = http.get('/v1/payment_methods') if methods.status_code == 200: cards = [m for m in methods.json() if m.get('payment_type_id') in ('credit_card', 'debit_card')] print('Cartões aceitos pela conta:') for m in cards: print(f" {m.get('id'):<12} {m.get('payment_type_id'):<12} {m.get('status')}") else: print(f'Meios de pagamento: HTTP {methods.status_code} {methods.text[:200]}') quote = http.get('/v1/payment_methods/installments', params={'bin': args.bin, 'amount': args.valor}) if quote.status_code == 200 and quote.json(): print(f'BIN {args.bin}:') for option in quote.json(): issuer = option.get('issuer') or {} counts = [c.get('installments') for c in option.get('payer_costs') or []] print(f" meio {option.get('payment_method_id')} · tipo {option.get('payment_type_id')} · " f"emissor {issuer.get('id')} ({issuer.get('name')}) · parcelas {counts}") else: print(f'BIN {args.bin}: HTTP {quote.status_code} {quote.text[:300]}') return 0 if __name__ == '__main__': sys.exit(main())