feat: offer credit card, debit card and PIX, with the bank's 3-D Secure step
All checks were successful
Build and deploy / Validate source (push) Successful in 5s
Build and deploy / Integration suite on a real stack (push) Successful in 2m3s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images (push) Successful in 1m31s
All checks were successful
Build and deploy / Validate source (push) Successful in 5s
Build and deploy / Integration suite on a real stack (push) Successful in 2m3s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images (push) Successful in 1m31s
The payment page lists credit card (preselected), debit card and PIX. Each card option limits Mercado Pago's form to its kind; debit is paid at once. Card payments ask for 3-D Secure when the issuer requires it, and a challenge opens the bank's page in a frame, which needs PAYMENT_CHALLENGE_SOURCES=https: (frames and form posts only). A card left waiting for that confirmation stops blocking a new attempt after ten minutes, and a refusal reported by the notification returns the customer to the payment choice. Written from the documentation; not yet run with a real debit card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -73,8 +73,11 @@ class MercadoPagoPayment:
|
||||
if method['type'] == 'pix':
|
||||
body['payment_method_id'] = 'pix'
|
||||
elif method['type'] == 'card':
|
||||
# The issuer decides whether the cardholder must confirm in the
|
||||
# bank's app or page (3-D Secure); debit cards usually must.
|
||||
body.update(token=method['token'], payment_method_id=method['payment_method_id'],
|
||||
installments=int(method.get('installments', 1)))
|
||||
installments=int(method.get('installments', 1)),
|
||||
three_d_secure_mode='optional')
|
||||
if method.get('issuer_id'):
|
||||
body['issuer_id'] = method['issuer_id']
|
||||
else:
|
||||
@@ -88,13 +91,20 @@ class MercadoPagoPayment:
|
||||
response.raise_for_status()
|
||||
payment = response.json()
|
||||
transaction = (payment.get('point_of_interaction') or {}).get('transaction_data') or {}
|
||||
# A payment waiting for 3-D Secure carries the bank's challenge page,
|
||||
# which the Site shows in a frame by posting `creq` to that address.
|
||||
three_ds = payment.get('three_ds_info') or {}
|
||||
challenge = ({'url': three_ds['external_resource_url'], 'creq': three_ds['creq']}
|
||||
if payment.get('status_detail') == 'pending_challenge'
|
||||
and three_ds.get('external_resource_url') and three_ds.get('creq') else None)
|
||||
return {'provider': self.name, 'id': str(payment['id']),
|
||||
'status': STATUSES.get(payment.get('status'), 'pending'),
|
||||
'status_detail': payment.get('status_detail'),
|
||||
'total_cents': total_cents,
|
||||
'pix_qr_code': transaction.get('qr_code'),
|
||||
'pix_qr_code_base64': transaction.get('qr_code_base64'),
|
||||
'ticket_url': transaction.get('ticket_url')}
|
||||
'ticket_url': transaction.get('ticket_url'),
|
||||
'challenge': challenge}
|
||||
|
||||
def lookup(self, payment_id: str) -> dict:
|
||||
response = self.http.get(f'/v1/payments/{payment_id}')
|
||||
|
||||
Reference in New Issue
Block a user