diff --git a/pipprapay.php b/pipprapay.php new file mode 100644 index 0000000..7570ecf --- /dev/null +++ b/pipprapay.php @@ -0,0 +1,281 @@ +assign('_title', 'PippraPay - Payment Gateway'); + $ui->display('pipprapay.tpl'); +} + +function pipprapay_save_config() +{ + global $admin; + $pipprapay_api_key = _post('pipprapay_api_key'); + $pipprapay_base_url = _post('pipprapay_base_url'); + + // Save API Key + $d = ORM::for_table('tbl_appconfig')->where('setting', 'pipprapay_api_key')->find_one(); + if ($d) { + $d->value = $pipprapay_api_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'pipprapay_api_key'; + $d->value = $pipprapay_api_key; + $d->save(); + } + + // Save Base URL + $d = ORM::for_table('tbl_appconfig')->where('setting', 'pipprapay_base_url')->find_one(); + if ($d) { + $d->value = $pipprapay_base_url; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'pipprapay_base_url'; + $d->value = $pipprapay_base_url; + $d->save(); + } + + _log('[' . $admin['username'] . ']: PippraPay ' . Lang::T('Settings_Saved_Successfully'), 'Admin', $admin['id']); + r2(U . 'paymentgateway/pipprapay', 's', Lang::T('Settings_Saved_Successfully')); +} + +function pipprapay_create_transaction($trx, $user) +{ + global $config; + + pipprapay_validate_config(); + + $callbackUrl = U . 'callback/pipprapay'; + $redirectUrl = U . 'order/view/' . $trx['id'] . '/check'; + + $payload = [ + 'amount' => $trx['price'] * 100, // Convert to kobo (assuming price is in main currency unit) + 'currency' => 'NGN', + 'email' => $user['email'], + 'invoice_id' => $trx['id'], + 'description' => 'Payment for invoice #' . $trx['id'], + 'callback_url' => $callbackUrl, + 'redirect_url' => $redirectUrl, + 'metadata' => [ + 'invoice_id' => $trx['id'], + 'customer_id' => $user['id'], + 'customer_username' => $user['username'], + 'system' => 'NuxBill' + ] + ]; + + $result = pipprapay_api_call('/create-charge', $payload); + + if (!$result['success']) { + sendTelegram("PippraPay payment failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction. " . $result['error'])); + } + + $paymentData = $result['data']; + + if ($paymentData['status'] === 'success' && !empty($paymentData['data']['checkout_url'])) { + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $paymentData['data']['transaction_id'] ?? $paymentData['data']['reference']; + $d->pg_url_payment = $paymentData['data']['checkout_url']; + $d->pg_request = json_encode($paymentData); + $d->expired_date = date('Y-m-d H:i:s', strtotime('+ 24 HOURS')); + $d->save(); + + header('Location: ' . $paymentData['data']['checkout_url']); + exit(); + } else { + sendTelegram("PippraPay payment creation failed\n\n" . json_encode($paymentData, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create payment: " . ($paymentData['message'] ?? 'Unknown error'))); + } +} + +function pipprapay_get_status($trx, $user) +{ + global $config; + + if (empty($trx['gateway_trx_id'])) { + r2(U . "order/view/" . $trx['id'], 'e', Lang::T("Transaction ID not found")); + } + + $result = pipprapay_api_call('/verify-payments', ['transaction_id' => $trx['gateway_trx_id']]); + + if (!$result['success']) { + sendTelegram("PippraPay payment verification failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'e', Lang::T("Failed to verify transaction. " . $result['error'])); + } + + $verificationData = $result['data']; + + if ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid.")); + } + + // Check payment status based on PippraPay response structure + $paymentStatus = strtolower($verificationData['data']['status'] ?? 'pending'); + + if ($paymentStatus == 'success' || $paymentStatus == 'completed') { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'PippraPay')) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, try again later.")); + } + + $trx->pg_paid_response = json_encode($verificationData); + $trx->payment_method = 'PippraPay'; + $trx->payment_channel = 'PippraPay'; + $trx->paid_date = date('Y-m-d H:i:s'); + $trx->status = 2; + $trx->save(); + + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been paid.")); + } elseif ($paymentStatus == 'failed' || $paymentStatus == 'cancelled') { + r2(U . "order/view/" . $trx['id'], 'e', Lang::T("Payment failed or was cancelled.")); + } else { + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still pending.")); + } +} + +// Callback handler +function pipprapay_payment_notification() +{ + $input = file_get_contents('php://input'); + $data = json_decode($input, true); + + if (empty($data) || !isset($data['transaction_id'])) { + http_response_code(400); + die('Invalid IPN data'); + } + + $transactionId = $data['transaction_id']; + $status = strtolower($data['status'] ?? 'pending'); + $invoiceId = $data['invoice_id'] ?? ''; + $amount = $data['amount'] ?? 0; + + // Verify the payment + $result = pipprapay_api_call('/verify-payments', ['transaction_id' => $transactionId]); + + if (!$result['success']) { + http_response_code(400); + die('Verification failed: ' . $result['error']); + } + + $verificationData = $result['data']; + $verifiedStatus = strtolower($verificationData['data']['status'] ?? 'pending'); + + // Find the transaction + $trx = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $transactionId) + ->find_one(); + + if (!$trx) { + http_response_code(404); + die('Transaction not found'); + } + + // Update transaction based on status + if ($verifiedStatus == 'success' || $verifiedStatus == 'completed') { + $user = ORM::for_table('tbl_customers')->where('username', $trx['username'])->find_one(); + + if ($user && $trx['status'] != 2) { + if (Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'PippraPay')) { + $trx->pg_paid_response = json_encode($verificationData); + $trx->payment_method = 'PippraPay'; + $trx->payment_channel = 'PippraPay'; + $trx->paid_date = date('Y-m-d H:i:s'); + $trx->status = 2; + $trx->save(); + + sendTelegram("PippraPay payment successful for invoice: " . $invoiceId); + } + } + } + + http_response_code(200); + echo 'OK'; +} + +function pipprapay_api_call($endpoint, $payload) +{ + global $config; + + $baseUrl = $config['pipprapay_base_url'] ?? 'https://pay.wifibills.com/api'; + $url = rtrim($baseUrl, '/') . $endpoint; + + $headers = [ + 'Authorization: Bearer ' . $config['pipprapay_api_key'], + 'Content-Type: application/json', + 'Accept: application/json' + ]; + + $ch = curl_init(); + + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode($payload), + CURLOPT_HTTPHEADER => $headers, + CURLOPT_TIMEOUT => 30, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_USERAGENT => 'NuxBill-PippraPay/1.0' + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $error = curl_error($ch); + curl_close($ch); + + if ($error) { + return [ + 'success' => false, + 'error' => 'cURL Error: ' . $error + ]; + } + + $decodedResponse = json_decode($response, true); + + if ($httpCode !== 200) { + return [ + 'success' => false, + 'error' => 'HTTP Error: ' . $httpCode, + 'response' => $decodedResponse + ]; + } + + if (json_last_error() !== JSON_ERROR_NONE) { + return [ + 'success' => false, + 'error' => 'Invalid JSON response' + ]; + } + + return [ + 'success' => true, + 'data' => $decodedResponse + ]; +} + +function pipprapay_get_server() +{ + global $config; + return $config['pipprapay_base_url'] ?? 'https://pay.wifibills.com/api'; +} +?> \ No newline at end of file