fix double payments - double purchases

Viewed 38

i'm implementing an online payment platform similar to paypal, the problem is that when they click on the buy button 2 times or more quickly and this causes the payment to register twice instead of once

When you click buy execute this action:

     public function invoke(Request $request) {
    
      $payment_id = $request->get('payment_id');
    
      $credenciales = config('services.mercadopago.token');
      $request->get('user_id'));
    
      $response = Http::get("https://api.mercadopago.com/v1/payments/$payment_id" . "?access_token=$credenciales");
      
      $response = json_decode($response);

  $request->session()->put('order', $response->order->id);
  $request->session()->put('ingreso', $response->transaction_details->net_received_amount);
  $request->session()->put('monto', $response->transaction_details->total_paid_amount);
  $request->session()->put('method', $response->payment_type_id); 
 $status = $response->status;

If the answer is approved run this:

if($status == 'approved') {


  Income::insert([
    'user_id'       => Session::get('user_id'),
    'evento_id'       => Session::get('variableName'),
    //Guardar el personal seleccionado
    'mp_id'  => Session::get('order'),
    'metodo'        => Session::get('metodo'),
    'monto'        => Session::get('monto'),
    'rrpp_id'         => Session::get('rrpp'),
    'ingreso'        => Session::get('ingreso'),


  ]);

  OrderNew::insert([
    'user_id'       => Session::get('user_id'),
    'dia_id'       => Session::get('variableName'),
    //Guardar el personal seleccionado
    'whatsapp'  => Session::get('telefono'),
    'cantidad'        => Session::get('cantidad'),
    'anticipada'        => Session::get('anticipada'),
    'horario'        => Session::get('horario'),
    'rrpp'         => Session::get('rrpp'),
    'pagado'        => '1',
    'tipo'        => 'vip',
    'codigo'        => rand(1580, 4005),


  ]);

in the first model I register the incoming money and in the second model I register the customer's order

and there is the problem, if they click on Buy several times, the records are duplicated and they get free products

How can I limit or solve this problem?

2 Answers

Instead of Insert use updateOrCreate or maybe firstOrCreate that accepts 2 parameters, first one an array to check the values against database records and second to insert/find data. If the records match, it will be updated/retrieved, otherwise a new one will be created. Please check Laravel docs for updateOrCreate or firstOrCreate.

In your case, for example:

Income::firstOrCreate([
    'user_id'       => Session::get('user_id'),
    'evento_id'       => Session::get('variableName'),
    //Guardar el personal seleccionado
    'mp_id'  => Session::get('order'),
    'metodo'        => Session::get('metodo'),
    'monto'        => Session::get('monto'),
    'rrpp_id'         => Session::get('rrpp'),
    'ingreso'        => Session::get('ingreso'),
  ]);

This will check the exact records and if it finds a match it retrieves the data, otherwise creates one which avoids duplicated entries.

However, since your second query has a random number generated, it will not find a match if we pass only one arguement, therefore, as a first arguement we need to pass the array to be checked against the database (all data, except for the rand() part).

OrderNew::firstOrCreate(
  [
    'user_id'       => Session::get('user_id'),
    'dia_id'       => Session::get('variableName'),
    //Guardar el personal seleccionado
    'whatsapp'  => Session::get('telefono'),
    'cantidad'        => Session::get('cantidad'),
    'anticipada'        => Session::get('anticipada'),
    'horario'        => Session::get('horario'),
    'rrpp'         => Session::get('rrpp'),
    'pagado'        => '1',
    'tipo'        => 'vip',
  ],
  [
    'user_id'       => Session::get('user_id'),
    'dia_id'       => Session::get('variableName'),
    //Guardar el personal seleccionado
    'whatsapp'  => Session::get('telefono'),
    'cantidad'        => Session::get('cantidad'),
    'anticipada'        => Session::get('anticipada'),
    'horario'        => Session::get('horario'),
    'rrpp'         => Session::get('rrpp'),
    'pagado'        => '1',
    'tipo'        => 'vip',
    'codigo'        => rand(1580, 4005),
  ]);

According to your data, you can change the array of data to be checked against the database.

Specify that the route should not allow concurrent requests from the same session.

Route::get('/deposit',ExampleController::class)->block(10);
Related