Custom PhonePe Payment Gateway: Cart available on redirect but null in verify method
-
Hi community,
I’m integrating a custom PhonePe payment gateway in Bagisto v2.3. The integration redirects to PhonePe successfully and the cart is correctly available during the initial payment request.
However, when the customer is redirected back for verification (after successful payment), the cart becomes null in the verify method. This causes the order placement to fail.
Below is my code for both the redirect and verify methods in the PhonepeController
public function redirect(Request $request) { try { $cart = Cart::getCart(); if (!$cart) { throw new \Exception('Cart not found'); } $billingAddress = $cart->billing_address; if (!$billingAddress || !$billingAddress->phone) { throw new \Exception('Billing address or phone number missing'); } $shipping = $cart->selected_shipping_rate ? $cart->selected_shipping_rate->price : 0; $discount = $cart->discount_amount; $amount = ($cart->sub_total + $cart->tax_total + $shipping) - $discount; $orderId = 'order_' . $cart->id . '_' . time(); $merchantId = core()->getConfigData('sales.payment_methods.phonepe.merchant_id'); $saltKey = core()->getConfigData('sales.payment_methods.phonepe.salt_key'); $saltIndex = core()->getConfigData('sales.payment_methods.phonepe.salt_index'); $env = core()->getConfigData('sales.payment_methods.phonepe.env'); // 'sandbox' or 'production' // Validate required configuration if (empty($merchantId) || empty($saltKey) || empty($saltIndex)) { throw new \Exception('PhonePe payment configuration is incomplete'); } $callbackUrl = route('phonepe.verify') . '?order_id=' . $orderId; $payload = [ "merchantId" => $merchantId, "merchantTransactionId" => $orderId, "merchantUserId" => auth()->id() ?? 'guest_' . $billingAddress->phone, "amount" => intval($amount * 100), // in paise "redirectUrl" => $callbackUrl, "redirectMode" => "POST", "callbackUrl" => $callbackUrl, "mobileNumber" => $billingAddress->phone, "paymentInstrument" => [ "type" => "PAY_PAGE" ] ]; $base64Payload = base64_encode(json_encode($payload)); $checksum = hash('sha256', $base64Payload . "/pg/v1/pay" . $saltKey) . "###" . $saltIndex; $url = $env === 'sandbox' ? "https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay" : "https://api.phonepe.com/apis/hermes/pg/v1/pay"; $response = Http::withHeaders([ 'Content-Type' => 'application/json', 'X-VERIFY' => $checksum, 'Accept' => 'application/json', ])->post($url, [ "request" => $base64Payload ]); if (!$response->successful()) { throw new \Exception('PhonePe API request failed: ' . $response->status()); } $responseData = $response->json(); // Log the response for debugging \Log::info('PhonePe Payment Init Response:', $responseData); if (isset($responseData['success']) && $responseData['success'] === true && isset($responseData['data']['instrumentResponse']['redirectInfo']['url'])) { $request->session()->put('phonepe_order_id', $orderId); return redirect()->to($responseData['data']['instrumentResponse']['redirectInfo']['url']); } $errorMessage = $responseData['message'] ?? 'Unable to initiate payment'; throw new \Exception($errorMessage); } catch (\Exception $e) { \Log::error('PhonePe Payment Error: ' . $e->getMessage()); session()->flash('error', $e->getMessage()); return redirect()->route('shop.checkout.cart.index'); } } public function verify(Request $request) { try { // Log the full incoming request to debug what's coming from PhonePe // \Log::info('PhonePe Verify Incoming Request:', $request->all()); // Get the merchant transaction ID (i.e., your order ID) $orderId = $request->input('order_id') ?? $request->get('order_id'); if (!$orderId) { session()->flash('error', 'PhonePe payment verification failed: Missing order ID'); return redirect()->route('shop.checkout.cart.index'); } // Fetch configuration values $merchantId = core()->getConfigData('sales.payment_methods.phonepe.merchant_id'); $saltKey = core()->getConfigData('sales.payment_methods.phonepe.salt_key'); $saltIndex = core()->getConfigData('sales.payment_methods.phonepe.salt_index'); $env = core()->getConfigData('sales.payment_methods.phonepe.env'); // Determine base URL based on environment $baseUrl = $env === 'sandbox' ? 'https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/status' : 'https://api.phonepe.com/apis/hermes/pg/v1/status'; // Create the request path $path = "/pg/v1/status/{$merchantId}/{$orderId}"; $statusUrl = "{$baseUrl}/{$merchantId}/{$orderId}"; // Create the checksum $checksum = hash('sha256', $path . $saltKey) . "###" . $saltIndex; // Log the constructed URL and checksum \Log::info('PhonePe Status URL: ' . $statusUrl); \Log::info('PhonePe Checksum: ' . $checksum); // Make the request to PhonePe status API $response = Http::withHeaders([ 'Content-Type' => 'application/json', 'X-VERIFY' => $checksum, 'Accept' => 'application/json', ])->get($statusUrl); // Log raw response for debugging \Log::info('PhonePe Status API Raw Response: ' . $response->body()); if (!$response->successful()) { session()->flash('error', 'PhonePe verification failed. Try again later.'); return redirect()->route('shop.checkout.cart.index'); } $data = $response->json(); // Log parsed response \Log::info('PhonePe Status API Parsed Response:', $data); if ( isset($data['success']) && $data['success'] === true && isset($data['code']) && $data['code'] === 'PAYMENT_SUCCESS' && isset($data['data']['state']) && in_array($data['data']['state'], ['SUCCESS', 'COMPLETED']) && isset($data['data']['merchantTransactionId']) && $data['data']['merchantTransactionId'] === $orderId ) { $cart = Cart::getCart(); // Retrieve the cart $order = $this->orderRepository->create((new OrderResource($cart))->jsonSerialize()); $this->orderRepository->update(['status' => 'processing'], $order->id); if ($order->canInvoice()) { $this->invoiceRepository->create($this->prepareInvoiceData($order)); } Cart::deActivateCart(); session()->flash('order_id', $order->id); return redirect()->route('shop.checkout.onepage.success'); } session()->flash('error', 'PhonePe payment failed or cancelled.'); return redirect()->route('shop.checkout.cart.index'); } catch (\Exception $e) { \Log::error('PhonePe Verify Exception: ' . $e->getMessage()); session()->flash('error', 'Something went wrong during payment verification.'); return redirect()->route('shop.checkout.cart.index'); } }
-
Hello @arunchahar
For this, we will need to review your entire package to see what changes you have made and where. To do that, you can purchase support hours for this.
https://store.webkul.com/bagisto-hourly-customization-package.html
Regards
Team Bagisto