refactoring, airtelmoney test

This commit is contained in:
Kwesi Banson Jnr
2025-11-17 18:39:10 +00:00
parent d8164b3139
commit 54edafc9e7
34 changed files with 2811 additions and 27 deletions

View File

@@ -0,0 +1,279 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Models;
use App\Library\AirtelMoneyMw;
use Carbon\Carbon;
use Config;
class AirtelMoneyMalawiController extends Controller
{
public function collectTest(Request $request){
return response()->json(['code' => 1, 'data' => json_decode($request->all())]);
}
public function Collect(Requests\CollectPaymentsRequest $request){
$current_date = date('Y-m-d');
// $incoming=file_get_contents("php://input");
// $data = json_decode($incoming, true);
$data = $request->only(['msisdn', 'country', 'currency']);
//country, currency, msisdn,
// $subscriber_country = $data['subscriber']['country'];
// $subscriber_currency = $data['subscriber']['currency'];
// $subscriber_msisdn = $data['subscriber']['msisdn'];
// $transaction_amount = $data['transaction']['amount'];
// $transaction_country = $data['transaction']['country'];
// $transaction_currency = $data['transaction']['currency'];
// $transaction_id = $data['transaction']['id'];
$authURL = "https://openapiuat.airtel.africa/auth/oauth2/token";
//CONTINENTAL CAPITAL
$clientID = "9ff18a6d-331e-4ec5-9ecc-4e512e13747c";
$clientSecret = "40f44254-10e7-4eb8-b161-38125117f4ba";
$result = $this->authenticate($authURL, $clientID, $clientSecret);
if($result['success']){
$bearerToken = $result['token'];
//send a ussd push
$retval = $this->sendUSSDPush($bearerToken, $data);
$result_data = json_decode($retval, true);
// dump($result_data);
// Check if the response has a status and success flag
if (isset($result_data['status']['success']) && $result_data['status']['success'] === true) {
// Success case
$transactionId = $result_data['data']['transaction']['id'];
$transactionStatus = $result_data['data']['transaction']['status'];
$message = $result_data['status']['message'];
$msg = "✅ Transaction Successful!\n";
$msg .= "Transaction ID: $transactionId\n";
$msg .= "Status: $transactionStatus\n";
$msg .= "Message: $message\n";
return response()->json(['code' => 1, 'msg' => $msg]);
} else {
// Failure case
$errorCode = $result_data['status']['result_code'] ?? 'N/A';
$errorMessage = $result_data['status']['message'] ?? 'Unknown error';
$msg = "❌ Transaction Failed!\n";
$msg .= "Error Code: $errorCode\n";
$msg .= "Message: $errorMessage\n";
return response()->json(['code' => 3, 'msg' => $msg, 'responseRaw' => $result_data ]);
}
}
else{
$msg = $result;
return response()->json(['code' => 5, 'msg' => $msg]);
exit();
}
}
public function getProductIDs($product_name){
$product = Models\Product::where('name', $product_name)->first();
return $product;
}
public function getProductIDsFirst($session_uuid){
$params = [
"request_reference" => 31000,
"session_uuid" => $session_uuid
];
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
$url = "$kaz_host/apimanager/api_rest/v1/productList";
$retval = $this->globalCurlPost($url, $params);
return $retval;
}
public function sendUSSDPush($token, $data) {
// Endpoint
$url = "https://openapiuat.airtel.africa/merchant/v1/payments/";
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json",
"X-Country: MW",
"X-Currency: MWK"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode and return response
return $response;
}
public function changePassword($baseURL, $token,$newPassword, $newPasswordConfirmation) {
// Endpoint URL
$url = rtrim($baseURL, "/") . "/password";
// Prepare data
$data = [
"new_password" => $newPassword,
"new_password_confirmation" => $newPasswordConfirmation
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); // PATCH request
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute and capture response
$response = curl_exec($ch);
// Check for errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode JSON response
return json_decode($response, true);
}
public function validate_msisdn($baseURL, $msisdn, $bearerToken){
// Ensure proper endpoint format
$url = rtrim($baseURL, '/') . '/payments/validate/' . urlencode($msisdn);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $bearerToken,
'Accept: application/json'
]);
// Execute the request
$response = curl_exec($ch);
// Handle cURL error
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
if ($httpCode === 200 && isset($result['data']['full_name'])) {
return [
'success' => true,
'full_name' => $result['data']['full_name']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
public function authenticate($baseURL, $clientID, $clientSecret){
// JSON payload
$postData = json_encode([
'client_id' => $clientID,
'client_secret' => $clientSecret,
'grant_type' => "client_credentials"
]);
// Initialize cURL
$ch = curl_init($baseURL);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['access_token'])) {
return [
'success' => true,
'token' => $result['access_token']
];
} else {
return [
'success' => false,
'error' => $result['error_description'] ?? 'Unknown error',
'details' => $result['error'] ?? []
];
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ApiTokenController extends Controller
{
public function update(Request $request)
{
$token = Str::random(80);
$request->user()->forceFill([
'api_token' => hash('sha256', $token),
])->save();
return ['token' => $token];
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Models;
use App\Library\Kazang;
use Carbon\Carbon;
use Config;
class ConfirmCollectionController extends Controller
{
public function Confirm(Requests\ConfirmPaymentsRequest $request)
{
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
$this->log_query();
$session_uuid = $this->KazangLogin();
$transaction = Models\KazangTransaction::where('routem_client_reference', $request->refID)->first();
$request_reference = substr(time(), 0, 9);
#"supplier_transaction_id" => $request->supplier_transaction_id,
if ($transaction) {
$curl_params = [
"session_uuid" => $session_uuid,
"request_reference" => $request_reference,
"product_id" => $transaction->product_id,
"confirmation_number" => $transaction->confirmation_number,
];
$url = "kaz_host/apimanager/api_rest/v1/airtelPayPaymentConfirm";
$retval = $this->globalCurlPost($url, $curl_params);
return response()->json(['code' => 1, 'msg' => json_decode($retval)]);
}
else{
return response()->json(['code' => 3, 'msg' => "Transaction not found"]);
}
# Airtel Params for approval
/*
{
"session_uuid": "{{kaz_session_uuid}}",
"request_reference": "{{kaz_request_reference}}",
"product_id": {{airtel_pay_payment_prod_id}},
"confirmation_number": "{{airtel_pay_confirmation_number}}"
}
*/
# : MTN Params : supplier_transaction_id received in Pay 1
# :
/*
{
"session_uuid": "6df64e35-0fa4-4c7e-86bc-eefd92255c2b",
"request_reference": "routem1008",
"product_id": {{mtn_momo_pay_fin_prod_id}},
"wallet_msisdn": "+260981112134",
"amount": "50000",
"supplier_transaction_id": "{{mtn_cash_out_supplier_transaction_id}}",
"client_transaction_reference": "0987654321"
}
*/
}
public function ConfirmAirtel(Requests\ConfirmPaymentsRequest $request)
{
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
$session_uuid = $this->KazangLogin();
$transaction = Models\KazangTransaction::where('routem_client_reference', $request->refID)->first();
return response()->json(['code' => 1, 'msg' => json_decode($transaction)]);
$transaction = Models\KazangTransaction::where('request_reference', $request->refID)->first();
$request_reference = substr(time(), 0, 9);
//Retrieve the last request from the transactions
if ($transaction) {
$curl_params = [
"session_uuid" => $session_uuid,
"request_reference" => $request_reference,
"product_id" => $transaction->product_id,
"wallet_msisdn" => $transaction->msisdn,
"amount" => $transaction->amount,
"confirmation_number" => $transaction->confirmation_number,
"client_transaction_reference" => $transaction->request_reference
];
$url = "kaz_host/apimanager/api_rest/v1/mtnDebitApproval";
$retval = $this->globalCurlPost($url, $curl_params);
return response()->json(['code' => 1, 'msg' => json_decode($retval)]);
}
else{
return response()->json(['code' => 3, 'msg' => "Transaction not found"]);
}
# Response from RoutePay Collect
/*
{
"code": 1,
"msg": "success",
"data": {
"reference_id": "4393901145",
"confirmation_number": "333720",
"confirmation_message": "\nPlease confirm\nCust. Msisdn: +260978981953\nCust. First Name: Jean-Luc\nCust. Last name: Picard\nAmount: 0.05\n\n\n\n"
}
}
*/
# : MTN Params : supplier_transaction_id received in Pay 1
# :
/*
{
"session_uuid": "6df64e35-0fa4-4c7e-86bc-eefd92255c2b",
"request_reference": "routem1008",
"product_id": {{mtn_momo_pay_fin_prod_id}},
"wallet_msisdn": "+260981112134",
"amount": "50000",
"supplier_transaction_id": "{{mtn_cash_out_supplier_transaction_id}}",
"client_transaction_reference": "0987654321"
}
*/
}
}

View File

@@ -10,4 +10,46 @@ use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function log_query() {
// , $binding, $timing 'bindings' => $binding)
\DB::listen(function ($sql) {
\Log::info('showing query', array('sql' => $sql));
}
);
}
public function globalCurlPost($url, $params){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($params),
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
public function KazangLogin(){
$kaz_config = config('kazang');
// $url = 'https://testapi.kazang.net/apimanager/api_rest/v1/authClient';
$url = $kaz_config['test_base_url'] . '/apimanager/api_rest/v1/authClient';
$postfields = [
"username" => env('KAZ_USERNAME'),
"password" => env('KAZ_PASS'),
"channel" => env('KAZ_CHANNEL'),
];
$session_data = $this->globalCurlPost($url, $postfields);
$decoded = json_decode($session_data, true);
return $decoded['session_uuid'];
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Config;
class KazTestController extends Controller
{
public function main(){
//Testing the retrieval of kazang Base Url from Config
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
return $kaz_host;
}
}

View File

@@ -1,20 +1,233 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
// Requests\CollectPaymentsRequest
use App\Models;
// use App\Library\Kazang;
use App\Library\AirtelMoneyMw;
use App\Library\MpambaTnm;
use Carbon\Carbon;
use Config;
// Requests\CollectPaymentsRequest //
class MoneyCollectionController extends Controller
{
public function Collect(Requests\CollectPaymentsRequest $request)
{
{
public function collectTest(Request $request){
return response()->json(['code' => 1, 'data' => json_decode($request->all())]);
}
public function CollectFirst(Requests\CollectPaymentsRequest $request, Kazang $kazang){
$current_date = date('Y-m-d');
// Todo : check network and call appropriate endpoint to initiate payment
//$session_uuid = $this->getSessionUuid($kazang);
$endpoint = $this->getEnpoint($request->product_name);
// dd($endpoint);
//TODO : find a way to dynamically retrieve Product ID from the list
#$product_list = $this->getProductIDs($session_uuid);
// {
// "msisdn", "amount", "refID",
// product_name
return response()->json(['code' => 1]);
// dd($product_list);
if ($endpoint !== false) {
$session_uuid = $this->getSessionUuid($kazang);
// send step 1 request here
$transaction_params = [
'session_uuid' => $session_uuid,
'request_reference' => substr(time(), 0, 9), // add a reference from the transactions table
'product_id' => $endpoint['productid'],
'wallet_msisdn' => $request->msisdn,
'routem_client_reference' => $request->refID,
'amount' => $request->amount
];
$saveTransaction = Models\KazangTransaction::create($transaction_params);
if ($saveTransaction == false) {
// code... return to sender
}
$curl_params = [
'session_uuid' => $session_uuid,
'request_reference' => substr(time(), 0, 9), // add a reference from the transactions table
'product_id' => $endpoint['productid'],
'routem_client_reference' => $request->refID,
'amount' => $request->amount
];
if ($request->product_name == 'zamtel_money') {
$curl_params['msisdn'] = $request->msisdn;
}
else{
$curl_params['wallet_msisdn'] = $request->msisdn;
}
$retval = $this->globalCurlPost($endpoint['url'], $curl_params);
$transaction = Models\KazangTransaction::find($saveTransaction->id);
// dd($retval);
// return response()->json(['code' => 1, 'msg' => 'success', 'data' => json_decode($retval)]);
$retval = json_decode($retval, true);
file_put_contents(public_path("logs/" . $current_date . "_api_response_logs.txt"), json_encode($retval) . PHP_EOL, FILE_APPEND);
$transaction->response_code = $retval['response_code'];
$transaction->balance = $retval['balance'];
if (isset($retval['supplier_transaction_id'])) {
$transaction->supplier_transaction_id = $retval['supplier_transaction_id'];
}
if (isset($retval['confirmation_number'])) {
$transaction->confirmation_number = $retval['confirmation_number'];
}
if (isset($retval['confirmation_message'])) {
$transaction->confirmation_message = $retval['confirmation_message'];
}
$transaction->save();
if ($request->product_name == 'mtn_momo_zambia') {
//TODO : check response_code = "0"
if ($retval['response_code'] == "0") {
$data = ['reference_id' => $request->refID, 'supplier_transaction_id' => $retval['supplier_transaction_id'], 'response_message' => $retval['response_message']];
return response()->json(['code' => 1, 'msg' => 'success', 'data' => $data]);
}
else{
return response()->json(['code' => 3, 'msg' => $retval['response_message']]);
}
}
else{
if ($retval['response_code'] == "0") {
$data = ['reference_id' => $request->refID, 'confirmation_number' => $retval['confirmation_number'], 'confirmation_message' => $retval['confirmation_message']];
return response()->json(['code' => 1, 'msg' => 'success', 'data' => $data]);
}
else{
return response()->json(['code' => 3, 'msg' => $retval['$confirmation_message']]);
}
}
//Airtel : confirmation_number
/*
MTN
"data": {
"wallet_msisdn": "+260981112134",
"amount": "0.05",
"request_reference": "167079990",
"response_code": "0",
"balance": "20490.05",
"supplier_transaction_id": "52878",
"response_message": "\r\n********************************\r\n KAZANG \r\n********************************\r\n MOMO Pay Step 1 \r\n--------------------------------\r\n 2022-12-12 01:05 \r\n Pending Payment Created \r\n--------------------------------\r\n API V2 Test - Zambia \r\nVendor: 1000631438\r\nMTN Phone No.: 260981112134\r\nReference: 4458\r\n--------------------------------\r\n MTN Reference \r\n<b> 5287 8 \n\r\n--------------------------------\r\nAmount: 0.05\r\n--------------------------------\r\n A pending transaction has been \ncreated. Please approve on your \nmobile device. Keep this receipt\n to prove payment to the vendor \n after approval. \r\n--------------------------------\r\n Thank you! "
}
Airtel
"data": {
"wallet_msisdn": "978981953",
"confirmation_number": "333366",
"request_reference": "167079973",
"customer_last_name": "Picard",
"response_code": "0",
"amount": "0.05",
"confirmation_message": "\nPlease confirm\nCust. Msisdn: +260978981953\nCust. First Name: Jean-Luc\nCust. Last name: Picard\nAmount: 0.05\n\n\n\n",
"customer_first_name": "Jean-Luc",
"balance": "20490.05"
}
Zamtel
"data": {
"customer_last_name": "killian",
"confirmation_number": "333360",
"request_reference": "167079058",
"msisdn": "+260981112134",
"response_code": "0",
"amount": "0.05",
"confirmation_message": "\nPlease confirm\nCust. Msisdn: +260981112134\nAmount: 0.05\n\nCustomer Details\nName: aaa\nSurname: killian\nID Number: 1234567\n\n\n\n\n\n",
"customer_first_name": "aaa",
"customer_id_number": "1234567",
"balance": "20490.05"
}
*/
return response()->json(['code' => 1, 'data' => json_decode($retval)]);
}
return response()->json(['code' => 3, 'msg' => 'Your request could not handled at this time']);
}
public function Collect(Requests\CollectPaymentsRequest $request){
$current_date = date('Y-m-d');
// Todo : check network and call appropriate endpoint to initiate payment
// log request
// check broker
// check payment mode
// use payment mode pay logic to respond
#$endpoint = $this->getEnpoint($request->product_name);
// dd($endpoint);
//TODO : find a way to dynamically retrieve Product ID from the list
#$product_list = $this->getProductIDs($request->product_name);
return response()->json(['code' => 1, 'data' => json_decode($product_list)]);
return response()->json(['code' => 3, 'msg' => 'Your request could not handled at this time', 'endpoint' => $endpoint]);
}
public function getSessionUuid($kazang){
$kas_session = Models\KazangSession::find(1);
if ($kas_session) {
$current_time = date('Y-m-d H:i:s');
$to = Carbon::createFromFormat('Y-m-d H:s:i', $kas_session->updated_at);
$from = Carbon::createFromFormat('Y-m-d H:s:i', $current_time);
$diff_in_minutes = $to->diffInMinutes($from);
// dd($diff_in_hours);
if ($diff_in_minutes <= 60) {
$session_uuid = $kas_session->session_uuid;
return $session_uuid;
}
else{
$session_uuid = $kazang->login();
$kas_session->session_uuid = $session_uuid;
$kas_session->save();
return $session_uuid;
}
}
else {
$session_uuid = $kazang->login();
$kas_session->session_uuid = $session_uuid;
$kas_session->save();
return $session_uuid;
}
}
public function getEnpoint($product_name){
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
//TODO : remove the hardcoded productIDs
switch ($product_name) {
case 'airtel_money_zambia':
$productID = 1663;
$endpoint = "$kaz_host/apimanager/api_rest/v1/airtelPayPayment";
break;
case 'mtn_momo_zambia':
$productID = 1612;
$endpoint = "$kaz_host/apimanager/api_rest/v1/mtnDebit";
break;
case 'zamtel_money':
$productID = 1706;
$endpoint = "$kaz_host/apimanager/api_rest/v1/zamtelMoneyPay";
break;
default:
return false;
break;
}
return ['productid' => $productID, 'url' => $endpoint];
}
public function getProductIDs($product_name){
$product = Models\Product::where('name', $product_name)->first();
return $product;
}
public function getProductIDsFirst($session_uuid){
$params = [
"request_reference" => 31000,
"session_uuid" => $session_uuid
];
$kazang = Config('kazang');
$kaz_host = $kazang['test_base_url'];
$url = "$kaz_host/apimanager/api_rest/v1/productList";
$retval = $this->globalCurlPost($url, $params);
return $retval;
}
}
//b1d7d86b-8906-4a24-bb8d-268b085d539c

View File

@@ -18,7 +18,11 @@ class CollectPaymentsRequest extends FormRequest
public function messages(){
return array(
'product_name.required' => 'You need to specify the product name'
'channel.required' => 'You need to specify the channel',
'payment_mode.required' => 'You need to specify the payment mode',
'broker_id.required' => 'You need to specify the borker',
'refID.required' => 'No reference ID found',
// 'refID.unique' => 'Duplicate refID, check and try again'
);
}
public function responsenn(array $errors){
@@ -34,11 +38,14 @@ class CollectPaymentsRequest extends FormRequest
public function rules()
{
return [
'msisdn' => 'required|regex:/^(0)[89]\d{8}$/',
'msisdn' => 'required|regex:/\d{10}$/',
'amount' => 'required',
'product_name' => 'required',
'country' => 'required',
'currency' => 'required',
'channel' => 'required', //web, ussd, mobile app
'refID' => 'required',
'country' => 'required'
'payment_mode' => 'required',
'broker_id' => 'required',
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ConfirmPaymentsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'confirmation_number' => 'sometimes',
'supplier_transaction_id' => 'sometimes',
'refID' => 'required',
];
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Library\AirtelMoneyMw;
class AirtelPush {
/**
* @param Collection $collection
*/
}
?>

View File

@@ -0,0 +1,50 @@
<?php
/*
Developer: David Kumwenda
Contact: 0881161942 or 0996139030
App: Mpamba 4 MSE
Date: 30 August 2025
Duration: 1 day dev work*/
// Read raw POST data
$rawData = file_get_contents("php://input");
// Decode JSON
$data = json_decode($rawData, true);
// Basic logging (optional, useful for debugging)
file_put_contents("logs/callback_log_".date('Ymd').'.txt', date("Y-m-d H:i:s") . " - " . $rawData . PHP_EOL, FILE_APPEND); exit();
// Validate required fields
if (isset($data["receipt_number"], $data["result_code"], $data["transaction_id"])) {
$receiptNumber = $data["receipt_number"];
$resultCode = $data["result_code"];
$resultDescription = $data["result_description"] ?? "";
$resultTime = $data["result_time"] ?? date("Y-m-d H:i:s");
$transactionId = $data["transaction_id"];
$success = $data["success"] ?? false;
// Example: Save to database
// (Replace this with your actual DB insert/update code)
/*
$conn = mysqli_connect("localhost", "user", "password", "dbname");
$stmt = mysqli_prepare($conn, "INSERT INTO payments (transaction_id, receipt_number, result_code, result_description, result_time, success) VALUES (?, ?, ?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, "ssissi", $transactionId, $receiptNumber, $resultCode, $resultDescription, $resultTime, $success);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
mysqli_close($conn);
*/
// Respond with 200 OK to acknowledge receipt
http_response_code(200);
echo json_encode(["status" => "callback received"]);
} else {
// Missing required fields
http_response_code(400);
echo json_encode(["error" => "Invalid callback payload"]);
}
?>

View File

@@ -0,0 +1,170 @@
<?php
$clientID="94351d4d-4909-4056-ad9d-8052a332d6b9";
$clientSecret="bf665590-2519-49af-8d1f-7cd0dce1dc7a";
//CONTINENTAL CAPITAL
$clientID="9ff18a6d-331e-4ec5-9ecc-4e512e13747c";
$clientSecret="40f44254-10e7-4eb8-b161-38125117f4ba";
$authURL="https://openapiuat.airtel.africa/auth/oauth2/token";
$res=authenticate($authURL, $clientID, $clientSecret);
if($res['success']){
$bearerToken=$res['token'];
$country = "MW";
$currency = "MWK";
//enquire trans status
$res=getAirtelBalance($country, $currency, $bearerToken);
if ($res["status"] === "SUCCESS") {
echo "Balance: {$res['balance']} {$res['currency']}\n";
echo "Account Status: {$res['account_status']}";
} else {
echo "Error: " . $res["message"];
}
}else{
echo(print_r($res,true));
exit();
}
function getAirtelBalance($country, $currency, $token) {
$url = "https://openapiuat.airtel.africa/standard/v1/users/balance";
// Initialize cURL
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"X-Country: $country",
"X-Currency: $currency",
"Authorization: Bearer $token"
],
]);
$response = curl_exec($curl);
if (curl_errno($curl)) {
$error = curl_error($curl);
curl_close($curl);
return [
"status" => "ERROR",
"message" => "cURL Error: $error"
];
}
curl_close($curl);
// Decode response
$result = json_decode($response, true);
// Handle invalid JSON
if (!$result) {
return [
"status" => "ERROR",
"message" => "Invalid JSON response from Airtel API"
];
}
// Check for API structure
if (!isset($result["status"])) {
return [
"status" => "ERROR",
"message" => "Unexpected API response format".print_r($result,true)
];
}
$statusCode = $result["status"]["code"] ?? null;
$message = $result["status"]["message"] ?? "Unknown error";
// ✅ SUCCESS case
if ($statusCode == "200" && isset($result["data"])) {
return [
"status" => "SUCCESS",
"balance" => $result["data"]["balance"] ?? "0",
"currency" => $result["data"]["currency"] ?? $currency,
"account_status" => $result["data"]["account_status"] ?? "Unknown"
];
}
// ❌ ERROR case (e.g. "User not found", "Invalid token", etc.)
return [
"status" => "ERROR",
"message" => $message,
"code" => $statusCode,
"responseCode" => $result["status"]["response_code"] ?? null,
"resultCode" => $result["status"]["result_code"] ?? null
];
}
function authenticate($baseURL, $wallet, $password)
{
// JSON payload
$postData = json_encode([
'client_id' => $wallet,
'client_secret' => $password,
'grant_type' => "client_credentials"
]);
// Initialize cURL
$ch = curl_init($baseURL);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['access_token'])) {
return [
'success' => true,
'token' => $result['access_token']
];
} else {
return [
'success' => false,
'error' => $result['error_description'] ?? 'Unknown error',
'details' => $result['error'] ?? []
];
}
}
?>

View File

@@ -0,0 +1,246 @@
<?php
$incoming=file_get_contents("php://input");
$data=json_decode($incoming,true);
$subscriber_country = $data['subscriber']['country'];
$subscriber_currency = $data['subscriber']['currency'];
$subscriber_msisdn = $data['subscriber']['msisdn'];
$transaction_amount = $data['transaction']['amount'];
$transaction_country = $data['transaction']['country'];
$transaction_currency = $data['transaction']['currency'];
$transaction_id = $data['transaction']['id'];
$authURL="https://openapiuat.airtel.africa/auth/oauth2/token";
/*CEDAR CAPITAL
$clientID="94351d4d-4909-4056-ad9d-8052a332d6b9";
$clientSecret="bf665590-2519-49af-8d1f-7cd0dce1dc7a";*/
//CONTINENTAL CAPITAL
$clientID="9ff18a6d-331e-4ec5-9ecc-4e512e13747c";
$clientSecret="40f44254-10e7-4eb8-b161-38125117f4ba";
$res=authenticate($authURL, $clientID, $clientSecret);
if($res['success']){
$bearerToken=$res['token'];
//send a ussd push
$res=sendUSSDPush($bearerToken, $data);
$data = json_decode($res, true);
// Check if the response has a status and success flag
if (isset($data['status']['success']) && $data['status']['success'] === true) {
// Success case
$transactionId = $data['data']['transaction']['id'];
$transactionStatus = $data['data']['transaction']['status'];
$message = $data['status']['message'];
echo "✅ Transaction Successful!\n";
echo "Transaction ID: $transactionId\n";
echo "Status: $transactionStatus\n";
echo "Message: $message\n";
} else {
// Failure case
$errorCode = $data['status']['result_code'] ?? 'N/A';
$errorMessage = $data['status']['message'] ?? 'Unknown error';
echo "❌ Transaction Failed!\n";
echo "Error Code: $errorCode\n";
echo "Message: $errorMessage\n";
}
}else{
echo(print_r($res,true));
exit();
}
function sendUSSDPush($token, $data) {
// Endpoint
$url = "https://openapiuat.airtel.africa/merchant/v1/payments/";
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json",
"X-Country: MW",
"X-Currency: MWK"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode and return response
return $response;
}
function changePassword($baseURL, $token,$newPassword, $newPasswordConfirmation) {
// Endpoint URL
$url = rtrim($baseURL, "/") . "/password";
// Prepare data
$data = [
"new_password" => $newPassword,
"new_password_confirmation" => $newPasswordConfirmation
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); // PATCH request
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute and capture response
$response = curl_exec($ch);
// Check for errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode JSON response
return json_decode($response, true);
}
function validate_msisdn($baseURL, $msisdn, $bearerToken)
{
// Ensure proper endpoint format
$url = rtrim($baseURL, '/') . '/payments/validate/' . urlencode($msisdn);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $bearerToken,
'Accept: application/json'
]);
// Execute the request
$response = curl_exec($ch);
// Handle cURL error
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
if ($httpCode === 200 && isset($result['data']['full_name'])) {
return [
'success' => true,
'full_name' => $result['data']['full_name']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
function authenticate($baseURL, $wallet, $password)
{
// JSON payload
$postData = json_encode([
'client_id' => $wallet,
'client_secret' => $password,
'grant_type' => "client_credentials"
]);
// Initialize cURL
$ch = curl_init($baseURL);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['access_token'])) {
return [
'success' => true,
'token' => $result['access_token']
];
} else {
return [
'success' => false,
'error' => $result['error_description'] ?? 'Unknown error',
'details' => $result['error'] ?? []
];
}
}
?>

View File

@@ -0,0 +1,142 @@
<?php
//$requestUri = $_SERVER['REQUEST_URI'];
//$parts = explode('/', trim($requestUri, '/'));
$id = $_GET['id'];//end($parts);
//echo $id;
$enqURL="https://openapiuat.airtel.africa/standard/v1/payments/".$id;
$authURL="https://openapiuat.airtel.africa/auth/oauth2/token";
$clientID="94351d4d-4909-4056-ad9d-8052a332d6b9";
$clientSecret="bf665590-2519-49af-8d1f-7cd0dce1dc7a";
//CONTINENTAL CAPITAL
$clientID="9ff18a6d-331e-4ec5-9ecc-4e512e13747c";
$clientSecret="40f44254-10e7-4eb8-b161-38125117f4ba";
$res=authenticate($authURL, $clientID, $clientSecret);
if($res['success']){
$bearerToken=$res['token'];
//enquire trans status
$res=trans_enquiry($enqURL,$bearerToken);
echo $res;
exit();
$data = json_decode($res, true);
// Check if the response has a status and success flag
if (isset($data['status']['success']) && $data['status']['success'] === true) {
// Success case
$transactionId = $data['data']['transaction']['id'];
$transactionStatus = $data['data']['transaction']['status'];
$message = $data['status']['message'];
echo "✅ Transaction Successful!\n";
echo "Transaction ID: $transactionId\n";
echo "Status: $transactionStatus\n";
echo "Message: $message\n";
} else {
// Failure case
$errorCode = $data['status']['result_code'] ?? 'N/A';
$errorMessage = $data['status']['message'] ?? 'Unknown error';
echo "❌ Transaction Failed!\n";
echo "Error Code: $errorCode\n";
echo "Message: $errorMessage\n";
}
}else{
echo(print_r($res,true));
exit();
}
function trans_enquiry($enqURL,$token){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $enqURL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Authorization:'.$token,
'Accept: */* ',
'X-Country: MW',
'X-Currency: MWK'
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
function authenticate($baseURL, $wallet, $password)
{
// JSON payload
$postData = json_encode([
'client_id' => $wallet,
'client_secret' => $password,
'grant_type' => "client_credentials"
]);
// Initialize cURL
$ch = curl_init($baseURL);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['access_token'])) {
return [
'success' => true,
'token' => $result['access_token']
];
} else {
return [
'success' => false,
'error' => $result['error_description'] ?? 'Unknown error',
'details' => $result['error'] ?? []
];
}
}
?>

63
app/Library/Kazang.php Normal file
View File

@@ -0,0 +1,63 @@
<?php
namespace App\Library;
use Config;
use Log;
use App\Models;
class Kazang
{
public function __construct()
{
}
public function HttpPost($url, $postfields){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($postfields),
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
public function Login(){
$kaz_config = config('kazang');
// $url = 'https://testapi.kazang.net/apimanager/api_rest/v1/authClient';
$url = $kaz_config['test_base_url'] . '/apimanager/api_rest/v1/authClient';
$postfields = [
"username" => env('KAZ_USERNAME'),
"password" => env('KAZ_PASS'),
"channel" => env('KAZ_CHANNEL'),
];
$session_data = $this->HttpPost($url, $postfields);
$decoded = json_decode($session_data, true);
return $decoded['session_uuid'];
}
public function get_products($kaz_session_uuid){
// $url = 'https://testapi.kazang.net/apimanager/api_rest/v1/productList';
$url = $url = $kaz_config['test_base_url'] . '/apimanager/api_rest/v1/productList';
$kaz_request_reference = uniqid("_route");
$postfields = [
"request_reference" => $kaz_request_reference,
"session_uuid" => $kaz_session_uuid
];
$products = $this->HttpPost($url, $postfields);
}
}

View File

@@ -0,0 +1,193 @@
<?php
namespace App\Library\MpambaTnm;
class MpambaPush {
public function sendUSSDPush($baseURL, $token, $invoiceNumber, $amount, $msisdn, $description) {
// Endpoint
$url = rtrim($baseURL, "/") . "/invoices";
// Prepare payload
$data = [
"invoice_number" => $invoiceNumber,
"amount" => (int)$amount,
"msisdn" => $msisdn,
"description" => $description
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode and return response
return json_decode($response, true);
}
public function changePassword($baseURL, $token,$newPassword, $newPasswordConfirmation) {
// Endpoint URL
$url = rtrim($baseURL, "/") . "/password";
// Prepare data
$data = [
"new_password" => $newPassword,
"new_password_confirmation" => $newPasswordConfirmation
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); // PATCH request
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute and capture response
$response = curl_exec($ch);
// Check for errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode JSON response
return json_decode($response, true);
}
public function validate_msisdn($baseURL, $msisdn, $bearerToken){
// Ensure proper endpoint format
$url = rtrim($baseURL, '/') . '/payments/validate/' . urlencode($msisdn);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $bearerToken,
'Accept: application/json'
]);
// Execute the request
$response = curl_exec($ch);
// Handle cURL error
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
if ($httpCode === 200 && isset($result['data']['full_name'])) {
return [
'success' => true,
'full_name' => $result['data']['full_name']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
public function authenticate($baseURL, $wallet, $password){
// Endpoint URL
$url = rtrim($baseURL, '/') . '/authenticate';
// JSON payload
$postData = json_encode([
'wallet' => $wallet,
'password' => $password
]);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['data']['token'])) {
return [
'success' => true,
'token' => $result['data']['token'],
'expires_at' => $result['data']['expires_at']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
}
?>

View File

@@ -0,0 +1,50 @@
<?php
/*
Developer: David Kumwenda
Contact: 0881161942 or 0996139030
App: Mpamba 4 MSE
Date: 30 August 2025
Duration: 1 day dev work*/
// Read raw POST data
$rawData = file_get_contents("php://input");
// Decode JSON
$data = json_decode($rawData, true);
// Basic logging (optional, useful for debugging)
file_put_contents("logs/callback_log_".date('Ymd').'.txt', date("Y-m-d H:i:s") . " - " . $rawData . PHP_EOL, FILE_APPEND);
// Validate required fields
if (isset($data["receipt_number"], $data["result_code"], $data["transaction_id"])) {
$receiptNumber = $data["receipt_number"];
$resultCode = $data["result_code"];
$resultDescription = $data["result_description"] ?? "";
$resultTime = $data["result_time"] ?? date("Y-m-d H:i:s");
$transactionId = $data["transaction_id"];
$success = $data["success"] ?? false;
// Example: Save to database
// (Replace this with your actual DB insert/update code)
/*
$conn = mysqli_connect("localhost", "user", "password", "dbname");
$stmt = mysqli_prepare($conn, "INSERT INTO payments (transaction_id, receipt_number, result_code, result_description, result_time, success) VALUES (?, ?, ?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, "ssissi", $transactionId, $receiptNumber, $resultCode, $resultDescription, $resultTime, $success);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
mysqli_close($conn);
*/
// Respond with 200 OK to acknowledge receipt
http_response_code(200);
echo json_encode(["status" => "callback received"]);
} else {
// Missing required fields
http_response_code(400);
echo json_encode(["error" => "Invalid callback payload"]);
}
?>

View File

@@ -0,0 +1,5 @@
<?php
$data=file_get_contents('php://input');
echo 'This is the correct path.';
?>

View File

@@ -0,0 +1,214 @@
<?php
$incoming=file_get_contents("php://input");
$details=json_decode($incoming,true);
$invoiceNumber=$details['invoiceNumber'];
$amount=$details['amount'];
$msisdn=$details['msisdn'];
$description=$details['description'];
$baseURL="https://devpayouts.tnmmpamba.co.mw/api";
$wallet="505072";
$password="N8O7L0vpl5mflfwHzf4DSle9bToV*";//CEDAR PASSWORD
//$res=authenticate($baseURL, $wallet, $password);
$bearerToken="102164|newoEd6QOFaTptUiGAp232jULtUmgMtaX1x2CRww4Ka2270dc49";
//$res=validate_msisdn($baseURL, '265881161942', $bearerToken);
//$res=changePassword($baseURL, $bearerToken, "N8O7L0vpl5mflfwHzf4DSle9bToV*", "N8O7L0vpl5mflfwHzf4DSle9bToV*");
$res=sendUSSDPush($baseURL, $bearerToken, $invoiceNumber, $amount, $msisdn, $description);
echo (print_r($res,true));
function sendUSSDPush($baseURL, $token, $invoiceNumber, $amount, $msisdn, $description) {
// Endpoint
$url = rtrim($baseURL, "/") . "/invoices";
// Prepare payload
$data = [
"invoice_number" => $invoiceNumber,
"amount" => (int)$amount,
"msisdn" => $msisdn,
"description" => $description
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode and return response
return json_decode($response, true);
}
function changePassword($baseURL, $token,$newPassword, $newPasswordConfirmation) {
// Endpoint URL
$url = rtrim($baseURL, "/") . "/password";
// Prepare data
$data = [
"new_password" => $newPassword,
"new_password_confirmation" => $newPasswordConfirmation
];
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); // PATCH request
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// Execute and capture response
$response = curl_exec($ch);
// Check for errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return false;
}
// Close connection
curl_close($ch);
// Decode JSON response
return json_decode($response, true);
}
function validate_msisdn($baseURL, $msisdn, $bearerToken)
{
// Ensure proper endpoint format
$url = rtrim($baseURL, '/') . '/payments/validate/' . urlencode($msisdn);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $bearerToken,
'Accept: application/json'
]);
// Execute the request
$response = curl_exec($ch);
// Handle cURL error
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
if ($httpCode === 200 && isset($result['data']['full_name'])) {
return [
'success' => true,
'full_name' => $result['data']['full_name']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
function authenticate($baseURL, $wallet, $password)
{
// Endpoint URL
$url = rtrim($baseURL, '/') . '/authenticate';
// JSON payload
$postData = json_encode([
'wallet' => $wallet,
'password' => $password
]);
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
curl_setopt($ch, CURLOPT_POST, true); // Use POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);// Set the request body
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_errno($ch)) {
curl_close($ch);
return [
'success' => false,
'error' => 'Curl error: ' . curl_error($ch)
];
}
// Get HTTP status code
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Decode JSON response
$result = json_decode($response, true);
// Check if token is present
if ($httpCode === 200 && isset($result['data']['token'])) {
return [
'success' => true,
'token' => $result['data']['token'],
'expires_at' => $result['data']['expires_at']
];
} else {
return [
'success' => false,
'error' => $result['message'] ?? 'Unknown error',
'details' => $result['errors'] ?? []
];
}
}
?>

View File

@@ -0,0 +1,58 @@
<?php
$incoming=file_get_contents("php://input");
$details=json_decode($incoming,true);
$invoiceNumber=$details['invoiceNumber'];
$token=$details['token'];
$baseURL="https://devpayouts.tnmmpamba.co.mw/api";
//$res=authenticate($baseURL, $wallet, $password);
$bearerToken="102164|newoEd6QOFaTptUiGAp232jULtUmgMtaX1x2CRww4Ka2270dc49";
$res=checkInvoiceStatus($invoiceNumber, $bearerToken, $baseURL);
echo (print_r($res,true));
function checkInvoiceStatus($invoiceNumber, $bearerToken, $baseURL) {
// Build request URL
$url = rtrim($baseURL, '/') . "/invoices/" . urlencode($invoiceNumber);
// Initialize cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . $bearerToken,
"Accept: application/json"
]
]);
// Execute the request
$response = curl_exec($ch);
// Handle errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
curl_close($ch);
return null;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check for successful response
if ($httpCode === 200 && $response) {
return json_decode($response, true);
} else {
echo "Request failed. HTTP Code: " . $httpCode . "\nResponse: " . $response;
return null;
}
}
?>

10
app/Models/KazangApi.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class KazangApi extends Model
{
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class KazangSession extends Model
{
protected $fillable = [
'session_uuid',
];
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class KazangTransaction extends Model
{
protected $guarded = [
'id'
];
public $table = 'transactions_kazang';
}

View File

@@ -15,14 +15,14 @@ class Transaction extends Model
public function createAirtel($org_id, $msisdn, $reference_id, $amount, $product_name, $result_code){
$bind = [
"org_id" => $org_id,
"msisdn" => $msisdn,
"reference_id" => $reference_id,
"amount" => $amount,
"product_name" => $product_name,
"result_code" => $result_code,
"ussd_push_result_code" => $result_code,
"last_updated_by" => 'clientRequest'
"org_id" => $org_id,
"msisdn" => $msisdn,
"reference_id" => $reference_id,
"amount" => $amount,
"product_name" => $product_name,
"result_code" => $result_code,
"ussd_push_result_code" => $result_code,
"last_updated_by" => 'clientRequest'
];
$result = Models\AirtelTransaction::create($bind);
return ($result) ? 1 : 0;

View File

@@ -9,7 +9,7 @@ use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
public $table = 'auth_users';
/**
* The attributes that are mass assignable.
*