Add yoomee v2 controller
This commit is contained in:
parent
93890a13b8
commit
d0e69790b3
|
@ -25,6 +25,10 @@ SWAGGER_DOCS_TOKEN=kTKyDQJhYZLkm7wVZx2pJ90CuYpHcndx
|
|||
|
||||
YOOMEE_MERCHANT_CODE=47ttazydghzd/bfzdv85z4dzhutFRYRyzhdgtrehdnfglltmfjkk85421@er
|
||||
YOOMEE_API_URL=https://quality-env.yoomeemoney.cm/yoomee_ext_paymentv3/
|
||||
YOOMEE_API_V2_URL=https://quality-env.yoomeemoney.cm/run/b2i/collect/webservice/payment/
|
||||
YOOMEE_APP_ID=iLinkWorld
|
||||
YOOMEE_USERNAME=ilink2022
|
||||
YOOMEE_PASSWORD=Ilink@2022
|
||||
|
||||
CINETPAY_API_KEY=176445314662bebd39b1b6f8.42908045
|
||||
CINETPAY_SECRET_KEY=140983310662e79736e8ae45.38146680
|
||||
|
|
|
@ -10,4 +10,5 @@ abstract class PaymentTransactionState
|
|||
const PENDING = 'PENDING';
|
||||
const PENDING_OTP = 'PENDING_OTP';
|
||||
const REFUSED = 'REFUSED';
|
||||
const CANCELLED = 'CANCELLED';
|
||||
}
|
||||
|
|
|
@ -27,6 +27,31 @@ class CinetpayController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,
|
||||
* "response" : {{"ALL","MOBILE_MONEY","CREDIT_CARD","WALLET"}},
|
||||
* "error":null
|
||||
* }
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getMethods()
|
||||
{
|
||||
return $this->successResponse(['ALL', 'MOBILE_MONEY','CREDIT_CARD','WALLET']);
|
||||
}
|
||||
|
||||
//
|
||||
public function pay(Request $request)
|
||||
{
|
||||
|
@ -130,8 +155,6 @@ class CinetpayController extends Controller
|
|||
'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') .
|
||||
|
|
|
@ -4,9 +4,30 @@ namespace App\Http\Controllers;
|
|||
|
||||
use App\Models\PaymentAggregator;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
public function getMethods(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'aggregator_id' => 'required|integer|exists:payment_aggregators,id',
|
||||
]);
|
||||
|
||||
$aggregator = PaymentAggregator::findOrFail($request->input('aggregator_id'));
|
||||
|
||||
switch(strtolower($aggregator->name)){
|
||||
case 'yoomee':
|
||||
return redirect()->route('yoomee.methods', $request->all());
|
||||
case 'yoomeev2':
|
||||
return redirect()->route('yoomee.v2.methods', $request->all());
|
||||
case 'cinetpay':
|
||||
return redirect()->route('cinetpay.methods', $request->all());
|
||||
default:
|
||||
return $this->errorResponse(__('errors.unexpected_error'));
|
||||
}
|
||||
}
|
||||
|
||||
public function pay(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
|
@ -18,6 +39,8 @@ class PaymentController extends Controller
|
|||
switch(strtolower($aggregator->name)){
|
||||
case 'yoomee':
|
||||
return redirect()->route('yoomee.pay', $request->all());
|
||||
case 'yoomeev2':
|
||||
return redirect()->route('yoomee.v2.pay', $request->all());
|
||||
case 'cinetpay':
|
||||
return redirect()->route('cinetpay.pay', $request->all());
|
||||
default:
|
||||
|
|
|
@ -6,8 +6,7 @@ use App\Enums\PaymentTransactionState;
|
|||
use App\Models\PaymentTransaction;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class YoomeeController extends Controller
|
||||
{
|
||||
|
@ -29,8 +28,8 @@ class YoomeeController extends Controller
|
|||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/yoomee/operators",
|
||||
* summary="Afficher la liste des operateurs de Yoomee",
|
||||
* path="/yoomee/methods",
|
||||
* summary="Afficher la liste des methodes de paiements de Yoomee",
|
||||
* tags={"Yoomee"},
|
||||
* security={{"api_key":{}}},
|
||||
* @OA\Response(
|
||||
|
@ -47,7 +46,7 @@ class YoomeeController extends Controller
|
|||
* )
|
||||
* )
|
||||
*/
|
||||
public function getOperators()
|
||||
public function getMethods()
|
||||
{
|
||||
$response = $this->client->get('operators');
|
||||
return $this->successResponse(json_decode($response->getBody()->getContents()));
|
||||
|
@ -77,20 +76,20 @@ class YoomeeController extends Controller
|
|||
$otp = $request->input('otp');
|
||||
|
||||
// Create passport payment
|
||||
$createResponse = $this->client->post('passport',[
|
||||
$createResponse = $this->client->post('passport', [
|
||||
'json' => [
|
||||
"currency" => $request->input('currency'),
|
||||
"customerEmail" => $request->input('customer_email'),
|
||||
"customerName" => $request->input('customer_name'),
|
||||
"customerPhone" => $request->input('customer_phone_number'),
|
||||
"merchantCode" => config('variables.yoomee_merchant_code'),
|
||||
"orderNumber" => $transaction_id,
|
||||
"transactionAmount" => $request->input('amount')
|
||||
"currency" => $request->input('currency'),
|
||||
"customerEmail" => $request->input('customer_email'),
|
||||
"customerName" => $request->input('customer_name'),
|
||||
"customerPhone" => $request->input('customer_phone_number'),
|
||||
"merchantCode" => config('variables.yoomee_merchant_code'),
|
||||
"orderNumber" => $transaction_id,
|
||||
"transactionAmount" => $request->input('amount')
|
||||
],
|
||||
'timeout'=> $this->timeout
|
||||
'timeout' => $this->timeout
|
||||
]);
|
||||
|
||||
if($createResponse->getStatusCode() == 201){
|
||||
if ($createResponse->getStatusCode() == 201) {
|
||||
$createResponse = json_decode($createResponse->getBody()->getContents());
|
||||
|
||||
$transaction = PaymentTransaction::create([
|
||||
|
@ -99,6 +98,7 @@ class YoomeeController extends Controller
|
|||
"transaction_id" => $transaction_id,
|
||||
"amount" => $createResponse->transactionAmount,
|
||||
"payment_method" => $payment_method,
|
||||
'payment_token' => Str::random(32),
|
||||
'state' => $createResponse->paymentStatus,
|
||||
"reason" => $request->input('reason'),
|
||||
"customer_id" => $request->input('customer_id'),
|
||||
|
@ -120,18 +120,18 @@ class YoomeeController extends Controller
|
|||
"merchantCode" => config('variables.yoomee_merchant_code'),
|
||||
"paymentMethod" => $payment_method
|
||||
];
|
||||
if(!empty($otp)){
|
||||
if (!empty($otp)) {
|
||||
$paymentData['secretOTP'] = $otp;
|
||||
}
|
||||
$payResponse = $this->client->put("passport/pay/$transaction_id",[
|
||||
$payResponse = $this->client->put("passport/pay/$transaction_id", [
|
||||
'json' => $paymentData,
|
||||
'timeout'=> $this->timeout
|
||||
'timeout' => $this->timeout
|
||||
]);
|
||||
|
||||
$responseData = json_decode($payResponse->getBody()->getContents());
|
||||
$responseCode = $payResponse->getStatusCode();
|
||||
|
||||
if($responseCode == 202){
|
||||
if ($responseCode == 202) {
|
||||
$transaction->update([
|
||||
'state' => PaymentTransactionState::ACCEPTED,
|
||||
'aggregator_payment_ref' => $this->getTransactionRef($responseData->message),
|
||||
|
@ -140,40 +140,17 @@ class YoomeeController extends Controller
|
|||
'transaction_id' => $transaction_id,
|
||||
'token' => $transaction->payment_token
|
||||
]);
|
||||
}else{
|
||||
return $this->errorResponse($responseData,$responseCode);
|
||||
} else {
|
||||
return $this->errorResponse($responseData, $responseCode);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->errorResponse(__('errors.unexpected_error'));
|
||||
}
|
||||
|
||||
private function getTransactionRef($message){
|
||||
$needle = 'REF: ';
|
||||
return substr($message,strlen($needle) + strpos($message,$needle));
|
||||
}
|
||||
|
||||
public function capturePaymentResult(Request $request)
|
||||
private function getTransactionRef($message)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'action' => 'required|in:return,cancel',
|
||||
'cpm_trans_id' => 'required|integer|exists:payment_transactions,transaction_id'
|
||||
]);
|
||||
|
||||
$action = $request->input('action');
|
||||
$transaction = PaymentTransaction::find($request->input('PaymentTransaction_id'));
|
||||
if (!isset($transaction)) {
|
||||
return redirect()->to(route('PaymentTransactions.create'))->with('error', __('messages.not_found_payment'));
|
||||
}
|
||||
|
||||
if ($action == 'cancel') {
|
||||
$transaction->update([
|
||||
'state' => PaymentTransactionState::CANCELLED
|
||||
]);
|
||||
return redirect()->to(route('PaymentTransactions.create'))->with('success', __('messages.cancelled_payment'));
|
||||
} else {
|
||||
return $this->getPaymentStatus($transaction, route('PaymentTransactions.create'));
|
||||
}
|
||||
$needle = 'REF: ';
|
||||
return substr($message, strlen($needle) + strpos($message, $needle));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\PaymentTransactionState;
|
||||
use App\Models\PaymentTransaction;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
class YoomeeV2Controller extends Controller
|
||||
{
|
||||
private $client;
|
||||
private $timeout = 60; //In seconds
|
||||
private $isSyncRequest = false ;// Async request
|
||||
|
||||
/**
|
||||
* 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.yoomee_api_v2_url'),
|
||||
'timeout' => $this->timeout,
|
||||
'http_errors' => false
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/yoomee/v2/methods",
|
||||
* summary="Afficher la liste des methodes de paiment de Yoomee",
|
||||
* tags={"Yoomee"},
|
||||
* security={{"api_key":{}}},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="OK",
|
||||
* @OA\JsonContent(
|
||||
* ref="#/components/schemas/ApiResponse",
|
||||
* example = {
|
||||
* "status" : 200,
|
||||
* "response" : {{"Yoomee","MTN","Orange","EU"}},
|
||||
* "error":null
|
||||
* }
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getMethods()
|
||||
{
|
||||
$response = $this->client->get('providers/v1');
|
||||
return $this->successResponse(json_decode($response->getBody()->getContents()));
|
||||
}
|
||||
|
||||
|
||||
public function pay(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'aggregator_id' => 'required|integer|exists:payment_aggregators,id',
|
||||
'amount' => 'required|numeric|min:5',
|
||||
'currency' => 'required|string|size:3',
|
||||
'payment_method' => 'required|string',
|
||||
'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_country' => 'required|string|size:2',
|
||||
'reason' => 'required|string',
|
||||
]);
|
||||
|
||||
$transaction_id = $this->getTransactionID();
|
||||
$payment_method = $request->input('payment_method');
|
||||
$customer_phone_number = $request->input('customer_phone_number');
|
||||
if(str_contains($customer_phone_number,'+237')){
|
||||
$customer_phone_number = substr($customer_phone_number,4);
|
||||
}
|
||||
// Create passport payment
|
||||
$createResponse = $this->client->post('start/v1', [
|
||||
'json' => [
|
||||
'order_merchant' => config('variables.yoomee_username'),
|
||||
'order_merchant_password' => config('variables.yoomee_password'),
|
||||
'order_type' => 'MemberAccount.merchantPaymentWithoutFees',
|
||||
'order_payer' => $customer_phone_number,
|
||||
'order_method' => $payment_method,
|
||||
'order_app_id' => config('variables.yoomee_app_id'),
|
||||
'order_ext_id' => $transaction_id,
|
||||
"order_base_amount" => $request->input('amount'),
|
||||
"order_currency" => $request->input('currency'),
|
||||
"order_description" => $request->input('reason'),
|
||||
"order_wait_final_status" => $this->isSyncRequest
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
if ($createResponse->getStatusCode() == 400) {
|
||||
$createResponse = json_decode($createResponse->getBody()->getContents());
|
||||
|
||||
$transaction = PaymentTransaction::create([
|
||||
'aggregator_id' => $request->input('aggregator_id'),
|
||||
"currency" => $request->input('currency'),
|
||||
'aggregator_payment_ref' => $createResponse->transaction_number,
|
||||
"transaction_id" => $transaction_id,
|
||||
"amount" => $createResponse->transaction_amount,
|
||||
'payment_date' => $createResponse->transaction_date,
|
||||
"payment_method" => $payment_method,
|
||||
'payment_token' => Str::random(32),
|
||||
'state' => strtoupper($createResponse->transaction_status),
|
||||
"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" => $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'),
|
||||
]);
|
||||
|
||||
if($transaction->state == PaymentTransactionState::PENDING){
|
||||
return $this->successResponse([
|
||||
'verification_url' => route('yoomee.v2.webhook',['transaction_id' => $transaction_id])
|
||||
]);
|
||||
}else{
|
||||
return $this->successResponse([
|
||||
'transaction_id' => $transaction_id,
|
||||
'token' => $transaction->payment_token
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->errorResponse(__('errors.unexpected_error'));
|
||||
}
|
||||
|
||||
public function capturePaymentResult(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'transaction_id' => 'required|string|exists:payment_transactions,transaction_id'
|
||||
]);
|
||||
|
||||
$transaction = PaymentTransaction::where('transaction_id',$request->input('transaction_id'))->first();
|
||||
return $this->getPaymentStatus($transaction);
|
||||
}
|
||||
|
||||
private function getPaymentStatus(PaymentTransaction $transaction)
|
||||
{
|
||||
try {
|
||||
$response = $this->client->post('status/v1', [
|
||||
'json' => [
|
||||
'order_merchant' => config('variables.yoomee_username'),
|
||||
'order_merchant_password' => config('variables.yoomee_password'),
|
||||
'order_method' => $transaction->payment_method,
|
||||
'order_app_id' => config('variables.yoomee_app_id'),
|
||||
'order_ext_id' => $transaction->transaction_id,
|
||||
"order_wait_final_status" => $this->isSyncRequest
|
||||
]
|
||||
]);
|
||||
|
||||
$responseData = json_decode($response->getBody()->getContents());
|
||||
$responseCode = $response->getStatusCode();
|
||||
|
||||
if ($responseCode == 400) {
|
||||
|
||||
$state = strtoupper($responseData->transaction_status);
|
||||
if($state == 'SUCCESS'){
|
||||
$state = PaymentTransactionState::ACCEPTED;
|
||||
}else{
|
||||
if(str_starts_with($state,'C')){
|
||||
$state = PaymentTransactionState::REFUSED;
|
||||
}
|
||||
}
|
||||
|
||||
$transaction->update([
|
||||
'state' => $state,
|
||||
'payment_date' => $responseData->transaction_date ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (Throwable $e) {
|
||||
Log::info("Get Yoomee 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,10 @@ return [
|
|||
'swagger_docs_token' => env('SWAGGER_DOCS_TOKEN', true),
|
||||
'yoomee_merchant_code' => env('YOOMEE_MERCHANT_CODE', ''),
|
||||
'yoomee_api_url' => env('YOOMEE_API_URL', ''),
|
||||
'yoomee_api_v2_url' => env('YOOMEE_API_V2_URL', ''),
|
||||
'yoomee_app_id' => env('YOOMEE_APP_ID', ''),
|
||||
'yoomee_username' => env('YOOMEE_USERNAME', ''),
|
||||
'yoomee_password' => env('YOOMEE_PASSWORD', ''),
|
||||
'cinetpay_api_key' => env('CINETPAY_API_KEY', ''),
|
||||
'cinetpay_secret_key' => env('CINETPAY_SECRET_KEY', ''),
|
||||
'cinetpay_site_id' => env('CINETPAY_SITE_ID', ''),
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
/**
|
||||
* Webhooks
|
||||
*/
|
||||
$router->addRoute(['GET','POST'],'/yoomee/webhook', ['as' => 'yoomee.webhook' , 'uses' => 'YoomeeController@capturePaymentResult']);
|
||||
$router->addRoute(['GET','POST'],'/yoomee/v2/webhook', ['as' => 'yoomee.v2.webhook' , 'uses' => 'YoomeeV2Controller@capturePaymentResult']);
|
||||
$router->addRoute(['GET','POST'],'/cinetpay/webhook', ['as' => 'cinetpay.webhook' , 'uses' => 'CinetpayController@capturePaymentResult']);
|
||||
|
||||
$router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($router) {
|
||||
|
@ -24,6 +24,7 @@ $router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($route
|
|||
/**
|
||||
* Entry Endpoints
|
||||
*/
|
||||
$router->post('methods','PaymentController@getMethods');
|
||||
$router->post('pay','PaymentController@pay');
|
||||
|
||||
|
||||
|
@ -31,15 +32,20 @@ $router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($route
|
|||
* Yoomee Endpoints
|
||||
*/
|
||||
$router->group(['prefix' => 'yoomee'], function () use ($router) {
|
||||
$router->get('operators','YoomeeController@getOperators');
|
||||
$router->get('methods',['as' => 'yoomee.methods', 'uses' => 'YoomeeController@getMethods']);
|
||||
$router->addRoute(['GET','POST'],'pay', ['as' => 'yoomee.pay', 'uses' => 'YoomeeController@pay']);
|
||||
|
||||
$router->group(['prefix' => 'v2'] , function () use ($router){
|
||||
$router->get('methods',['as' => 'yoomee.v2.methods', 'uses' => 'YoomeeV2Controller@getMethods']);
|
||||
$router->addRoute(['GET','POST'],'pay', ['as' => 'yoomee.v2.pay', 'uses' => 'YoomeeV2Controller@pay']);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* CinetPay Endpoints
|
||||
*/
|
||||
$router->group(['prefix' => 'cinetpay'], function () use ($router) {
|
||||
$router->get('operators','CinetpayController@getOperators');
|
||||
$router->get('methods',['as' => 'cinetpay.methods', 'uses' => 'CinetpayController@getMethods']);
|
||||
$router->addRoute(['GET','POST'],'pay',['as' => 'cinetpay.pay', 'uses' => 'CinetpayController@pay']);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue