paymentservice/app/Http/Controllers/CinetpayController.php

205 lines
8.6 KiB
PHP
Raw Normal View History

2022-08-11 09:46:51 +00:00
<?php
namespace App\Http\Controllers;
use App\Enums\PaymentTransactionState;
use App\Models\PaymentTransaction;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
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')
]);
}
//
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',
'customer_name' => 'required|string',
'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 dAmé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,
'state' => PaymentTransactionState::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->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'
]);
Log::info(json_encode($request->all()));
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([
'state' => $responseData->data->status,
'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([
'state' => PaymentTransactionState::REFUSED
]);
}
if($transaction->state == PaymentTransactionState::ACCEPTED){
return $this->successResponse([
'transaction_id' => $transaction->transaction_id,
'token' => $transaction->payment_token
]);
}else{
return $this->errorResponse("Payment failed");
}
}
}