Search code examples
laravelflutterstripe-paymentslaravel-8laravel-9

Payment failed but order is Placed in Laravel with Stripe


I have integrated stripe payment in flutter app but After payment got failed even then order placed in Laravel database so please check, what I have done wrong.

Please check at save method, May be I am wrong and can't validate purchase response.

payment controller

 public function makePayment(Request $request)
    {
        try{
            $data = $request->input('cartItems');
            $cartItems = json_decode($data, true);
            $orderData = $request->input('order');
            $selectPaymentOption = json_decode($orderData, true);
            $totalAmount = 0.0;
            foreach ($cartItems as $cartItem){
                $order = new Order();
                $order->order_date = Carbon::now()->toDateString();
                $order->product_id = $cartItem['productId'];
                $order->payment_type = $selectPaymentOption['paymentType'];
                $order->user_id = $request->input('userId');
                $order->quantity = $cartItem['productQuantity'];
                $order->amount = ($cartItem['productPrice'] - $cartItem['productDiscount']);
                $totalAmount+= $order->amount * $order->quantity;
                $order->save();
            }
            
            if($selectPaymentOption['paymentType'] == 'Card'){
                
            \Stripe\Stripe::setApiKey('sk_test_hJUgYYzeXtitxxxx71lK8nE00MELJJS8c');

            $token = \Stripe\Token::create([
                'card' => [
                    'number' => $request->input('cardNumber'),
                    'exp_month' => $request->input('expiryMonth'),
                    'exp_year' => $request->input('expiryYear'),
                    'cvc' => $request->input('cvcNumber')
                ]
            ]);

            $charge = \Stripe\Charge::create([
                'amount' => $totalAmount * 100,
                'currency' => 'inr',
                'source' => $token,
                'receipt_email' => $request->input('email'),
            ]);
            
        }
            return response(['result' => true]);
            
        } catch (\Exception $exception){
            return response(['result' => $exception]);
        }
    }

and my Flutter's Post request is here. I want to POST _makePayment method after complete payment successful.

void _makePayment(BuildContext context, Payment payment) async {
    PaymentService _paymentService = PaymentService();
    var paymentData = await _paymentService.makePayment(payment);
    var result = json.decode(paymentData.body);
    print(paymentData);
    CartService _cartService = CartService();
    this.widget.cartItems!.forEach((cartItem) {
      _cartService.makeTheCartEmpty();
    });
    if (result['result'] == true) {
      _showPaymentSuccessMessage(context);
      Timer(Duration(seconds: 4), () {
        Navigator.pop(context);
        Navigator.push(
            context, MaterialPageRoute(builder: (context) => HomeScreen()));
      });
    }
  }

Solution

  • Referring to my comment above, this is the rough solution I suggested in your controller you have to switch the logic

    public function makePayment(Request $request)
    {
        try{
            $data = $request->input('cartItems');
            $cartItems = json_decode($data, true);
            $orderData = $request->input('order');
            $selectPaymentOption = json_decode($orderData, true);
    ##Change your frontend logic to pass total amount as variable
            $totalAmount = $request->totalAmount;
            
            if($selectPaymentOption['paymentType'] == 'Card'){
                
    ##Never have any sk or pk in your controller, switch this to config('common.sk_test')        
              \Stripe\Stripe::setApiKey(config('common.sk_test'));
    
               $token = \Stripe\Token::create([
                 'card' => [
                    'number' => $request->input('cardNumber'),
                    'exp_month' => $request->input('expiryMonth'),
                    'exp_year' => $request->input('expiryYear'),
                    'cvc' => $request->input('cvcNumber')
                  ]
               ]);
    
               $charge = \Stripe\Charge::create([
                  'amount' => $totalAmount * 100,
                  'currency' => 'inr',
                  'source' => $token,
                  'receipt_email' => $request->input('email'),
               ]);
            
              }
    
    ##After the stripe transaction is finished you can foreach your cart and do what you need to your database 
            foreach ($cartItems as $cartItem){
                    $order = new Order();
                    $order->order_date = Carbon::now()->toDateString();
                    $order->product_id = $cartItem['productId'];
                    $order->payment_type = $selectPaymentOption['paymentType'];
                    $order->user_id = $request->input('userId');
                    $order->quantity = $cartItem['productQuantity'];
                    $order->amount = ($cartItem['productPrice'] - $cartItem['productDiscount']);
                    $order->save();
                }
            return response(['result' => true]);
            
        } catch (\Exception $exception){
            return response(['result' => $exception]);
        }
    }
    

    For the config('common.sk_test') part of my answer, in you config folder you can create a new file where you have you custom app variables, so create a file for instance common.php and 'sk_test' that takes its value from you .env file