Es una ayuda memora en referencia a la excelente información que está en Mercadopago Developers
-
Crear una aplicación para marketplace donde:
- en Redirect URI deben poner la url con https://dominio.com/auth/mercadopago ese formato uso en mi caso; esta url es la que los usuarios van a ser redireccionados luego de confirmar la autorización.
- tildar los scopes read, write, offline access
- topicos recomendados: items, orders, create orders, payments
- url de callback, es la url en donde van a recibir las notificaciones de MP, yo uso https://dominio.com/webhook/mercadopago
-
Crear un boton en el backend o panel de administración de tu vendedor, para que pueda vincular su cuenta de mercadopago al marketplace. Ese boton debe tener el siguiente formato:
https://auth.mercadopago.com.ar/authorization?client_id={APP_ID}&response_type=code&platform_id=mp&state={USER_ID_REF}&redirect_uri=https%3A%2F%2Fdominio.com/auth/mercadopago
, donde{APP_ID}
es el número que corresponde a tu app de marketplace;{USER_ID_REF}
es un código identificador para luego saber que usuario estás conectando yredirect_uri
es la misma url que setearon al crear la app. -
En el código, en la entrada en donde es redireccionado el vendedor, siguiendo el ejemplo
dominio.com/auth/mercadopago
tenes que tener un código similar a esto:
public function auth_provider()
{
$code = $this->input->get('code');
$state = $this->input->get('state');
// Compruebo que la url tenga el ?code= y el state de mercadopago
if (isset($code) AND isset($docId)) {
// Configuro para hacer el POST y obtener el token y datos del usuario
$url = 'https://api.mercadopago.com/oauth/token';
$post = '&client_secret='.$this->accessToken.'&grant_type=authorization_code&code='.$code.'&redirect_uri=https://dominio.com/auth/mercadopago';
$mpResp = $this->utility->curlAPIRestPOST($url,$post,$this->accessToken);
if ($mpResp->status == 200) {
// Actualizo en mi DB los datos obtenidos
$info = array(
'mp_access_token' => $mpResp->access_token,
'mp_public_key' => $mpResp->public_key,
'mp_refresh_token' => $mpResp->refresh_token,
'mp_user_id' => $mpResp->user_id,
'mp_expires_in' => $mpResp->expires_in,
'mp_created_at' => date('Y-m-d H:i:s', time()),
'mp_scope' => $mpResp->scope,
'mp_live_mode' => $mpResp->live_mode,
'mp_token_type' => $mpResp->token_type,
'mp_status' => 1
);
$update = $this->professionals->update_info($info, $docId);
// Esto no es necesario pero lo hago para obtener el nick en ML del usuario para que pueda identificar la cuenta
$url_get = 'https://api.mercadolibre.com/users/me';
$mpResp = $this->utility->curlAPIRestGET($url_get,$this->accessToken);
$info = array(
'doc_mp_nick_name' => $mpResp->nickname,
'doc_email_mercadopago' => $mpResp->email
);
$update = $this->professionals->update_info($info, $pdocIdid);
}
}
// Redireccionar a otra web o mostrarle una vista.
........
}
public function curlAPIRestPOST($url,$post,$accessToken)
{
$curl = curl_init();
curl_setopt_array($curl,[
CURLOPT_URL => $url,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $post,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer ".$accessToken,
),
]);
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$contents = json_decode($response);
if ($httpcode == 200) {
$contents->status = 200;
return $contents;
} else {
$contents->status = 400;
return $contents;
}
}
public function curlAPIRestGET($url, $accessToken)
{
$curl = curl_init();
curl_setopt_array($curl,[
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer ".$accessToken,
),
]);
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$contents = json_decode($response);
if ($httpcode == 200) {
$contents->status = 200;
return $contents;
} else {
$contents->status = 400;
return $contents;
}
}
// Set del Access Token del vendedor
MercadoPago\SDK::setAccessToken(ACCESS_TOKEN_DEL_VENDEDOR);
// Si son Mercadopago Dev Certificados, tienen ese código, sino omitir esa linea
MercadoPago\SDK::setIntegratorId(getenv('MP_DEV_CODE'));
$preference = new MercadoPago\Preference();
$item = new MercadoPago\Item();
$item->id = 22233;
$item->title = 'Nombre del Producto o texto para que el comprador identifique que está pagando';
$item->currency_id = 'ARS';
$item->description = 'Breve descripción';
$item->picture_url = 'URL de la imagen del producto';
$item->quantity = 1;
$item->unit_price = (float)$price;
$preference->items = array($item);
$payer = new MercadoPago\Payer();
$payer->name = 'Nombre del Comprador';
$payer->surname = 'Apellido del Comprador';
$payer->email = 'Dirección de Email;
$payer->date_created = 'Fecha de registro del usuario en nuestro sistema, en formato: date('Y-m-d\TH:i:s.vP')';
$payer->identification = array(
"type" => "DNI",
"number" => 'Número de DNI'
);
$payer->identification_type = 'DNI';
$payer->identification_number = 'Número de DNI';
$payer->phone = array(
"area_code" => "54",
"number" => 'Número de Teléfono'
);
$payer->area_code = '54';
$payer->number = 'Número de Teléfono';
$payer->address = array(
"street_name" => 'Domicilio',
"zip_code" => 'Código Postal'
);
$payer->authentication_type = 'Web Nativa'; // Pueden ser Gmail, Facebook, Web Nativa, Otro.
$payer->registration_date = 'Fecha de registro del usuario en nuestro sistema, en formato: date('Y-m-d\TH:i:s.vP')';
$payer->is_first_purchase_online = 'TRUE o FALSE si es la primera vez que compra.;
$payer->last_purchase = "Si is_first_purchase_online = TRUE deberán ingresar la fecha de la última vez que compró en formato: date('Y-m-d\TH:i:s.vP')";
$preference->payer = $payer;
// Opcional por si quieren quitar métodos de pago de la preferencia y setear las cuotas
$preference->payment_methods = array(
"excluded_payment_types" => array(
array("id" => "atm"),
array('id' => 'bank_transfer'),
array('id' => 'ticket')
),
"installments" => 12,
"default_installments" => 1
);
// Opcional para setear las url de pago aprobado, fallido o pendiente
$preference->back_urls = array(
"success" => 'https://dominio.com/mp/ok',
"failure" => 'https://dominio.com/mp/error',
"pending" => 'https://dominio.com/mp/pending'
);
// Retorna siempre
$preference->auto_return = "all";
// Para que no tenga estados pendientes de pago
$preference->binary_mode = TRUE;
// Creación de un código external reference para vincular el pago con un pedido en nuestra DB
$preference->external_reference = $codecart;
// Si van a cobrar una comision por venta
$preference->marketplace_fee = (float)$mp_fee_owner;
// Opcional para setear las url del webhook
$preference->notification_url = 'https://dominio.com/webhook/mercadopago';
// Crea la preferencia
$preference->save();
// Redirecciona al webcheckout de mercadopago, pueden usar este método u otros como poner el link en un boton y mostrar en una vista con el detalle de la compra y el boton pagar.
redirect($preference->{gcfg('mp_mode',NULL)},'refresh');
-
Acceder en la siguiente URL
https://www.mercadopago.com/mla/account/webhooks
y configurar en modo producción la url donde van a recibir las notificaciones de mercadopago, y tildar los eventos que desean captar, mis recomendados son: pagos, aplicaciones conectadas/desconectadas y split de pagos. Siguiente el ejemplo, usarhttps://dominio.com/webhook/mercadopago
y al presionar probar, le debe dar un response ok 200 -
Luego crear un código en la ruta del dominio seteado:
https://dominio.com/webhook/mercadopago
mi código es algo así:
public function webhook()
{
MercadoPago\SDK::setAccessToken(ACCESS_TOKEN_MARKETPLACE);
MercadoPago\SDK::setIntegratorId(getenv('MP_DEV_CODE'));
$info = json_decode($this->input->raw_input_stream);
if (isset($info->type)) {
switch ($info->type) {
case 'mp-connect':
// Desvinculo de mi sistema cuando el usuario desautoriza la app desde su cuenta de Mercadopago.
if ($info->action == 'application.deauthorized') {
$data_update = array(
'mp_access_token' => NULL,
'mp_public_key' => NULL,
'mp_refresh_token' => NULL,
'mp_user_id' => NULL,
'mp_expires_in' => NULL,
'mp_status' => 0
);
$this->producers->update_mp_connect($data_update, $info->user_id);
$this->output->set_status_header(200);
return;
}
// Pueden tomar otra acción si el $info->action = 'application.authrized'
break;
case 'payment':
// Actualizo la información de pago recibida.
$or_collection_id = $info->data->id;
$info = MercadoPago\Payment::find_by_id($or_collection_id);
$or_number = $info->external_reference;
$data_update = array(
'or_collection_status' => $info->status,
'or_collection_status_detail' => $info->status_detail,
'or_payment_type' => $info->payment_type_id,
'or_payment_method' => $info->payment_method_id,
'or_status' => gcfg($info->status,'or_status_collection_status')
);
$this->cart->update_ipn_order($data_update,$or_number);
break;
default:
$this->output->set_status_header(200);
return;
break;
}
}
$this->output->set_status_header(200);
return;
}
Mi integracion usando checkout pro:
Con una cuenta real de MP crear 3 cuentas de prueba. Con una de esas cuentas ingresar al panel de developer y crear una aplicación. Esa será la cuenta marketplace. Las otras 2 comprador y vendedor.
El campo marketplace debe tener el valor
true
booleano.El campo MP-MKT-etc no se envia.
La public_key a utilizar debe ser la del marketplace (si estan usando el sdk de react esto se setea en el componente Payment)
El access token debe ser el del vendedor que debe haber sido obtenido previamente mediante la api de auth.
Cuando prueben la integración haganlo en un navegador sin sesiones de MP abiertas o ventana de incógnito ya que si tienen la sesion abierta con la cuenta Marketplace o vendedora van a recibir errores al momento de pagar.