DEV Community

Discussion on: ¿Cómo integrar Mercado Pago a tu web?

Collapse
 
nicolascastrogarcia profile image
Nicolás Castro Garcia • Edited

Hola Luis!

Te respondo por partes.
Primero que nada, es tal cual vos decis. Los pagos en efectivo (oxxo por ejemplo) se crean con un status pending. Es decir que al momento de generar el link, deberías plantear dentro de la preferencia del link, una back_urls.pending para que el usuario sepa que el pago todavía no fue realizado.

Segundo, vas a recibir 3 notificaciones de webhook. Una que se va a ver algo así:

{"action":"payment.created",
"api_version":"v1",
"data":{"id":"7125503101"},
"date_created":"2020-06-17T13:49:17Z",
"id":5990968261,
"live_mode":true,
"type":"payment",
"user_id":"469485398"}

luego te debería llegar esta notificación con topic: payment y resource:

    "id": 7125503101,
    "site_id": "MLA",
    "date_created": "2020-06-17T09:49:17.000-04:00",
    "date_approved": null,
    "money_release_date": null,
    "last_modified": "2020-06-17T09:49:17.000-04:00",
    "payer": {},
    "order_id": "1534217575",
    "external_reference": "referencia_externa",
    "merchant_order_id": "1534217575",
    "reason": "iPhone 8",
    "currency_id": "ARS",
    "transaction_amount": 600,
    "net_received_amount": 0,
    "total_paid_amount": 600,
    "shipping_cost": 0,
    "coupon_amount": 0,
    "coupon_fee": 0,
    "finance_fee": 0,
    "discount_fee": 0,
    "coupon_id": null,
    "status": "pending",
    "status_detail": "pending_waiting_payment",
    "issuer_id": null,
    "installment_amount": 0,
    "deferred_period": null,
    "payment_type": "ticket",
    "payment_method_id": "pagofacil", 
//aca te debería aparecer oxxo si lo seleccionaste
    "marketplace": "NONE",
    "operation_type": "regular_payment",
    "transaction_order_id": null,
    "statement_descriptor": null,
    "cardholder": null,
    "authorization_code": null,
    "marketplace_fee": 0,
    "deduction_schema": null,
    "refunds": [
    ],
    "amount_refunded": 0,
    "last_modified_by_admin": null,
    "api_version": "2",
    "concept_id": null,
    "concept_amount": 0,
    "collector": {}

y por último con topic: merchant_order:

{
  "id": 1534217575,
  "status": "closed",
  "external_reference": "referencia_externa",
  "preference_id": "469485398-1303f910-88c4-4fb1-ab09-6336e4b7e4c7",
  "payments": [
    {
      "id": 7125503101,
      "transaction_amount": 600,
      "total_paid_amount": 600,
      "shipping_cost": 0,
      "currency_id": "ARS",
      "status": "pending",
      "status_detail": "pending_waiting_payment",
      "operation_type": "regular_payment",
      "date_approved": "0001-01-01T00:00:00.000+00:00",
      "date_created": "2020-06-17T09:49:17.000-04:00",
      "last_modified": "2020-06-17T09:49:17.000-04:00",
      "amount_refunded": 0
    }
  ],
  "shipments": [
  ],
  "payouts": [
  ],
  "collector": {
    "id": 469485398,
    "email": "test_user_97555375@testuser.com",
    "nickname": "TETE2587273"
  },
  "marketplace": "NONE",
  "notification_url": "https://localhost:3000/webhook",
  "date_created": "2020-06-17T13:49:16.289+00:00",
  "last_updated": "2020-06-17T13:49:17.923+00:00",
  "sponsor_id": null,
  "shipping_cost": 0,
  "total_amount": 600,
  "site_id": "MLA",
  "paid_amount": 600,
  "refunded_amount": 0,
  "payer": {},
  "items": [
    {}
  ],
  "cancelled": false,
  "additional_info": "",
  "application_id": null,
  "order_status": "payment_in_process"
}

Y a partir de acá si sale todo bien, vas a volver a recibir 3 notificaciónes webhook:
Una con action: payment.updated:

{"action":"payment.updated", 
//nos dice que el pago con el id de data.id se actualizó
"api_version":"v1",
"data":{"id":"7125503101"},
"date_created":"2020-06-17T13:49:17Z",
"id":5990994133,
"live_mode":true,
"type":"payment",
"user_id":"469485398"
}

Una con topic: payment que va a recibir lo mismo que antes pero el status va a decir: approved

