'186691761268d6f85579c84532234998155044887968d6f85579c891167595247', 'base_url' => 'https://pay.wifibills.com/api', 'gateway_name' => 'PipraPay' ]; function piprapay_validate_config() { global $piprapay_config; } function piprapay_show_config() { global $ui, $piprapay_config; $ui->assign('_title', $piprapay_config['gateway_name'] . ' - Payment Gateway'); echo '
' . $piprapay_config['gateway_name'] . ' Configuration

' . $piprapay_config['gateway_name'] . ' Gateway

This payment gateway is pre-configured and ready to use.

PipraPay will redirect users to this URL after payment
Gateway Active
' . $piprapay_config['gateway_name'] . ' is ready to accept payments.
'; } function piprapay_save_config() { global $admin; _log('[' . $admin['username'] . ']: ' . Lang::T('PipraPay_Configuration_Viewed'), 'Admin', $admin['id']); r2(U . 'paymentgateway/piprapay', 's', Lang::T('PipraPay_is_preconfigured')); } function piprapay_create_transaction($trx, $user) { global $piprapay_config; try { // Use clean callback URL without extra parameters $success_url = U . 'callback/piprapay?invoice_id=' . $trx['id']; $cancel_url = U . 'order/view/' . $trx['id']; // Create simple metadata $metadata = [ 'invoice_id' => $trx['id'], 'customer_id' => $user['id'], 'customer_name' => $user['fullname'] ?: $user['username'], 'plan_id' => $trx['plan_id'] ]; // Payload with ALL required fields $payload = [ 'full_name' => $user['fullname'] ?: $user['username'], 'email_mobile' => $user['email'] ?: ($user['phonenumber'] ?: 'user@example.com'), 'amount' => number_format($trx['price'], 2, '.', ''), 'redirect_url' => $success_url, 'return_type' => 'GET', 'cancel_url' => $cancel_url, 'webhook_url' => U . 'callback/piprapay', 'currency' => 'BDT', 'metadata' => $metadata ]; $headers = [ 'accept: application/json', 'content-type: application/json', 'mh-piprapay-api-key: ' . $piprapay_config['api_key'] ]; $create_charge_url = $piprapay_config['base_url'] . '/create-charge'; _log("PipraPay Create Transaction Request: " . json_encode($payload), 'PipraPay'); // Make the API call $response = Http::postJsonData($create_charge_url, $payload, $headers); $result = json_decode($response, true); _log("PipraPay Create Transaction Response: " . $response, 'PipraPay'); // Check for success using the correct response format if (isset($result['status']) && $result['status'] === true) { if (isset($result['pp_url'])) { $transaction_id = $result['pp_id'] ?? uniqid(); // Save payment gateway transaction $d = ORM::for_table('tbl_payment_gateway') ->where('username', $user['username']) ->where('status', 1) ->find_one(); if (!$d) { $d = ORM::for_table('tbl_payment_gateway')->create(); $d->username = $user['username']; $d->user_id = $user['id']; $d->created_date = date('Y-m-d H:i:s'); } $d->gateway_trx_id = $transaction_id; $d->plan_id = $trx['plan_id']; $d->plan_name = $trx['plan_name']; $d->routers_id = $trx['routers']; $d->routers = $trx['name']; $d->price = $trx['price']; $d->pg_url_payment = $result['pp_url']; $d->pg_request = json_encode($result); $d->expired_date = date('Y-m-d H:i:s', strtotime('+24 HOURS')); $d->gateway = 'piprapay'; $d->trx_invoice = $trx['id']; $d->status = 1; $d->save(); // Update transaction with gateway_trx_id $trx->gateway_trx_id = $transaction_id; $trx->save(); _log("PipraPay - Created payment gateway record ID: " . $d->id(), 'PipraPay'); // Redirect to payment gateway header('Location: ' . $result['pp_url']); exit(); } else { $error_message = 'Payment URL not received from gateway'; _log("PipraPay Error: " . $error_message, 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("Failed to create transaction. ") . $error_message); } } else { $error_message = $result['message'] ?? 'Failed to create payment'; _log("PipraPay API Error: " . $error_message, 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("Failed to create transaction. ") . $error_message); } } catch (Exception $e) { _log("PipraPay Exception: " . $e->getMessage(), 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("System error occurred. Please try again.")); } } function piprapay_get_status($trx, $user) { global $piprapay_config; try { if (empty($trx['gateway_trx_id'])) { _log("PipraPay Verification - No gateway transaction ID", 'PipraPay'); r2(U . "order/view/" . $trx['id'], 'e', Lang::T("No transaction ID found for verification.")); } $verify_url = $piprapay_config['base_url'] . '/verify-payments'; $payload = [ 'transaction_id' => $trx['gateway_trx_id'] ]; $headers = [ 'accept: application/json', 'content-type: application/json', 'mh-piprapay-api-key: ' . $piprapay_config['api_key'] ]; _log("PipraPay Verification Request - Transaction ID: " . $trx['gateway_trx_id'], 'PipraPay'); $response = Http::postJsonData($verify_url, $payload, $headers); $result = json_decode($response, true); _log("PipraPay Verification Raw Response: " . $response, 'PipraPay'); _log("PipraPay Verification Parsed Response: " . json_encode($result), 'PipraPay'); // Check if API call was successful if (!$result || !is_array($result)) { _log("PipraPay Verification - Invalid response format", 'PipraPay'); r2(U . "order/view/" . $trx['id'], 'e', Lang::T("Invalid response from payment gateway.")); } // Check if transaction is already paid if ($trx['status'] == 2) { _log("PipraPay Verification - Transaction already paid", 'PipraPay'); r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been paid.")); } // Check for success - PipraPay API might have different response structure $is_paid = false; $payment_status = ''; $payment_method = ''; $payment_channel = ''; // Check multiple possible response formats from PipraPay if (isset($result['status']) && $result['status'] === true) { // Format 1: Direct status in response if (isset($result['payment_status'])) { $payment_status = strtolower(trim($result['payment_status'])); $is_paid = in_array($payment_status, ['success', 'completed', 'paid', 'successful', 'processed', 'complete']); } // Format 2: Data array with status elseif (isset($result['data']['payment_status'])) { $payment_status = strtolower(trim($result['data']['payment_status'])); $is_paid = in_array($payment_status, ['success', 'completed', 'paid', 'successful', 'processed', 'complete']); } // Format 3: Check if payment is verified directly elseif (isset($result['is_paid']) && $result['is_paid'] === true) { $is_paid = true; $payment_status = 'paid'; } // Format 4: Check payment object elseif (isset($result['payment']['status'])) { $payment_status = strtolower(trim($result['payment']['status'])); $is_paid = in_array($payment_status, ['success', 'completed', 'paid', 'successful', 'processed', 'complete']); } } // Extract payment method and channel if available if (isset($result['payment_method'])) { $payment_method = $result['payment_method']; } if (isset($result['payment_channel'])) { $payment_channel = $result['payment_channel']; } if (isset($result['data']['payment_method'])) { $payment_method = $result['data']['payment_method']; } if (isset($result['data']['payment_channel'])) { $payment_channel = $result['data']['payment_channel']; } _log("PipraPay Payment Analysis - Status: " . $payment_status . ", Is Paid: " . ($is_paid ? 'Yes' : 'No'), 'PipraPay'); if ($is_paid) { _log("PipraPay Payment Successful - Activating package", 'PipraPay'); // Update payment gateway record $pg_trx = ORM::for_table('tbl_payment_gateway') ->where('gateway_trx_id', $trx['gateway_trx_id']) ->find_one(); if ($pg_trx) { $pg_trx->pg_paid_response = json_encode($result); $pg_trx->payment_method = $payment_method ?: $piprapay_config['gateway_name']; $pg_trx->payment_channel = $payment_channel ?: $piprapay_config['gateway_name']; $pg_trx->paid_date = date('Y-m-d H:i:s'); $pg_trx->status = 2; // Paid $pg_trx->trx_invoice = $trx['id']; $pg_trx->save(); _log("PipraPay - Updated payment gateway record ID: " . $pg_trx['id'] . " with status 2", 'PipraPay'); } // Activate user package if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], $piprapay_config['gateway_name'])) { _log("PipraPay - Failed to activate package for user: " . $user['id'], 'PipraPay'); r2(U . "order/view/" . $trx['id'], 'e', Lang::T("Failed to activate your Package, try again later.")); } // Update transaction $trx->pg_paid_response = json_encode($result); $trx->payment_method = $payment_method ?: $piprapay_config['gateway_name']; $trx->payment_channel = $payment_channel ?: $piprapay_config['gateway_name']; $trx->paid_date = date('Y-m-d H:i:s'); $trx->status = 2; $trx->save(); _log("PipraPay - Transaction marked as paid: " . $trx['id'], 'PipraPay'); r2(U . "order/view/" . $trx['id'], 's', Lang::T("Payment successful! Your package has been activated.")); } else { _log("PipraPay Payment Not Successful - Status: " . $payment_status, 'PipraPay'); r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Payment status: ") . $payment_status); } } catch (Exception $e) { _log("PipraPay Verification Exception: " . $e->getMessage(), 'PipraPay'); r2(U . "order/view/" . $trx['id'], 'e', Lang::T("System error during verification.")); } } // Enhanced callback handler with better error handling function piprapay_callback_handler() { global $piprapay_config; _log("PipraPay Callback Accessed - GET: " . json_encode($_GET) . " POST: " . json_encode($_POST), 'PipraPay'); try { // Handle payment redirect from PipraPay if (isset($_GET['invoice_id'])) { $invoice_id = intval($_GET['invoice_id']); _log("PipraPay Callback - Processing Invoice ID: " . $invoice_id, 'PipraPay'); // Find the transaction $trx = ORM::for_table('tbl_transactions')->find_one($invoice_id); if (!$trx) { _log("PipraPay Callback - Transaction not found: " . $invoice_id, 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("Transaction not found.")); } // Find user $user = ORM::for_table('tbl_customers')->find_one($trx['customer_id']); if (!$user) { _log("PipraPay Callback - User not found for transaction: " . $invoice_id, 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("User not found.")); } // If we don't have gateway_trx_id, try to find it from payment_gateway table if (empty($trx['gateway_trx_id'])) { $pg_trx = ORM::for_table('tbl_payment_gateway') ->where('username', $user['username']) ->where('status', 1) // Unpaid status ->order_by_desc('id') ->find_one(); if ($pg_trx && !empty($pg_trx['gateway_trx_id'])) { $trx->gateway_trx_id = $pg_trx['gateway_trx_id']; $trx->save(); _log("PipraPay Callback - Updated transaction with gateway_trx_id: " . $pg_trx['gateway_trx_id'], 'PipraPay'); } } // Verify payment status via API piprapay_get_status($trx, $user); } // Handle webhook data (if any POST data from PipraPay) if (!empty($_POST)) { _log("PipraPay Webhook Data Received: " . json_encode($_POST), 'PipraPay'); // Check if this is a webhook notification from PipraPay if (isset($_POST['pp_id']) || isset($_POST['transaction_id'])) { $transaction_id = $_POST['pp_id'] ?? $_POST['transaction_id'] ?? ''; if (!empty($transaction_id)) { // Find payment gateway record $pg_trx = ORM::for_table('tbl_payment_gateway') ->where('gateway_trx_id', $transaction_id) ->find_one(); if ($pg_trx && !empty($pg_trx['trx_invoice'])) { // Find transaction and user $trx = ORM::for_table('tbl_transactions')->find_one($pg_trx['trx_invoice']); $user = ORM::for_table('tbl_customers')->find_one($pg_trx['user_id']); if ($trx && $user) { _log("PipraPay Webhook - Processing transaction: " . $transaction_id, 'PipraPay'); piprapay_get_status($trx, $user); } } } } } // Handle cancelled payment if (isset($_GET['status']) && $_GET['status'] == 'cancel') { r2(U . 'order/package', 'w', Lang::T("Payment was cancelled. Please try again.")); } // Default redirect _log("PipraPay Callback - No valid parameters, redirecting to package page", 'PipraPay'); r2(U . 'order/package'); } catch (Exception $e) { _log("PipraPay Callback Exception: " . $e->getMessage(), 'PipraPay'); r2(U . 'order/package', 'e', Lang::T("System error occurred.")); } } // Register callback route if (defined('CALLBACK_ROUTE')) { piprapay_callback_handler(); } /* ======================= PipraPay Verify Logic ======================= */ function piprapay_verify_payment($invoiceid) { // Call PipraPay verify API $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://pay.wifibills.com/api/verify"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, [ 'api_key' => 'YOUR_API_KEY', 'invoiceid' => $invoiceid ]); $response = curl_exec($ch); curl_close($ch); // Debug log file_put_contents(__DIR__ . '/piprapay.log', "Verify called: invoice=$invoiceid Response=$response ", FILE_APPEND); $data = $response ? json_decode($response, true) : null; if ($data && isset($data['status']) && $data['status'] == 'success') { // ✅ Extract gateway trx id if available $gateway_trx_id = isset($data['trx_id']) ? $data['trx_id'] : null; // ✅ Update tbl_payment_gateway $pg = ORM::for_table('tbl_payment_gateway')->where('trx_invoice', $invoiceid)->find_one(); if ($pg) { $pg->status = 2; $pg->paid_date = date('Y-m-d H:i:s'); $pg->pg_paid_response = json_encode($data); $pg->payment_method = "PipraPay"; $pg->payment_channel = "PipraPay"; if ($gateway_trx_id) { $pg->gateway_trx_id = $gateway_trx_id; } $pg->save(); } // ✅ Update invoice $invoice = ORM::for_table('tbl_invoices')->find_one($invoiceid); if ($invoice) { $invoice->status = 'Paid'; $invoice->datepaid = date('Y-m-d H:i:s'); $invoice->save(); // ✅ Activate package if (function_exists('activate_user_package')) { activate_user_package($invoiceid); } } return true; } else { // Store manual verify required $pg = ORM::for_table('tbl_payment_gateway')->where('trx_invoice', $invoiceid)->find_one(); if ($pg) { $pg->pg_paid_response = $response ?: 'PENDING_MANUAL_VERIFY'; $pg->save(); } return false; } } // Handle callback/return if (isset($_GET['p']) && $_GET['p'] == 'verify' && isset($_GET['invoiceid'])) { $invoiceid = intval($_GET['invoiceid']); if (piprapay_verify_payment($invoiceid)) { echo "✅ Payment verified and invoice updated."; } else { echo "⚠️ Payment could not be verified automatically. Manual verify required."; } }