2022-08-11 09:46:51 +00:00
< ? php
namespace App\Http\Controllers ;
2023-06-07 19:56:04 +00:00
use App\Enums\PaymentTransactionStatus ;
2022-08-11 09:46:51 +00:00
use App\Models\PaymentTransaction ;
use GuzzleHttp\Client ;
use Illuminate\Http\Request ;
2022-11-19 18:16:55 +00:00
use Illuminate\Support\Facades\Lang ;
2022-08-11 09:46:51 +00:00
use Illuminate\Support\Facades\Log ;
use Throwable ;
class CinetpayController extends Controller
{
private $client ;
private $timeout = 60 ; //In seconds
/**
* Create a new controller instance .
*
* @ return void
*/
public function __construct ()
{
// Create a client with a base URI
$this -> client = new Client ([
'base_uri' => config ( 'variables.cinetpay_api_url' )
]);
}
2022-10-08 21:12:51 +00:00
/**
* @ OA\Get (
* path = " /cinetpay/methods " ,
* summary = " Afficher la liste des methodes de Cinetpay " ,
* tags = { " Cinetpay " },
* security = {{ " api_key " : {}}},
* @ OA\Response (
* response = 200 ,
* description = " OK " ,
* @ OA\JsonContent (
* ref = " #/components/schemas/ApiResponse " ,
* example = {
* " status " : 200 ,
2022-11-21 22:29:50 +00:00
* " response " : { " hasWebview " : true , " methods " : { " MOBILE_MONEY " : " Mobile Money " , " CREDIT_CARD " : " Carte de crédit " }},
2022-10-08 21:12:51 +00:00
* " error " : null
* }
* )
* )
* )
*/
public function getMethods ()
{
2022-11-19 18:16:55 +00:00
$providers = [
// 'ALL',
'MOBILE_MONEY' ,
'CREDIT_CARD' ,
];
$methods = [];
foreach ( $providers as $provider ) {
$key = 'providers.' . $provider ;
2022-11-21 23:56:44 +00:00
$method [ 'title' ] = Lang :: has ( $key ) ? __ ( $key ) : $provider ;
$method [ 'value' ] = $provider ;
$methods [] = $method ;
2022-11-19 18:16:55 +00:00
}
return $this -> successResponse ([
'hasWebview' => true ,
'methods' => $methods ,
]);
2022-10-08 21:12:51 +00:00
}
2022-08-11 09:46:51 +00:00
//
public function pay ( Request $request )
{
$this -> validate ( $request , [
'aggregator_id' => 'required|integer' ,
'amount' => 'required|numeric|min:5' ,
'currency' => 'required|string|size:3' ,
'payment_method' => 'nullable|string|in:ALL,MOBILE_MONEY,CREDIT_CARD,WALLET' ,
'customer_id' => 'required|integer' ,
'customer_email' => 'required|email' ,
2023-06-07 19:56:04 +00:00
'customer_name' => 'nullable|string' ,
2022-08-11 09:46:51 +00:00
'customer_surname' => 'required|string' ,
'customer_phone_number' => 'required|string' ,
'customer_address' => 'required|string' ,
'customer_city' => 'required_if:payment_method,CREDIT_CARD|string' ,
'customer_country' => 'required|string|size:2' ,
'customer_state' => 'required_if:payment_method,CREDIT_CARD|string|size:2' , //Etat du pays dans lequel se trouve le client. Cette valeur est obligatoire si le client se trouve au États Unis d’ Amérique (US) ou au Canada (CA)
'customer_zip_code' => 'required_if:payment_method,CREDIT_CARD|string|size:5' ,
'reason' => 'required|string'
]);
$transaction_id = $this -> getTransactionID ();
$payment_method = $request -> input ( 'payment_method' , 'ALL' );
$amount = $request -> input ( 'amount' );
$currency = $request -> input ( 'currency' );
if ( $currency != 'USD' ) {
// Convertir en multiple de 5
$amount = $this -> roundUpToAny ( $amount );
}
// Init payment
$createResponse = $this -> client -> post ( 'payment' , [
'json' => [
" api_key " => config ( 'variables.cinetpay_api_key' ),
" site_id " => config ( 'variables.cinetpay_site_id' ),
" transaction_id " => $transaction_id ,
" amount " => $amount ,
" currency " => $request -> input ( 'currency' ),
" description " => $request -> input ( 'reason' ),
" notify_url " => route ( 'cinetpay.webhook' ),
" return_url " => route ( 'cinetpay.webhook' ),
" channels " => $payment_method ,
'lang' => app () -> getLocale (),
" 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' ),
],
'timeout' => $this -> timeout
]);
$responseData = json_decode ( $createResponse -> getBody () -> getContents ());
$responseCode = $createResponse -> getStatusCode ();
if ( $responseCode == 200 ) {
PaymentTransaction :: create ([
'aggregator_id' => $request -> input ( 'aggregator_id' ),
" currency " => $request -> input ( 'currency' ),
" transaction_id " => $transaction_id ,
" amount " => $amount ,
" payment_method " => $payment_method ,
" payment_token " => $responseData -> data -> payment_token ,
" payment_url " => $responseData -> data -> payment_url ,
2023-06-07 19:56:04 +00:00
'status' => PaymentTransactionStatus :: PENDING ,
2022-08-11 09:46:51 +00:00
" 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 -> payment_url
]);
} else {
return $this -> errorResponse ( $responseData -> error ? ? trans ( 'errors.unexpected_error' ), $responseCode );
}
}
public function capturePaymentResult ( Request $request )
{
$this -> validate ( $request , [
'cpm_site_id' => 'nullable|string' ,
'cpm_trans_id' => 'nullable|string|exists:payment_transactions,transaction_id'
]);
if ( $request -> has ( 'cpm_trans_id' )) {
$data = $request -> input ( 'cpm_site_id' ) . $request -> input ( 'cpm_trans_id' ) . $request -> input ( 'cpm_trans_date' ) . $request -> input ( 'cpm_amount' ) . $request -> input ( 'cpm_currency' ) .
$request -> input ( 'signature' ) . $request -> input ( 'payment_method' ) . $request -> input ( 'cel_phone_num' ) . $request -> input ( 'cpm_phone_prefixe' ) .
$request -> input ( 'cpm_language' ) . $request -> input ( 'cpm_version' ) . $request -> input ( 'cpm_payment_config' ) . $request -> input ( 'cpm_page_action' ) . $request -> input ( 'cpm_custom' ) . $request -> input ( 'cpm_designation' ) . $request -> input ( 'cpm_error_message' );
$generated_token = hash_hmac ( 'SHA256' , $data , config ( 'variables.cinetpay_secret_key' ));
$received_token = $request -> header ( 'x-token' );
if ( hash_equals ( $received_token , $generated_token )) {
$transaction = PaymentTransaction :: where ( 'transaction_id' , $request -> input ( 'cpm_trans_id' )) -> firstOrFail ();
return $this -> getPaymentStatus ( $transaction );
} else {
return $this -> errorResponse ( " Invalid token " );
}
} else if ( $request -> has ( 'transaction_id' )){
$transaction = PaymentTransaction :: where ( 'transaction_id' , $request -> input ( 'transaction_id' )) -> firstOrFail ();
return $this -> getPaymentStatus ( $transaction );
} else {
return response ( " OK " );
}
}
private function getPaymentStatus ( PaymentTransaction $transaction )
{
try {
$response = $this -> client -> post ( 'payment/check' , [
'json' => [
" apikey " => config ( 'variables.cinetpay_api_key' ),
" site_id " => config ( 'variables.cinetpay_site_id' ),
'transaction_id' => $transaction -> transaction_id ,
]
]);
$responseData = json_decode ( $response -> getBody () -> getContents ());
$responseCode = $response -> getStatusCode ();
if ( $responseCode == 200 ) {
$transaction -> update ([
2023-06-07 19:56:04 +00:00
'status' => $responseData -> data -> status ,
2022-08-11 09:46:51 +00:00
'payment_method_exact' => $responseData -> data -> payment_method ? ? null ,
'aggregator_payment_ref' => $responseData -> data -> operator_id ? ? null ,
'payment_date' => $responseData -> data -> payment_date ? ? null ,
]);
}
} catch ( Throwable $e ) {
Log :: info ( " Get Payment Status Error " );
Log :: info ( $e -> getMessage ());
$transaction -> update ([
2023-06-07 19:56:04 +00:00
'status' => PaymentTransactionStatus :: REFUSED
2022-08-11 09:46:51 +00:00
]);
}
2023-06-07 19:56:04 +00:00
if ( $transaction -> status == PaymentTransactionStatus :: ACCEPTED ){
2022-11-12 14:01:21 +00:00
return redirect () -> route ( 'paymentResult' ,[
2022-08-11 09:46:51 +00:00
'transaction_id' => $transaction -> transaction_id ,
2022-11-12 14:01:21 +00:00
'token' => $transaction -> payment_token ,
'status' => 1
2022-08-11 09:46:51 +00:00
]);
} else {
2022-11-12 14:01:21 +00:00
return redirect () -> route ( 'paymentResult' ,[
'message' => " Payment failed " ,
'status' => 0
]);
2022-08-11 09:46:51 +00:00
}
}
}