Final organization of resources

I changed a little the way the Webhook responds to the MercadoPago, better filtering requests and expected values, I also added to getRedirectUrl a check necessary for the MercadoPago Webhook to work.
This commit is contained in:
Drylian 2024-05-25 18:42:49 -03:00
parent 2b8c40b852
commit f57ee4674d
2 changed files with 43 additions and 21 deletions

View file

@ -39,6 +39,15 @@ class MercadoPagoExtension extends AbstractExtension
public static function getRedirectUrl(Payment $payment, ShopProduct $shopProduct, string $totalPriceString): string
{
/**
* For Mercado Pago to work correctly,
* it is necessary to use SSL and the app.url must start with "https://",
* this is necessary so that the webhook receives the information and not an error.
*/
if (!str_contains(config('app.url'), 'https://')) {
throw new Exception(__('It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago.'));
}
$user = Auth::user();
$user = User::findOrFail($user->id);
$url = 'https://api.mercadopago.com/checkout/preferences';
@ -61,7 +70,6 @@ class MercadoPagoExtension extends AbstractExtension
[
'title' => "Order #{$payment->id} - " . $shopProduct->name,
'quantity' => 1,
// convert to float
'unit_price' => floatval($totalPriceString),
'currency_id' => $shopProduct->currency_code,
],
@ -90,42 +98,50 @@ class MercadoPagoExtension extends AbstractExtension
$payment = Payment::findOrFail($request->input('payment'));
$payment->status = PaymentStatus::PROCESSING;
$payment->save();
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
Redirect::route('home')->with('success', 'Your payment is being processed!')->send();
return;
}
static function Webhook(Request $request): JsonResponse
{
$topic = $request->input('topic');
if ($topic === 'merchant_order') {
// ignore other types IPN
$action = $request->input('action');
/**
* Mercado Pago sends several requests for information in the webhook,
* but most are for other types of API, and that is why it is filtered here.
*/
if ($topic && ($topic === 'merchant_order' || $topic === 'payment')) {
return response()->json(['success' => true]);
} else if ($topic === 'payment') {
// ignore other types IPN
return response()->json(['success' => true]);
} else {
try {
$notificationId = $request->input('data_id') || $request->input('data.id') || "unknown";
if ($notificationId == 'unknown') {
return response()->json(['success' => false]);
} else if ($notificationId == '123456') {
// mercado pago api test
return response()->json(['success' => true]);
} else {
}
try {
if($action) {
$notification = $request['data']['id'];
// Filter the API for payments
if (!$notification || !$action) return response()->json(['success' => false], 400);
// Mercado pago test api, for testing webhook request
if ($notification == '123456') return response()->json(['success' => true], 200);
/**
* Check action have payment.*,
* what is expected for this type of api
*/
if (str_contains($action, 'payment')) {
$url = "https://api.mercadopago.com/v1/payments/" . $notificationId;
$settings = new MercadoPagoSettings();
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $settings->access_token,
])->get($url);
if ($response->successful()) {
$mercado = $response->json();
$status = $mercado['status'];
$payment = Payment::findOrFail($mercado['metadata']['crtl_panel_payment_id']);
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
if ($status == "approved") {
// avoids double additions, if the user enters after the webhook has already added the credits
// Avoid double addition of credits, whether due to double requests from the paid market, or a malicious user
if ($payment->status !== PaymentStatus::PAID) {
$user = User::findOrFail($payment->user_id);
$payment->status = PaymentStatus::PAID;
@ -145,12 +161,17 @@ class MercadoPagoExtension extends AbstractExtension
$payment->save();
event(new PaymentEvent($user, $payment, $shopProduct));
}
return response()->json(['success' => true]);
} else {
return response()->json(['success' => false]);
}
} else {
return response()->json(['success' => false]);
}
} catch (Exception $ex) {
Log::error('MercadoPago Webhook(IPN) Payment: ' . $ex->getMessage());
return response()->json(['success' => false]);
}
} catch (Exception $ex) {
Log::error('MercadoPago Webhook(IPN) Payment: ' . $ex->getMessage());
return response()->json(['success' => false]);
}
return response()->json(['success' => true]);
}

View file

@ -296,6 +296,7 @@
"Everyone": "Everyone",
"Clients": "Clients",
"Enable Ticketsystem": "Enable Ticketsystem",
"It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago":"It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago",
"PayPal Client-ID": "PayPal Client-ID",
"PayPal Secret-Key": "PayPal Secret-Key",
"PayPal Sandbox Client-ID": "PayPal Sandbox Client-ID",