{
  "collection": {
    "id": 7125503101,
//este id fijate que es el mismo que el de la notificación anterior
    "site_id": "MLA",
    "date_created": "2020-06-17T09:49:17.000-04:00",
    "date_approved": null,
    "money_release_date": null,
    "last_modified": "2020-06-17T09:58:44.000-04:00",
    "payer": {},
    "order_id": "1534217575",
    "external_reference": "referencia_externa",
    "merchant_order_id": "1534217575",
    "reason": "iPhone 8",
    "currency_id": "ARS",
    "transaction_amount": 600,
    "net_received_amount": 0,
    "total_paid_amount": 600,
    "shipping_cost": 0,
    "coupon_amount": 0,
    "coupon_fee": 0,
    "finance_fee": 0,
    "discount_fee": 0,
    "coupon_id": null,
    "status": "approved",
//acá es donde vemos si el usuario pagó o no
    "status_detail": "by_payer",
    "issuer_id": null,
    "installment_amount": 0,
    "deferred_period": null,
    "payment_type": "ticket",
    "payment_method_id": "pagofacil",
// aca el método que usó para pagar en tu caso sería oxxo
    "marketplace": "NONE",
    "operation_type": "regular_payment",
    "transaction_order_id": null,
    "statement_descriptor": null,
    "cardholder": null,
    "authorization_code": null,
    "marketplace_fee": 0,
    "deduction_schema": null,
    "refunds": [
    ],
    "amount_refunded": 0,
    "last_modified_by_admin": null,
    "api_version": "2",
    "concept_id": null,
    "concept_amount": 0,
    "collector": {}
  }
}

Una con topic: merchant_order que va a recibir exactamento lo mismo que antes, pero payments[0].status se va a haber actualizado a approved y order_status a paid

{
  "id": 1534217575,
  "status": "closed",
  "external_reference": "referencia_externa",
  "preference_id": "469485398-1303f910-88c4-4fb1-ab09-6336e4b7e4c7",
  "payments": [
    {
      "id": 7125503101,
// este id es el del pago, de la notificación anterior
      "transaction_amount": 600,
      "total_paid_amount": 600,
      "shipping_cost": 0,
      "currency_id": "ARS",
      "status": "approved",
//acá confirma que pagó
      "status_detail": "by_payer",
      "operation_type": "regular_payment",
      "date_approved": "0001-01-01T00:00:00.000+00:00",
      "date_created": "2020-06-17T09:49:17.000-04:00",
      "last_modified": "2020-06-17T09:58:44.000-04:00",
      "amount_refunded": 0
    }
  ],
  "shipments": [
  ],
  "payouts": [
  ],
  "collector": {},
  "marketplace": "NONE",
  "notification_url": "https://mercadopago-checkout.herokuapp.com/webhook",
  "date_created": "2020-06-17T13:49:16.289+00:00",
  "last_updated": "2020-06-17T13:58:46.588+00:00",
  "sponsor_id": null,
  "shipping_cost": 0,
  "total_amount": 600,
  "site_id": "MLA",
  "paid_amount": 600,
  "refunded_amount": 0,
  "payer": {},
  "items": [],
  "cancelled": false,
  "additional_info": "",
  "application_id": null,
  "order_status": "paid"
//acá se actualizó porque pagó
}

En síntesis, la manera correcta de hacer el track a lo largo de toda la aplicación es con el merchant_order. El payment.id es una propiedad del objeto merchant_order.

Recordá que dentro de merchant_order, podes tener más de un método de pago, es decir, el usuario puede haber modificado el método de pago desde la aplicación y en ese caso, el objeto merchant_order cambiaría, teniendo dentro del array payments, algo similar a esto:

"payments": [
    {
      "id": 7125503101,
      "transaction_amount": 600,
      "total_paid_amount": 600,
      "shipping_cost": 0,
      "currency_id": "ARS",
      "status": "cancelled",
 //acá canceló el pago en efectivo
      "status_detail": "by_payer",
      "operation_type": "regular_payment",
      "date_approved": "0001-01-01T00:00:00.000+00:00",
      "date_created": "2020-06-17T09:49:17.000-04:00",
      "last_modified": "2020-06-17T09:58:44.000-04:00",
      "amount_refunded": 0
    },
    {
      "id": 7125727198,
      "transaction_amount": 600,
      "total_paid_amount": 600,
      "shipping_cost": 0,
      "currency_id": "ARS",
      "status": "approved",
// y acá pagó con otro método, que para saberlo, 
//tenemos que pegarle a     
// https://api.mercadopago.com/v1/payments/[ID]?access_token=[ACCESS_TOKEN]
// donde id es el id del payment (7125727198 en nuestro ejemplo)
// y ACCESS_TOKEN es el token de acceso de MP
      "status_detail": "accredited",
      "operation_type": "regular_payment",
      "date_approved": "2020-06-17T09:58:46.000-04:00",
      "date_created": "2020-06-17T09:58:45.000-04:00",
      "last_modified": "2020-06-17T09:58:46.000-04:00",
      "amount_refunded": 0
    }
  ],

