adjust checkbalnce on PaymentController

This commit is contained in:
root 2025-11-04 11:59:12 +01:00
parent e9db02fcd3
commit 5ddab650c4
102 changed files with 150 additions and 56 deletions

0
.editorconfig Normal file → Executable file
View File

0
.env.example Normal file → Executable file
View File

0
.gitignore vendored Normal file → Executable file
View File

0
.styleci.yml Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

0
app/Console/Commands/.gitkeep Normal file → Executable file
View File

0
app/Console/Kernel.php Normal file → Executable file
View File

0
app/Enums/PaymentMethod.php Normal file → Executable file
View File

0
app/Enums/PaymentTransactionStatus.php Normal file → Executable file
View File

0
app/Enums/PaymentType.php Normal file → Executable file
View File

0
app/Events/Event.php Normal file → Executable file
View File

0
app/Events/ExampleEvent.php Normal file → Executable file
View File

0
app/Exceptions/Handler.php Normal file → Executable file
View File

0
app/Helpers/helpers.php Normal file → Executable file
View File

0
app/Helpers/utils.php Normal file → Executable file
View File

174
app/Http/Controllers/CinetpayController.php Normal file → Executable file
View File

@ -536,63 +536,145 @@ class CinetpayController extends Controller
'http_errors' => false
]);
$responseData = json_decode($loginResponse->getBody()->getContents());
$token = $responseData->data->token;
$responseCode = $loginResponse->getStatusCode();
if ( $responseCode == 200 && !empty($token)) {
// Add Contact
$balanceResponse = $client->get('transfer/check/balance', [
'query' => [
'token' => $token
],
'timeout' => $this->timeout,
'http_errors' => false
]);
$responseData = json_decode($loginResponse->getBody()->getContents(), false);
$responseCode = $balanceResponse->getStatusCode();
$responseData = json_decode($balanceResponse->getBody()->getContents());
if ($responseCode == 200) {
$amountAvailable = $responseData?->data?->countryBalance?->{$countryCode}?->available ?? 0;
$fees = 0;
$aggregator = PaymentAggregator::where('name','like','%cinetpay%')->first();
if(!empty($aggregator)){
$baseQuery = $aggregator->rates()->where('type', PaymentType::CASH_IN)
->where('method', PaymentMethod::WALLET)
->when($paymentChannel, function ($q) use($paymentChannel){
return $q->where('channel',$paymentChannel);
});
// Vérification de la validité de la réponse avant daccéder aux valeurs
if ($responseCode !== 200 || empty($responseData) || empty($responseData->data?->token)) {
Log::error("CinetPay Login Error :: code={$responseCode} | message=" . ($responseData->message ?? 'No message'));
return $this->errorResponse(__('errors.service_unavailable_try_later'));
}
$rate = (clone $baseQuery)->where('country', $countryCode)->first();
if(empty($rate)){
$rate = (clone $baseQuery)->where('country','ALL')->first();
}
$token = $responseData->data->token;
if(!empty($rate)){
if(!empty($rate->fixed_fees)){
$targetCurrency = $country->currency->code;
$sourceCurrency = $targetCurrency;
if(!empty($rate->fixed_fees_currency)){
$sourceCurrency = $rate->fixed_fees_currency;
}
$fixed_fees = $this->toMoneyAmount($rate->fixed_fees, $sourceCurrency, $targetCurrency);
$fees = (($amount - $fixed_fees) * $rate->rate / 100 ) + $fixed_fees;
}else{
$fees = $amount * $rate->rate / 100;
}
}
// Vérification du solde
$balanceResponse = $client->get('transfer/check/balance', [
'query' => ['token' => $token],
'timeout' => $this->timeout,
'http_errors' => false
]);
$responseCode = $balanceResponse->getStatusCode();
$responseData = json_decode($balanceResponse->getBody()->getContents(), false);
if ($responseCode == 200) {
// Récupération sécurisée du solde
$amountAvailable = $responseData?->data?->countryBalance?->{$countryCode}?->available ?? 0;
$fees = 0;
Log::info("CinetPay check Balance : " . $amountAvailable);
$aggregator = PaymentAggregator::where('name', 'like', '%cinetpay%')->first();
if (!empty($aggregator)) {
$baseQuery = $aggregator->rates()
->where('type', PaymentType::CASH_IN)
->where('method', PaymentMethod::WALLET)
->when($paymentChannel, function ($q) use ($paymentChannel) {
return $q->where('channel', $paymentChannel);
});
$rate = (clone $baseQuery)->where('country', $countryCode)->first();
if (empty($rate)) {
$rate = (clone $baseQuery)->where('country', 'ALL')->first();
}
$amount += $fees;
if (!empty($rate)) {
if (!empty($rate->fixed_fees)) {
$targetCurrency = $country->currency->code;
$sourceCurrency = !empty($rate->fixed_fees_currency)
? $rate->fixed_fees_currency
: $targetCurrency;
if ($amountAvailable >= $amount){
return $this->successResponse("Solde disponible");
}else{
Log::error("Solde insuffisant :: ".$amountAvailable);
return $this->errorResponse(__('errors.service_unavailable_try_later'));
$fixed_fees = $this->toMoneyAmount($rate->fixed_fees, $sourceCurrency, $targetCurrency);
$fees = (($amount - $fixed_fees) * $rate->rate / 100) + $fixed_fees;
} else {
$fees = $amount * $rate->rate / 100;
}
}
}
$amount += $fees;
if ($amountAvailable >= $amount) {
return $this->successResponse("Solde disponible");
} else {
Log::error("Solde insuffisant :: " . $amountAvailable);
return $this->errorResponse(__('errors.service_unavailable_try_later'));
}
} else {
Log::error("CinetPay Balance Error :: code={$responseCode} | message=" . ($responseData->message ?? 'No message'));
return $this->errorResponse(__('errors.service_unavailable_try_later'));
}
// Login
// $loginResponse = $client->post('auth/login', [
// 'form_params' => [
// "apikey" => config('variables.cinetpay_api_key'),
// "password" => config('variables.cinetpay_transfert_password'),
// ],
// 'timeout' => $this->timeout,
// 'http_errors' => false
// ]);
// $responseData = json_decode($loginResponse->getBody()->getContents());
// $token = $responseData->data->token;
// $responseCode = $loginResponse->getStatusCode();
// if ( $responseCode == 200 && !empty($token)) {
// // Add Contact
// $balanceResponse = $client->get('transfer/check/balance', [
// 'query' => [
// 'token' => $token
// ],
// 'timeout' => $this->timeout,
// 'http_errors' => false
// ]);
// $responseCode = $balanceResponse->getStatusCode();
// $responseData = json_decode($balanceResponse->getBody()->getContents());
// if ($responseCode == 200) {
// $amountAvailable = $responseData?->data?->countryBalance?->{$countryCode}?->available ?? 0;
// $fees = 0;
// LOG::info("CinetPay check Balance : ".$amountAvailable);
// $aggregator = PaymentAggregator::where('name','like','%cinetpay%')->first();
// if(!empty($aggregator)){
// $baseQuery = $aggregator->rates()->where('type', PaymentType::CASH_IN)
// ->where('method', PaymentMethod::WALLET)
// ->when($paymentChannel, function ($q) use($paymentChannel){
// return $q->where('channel',$paymentChannel);
// });
// $rate = (clone $baseQuery)->where('country', $countryCode)->first();
// if(empty($rate)){
// $rate = (clone $baseQuery)->where('country','ALL')->first();
// }
// if(!empty($rate)){
// if(!empty($rate->fixed_fees)){
// $targetCurrency = $country->currency->code;
// $sourceCurrency = $targetCurrency;
// if(!empty($rate->fixed_fees_currency)){
// $sourceCurrency = $rate->fixed_fees_currency;
// }
// $fixed_fees = $this->toMoneyAmount($rate->fixed_fees, $sourceCurrency, $targetCurrency);
// $fees = (($amount - $fixed_fees) * $rate->rate / 100 ) + $fixed_fees;
// }else{
// $fees = $amount * $rate->rate / 100;
// }
// }
// }
// $amount += $fees;
// if ($amountAvailable >= $amount){
// return $this->successResponse("Solde disponible");
// }else{
// Log::error("Solde insuffisant :: ".$amountAvailable);
// return $this->errorResponse(__('errors.service_unavailable_try_later'));
// }
// }
// }
$errorMessage = $responseData?->description ?? $responseData?->message;
Log::error("Error CinetPay check balance");
Log::error("Response data :: ".json_encode($responseData ?? ''));

0
app/Http/Controllers/Controller.php Normal file → Executable file
View File

7
app/Http/Controllers/FlutterwaveController.php Normal file → Executable file
View File

@ -433,7 +433,6 @@ class FlutterwaveController extends Controller
'type' => 'nullable|string' // mobilemoney,account
]);
$amount = floatval($request->input('amount'));
$type = $request->input('type', 'mobilemoney');
$countryId = $request->input('country_id');
@ -454,6 +453,7 @@ class FlutterwaveController extends Controller
$responseData = json_decode($balanceResponse->getBody()->getContents());
if ($responseCode == 200) {
$amountAvailable = $responseData?->data?->available_balance ?? 0;
Log::info("Flutterwave check balance :: ".$amountAvailable." ".$currencyCode);
// https://flutterwavedoc.readme.io/reference/get-transfer-fee
$fees = 0;
@ -477,7 +477,6 @@ class FlutterwaveController extends Controller
if(!empty($data)){
$fee = $data[0]->fee;
$feeType = $data[0]->fee_type;
if($feeType == 'value'){
$fees = $fee;
}
@ -492,14 +491,14 @@ class FlutterwaveController extends Controller
return $this->successResponse("Solde disponible");
}else{
Log::error("Solde insuffisant :: ".$amountAvailable);
Log::error(" Solde insuffisant :: ".$amountAvailable);
return $this->errorResponse(__('errors.service_unavailable_try_later'));
}
}
}
}
$errorMessage = $responseData?->description ?? $responseData?->message;
Log::error("Error CinetPay check balance");
Log::error("Error Flutterwave check balance");
Log::error("Response data :: ".json_encode($responseData ?? ''));
return $this->errorResponse($errorMessage ?? __('errors.unexpected_error'));

