diff --git a/.env.example b/.env.example index 453e5ca..34412d1 100755 --- a/.env.example +++ b/.env.example @@ -55,3 +55,5 @@ BANK_API_BRANCH_CODE=99001 BANK_API_LOGIN=admin BANK_API_PASSWORD=admin +BANK_API_OPERATION_TYPE_CODE=MOMODE +BANK_API_CUSTOMER_REL_CODE=399 diff --git a/app/Http/Controllers/WalletController.php b/app/Http/Controllers/WalletController.php index 6dc7096..3568b80 100755 --- a/app/Http/Controllers/WalletController.php +++ b/app/Http/Controllers/WalletController.php @@ -15,7 +15,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; -use App\Mail\BankAccountCreatedMail; +use App\Mail\BankAccountLinked; use App\Mail\BankAccountActivated; use App\Models\CustomerAccountType; use Illuminate\Support\Facades\Mail; @@ -898,7 +898,7 @@ INNER JOIN countries c ON oc.id_country = c.id INNER JOIN type_operators top ON 'identificationNumber' => $bank_account->identification_number, 'paySlip' => $request->doc_front, 'signatureCard' => $request->doc_back, - 'custRelCode' => '399' + 'custRelCode' => env('BANK_API_CUSTOMER_REL_CODE', '399') ]; try { @@ -944,7 +944,7 @@ INNER JOIN countries c ON oc.id_country = c.id INNER JOIN type_operators top ON LOG::info(' Compte activé avec succès ! Numero du compte bancaire du User : ' . $user->id . ' : ' . ($user->iban ?? 'N/A')); try { - // Mail::to($user->email)->send(new BankAccountActivated($bank_account, $name_of_account_type)); + Mail::to($user->email)->send(new BankAccountActivated($bank_account, $name_of_account_type)); } catch (\Exception $e) { Log::error("Mail error lors de l'activation: " . $e->getMessage()); return $this->successResponse(trans('messages.user_bank_account_activated_successfully', ['bank' => 'SunEx','account_number' => $bank_account->account_number]), 200); @@ -1045,24 +1045,27 @@ INNER JOIN countries c ON oc.id_country = c.id INNER JOIN type_operators top ON Log::info('Compte bancaire rattaché avec succès pour transaction: ' . $request->id_transaction); try { - // Mail::to($user->email)->send(new BankAccountLinked($user_bank_account_verfication)); + Mail::to($user->email)->send(new BankAccountLinked($user_bank_account_verfication)); } catch (\Exception $e) { Log::error("Mail error: " . $e->getMessage()); + return $this->successResponse(trans('messages.create_bank_account_linked_successfully'), 200); } return $this->successResponse(trans('messages.create_bank_account_linked_successfully'), 200); } } catch (RequestException $e) { $errorBody = $e->hasResponse() ? (string) $e->getResponse()->getBody() : $e->getMessage(); + $decodedBody = json_decode($errorBody, true); + $extractedMessage = $decodedBody['message'] ?? $errorBody; $user_bank_account_verfication->update([ 'is_verified' => 2, - 'was_traited' => 0, + 'was_treated' => 0, ]); - Log::error('Erreur API Bank Link pour transaction ' . $request->id_transaction . ' : ' . $errorBody); + Log::error('Erreur API Bank Link pour transaction ' . $request->id_transaction . ' : ' . $extractedMessage); - return $this->errorResponse(trans('errors.Error_occurred')); + return $this->errorResponse('Account: '. $request->iban . ', ' . $extractedMessage ?? trans('errors.Error_occurred'), 500); } catch (\Exception $e) { Log::error('Erreur inattendue Bank Link : ' . $e->getMessage()); return $this->errorResponse(trans('errors.Error_occurred')); diff --git a/app/Http/Controllers/iLinkTransactionController.php b/app/Http/Controllers/iLinkTransactionController.php index ea893a7..224d83d 100755 --- a/app/Http/Controllers/iLinkTransactionController.php +++ b/app/Http/Controllers/iLinkTransactionController.php @@ -625,24 +625,21 @@ class iLinkTransactionController extends Controller 'id_wallet_network' => 'required|integer|min:0|not_in:0', 'montant' => 'required|numeric|min:0', ]); - + $response_message = ''; $user = $walletUser->user; $this->validatePassword($request->password, $user->encrypted_password, $user->salt); $this->checkUserIdentification($user->id); - $userBankAccountVerification = UsersBankingAccountVerification::where('user_code', $user->user_code) - ->first(); + // Vérification des prérequis $accountNumber = $user->iban; - - if ((!$accountNumber || !$user->id_bank_country) && !$userBankAccountVerification) { - throw new Exception(trans('errors.wallet_not_linked_to_bank_account'), 422); + if (!$accountNumber || !$user->id_bank_country) { + throw new Exception(trans('errors.wallet_not_linked_to_bank_account'), 422); } if ($request->montant > $walletUser->balance) { throw new Exception(trans('errors.insufficient_balance'), 422); } - // Vérification de l'opérateur réseau $network_bank = NetworksOperator::where('id_network', $request->id_wallet_network) ->where('id_operator_country', $user->id_bank_country) ->first(); @@ -651,7 +648,24 @@ class iLinkTransactionController extends Controller throw new Exception(trans('errors.not_banking_operator')); } - // Préparation des données de transaction + // Récupération du matricule (Customer Code) + $verification = UsersBankingAccountVerification::where('user_code', $user->user_code) + ->where('account_number', $accountNumber)->first(); + $accountInfo = UserBankAccount::where('id_user', $user->id) + ->where('account_number', $accountNumber)->first(); + + if ($verification) { + $customer_code = $verification->iban; + } elseif ($accountInfo) { + $customer_code = $accountInfo->customer_number; + } else { + throw new Exception(trans('errors.bank_account_not_found'), 422); + } + + $bankName = $network_bank->operators_country->operator->nom; + $countryName = $network_bank->operators_country->country->name; + + // Préparation de la transaction $transaction->id_transaction = $this->getTransactionID(); $transaction->montant = $request->montant; $transaction->frais = 0; @@ -660,76 +674,106 @@ class iLinkTransactionController extends Controller $transaction->prenom_emetteur = $user->firstname; $transaction->email_emetteur = $user->email; $transaction->network_emetteur = $network_bank->id_network; - $transaction->bank = $network_bank->operators_country->operator->nom; - $transaction->country = $network_bank->operators_country->country->name; - $transaction->iban = $accountNumber; + $transaction->init_country = 38; + $transaction->final_country = 38; + $transaction->bank_account_number = $accountNumber; + $transaction->bank_name = $bankName; $transaction->date = $this->getCurrentTime($init_country); + $transaction->status = 'PENDING'; // --- DÉBUT DE LA TRANSACTION DB --- - DB::beginTransaction(); try { // Débit provisoire du Wallet + $oldBalance = $walletUser->balance; $walletUser->balance -= $transaction->montant; $walletUser->save(); + $transaction->save(); $baseUrl = env('BANK_API_BASE_URL'); $client = new Client(['connect_timeout' => 60]); - // Authentification (Bearer Token) $authResponse = $client->post($baseUrl . '/auth/authenticate', [ 'json' => ['login' => env('BANK_API_LOGIN'), 'password' => env('BANK_API_PASSWORD')] ]); - $token = json_decode($authResponse->getBody(), true)['data']['token'] ?? null; + $authData = json_decode($authResponse->getBody(), true); + $token = $authData['data']['token'] ?? null; if (!$token) throw new Exception(trans('errors.token_not_found')); - // Disbursement Payload - $payload = [ - "clientMatricule" => $userBankAccountVerification->iban, - "crAccountId" => $accountNumber, - "description" => "Credit wallet sunEx vers compte bancaire", - "operationDate" => $transaction->date, - "operationTypeCode" => env('BANK_API_OPERATION_TYPE_CODE' ), - "traceNo" => $transaction->id_transaction, - "transactionAmt" => (float)$transaction->montant - ]; - + // Appel API Disbursement $apiResponse = $client->post($baseUrl . '/account/disbursement', [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $token, - 'Accept' => 'application/json', - ], - 'json' => $payload + 'headers' => ['Authorization' => 'Bearer ' . $token, 'Accept' => 'application/json'], + 'json' => [ + "clientMatricule" => (string)$customer_code, + "crAccountId" => (string)$accountNumber, + "description" => "Credit wallet sunEx vers compte bancaire", + "operationDate" => $transaction->date, + "operationTypeCode" => env('BANK_API_OPERATION_TYPE_CODE'), + "traceNo" => $transaction->id_transaction, + "transactionAmt" => (float)$transaction->montant + ] ]); $result = json_decode($apiResponse->getBody(), true); - if ($apiResponse->getStatusCode() <= 301 && ($result['success'] ?? true) != false) { - $transaction->canceled = 0; + // Analyse de la réponse + if ($apiResponse->getStatusCode() <= 301 && isset($result['message']) && $result['message'] == 'Success') { + + // Sécurisation des données de retour + $apiData = $result['data'] ?? []; + + $transaction->status = 'Success'; + $transaction->payment_transaction_id = $apiData['transactionId'] ?? null; $transaction->save(); - DB::commit(); + + if(isset($accountInfo)){ + $accountInfo->balance = $apiData['realBalance'] ?? $accountInfo->balance; + $accountInfo->save(); + } // Envoi Mail $message = trans('messages.successful_user_send_to_bank', [ 'id_transaction' => $transaction->id_transaction, - 'amount' => $this->toMoney($transaction->montant, $init_country), - 'iban' => $accountNumber, - 'net' => $this->toMoney($transaction->montant, $init_country), - 'sender_code' => $user->user_code, - 'country' => $network_bank->operators_country->country->name, - 'bank' => $network_bank->operators_country->operator->nom + 'amount' => $this->toMoney($transaction->montant, $init_country), + 'iban' => $accountNumber, + 'net' => $this->toMoney($transaction->montant, $init_country), + 'sender_code' => $user->user_code, + 'country' => $countryName, + 'bank' => $bankName ]); - $this->sendMail($user->email, trans('messages.successful_transaction'), $message); - Log::info("SUCCESS: Wallet to Bank - Trx: " . $transaction->id_transaction); + // Log de succès + $this->sendMail($user->email, trans('messages.successful_transaction'), $message); + Log::info($result['data']['outMessage']. ' Transaction ID: ' . $result['data']['transactionId'].' Bank Account: ' . $result['data']['accountId'] . ' -Wallet New Balance: ' . $walletUser->balance.' -Old Wallet Balance: ' . $oldBalance); + + $response_message = + (($apiData['outMessage'] ?? 'Success') . + ' | ID: ' . ($apiData['transactionId'] ?? 'N/A') . + ' | Bank New Balance: ' . ($apiData['realBalance'] ?? 'N/A')); + } else { - throw new Exception("API Bank Refused: " . $apiResponse->getBody()); + // La banque a refusé l'opération + DB::rollBack(); + + // Optionnel : Enregistrer l'échec en base (nécessite une nouvelle instance car le rollback a tout annulé) + Log::warning("BANK REFUSED: " . ($result['message'] ?? 'Unknown error')); + return $this->errorResponse($result['message'] ?? trans('errors.Error_occurred'), 400); } } catch (\Exception $e) { DB::rollBack(); - Log::error("FAILED: Wallet to Bank - Error: " . $e->getMessage()); - throw new Exception(trans('errors.bank_api_exception'), 500); + $errorMessage = $e->getMessage(); + + if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) { + $response = $e->getResponse(); + $body = (string) $response->getBody(); + $result = json_decode($body, true); + if (isset($result['message'])) { + $errorMessage = $result['message']; + } + } + Log::error("CRITICAL ERROR Wallet2Bank: " . $errorMessage); + return $this->errorResponse($errorMessage, 500); } break; // case 5: //User - Envoi de carte à wallet @@ -1599,14 +1643,16 @@ class iLinkTransactionController extends Controller 'prenom_destinataire' => 'required', ]); + $response_message = ''; $agent = AgentPlus::findOrFail($network_agent->agent_id); $this->validatePassword($request->password, $agent->encrypted_password, $agent->salt); - // Vérifications de solde et réseau + // 1. Vérifications de solde if ($request->montant > $walletAgent->balance_princ) { throw new Exception(trans('errors.insufficient_balance'), 422); } + // 2. Vérification réseau et banque $network_bank = NetworksOperator::where('id_network', $request->id_wallet_network) ->where('id_operator_country', $request->id_bank) ->first(); @@ -1615,7 +1661,34 @@ class iLinkTransactionController extends Controller throw new Exception(trans('errors.bank_not_associated_with_network')); } - // Préparation des données de la transaction + // Récupération du matricule (Customer Code) + $accountInfo = UserBankAccount::where('account_number', $request->iban)->first(); + $verification = UsersBankingAccountVerification::where('account_number', $request->iban)->first(); + + if ($verification) { + $client_matricule = $verification->iban; + $beneficiary_user = User::where('user_code', $verification->user_code)->first(); + } elseif ($accountInfo) { + $client_matricule = $accountInfo->customer_number; + $beneficiary_user = User::where('id', $accountInfo->id_user)->first(); + } else { + throw new Exception(trans('errors.bank_account_not_found'), 422); + } + + if (!$beneficiary_user) { + throw new Exception(trans('errors.user_not_found'), 422); + } + + if (!$beneficiary_user->iban && !$beneficiary_user->id_bank_country) { + throw new Exception(trans('errors.wallet_not_linked_to_bank_account'), 422); + } + $accout_number = $beneficiary_user->iban; + + // Préparation des variables de texte + $bankName = $network_bank->operators_country->operator->nom; + $countryName = $network_bank->network->country->name; + + // 4. Préparation de la transaction $transaction->id_transaction = $this->getTransactionID(); $transaction->montant = $request->montant; $transaction->frais = 0; @@ -1635,37 +1708,39 @@ class iLinkTransactionController extends Controller $transaction->nom_destinataire = $request->nom_destinataire; $transaction->prenom_destinataire = $request->prenom_destinataire; - $transaction->bank = $network_bank->operators_country->operator->nom; - $transaction->country = $network_bank->network->country->name; - $transaction->id_bank = $request->id_bank; - $transaction->iban = $request->iban; + $transaction->bank_name = $bankName; + $transaction->init_country = 38; + $transaction->final_country = 38; + $transaction->bank_account_number = $accout_number; $transaction->date = $this->getCurrentTime($init_country); - $receiver_client_matricule = UserBankAccount::where('iban', $request->iban)->first()->customer_number ?? null; + $transaction->status = 'PENDING'; - // --- DÉBUT DE LA TRANSACTION DB --- - DB::beginTransaction(); try { - // Débit du compte Agent (balance_princ car c'est une opération Cash) + // Débit provisoire du Wallet Agent + $oldBalance = $walletAgent->balance_princ; $walletAgent->balance_princ -= $transaction->montant; $walletAgent->save(); + $transaction->save(); $baseUrl = env('BANK_API_BASE_URL'); $client = new Client(['connect_timeout' => 60]); // Authentification Bearer $authResponse = $client->post($baseUrl . '/auth/authenticate', [ - 'json' => ['login' => env('BANK_API_LOGIN'), 'password' => env('BANK_API_PASSWORD')] + 'json' => [ + 'login' => env('BANK_API_LOGIN'), + 'password' => env('BANK_API_PASSWORD') + ] ]); - $token = json_decode($authResponse->getBody(), true)['data']['token'] ?? null; + $authData = json_decode($authResponse->getBody(), true); + $token = $authData['data']['token'] ?? null; if (!$token) throw new Exception(trans('errors.token_not_found')); - // Payload de décaissement (Disbursement) - // Note: Ici le clientMatricule est souvent un matricule système ou celui de l'agent - // s'il possède un compte banque rattaché. + // Payload de décaissement $payload = [ - "clientMatricule" => $receiver_client_matricule, // Matricule receveur - "crAccountId" => $request->iban, //Numero de compte bancaire receveur + "clientMatricule" => (string)$client_matricule, + "crAccountId" => (string)$accout_number, "description" => "Transfert Cash vers Banque - Emetteur: " . $request->prenom_emetteur . ' ' . $request->nom_emetteur, "operationDate" => $transaction->date, "operationTypeCode" => env('BANK_API_OPERATION_TYPE_CODE'), @@ -1683,36 +1758,53 @@ class iLinkTransactionController extends Controller $result = json_decode($apiResponse->getBody(), true); - if ($apiResponse->getStatusCode() <= 301 && ($result['success'] ?? true) != false) { - $transaction->canceled = 0; + // Analyse de la réponse + if ($apiResponse->getStatusCode() <= 301 && isset($result['message']) && $result['message'] == 'Success') { + + // Sécurisation des données de retour + $apiData = $result['data'] ?? []; + + $transaction->status = 'Success'; + $transaction->payment_transaction_id = $apiData['transactionId'] ?? null; $transaction->save(); - DB::commit(); - // Logs et Envoi Mail - Log::info('SUCCESS: Agent Cash to Bank - Trx: ' . $transaction->id_transaction); + if(isset($accountInfo)){ + $accountInfo->balance = $apiData['realBalance'] ?? $accountInfo->balance; + $accountInfo->save(); + } + // Envoi Mail (Commenté comme demandé pour correspondre au Case 4) $message = trans('messages.successful_agent_send_from_cash_to_bank', [ 'id_transaction' => $transaction->id_transaction, 'amount' => $this->toMoney($transaction->montant, $init_country), 'receiver_name' => $request->prenom_destinataire . ' ' . $request->nom_destinataire, 'iban' => $request->iban, 'sender_name' => $request->prenom_emetteur . ' ' . $request->nom_emetteur, - 'bank' => $transaction->bank, - 'country' => $transaction->country + 'bank' => $bankName, + 'country' => $countryName ]); $this->sendMail($request->email_emetteur, trans('messages.successful_transaction'), $message); - $response_message = ($message . trans('messages.sent_by_mail')); + + Log::info($result['data']['outMessage']. ' Transaction ID: ' . $result['data']['transactionId'].' Bank Account: ' . $result['data']['accountId'] . ' -Agent New Balance: ' . $walletAgent->balance_princ.' -Old Agent Balance: ' . $oldBalance); + + $response_message = + (($apiData['outMessage'] ?? 'Success') . + ' | ID: ' . ($apiData['transactionId'] ?? 'N/A') . + ' | Bank New Balance: ' . ($apiData['realBalance'] ?? 'N/A')); } else { - throw new Exception("API Bank Refused: " . $apiResponse->getBody()); + // La banque a refusé l'opération + DB::rollBack(); + + Log::warning("BANK REFUSED Agent Cash to Bank: " . ($result['message'] ?? 'Unknown error')); + return $this->errorResponse($result['message'] ?? trans('errors.Error_occurred'), 400); } } catch (\Exception $e) { - // D. Échec : Annulation du débit agent DB::rollBack(); - Log::error("FAILED: Agent Cash to Bank - Error: " . $e->getMessage()); - throw new Exception(trans('errors.bank_api_exception'), 500); + Log::error("CRITICAL ERROR AgentCash2Bank: " . $e->getMessage()); + throw new Exception(trans('errors.Error_occurred'), 500); } break; @@ -1845,29 +1937,49 @@ class iLinkTransactionController extends Controller * ) * ) */ - case 20: //User - Retrait de la banque vers le wallet - - //$this->validate($request, [ - //'code_retrait' => 'required', - //]); + case 20: // User - Retrait de la banque vers le wallet (Bank to Wallet) + $this->validate($request, [ + 'montant' => 'required|numeric|min:1', + 'password' => 'required' + ]); + $response_message = ''; $user = $walletUser->user; $this->validatePassword($request->password, $user->encrypted_password, $user->salt); - $this->checkUserIdentification($user->id); - if (!(isset($user->iban) && isset($user->id_bank_country))) - throw new Exception(trans('errors.wallet_not_linked_to_bank_account')); + // Vérification des prérequis de liaison + $accountNumber = $user->iban; + if (!$accountNumber || !$user->id_bank_country) { + throw new Exception(trans('errors.wallet_not_linked_to_bank_account'), 422); + } - //Reverifier si l'operateur est toujours associé au reseau - $network_bank = NetworksOperator::where('id_network', $transaction->network_emetteur)->where('id_operator_country', $user->id_bank_country)->first(); - if (!$network_bank) + $verification = UsersBankingAccountVerification::where('user_code', $user->user_code) + ->where('account_number', $accountNumber) + ->first(); + + $accountInfo = UserBankAccount::where('id_user', $user->id) + ->where('account_number', $accountNumber) + ->first(); + + if ($verification) { + $customer_code = $verification->iban; + } elseif ($accountInfo) { + $customer_code = $accountInfo->customer_number; + } else { + throw new Exception(trans('errors.bank_account_not_found'), 422); + } + + // Re-vérifier si l'opérateur est toujours associé au réseau + $network_bank = NetworksOperator::where('id_network', $transaction->network_emetteur) + ->where('id_operator_country', $user->id_bank_country) + ->first(); + + if (!$network_bank || $network_bank->operators_country->operator->type != 'bank') { throw new Exception(trans('errors.operator_not_associated_with_network') . '. ' . trans('errors.update_banking_information')); + } - if ($network_bank->operators_country->operator->type != 'bank') - throw new Exception(trans('errors.not_banking_operator') . '. ' . trans('errors.update_banking_information')); - - //Reverifier le code IBAN correspond toujours + // Reverifier le code IBAN correspond toujours // $country_code = $network_bank->network->country->code_country; // $bank_code = $network_bank->operators_country->code; // switch ($this->checkIBAN($user->iban, $country_code, $bank_code)) { @@ -1879,35 +1991,134 @@ class iLinkTransactionController extends Controller // throw new Exception(trans('errors.bank_not_match_iban') . '. ' . trans('errors.update_banking_information')); // } - + // 4. Préparation des données de transaction + $transaction->id_transaction = $this->getTransactionID(); + $transaction->montant = $request->montant; $transaction->frais = $frais = 0; $transaction->taxe = $taxe = 0; - //$walletUser->balance += $transaction->montant; $transaction->commission_banque = 0; - $transaction->commission_hyp = 0; - $transaction->id_wallet_hyp = $walletHyperviseur->id; - $transaction->frais = $frais; + + $bankName = $network_bank->operators_country->operator->nom; + $countryName = $network_bank->network->country->name; + + + $transaction->init_country = 38; + $transaction->final_country = 38; + $transaction->bank_account_number = $accountNumber; + $transaction->bank_name = $bankName; $transaction->date = $this->getCurrentTime($init_country); - $transaction->bank = $user->bank->operators_country->operator->nom; - $transaction->country = $user->bank->network->country->name; - $transaction->id_bank = $user->id_bank_country; - $transaction->iban = $user->iban; - //$walletUser->save(); - $transaction->id_transaction = $this->getTransactionID(); - //$transaction->save(); + $transaction->status = 'PENDING'; - Log::info('-------------------------- User - Retrait de la banque vers le wallet ------------------------------------'); - Log::info(json_encode($transaction)); - Log::info('------------------------------------------------------------------------------------------------'); - $message = trans('messages.successful_user_remove_from_bank_to_wallet', - ['id_transaction' => $transaction->id_transaction, 'amount' => $this->toMoney($transaction->montant, $init_country), - 'net' => $this->toMoney($transaction->montant, $init_country), 'iban' => $user->iban, 'fees' => $this->toMoney($frais, $init_country), - 'sender_code' => $user->user_code, 'bank' => $transaction->bank, 'country' => $transaction->country]); - $this->sendMail($user->email, trans('messages.successful_transaction'), $message); - $response_message = ($message . trans('messages.sent_by_mail')); + try { + // Sauvegarde initiale de la transaction + $transaction->save(); + $oldBalance = $walletUser->balance; + + $baseUrl = env('BANK_API_BASE_URL'); + $client = new Client(['connect_timeout' => 60]); + + // Authentification Bearer Token + $authResponse = $client->post($baseUrl . '/auth/authenticate', [ + 'json' => [ + 'login' => env('BANK_API_LOGIN'), + 'password' => env('BANK_API_PASSWORD') + ] + ]); + $authData = json_decode($authResponse->getBody(), true); + $token = $authData['data']['token'] ?? null; + + if (!$token) throw new Exception(trans('errors.token_not_found')); + + // Payload de débit + $payload = [ + "clientMatricule" => (string)$customer_code, + "crAccountId" => (string)$accountNumber, + "drAccountId" => (string)$accountNumber, + "description" => "Retrait Banque vers Wallet SunEx", + "operationDate" => $transaction->date, + "operationTypeCode" => env('BANK_API_OPERATION_TYPE_CODE'), + "traceNo" => $transaction->id_transaction, + "transactionAmt" => (float)$transaction->montant + ]; + + $apiResponse = $client->post($baseUrl . '/account/debit', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ], + 'json' => $payload + ]); + + $result = json_decode($apiResponse->getBody(), true); + + // Analyse de la réponse + if ($apiResponse->getStatusCode() <= 301 && isset($result['message']) && $result['message'] == 'Success') { + + // Sécurisation des données de retour + $apiData = $result['data'] ?? []; + + // Crédit du Wallet du user dans notre système + $walletUser->balance += $transaction->montant; + $walletUser->save(); + + $transaction->status = $result['message'] ?? 'SUCCESS'; + $transaction->payment_transaction_id = $apiData['transactionId'] ?? null; + $transaction->save(); + + if(isset($accountInfo)){ + $accountInfo->balance = $apiData['realBalance'] ?? $accountInfo->balance; + $accountInfo->save(); + } + + // Préparation du message + $message = trans('messages.successful_user_remove_from_bank_to_wallet', [ + 'id_transaction' => $transaction->id_transaction, + 'amount' => $this->toMoney($transaction->montant, $init_country), + 'net' => $this->toMoney($transaction->montant, $init_country), + 'iban' => $accountNumber, + 'fees' => $this->toMoney($frais, $init_country), + 'sender_code' => $user->user_code, + 'bank' => $bankName, + 'country' => $countryName + ]); + + // Envoi Mail + $this->sendMail($user->email, trans('messages.successful_transaction'), $message); + + Log::info($apiData['outMessage']. ' Transaction ID: ' . ($apiData['transactionId'] ?? 'N/A') . ' Bank Account: ' . ($apiData['accountId'] ?? 'N/A') . ' -Wallet New Balance: ' . $walletUser->balance . ' -Old Wallet Balance: ' . $oldBalance); + + $response_message = (($apiData['outMessage'] ?? 'Success') . + ' | ID: ' . ($apiData['transactionId'] ?? 'N/A') . + ' | Bank New Balance: ' . ($apiData['realBalance'] ?? 'N/A')); + + } else { + // La banque a refusé l'opération + DB::rollBack(); + + Log::warning("BANK REFUSED Bank to Wallet: " . ($result['message'] ?? 'Unknown error')); + return $this->errorResponse($result['message'] ?? trans('errors.Error_occurred'), 400); + } + + } catch (\Exception $e) { + DB::rollBack(); + + $errorMessage = $e->getMessage(); + + if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) { + $response = $e->getResponse(); + $body = (string) $response->getBody(); + $result = json_decode($body, true); + if (isset($result['message'])) { + $errorMessage = $result['message']; + } + } + + Log::error("CRITICAL ERROR Bank2Wallet: " . $errorMessage); + return $this->errorResponse($errorMessage, 400); + } break; case 21: //User - Retrait de carte vers autre wallet @@ -2125,7 +2336,7 @@ class iLinkTransactionController extends Controller throw $e; } Log::error($e->getMessage() . "\n" . $e->getTraceAsString()); - return $this->errorResponse($e->getMessage(), $e->getCode()); + return $this->errorResponse(trans('errors.Error_occurred'), $e->getCode()); } } diff --git a/app/Models/WalletIlinkTransaction.php b/app/Models/WalletIlinkTransaction.php index 08a5ce9..0ca7951 100755 --- a/app/Models/WalletIlinkTransaction.php +++ b/app/Models/WalletIlinkTransaction.php @@ -159,7 +159,10 @@ class WalletIlinkTransaction extends Model 'pspReference', 'from_network_emetteur', 'id_transaction_network_emetteur', - 'montant_commission' + 'montant_commission', + 'status', + 'bank_account_number', + 'bank_name' ]; public function country()