Recordá que para hacer las pruebas en sandbox tenes que:
1- Utilizar el init_point para el link de pago y no el sandbox_init_point
2- Podes ingresar a la página de MP con tu usuario de test comprador, y ver el detalle de las transacciones directamente desde ahi
3- Podes cambiar el método de pago con tu usuario de test comprador, desde la página de MP

Te dejo por acá la documentación de los webhooks

Espero que te sea útil!

Collapse
 
luispastendev profile image
Luis Pastén • Edited

Gracias por contestar Nicolás, ahora me queda un poco mas claro, en este caso en producción llegan 3 notificaciones post al webhook?, actualmente estoy trabajando con php y estoy usando la sdk que proporcionan la cuestión es que en modo sandbox solo me esta llegando una notificación con la siguiente estructura:

{
    "action": "payment.created",
    "api_version": "v1",
    "data": {
        "id": "26774573"
    },
    "date_created": "2020-06-17T00:36:16Z",
    "id": 5988776238,
    "live_mode": false,
    "type": "payment",
    "user_id": "583365872"
}

En este caso lo que yo hago es utilizar el sdk que me imagino que internamente se conecta con la api de MP para extraer información extra de la orden como: (medio con el cual pago, monto etc.. etc..)

$body = @file_get_contents('php://input');
$data = json_decode($body);
$payment = \MercadoPago\Payment::find_by_id($data->data->id);
// TOMO LOS DATOS NECESARIOS PARA ACTUALIZAR MI ORDEN EN MI BASE DE DATOS... 

Te comparto mi estrategia haber que te parece

1-. cliente entra al checkout y realiza el submit
2-. genero la preferencia con los datos que me proporciono y los montos a cobrar
3-. genero una id única aleatoria para guardarla como folio de orden en mi base de datos la misma que pongo en la preferencia external_reference
4-. el cliente entra a mp y paga por el medio que quiera
5-. una ves concluido su pago puede haber 2 escenarios

5.1 PAGO CON TARJETA

  • capturo la el collection_id que me llega por get con la back_url de success y ejecuto de nuevo \MercadoPago\Payment::find_by_id() para buscar los datos de la orden
  • actualizo mi base de datos con algunos datos que me regresa y el status

5.2 PAGO CON TRANSFERENCIA O TICKET (OXXO 7VEN ETC)

  • genero una thankyou page con status pendiente he instrucciones postcompra
  • una ves pago el cliente me llega al webhook una notificación payment.updated en la cual también utilizo el id para buscar con \MercadoPago\Payment::find_by_id() y usar los datos para actualizar mi base de datos

A grandes rasgos esa es mi estrategia pero aún no subo mi plataforma a producción espero que todo se comporte de la misma manera aunque me deja un poco inquieto el saber que llegan 3 notificaciones cuando se recibe un pago por eso mismo te preguntaba si tu ya lo habías probado en live mode.

Nuevamente gracias por contestar y te envío un saludo!!

Thread Thread
 
nicolascastrogarcia profile image
Nicolás Castro Garcia • Edited

Debes estar recibiendo una sola notificación porque nunca se paga el link de sandbox, fijate de pagarlo con una cuenta de test.

Siempre podes filtrar las notificaciones, de las 3 que llegan son:
1- Una que es type: payment.created (se creo el link)
2- Una que es topic: payment (se creo el pago)
3- Una que es topic merchant_order (se creo la transacción)

Luego, una vez que la persona paga:

1- type: payment.updated (pagó)
2- topic: payment (se updatea la información del pago)
3- topic: merchant_order(se updateo la información de la transacción)

Después, en cuanto tu estratégia, la veo muy sólida. El único caso te quedaría para probar, es si la persona decide cambiar el método de pago desde la aplicación de Mercado Pago. Esto lo digo porque si sucede, es probable que se te cambie el payment_id que viene en la notificación del payment updated.

Thread Thread
 
luispastendev profile image
Luis Pastén • Edited

Muchas gracias Nico, dejo pendiente a ver como me va en las próximas semanas que subo el proyecto al servidor y te comento que tal me fue.

Gracias por el post, realmente de mucha ayuda para integrar ese medio de pago. Saludos!!