19
app/Http/Controllers/PaymentController.php Normal file → Executable file
View File

@ -93,7 +93,7 @@ class PaymentController extends Controller
$networkName = strtolower($request->input('network_name'));
if(str_contains($networkName,'orange') || str_contains($networkName,'mtn')){
// return app(CinetpayController::class)->payOut($request);
//return app(CinetpayController::class)->payOut($request);
return app(FlutterwaveController::class)->payOut($request);
}
}
@ -229,8 +229,21 @@ class PaymentController extends Controller
*/
public function checkBalance(Request $request)
{
// return app(CinetpayController::class)->checkBalance($request);
return app(FlutterwaveController::class)->checkBalance($request);
$aggregator = PaymentAggregator::where('status', 1)->first();
if (!$aggregator) {
return $this->errorResponse(trans('errors.model_not_found', ['model' => 'methods']));
}
switch (strtolower($aggregator->name)) {
case 'cinetpay':
return app(CinetpayController::class)->checkBalance($request);
case 'flutterwave':
return app(FlutterwaveController::class)->checkBalance($request);
default:
return $this->errorResponse(__('errors.unexpected_error'));
}
//return app(CinetpayController::class)->checkBalance($request);
// return app(FlutterwaveController::class)->checkBalance($request);
}

6
app/Http/Controllers/StripeController.php Normal file → Executable file
View File

