paymentservice/app/Http/Controllers/FlutterwaveController.php

195 lines
7.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\PaymentMethod;
use App\Enums\PaymentTransactionStatus;
use App\Enums\PaymentType;
use App\Models\Country;
use App\Models\PaymentAggregator;
use App\Models\PaymentTransaction;
use DateTime;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Log;
use Propaganistas\LaravelPhone\PhoneNumber;
use Propaganistas\LaravelPhone\Rules\Phone;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Throwable;
class FlutterwaveController extends Controller
{
private $timeout = 60; //In seconds
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
}
//
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" => config('variables.flw_secret_key')
],
'json' => [
"tx_ref" => $transaction_id,
"amount" => $amount,
"currency" => $request->input('currency'),
"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
]);
}
}
}