successResponse([ 'hasWebview' => true, 'methods' => $methods, ]); } // public function pay(Request $request) { $this->validate($request, [ // 'aggregator_id' => 'required|integer', 'amount' => 'required|numeric|min:5', 'currency' => 'required|string|size:3', 'customer_id' => 'required|integer', 'customer_email' => 'required|email', 'customer_name' => 'nullable|string', 'customer_surname' => 'required|string', 'customer_phone_number' => 'required|string', 'customer_address' => 'required|string', 'reason' => 'required|string' ]); $aggregator = PaymentAggregator::where('name','like','%flutterwave%')->firstOrFail(); $transaction_id = $this->getTransactionID(); $amount = $request->input('amount'); $currency = $request->input('currency'); if ($currency != 'USD') { // Convertir en multiple de 5 $amount = $this->roundUpToAny($amount); } // Init payment $createResponse = (new Client())->post('https://api.flutterwave.com/v3/payments', [ 'headers' => [ "Authorization" => 'Bearer '.config('variables.flw_secret_key') ], 'json' => [ "tx_ref" => $transaction_id, "amount" => $amount, "currency" => $request->input('currency'), "payment_options" => "mobilemoneyfranco", "redirect_url" => route('flutterwave.webhook'), "customer" => [ "email" => $request->input('customer_email'), "phonenumber" => $request->input('customer_phone_number'), "name" => $request->input('customer_surname').' '.$request->input('customer_name') ], "customizations" => [ "title" => $request->input('reason'), "logo" => 'https://ilink-app.com/backoffice/images/logo_blueback.png' ], "meta" => [ "customer_id" => $request->input('customer_id'), "customer_address" => $request->input('customer_address') ] ], 'timeout' => $this->timeout ]); $responseData = json_decode($createResponse->getBody()->getContents()); $responseCode = $createResponse->getStatusCode(); if ($responseCode == 200) { PaymentTransaction::create([ 'aggregator_id' => $aggregator->id, "currency" => $request->input('currency'), "transaction_id" => $transaction_id, "amount" => $amount, "payment_method" => "ALL", "payment_url" => $responseData->data->link, 'status' => PaymentTransactionStatus::PENDING, "reason" => $request->input('reason'), "customer_id" => $request->input('customer_id'), "customer_name" => $request->input('customer_name'), "customer_surname" => $request->input('customer_surname'), "customer_email" => $request->input('customer_email'), "customer_phone_number" => $request->input('customer_phone_number'), "customer_address" => $request->input('customer_address'), "customer_city" => $request->input('customer_city'), "customer_country" => $request->input('customer_country'), "customer_state" => $request->input('customer_state'), "customer_zip_code" => $request->input('customer_zip_code'), ]); return $this->successResponse([ 'message' => $responseData->message, 'payment_url' => $responseData->data->link ], ResponseAlias::HTTP_MOVED_PERMANENTLY); }else{ return $this->errorResponse($responseData->error->message ?? trans('errors.unexpected_error'),$responseCode); } } public function capturePaymentResult(Request $request) { $this->validate($request, [ 'transaction_id' => 'nullable|string', 'tx_ref' => 'nullable|string|exists:payment_transactions,transaction_id', 'status' => 'nullable|string' ]); Log::info(json_encode($request->all())); if($request->has('tx_ref')){ $transaction = PaymentTransaction::where('transaction_id',$request->input('tx_ref'))->firstOrFail(); return $this->getPaymentStatus($transaction, $request->input('transaction_id')); }else{ return response("OK"); } } private function getPaymentStatus(PaymentTransaction $transaction, $flwTransactionId) { try { // Create a client with a base URI $response = (new Client())->get('https://api.flutterwave.com/v3/transactions/'.$flwTransactionId.'/verify', [ 'headers' => [ "Authorization" => config('variables.flw_secret_key') ], ]); $responseData = json_decode($response->getBody()->getContents()); $responseCode = $response->getStatusCode(); if ($responseCode == 200 && $responseData?->data?->status == 'successful' && $responseData?->data?->tx_ref == $transaction->transaction_id) { $transaction->update([ 'status' => PaymentTransactionStatus::ACCEPTED, 'payment_method_exact' => $responseData?->data?->payment_type ?? null, 'aggregator_payment_ref' => $responseData?->data?->flw_ref ?? null, 'payment_date' => $responseData?->data?->created_at != null ? new DateTime($responseData?->data?->created_at) : null, ]); } } catch (Throwable $e) { Log::info("Get Payment Status Error"); Log::info($e->getMessage()); $transaction->update([ 'status' => PaymentTransactionStatus::REFUSED ]); } if($transaction->status == PaymentTransactionStatus::ACCEPTED){ return redirect()->route('paymentResult',[ 'transaction_id' => $transaction->transaction_id, 'token' => $transaction->payment_token, 'status' => 1 ]); }else{ return redirect()->route('paymentResult',[ 'message' => "Payment failed", 'status' => 0 ]); } } public function payOut(Request $request) { $this->validate($request, [ // 'aggregator_id' => 'required|integer', 'amount' => 'required|numeric|min:5', 'currency' => 'required|string|size:3', 'customer_id' => 'nullable', // 'payment_method' => 'required|string|in:WALLET', 'customer_email' => 'required|email', 'customer_name' => 'nullable|string', 'customer_surname' => 'required|string', 'customer_phone_number' => ['nullable','string',(new Phone())->country(['CI','SN','ML','CM','TG','BF','CD','GN','BJ'])], 'customer_address' => 'nullable|string', 'customer_city' => 'nullable|string', 'customer_country' => 'required|string|size:2|in:CI,SN,ML,CM,TG,BF,CD,GN,BJ', 'reason' => 'required|string', 'network_name' => 'required|string', ]); $aggregator = PaymentAggregator::where('name','like','%flutterwave%')->firstOrFail(); try{ $customer_surname = $request->input('customer_surname'); $customer_name = $request->input('customer_name') ?? $customer_surname; $customer_email = $request->input('customer_email'); $networkName = strtolower($request->input('network_name')); $country_code = $request->input('customer_country'); $phoneNumber = str_replace(' ','',$request->input('customer_phone_number')); $phone = new PhoneNumber($phoneNumber, $country_code); $phoneNumber = str_replace(' ','',$phone->formatInternational()); $accountNumber = substr($phoneNumber,1); $amount = $request->input('amount'); $payment_method = 'WALLET'; // if($amount < 500){ // return $this->errorResponse('Minimun amount is 500'); // } $transactionId = $this->getTransactionID(); $transaction = PaymentTransaction::create([ 'aggregator_id' => $aggregator->id, "currency" => $request->input('currency'), "transaction_id" => $transactionId, "amount" => $amount, "payment_method" => $payment_method, 'status' => PaymentTransactionStatus::INITIATED, "reason" => $request->input('reason'), "customer_id" => $request->input('customer_id'), "customer_name" => $customer_name, "customer_surname" => $customer_surname, "customer_email" => $customer_email, "customer_phone_number" => $phoneNumber, "customer_address" => $request->input('customer_address'), "customer_city" => $request->input('customer_city'), "customer_country" => $request->input('customer_country'), "customer_state" => $request->input('customer_state'), "customer_zip_code" => $request->input('customer_zip_code'), ]); // Transfert Fund $transfertResponse = (new Client())->post('https://api.flutterwave.com/v3/transfers', [ 'headers' => [ "Authorization" => 'Bearer '.config('variables.flw_secret_key') ], 'json' => [ "account_bank" => str_contains($networkName,'orange') ? 'orangemoney' : 'MTN', "account_number" => $accountNumber, 'beneficiary_name' => $customer_surname.' '.$customer_name, 'amount' => $amount, 'narration' => $request->input('reason'), 'currency' => $request->input('currency'), 'reference' => $transactionId, 'callback_url' => route('cinetpay.transfert.webhook'), 'debit_currency' => $request->input('currency'), ], 'timeout' => $this->timeout, 'http_errors' => false ]); $responseData = json_decode($transfertResponse->getBody()->getContents()); $responseCode = $transfertResponse->getStatusCode(); if ($responseCode == 200) { Log::info("Response of transfert"); Log::info(json_encode($responseData)); // $transaction->update([ // 'aggregator_payment_ref' => $responseData->data[0][0]?->transaction_id, // 'status' => $this->convertTransfertStatus($responseData->data[0][0]?->treatment_status) , // ]); return $this->successResponse([ 'message' => 'Transfert is pending', 'transaction_id' => $transactionId, 'transaction_status' => $transaction->status ]); }else{ Log::error("Error Flutterwave make transfert payment"); Log::error(json_encode($responseData)); return $this->errorResponse(__('errors.service_unavailable_try_later')); } // $errorMessage = $responseData?->description ?? $responseData?->message; }catch (Throwable $e){ Log::error("Error Flutterwave transfert payment"); $errorMessage = $e->getMessage(); Log::error("Response data :: ".json_encode($responseData ?? '')); Log::error($errorMessage); } return $this->errorResponse($errorMessage ?? __('errors.unexpected_error')); } public function captureTransfertResult(Request $request) { Log::info("Transfert wevbook"); Log::info(json_encode($request->all())); $this->validate($request, [ 'transaction_id' => 'nullable|string', 'client_transaction_id' => 'nullable|string|exists:payment_transactions,transaction_id' ]); // if($request->has('transaction_id') && $request->has('client_transaction_id')){ // $transaction = PaymentTransaction::where('transaction_id',$request->input('client_transaction_id'))->firstOrFail(); // try { // // $client = new Client([ // 'base_uri' => config('variables.cinetpay_transfert_url') // ]); // // // Login // $loginResponse = $client->post('auth/login', [ // 'form_params' => [ // "apikey" => config('variables.cinetpay_api_key'), // "password" => config('variables.cinetpay_transfert_password'), // ], // 'timeout' => $this->timeout // ]); // // $responseData = json_decode($loginResponse->getBody()->getContents()); // $token = $responseData->data->token; // $responseCode = $loginResponse->getStatusCode(); // if ($responseCode == 200 && !empty($token)) { // // $response = $client->get('transfer/check/money', [ // 'query' => [ // 'token' => $token, // 'transaction_id' => $request->input('transaction_id') // ], // ]); // // $responseData = json_decode($response->getBody()->getContents()); // $responseCode = $response->getStatusCode(); // if ($responseCode == 200) { // // $transaction->update([ // 'aggregator_payment_ref' => $responseData->data[0]?->transaction_id, // 'status' => $this->convertTransfertStatus($responseData->data[0]?->treatment_status), // ]); // // } // } // // } catch (Throwable $e) { // Log::info("Get Cinetpay Transfert Status Error"); // $errorMessage = $e->getMessage(); // Log::error("Response data :: ".json_encode($responseData ?? '')); // Log::info($errorMessage); // $transaction->update([ // 'status' => PaymentTransactionStatus::REFUSED // ]); // } // // return $this->errorResponse($errorMessage ?? __('errors.unexpected_error')); // }else{ return response("OK"); // } } // Check Balance for payout or transfer /** * @throws GuzzleException */ public function checkBalance(Request $request) { $this->validate($request, [ 'country_id' => 'required|integer|exists:countries,id', 'amount' => 'required|numeric', 'type' => 'nullable|string' // mobilemoney,account ]); $amount = floatval($request->input('amount')); $type = $request->input('type', 'mobilemoney'); $countryId = $request->input('country_id'); $country = Country::with('currency')->where('id', $countryId)->firstOrFail(); $currencyCode = $country->currency->code; // https://flutterwavedoc.readme.io/reference/get-all-wallet-balances $balanceResponse = (new Client())->get('https://api.flutterwave.com/v3/balances/'.$currencyCode, [ 'headers' => [ "Authorization" => 'Bearer '.config('variables.flw_secret_key') ], 'timeout' => $this->timeout, 'http_errors' => false ]); $responseCode = $balanceResponse->getStatusCode(); $responseData = json_decode($balanceResponse->getBody()->getContents()); if ($responseCode == 200) { $amountAvailable = $responseData?->data?->available_balance ?? 0; // https://flutterwavedoc.readme.io/reference/get-transfer-fee $fees = 0; $feesResponse = (new Client())->get('https://api.flutterwave.com/v3/transfers/fee', [ 'headers' => [ "Authorization" => 'Bearer '.config('variables.flw_secret_key') ], 'query' => [ 'amount' => $amount, 'currency' => $currencyCode, 'type' => $type ], 'timeout' => $this->timeout, 'http_errors' => false ]); $responseCode = $feesResponse->getStatusCode(); $responseData = json_decode($feesResponse->getBody()->getContents()); if ($responseCode == 200) { $data = $responseData?->data; if(!empty($data)){ $fee = $data[0]->fee; $feeType = $data[0]->fee_type; if($feeType == 'value'){ $fees = $fee; } if($feeType == 'percentage'){ $fees = $amount * $fee; } $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 ?? '')); return $this->errorResponse($errorMessage ?? __('errors.unexpected_error')); } }