@ -353,11 +353,11 @@ class StripeController extends Controller
'card_no' => 'required_if:payment_method,CARD',
'exp_month' => 'required_if:payment_method,CARD',
'exp_year' => 'required_if:payment_method,CARD',
// 'cvc' => 'required_if:payment_method,CARD',
// 'cvc' => 'required_if:payment_method,CARD',
'bank_country' => 'required_if:payment_method,BANK|string|size:2',
'bank_currency' => 'required_if:payment_method,BANK|string|size:3',
'bank_account_number' => 'required_if:payment_method,BANK|string',
// 'aggregator_id' => 'required|integer',
//'aggregator_id' => 'required|integer',
'amount' => 'required|numeric',
'currency' => 'required|string|size:3',
'customer_id' => 'nullable',
@ -417,7 +417,7 @@ class StripeController extends Controller
'number' => $request->input('card_no'),
'exp_month' => $request->input('exp_month'),
'exp_year' => $request->input('exp_year'),
// 'cvc' => $request->input('cvc'),
// 'cvc' => $request->input('cvc'),
]
]
);

0
app/Http/Controllers/YnoteOrangeController.php Normal file → Executable file
View File

0
app/Http/Controllers/YoomeeController.php Normal file → Executable file
View File

0
app/Http/Controllers/YoomeeV2Controller.php Normal file → Executable file
View File

0
app/Http/Middleware/Authenticate.php Normal file → Executable file
View File

0
app/Http/Middleware/ExampleMiddleware.php Normal file → Executable file
View File

0
app/Http/Middleware/SecureApiDocs.php Normal file → Executable file
View File

0
app/Http/Middleware/VerifyCsrfToken.php Normal file → Executable file
View File

0
app/Jobs/ExampleJob.php Normal file → Executable file
View File

0
app/Jobs/Job.php Normal file → Executable file
View File

0
app/Listeners/ExampleListener.php Normal file → Executable file
View File

0
app/Models/Currency.php Normal file → Executable file
View File

0
app/Models/PaymentAggregator.php Normal file → Executable file
View File

0
app/Models/PaymentAggregatorRate.php Normal file → Executable file
View File

0
app/Models/PaymentRefund.php Normal file → Executable file
View File

0
app/Models/PaymentTransaction.php Normal file → Executable file
View File

0
app/Models/User.php Normal file → Executable file
View File

0
app/Providers/AppServiceProvider.php Normal file → Executable file
View File

0
app/Providers/AuthServiceProvider.php Normal file → Executable file
View File

0
app/Providers/EventServiceProvider.php Normal file → Executable file
View File

0
app/Traits/Helper.php Normal file → Executable file
View File

0
bootstrap/app.php Normal file → Executable file
View File

0
composer.json Normal file → Executable file
View File

0
composer.lock generated Normal file → Executable file
View File

0
config/session.php Normal file → Executable file
View File

0
config/swagger-lume.php Normal file → Executable file
View File

0
config/variables.php Normal file → Executable file
View File

0
database/factories/UserFactory.php Normal file → Executable file
View File

0
database/migrations/.gitkeep Normal file → Executable file
View File

View File

0
database/seeders/DatabaseSeeder.php Normal file → Executable file
View File

0
phpunit.xml Normal file → Executable file
View File

0
public/.htaccess Normal file → Executable file
View File

0
public/assets/app.css Normal file → Executable file
View File

0
public/assets/app.js Normal file → Executable file
View File

0
public/assets/images/default.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

0
public/assets/images/express-union.jpeg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

0
public/assets/images/failed.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
public/assets/images/flags.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

0
public/assets/images/flags@2x.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

0
public/assets/images/mtn.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

0
public/assets/images/orange.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

0
public/assets/images/stripe.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

0
public/assets/images/success.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

0
public/assets/images/yoomee.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

0
public/assets/sweetalert2/sweetalert2.all.js Normal file → Executable file
View File

0
public/assets/sweetalert2/sweetalert2.all.min.js vendored Normal file → Executable file
View File

0
public/assets/sweetalert2/sweetalert2.css Normal file → Executable file
View File

0
public/assets/sweetalert2/sweetalert2.js Normal file → Executable file
View File

0
public/assets/sweetalert2/sweetalert2.min.css vendored Normal file → Executable file
View File

0
public/assets/sweetalert2/sweetalert2.min.js vendored Normal file → Executable file
View File

0
public/assets/utils.js Normal file → Executable file
View File

0
public/index.php Normal file → Executable file
View File

0
resources/lang/en/stripe.php Normal file → Executable file
View File

0
resources/lang/en/validation.php Normal file → Executable file
View File

0
resources/lang/fr/stripe.php Normal file → Executable file
View File

0
resources/lang/fr/validation.php Normal file → Executable file
View File

0
resources/views/.gitkeep Normal file → Executable file
View File

0
resources/views/checkout.blade.php Normal file → Executable file
View File

0
resources/views/footer.blade.php Normal file → Executable file
View File

0
resources/views/payment-status.blade.php Normal file → Executable file
View File

0
resources/views/payment-webhook.blade.php Normal file → Executable file
View File

0
resources/views/stripe-checkout.blade.php Normal file → Executable file
View File

0
resources/views/vendor/swagger-lume/index.blade.php vendored Normal file → Executable file
View File

0
resources/views/verify-payment.blade.php Normal file → Executable file
View File

0
routes/web.php Normal file → Executable file
View File

0
storage/app/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/data/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/sessions/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/views/.gitignore vendored Normal file → Executable file
View File

0
storage/logs/.gitignore vendored Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More