Compare commits
10 Commits
ca61b6bc6f
...
e9db02fcd3
Author | SHA1 | Date |
---|---|---|
|
e9db02fcd3 | |
|
251578adb9 | |
|
5ef2ff4cf4 | |
|
cedd5db6b4 | |
|
1472daa363 | |
|
9f9ad14083 | |
|
1178006d65 | |
|
4de520e861 | |
|
5bdc61414f | |
|
a808210b3a |
|
@ -47,3 +47,5 @@ STRIPE_KEY=pk_test_51NAILHJ6IfmAiBwqd8t8ZL9WjTdcMOSDt46TfLT1DS1VPRTrEY0UC3RDUF0b
|
||||||
STRIPE_SECRET=sk_test_51NAILHJ6IfmAiBwqgblKnBatWzIt3mtMYyw9Tc2RRFWUJJDVJ2VGKCBo3o0eTPCAigLB8lAbPiDiuvQ9Arwg0fad00fv7zIJdY
|
STRIPE_SECRET=sk_test_51NAILHJ6IfmAiBwqgblKnBatWzIt3mtMYyw9Tc2RRFWUJJDVJ2VGKCBo3o0eTPCAigLB8lAbPiDiuvQ9Arwg0fad00fv7zIJdY
|
||||||
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret
|
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret
|
||||||
STRIPE_ACCOUNT=acct_1NAILHJ6IfmAiBwq
|
STRIPE_ACCOUNT=acct_1NAILHJ6IfmAiBwq
|
||||||
|
|
||||||
|
FLW_SECRET_KEY=FLWSECK_TEST-8bf06ec7ac19eb8f045e9f3ebe9dfb97-X
|
||||||
|
|
|
@ -6,6 +6,6 @@ namespace App\Enums;
|
||||||
|
|
||||||
abstract class PaymentMethod
|
abstract class PaymentMethod
|
||||||
{
|
{
|
||||||
const CARD = 'CARD'; // Les remboursements ou recharges vers des clients
|
const CARD = 'CARD';
|
||||||
const WALLET = 'WALLET'; // Les paiements effectués par les clients
|
const WALLET = 'WALLET';
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,4 +12,6 @@ abstract class PaymentTransactionStatus
|
||||||
const PENDING_OTP = 'PENDING_OTP';
|
const PENDING_OTP = 'PENDING_OTP';
|
||||||
const REFUSED = 'REFUSED';
|
const REFUSED = 'REFUSED';
|
||||||
const CANCELLED = 'CANCELLED';
|
const CANCELLED = 'CANCELLED';
|
||||||
|
|
||||||
|
const EXPIRED = 'EXPIRED';
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use Illuminate\Auth\AuthenticationException;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Database\QueryException;
|
use Illuminate\Database\QueryException;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\Lang;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
|
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
|
||||||
|
@ -32,6 +33,7 @@ class Handler extends ExceptionHandler
|
||||||
HttpException::class,
|
HttpException::class,
|
||||||
ModelNotFoundException::class,
|
ModelNotFoundException::class,
|
||||||
ValidationException::class,
|
ValidationException::class,
|
||||||
|
\Stripe\Exception\ApiErrorException::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,17 +111,57 @@ class Handler extends ExceptionHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($exception instanceof ClientException) {
|
if ($exception instanceof ClientException) {
|
||||||
$message = $exception->getResponse()->getBody()->getContents();
|
$response = json_decode($exception->getResponse()->getBody()->getContents());
|
||||||
$code = $exception->getCode();
|
$code = $exception->getCode();
|
||||||
|
|
||||||
Log::error(json_encode($message));
|
return $this->errorResponse($response->message ?? $response , $code);
|
||||||
return $this->errorResponse($message, $code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($exception instanceof ConnectException){
|
if($exception instanceof ConnectException){
|
||||||
return $this->errorResponse(trans('errors.timeout'), Response::HTTP_REQUEST_TIMEOUT);
|
return $this->errorResponse(trans('errors.timeout'), Response::HTTP_REQUEST_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Stripe Exceptions
|
||||||
|
//https://stripe.com/docs/api/errors/handling?lang=php
|
||||||
|
// if($exception instanceof \Stripe\Exception\CardException){
|
||||||
|
// // Since it's a decline, \Stripe\Exception\CardException will be caught
|
||||||
|
// echo 'Status is:' . $exception->getHttpStatus() . '\n';
|
||||||
|
// echo 'Type is:' . $exception->getError()->type . '\n';
|
||||||
|
// echo 'Code is:' . $exception->getError()->code . '\n';
|
||||||
|
// // param is '' in this case
|
||||||
|
// echo 'Param is:' . $exception->getError()->param . '\n';
|
||||||
|
// echo 'Message is:' . $exception->getError()->message . '\n';
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if($exception instanceof \Stripe\Exception\RateLimitException){
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if($exception instanceof \Stripe\Exception\InvalidRequestException){
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if($exception instanceof \Stripe\Exception\AuthenticationException){
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if($exception instanceof \Stripe\Exception\ApiConnectionException){
|
||||||
|
// }
|
||||||
|
|
||||||
|
if($exception instanceof \Stripe\Exception\ApiErrorException){
|
||||||
|
$errorMessage = $exception->getMessage();
|
||||||
|
Log::error("Error Stripe API");
|
||||||
|
|
||||||
|
//https://stripe.com/docs/error-codes
|
||||||
|
//https://stripe.com/docs/declines/codes
|
||||||
|
$code = $exception->getError()->decline_code ?? $exception->getError()->code;
|
||||||
|
if(Lang::has('stripe.'.$code)){
|
||||||
|
Log::error($code);
|
||||||
|
$errorMessage = __('stripe.'.$code);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error($errorMessage);
|
||||||
|
return $this->errorResponse($errorMessage ?? __('errors.unexpected_error'));
|
||||||
|
}
|
||||||
|
|
||||||
// if ($exception instanceof AppException) {
|
// if ($exception instanceof AppException) {
|
||||||
// return $this->errorResponse($exception->getMessage(), $exception->getCode());
|
// return $this->errorResponse($exception->getMessage(), $exception->getCode());
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -78,7 +78,7 @@ class CinetpayController extends Controller
|
||||||
// 'aggregator_id' => 'required|integer',
|
// 'aggregator_id' => 'required|integer',
|
||||||
'amount' => 'required|numeric|min:5',
|
'amount' => 'required|numeric|min:5',
|
||||||
'currency' => 'required|string|size:3',
|
'currency' => 'required|string|size:3',
|
||||||
// 'payment_method' => 'nullable|string|in:ALL,MOBILE_MONEY,CREDIT_CARD,WALLET',
|
'payment_method' => 'nullable|string',
|
||||||
'customer_id' => 'required|integer',
|
'customer_id' => 'required|integer',
|
||||||
'customer_email' => 'required|email',
|
'customer_email' => 'required|email',
|
||||||
'customer_name' => 'nullable|string',
|
'customer_name' => 'nullable|string',
|
||||||
|
@ -92,10 +92,14 @@ class CinetpayController extends Controller
|
||||||
'reason' => 'required|string'
|
'reason' => 'required|string'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$paymentMethods = ['ALL','MOBILE_MONEY','CREDIT_CARD','WALLET'];
|
||||||
$aggregator = PaymentAggregator::where('name','like','%cinetpay%')->firstOrFail();
|
$aggregator = PaymentAggregator::where('name','like','%cinetpay%')->firstOrFail();
|
||||||
|
|
||||||
$transaction_id = $this->getTransactionID();
|
$transaction_id = $this->getTransactionID();
|
||||||
|
$payment_method = $request->input('payment_method');
|
||||||
|
if(!in_array($payment_method, $paymentMethods)){
|
||||||
$payment_method = 'ALL';
|
$payment_method = 'ALL';
|
||||||
|
}
|
||||||
$amount = $request->input('amount');
|
$amount = $request->input('amount');
|
||||||
$currency = $request->input('currency');
|
$currency = $request->input('currency');
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,507 @@
|
||||||
|
<?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 GuzzleHttp\Exception\GuzzleException;
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/flutterwave/methods",
|
||||||
|
* summary="Afficher la liste des methodes de Flutterwave",
|
||||||
|
* tags={"Flutterwave"},
|
||||||
|
* security={{"api_key":{}}},
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="OK",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* ref="#/components/schemas/ApiResponse",
|
||||||
|
* example = {
|
||||||
|
* "status" : 200,
|
||||||
|
* "response" : {"hasWebview": true, "methods": { "MOBILE_MONEY": "Mobile Money", "CREDIT_CARD": "Carte de crédit" }},
|
||||||
|
* "error":null
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function getMethods()
|
||||||
|
{
|
||||||
|
$providers = [
|
||||||
|
// 'ALL',
|
||||||
|
'MOBILE_MONEY',
|
||||||
|
// 'CREDIT_CARD',
|
||||||
|
];
|
||||||
|
$methods = [];
|
||||||
|
foreach ($providers as $provider) {
|
||||||
|
$key = 'providers.' . $provider;
|
||||||
|
$method['title'] = Lang::has($key) ? __($key) : $provider;
|
||||||
|
$method['value'] = $provider;
|
||||||
|
$methods[] = $method;
|
||||||
|
}
|
||||||
|
return $this->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'));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ use App\Models\Country;
|
||||||
use App\Models\PaymentAggregator;
|
use App\Models\PaymentAggregator;
|
||||||
use App\Models\PaymentTransaction;
|
use App\Models\PaymentTransaction;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Lang;
|
use Illuminate\Support\Facades\Lang;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
@ -29,6 +30,8 @@ class PaymentController extends Controller
|
||||||
return app(YoomeeV2Controller::class)->getMethods();
|
return app(YoomeeV2Controller::class)->getMethods();
|
||||||
case 'cinetpay':
|
case 'cinetpay':
|
||||||
return app(CinetpayController::class)->getMethods();
|
return app(CinetpayController::class)->getMethods();
|
||||||
|
case 'flutterwave':
|
||||||
|
return app(FlutterwaveController::class)->getMethods();
|
||||||
default:
|
default:
|
||||||
return $this->errorResponse(__('errors.unexpected_error'));
|
return $this->errorResponse(__('errors.unexpected_error'));
|
||||||
}
|
}
|
||||||
|
@ -38,17 +41,22 @@ class PaymentController extends Controller
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'payment_method' => 'nullable|string',
|
'payment_method' => 'nullable|string',
|
||||||
// 'aggregator_id' => 'required_without:payment_method|integer|exists:payment_aggregators,id',
|
'aggregator_id' => 'nullable|integer|exists:payment_aggregators,id',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$payment_method = $request->input('payment_method', PaymentMethod::CARD);
|
$payment_method = $request->input('payment_method', PaymentMethod::CARD);
|
||||||
|
$aggregator_id = $request->input('aggregator_id');
|
||||||
|
|
||||||
|
if($aggregator_id){
|
||||||
|
$aggregator = PaymentAggregator::findOrFail($aggregator_id);
|
||||||
|
}else{
|
||||||
if($payment_method == PaymentMethod::CARD){
|
if($payment_method == PaymentMethod::CARD){
|
||||||
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
||||||
}else{
|
}else{
|
||||||
$aggregator = PaymentAggregator::where('status',1)->firstOrFail();
|
$aggregator = PaymentAggregator::where('status',1)->firstOrFail();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$data = $request->all();
|
$data = $request->all();
|
||||||
$request = new Request();
|
$request = new Request();
|
||||||
|
@ -63,6 +71,8 @@ class PaymentController extends Controller
|
||||||
return app(YoomeeV2Controller::class)->initPay($request);
|
return app(YoomeeV2Controller::class)->initPay($request);
|
||||||
case 'cinetpay':
|
case 'cinetpay':
|
||||||
return app(CinetpayController::class)->pay($request);
|
return app(CinetpayController::class)->pay($request);
|
||||||
|
case 'flutterwave':
|
||||||
|
return app(FlutterwaveController::class)->pay($request);
|
||||||
case 'stripe':
|
case 'stripe':
|
||||||
return app(StripeController::class)->payIn($request);
|
return app(StripeController::class)->payIn($request);
|
||||||
default:
|
default:
|
||||||
|
@ -83,7 +93,8 @@ class PaymentController extends Controller
|
||||||
$networkName = strtolower($request->input('network_name'));
|
$networkName = strtolower($request->input('network_name'));
|
||||||
|
|
||||||
if(str_contains($networkName,'orange') || str_contains($networkName,'mtn')){
|
if(str_contains($networkName,'orange') || str_contains($networkName,'mtn')){
|
||||||
return app(CinetpayController::class)->payOut($request);
|
// return app(CinetpayController::class)->payOut($request);
|
||||||
|
return app(FlutterwaveController::class)->payOut($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +108,8 @@ class PaymentController extends Controller
|
||||||
|
|
||||||
public function paymentResult(Request $request)
|
public function paymentResult(Request $request)
|
||||||
{
|
{
|
||||||
if($request->has('transaction_id')){
|
$data = $request->all();
|
||||||
return $this->successResponse($request->all());
|
return view('payment-webhook', compact('data'));
|
||||||
}else{
|
|
||||||
return $this->errorResponse($request->all());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkout(Request $request, $payment_token)
|
public function checkout(Request $request, $payment_token)
|
||||||
|
@ -113,14 +121,16 @@ class PaymentController extends Controller
|
||||||
$amount = money($transaction->amount, $transaction->currency)->format(app()->getLocale());
|
$amount = money($transaction->amount, $transaction->currency)->format(app()->getLocale());
|
||||||
$receiver = config('variables.receiver_name');
|
$receiver = config('variables.receiver_name');
|
||||||
$receiver_logo = asset('assets/images/logo.jpeg');
|
$receiver_logo = asset('assets/images/logo.jpeg');
|
||||||
|
$paymentEndpoint = $transaction->payment_endpoint;
|
||||||
|
$paymentVerifyEndpoint = $transaction->payment_verify_endpoint;
|
||||||
|
|
||||||
|
|
||||||
if($transaction->status == PaymentTransactionStatus::INITIATED){
|
if($transaction->status == PaymentTransactionStatus::INITIATED){
|
||||||
return view('checkout',compact('payment_token','method','amount', 'receiver','receiver_logo'));
|
return view('checkout',compact('paymentEndpoint', 'payment_token','method','amount', 'receiver','receiver_logo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($transaction->status == PaymentTransactionStatus::PENDING){
|
if($transaction->status == PaymentTransactionStatus::PENDING){
|
||||||
return view('verify-payment',compact('transaction_id','method','amount', 'receiver','receiver_logo'));
|
return view('verify-payment',compact('paymentVerifyEndpoint','transaction_id','method','amount', 'receiver','receiver_logo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = $transaction->status == PaymentTransactionStatus::ACCEPTED;
|
$status = $transaction->status == PaymentTransactionStatus::ACCEPTED;
|
||||||
|
@ -214,8 +224,36 @@ class PaymentController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws GuzzleException
|
||||||
|
*/
|
||||||
public function checkBalance(Request $request)
|
public function checkBalance(Request $request)
|
||||||
{
|
{
|
||||||
return app(CinetpayController::class)->checkBalance($request);
|
// return app(CinetpayController::class)->checkBalance($request);
|
||||||
|
return app(FlutterwaveController::class)->checkBalance($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function webPaymentRedirection(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->validate($request, [
|
||||||
|
'transaction_id' => 'required|string|exists:payment_transactions,transaction_id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$transaction = PaymentTransaction::where('transaction_id',$request->input('transaction_id'))->first();
|
||||||
|
|
||||||
|
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
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,14 @@ class StripeController extends Controller
|
||||||
return view('stripe-checkout', compact('amount','receiver','receiver_logo','payment_token'));
|
return view('stripe-checkout', compact('amount','receiver','receiver_logo','payment_token'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formulaire de paiement
|
||||||
public function pay(Request $request)
|
public function pay(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'aggregator_id' => 'required|integer',
|
'aggregator_id' => 'required|integer',
|
||||||
'amount' => 'required|numeric|min:5',
|
'amount' => 'required|numeric',
|
||||||
'currency' => 'required|string|size:3',
|
'currency' => 'required|string|size:3',
|
||||||
'customer_id' => 'nullable',
|
'customer_id' => 'nullable',
|
||||||
'payment_method' => 'nullable|string',
|
'payment_method' => 'nullable|string',
|
||||||
|
@ -84,8 +85,8 @@ class StripeController extends Controller
|
||||||
$amount = $request->input('amount');
|
$amount = $request->input('amount');
|
||||||
$currency = $request->input('currency');
|
$currency = $request->input('currency');
|
||||||
|
|
||||||
if($amount < 325 && $currency == 'XAF'){
|
if($amount <= 0 || $this->toMoneyAmount($amount, $currency , 'USD') < 1 ){
|
||||||
$amount = 325;
|
return $this->errorResponse(__('errors.minimum_amount_required'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$payment_token = $this->getTransactionToken();
|
$payment_token = $this->getTransactionToken();
|
||||||
|
@ -199,7 +200,7 @@ class StripeController extends Controller
|
||||||
$transaction = PaymentTransaction::where('transaction_id', $request->input('transaction_id'))->where('status', PaymentTransactionStatus::ACCEPTED)->firstOrFail();
|
$transaction = PaymentTransaction::where('transaction_id', $request->input('transaction_id'))->where('status', PaymentTransactionStatus::ACCEPTED)->firstOrFail();
|
||||||
$reason = $request->input('reason','requested_by_customer');
|
$reason = $request->input('reason','requested_by_customer');
|
||||||
|
|
||||||
try{
|
|
||||||
$reference = $transaction->aggregator_payment_ref;
|
$reference = $transaction->aggregator_payment_ref;
|
||||||
$twoFirstChars = substr($reference,0,2);
|
$twoFirstChars = substr($reference,0,2);
|
||||||
$keyToRefund = $twoFirstChars == 'ch' ? 'charge' : 'payment_intent';
|
$keyToRefund = $twoFirstChars == 'ch' ? 'charge' : 'payment_intent';
|
||||||
|
@ -222,17 +223,13 @@ class StripeController extends Controller
|
||||||
return $this->successResponse("Payment refunded successfully");
|
return $this->successResponse("Payment refunded successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (Throwable $e){
|
|
||||||
Log::error("Error Stripe refund");
|
|
||||||
$errorMessage = $e->getMessage();
|
|
||||||
Log::error($errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->errorResponse($errorMessage ?? __('errors.unexpected_error'));
|
return $this->errorResponse(__('errors.unexpected_error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Encaissement de l'argent des clients
|
||||||
public function payIn(Request $request)
|
public function payIn(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
|
@ -241,7 +238,7 @@ class StripeController extends Controller
|
||||||
'exp_year' => 'required',
|
'exp_year' => 'required',
|
||||||
'cvc' => 'required',
|
'cvc' => 'required',
|
||||||
// 'aggregator_id' => 'required|integer',
|
// 'aggregator_id' => 'required|integer',
|
||||||
'amount' => 'required|numeric|min:5',
|
'amount' => 'required|numeric',
|
||||||
'currency' => 'required|string|size:3',
|
'currency' => 'required|string|size:3',
|
||||||
'customer_id' => 'nullable',
|
'customer_id' => 'nullable',
|
||||||
// 'payment_method' => 'nullable|string', // Actuallu it's only CARD
|
// 'payment_method' => 'nullable|string', // Actuallu it's only CARD
|
||||||
|
@ -260,13 +257,11 @@ class StripeController extends Controller
|
||||||
|
|
||||||
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
$amount = $request->input('amount');
|
$amount = $request->input('amount');
|
||||||
$currency = $request->input('currency');
|
$currency = $request->input('currency');
|
||||||
|
|
||||||
if($amount < 325 && $currency == 'XAF'){
|
if($amount <= 0 || $this->toMoneyAmount($amount, $currency , 'USD') < 1 ){
|
||||||
$amount = 325;
|
return $this->errorResponse(__('errors.minimum_amount_required'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -342,22 +337,16 @@ class StripeController extends Controller
|
||||||
], ResponseAlias::HTTP_MOVED_PERMANENTLY);
|
], ResponseAlias::HTTP_MOVED_PERMANENTLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->handlePaymentIntentResult($transaction, $paymentIntent);
|
return $this->handlePaymentIntentResult($transaction, $paymentIntent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->errorResponse(__('errors.unexpected_error'));
|
||||||
}catch (Throwable $e){
|
|
||||||
Log::error("Error Stripe submit payment intent");
|
|
||||||
$errorMessage = $e->getMessage();
|
|
||||||
Log::error($errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->errorResponse($errorMessage ?? __('errors.unexpected_error'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Recharge des comptes clients
|
||||||
public function payOut(Request $request)
|
public function payOut(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
|
@ -369,7 +358,7 @@ class StripeController extends Controller
|
||||||
'bank_currency' => 'required_if:payment_method,BANK|string|size:3',
|
'bank_currency' => 'required_if:payment_method,BANK|string|size:3',
|
||||||
'bank_account_number' => 'required_if:payment_method,BANK|string',
|
'bank_account_number' => 'required_if:payment_method,BANK|string',
|
||||||
// 'aggregator_id' => 'required|integer',
|
// 'aggregator_id' => 'required|integer',
|
||||||
'amount' => 'required|numeric|min:5',
|
'amount' => 'required|numeric',
|
||||||
'currency' => 'required|string|size:3',
|
'currency' => 'required|string|size:3',
|
||||||
'customer_id' => 'nullable',
|
'customer_id' => 'nullable',
|
||||||
'payment_method' => 'required|string|in:CARD,BANK',
|
'payment_method' => 'required|string|in:CARD,BANK',
|
||||||
|
@ -388,12 +377,14 @@ class StripeController extends Controller
|
||||||
|
|
||||||
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
$aggregator = PaymentAggregator::where('name','like','%stripe%')->firstOrFail();
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
$amount = $request->input('amount');
|
$amount = $request->input('amount');
|
||||||
$currency = $request->input('currency');
|
$currency = $request->input('currency');
|
||||||
$payment_method = $request->input('payment_method');
|
$payment_method = $request->input('payment_method');
|
||||||
|
|
||||||
|
if($amount <= 0 || $this->toMoneyAmount($amount, $currency , 'USD') < 1 ){
|
||||||
|
return $this->errorResponse(__('errors.minimum_amount_required'));
|
||||||
|
}
|
||||||
|
|
||||||
$transaction = PaymentTransaction::create([
|
$transaction = PaymentTransaction::create([
|
||||||
'aggregator_id' => $aggregator->id,
|
'aggregator_id' => $aggregator->id,
|
||||||
"currency" => $request->input('currency'),
|
"currency" => $request->input('currency'),
|
||||||
|
@ -475,15 +466,7 @@ class StripeController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->errorResponse(__('errors.unexpected_error'));
|
||||||
|
|
||||||
}catch (Throwable $e){
|
|
||||||
Log::error("Error Stripe submit payment intent");
|
|
||||||
$errorMessage = $e->getMessage();
|
|
||||||
Log::error($errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->errorResponse($errorMessage ?? __('errors.unexpected_error'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -506,18 +489,24 @@ class StripeController extends Controller
|
||||||
return $this->errorResponse(__('errors.unexpected_error'));
|
return $this->errorResponse(__('errors.unexpected_error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handlePaymentIntentResult(PaymentTransaction $transaction, PaymentIntent $intent){
|
private function handlePaymentIntentResult(PaymentTransaction $transaction, PaymentIntent $intent , bool $returnView = true){
|
||||||
|
|
||||||
if($intent->status == 'succeeded'){
|
if($intent->status == 'succeeded'){
|
||||||
$transaction->update([
|
$transaction->update([
|
||||||
'status' => PaymentTransactionStatus::ACCEPTED
|
'status' => PaymentTransactionStatus::ACCEPTED
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()->route('paymentResult',[
|
$data = [
|
||||||
'message' => 'Payment Accepted',
|
'message' => 'Payment Accepted',
|
||||||
'transaction_id' => $transaction->transaction_id,
|
'transaction_id' => $transaction->transaction_id,
|
||||||
'status' => 1
|
'status' => 1
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if($returnView){
|
||||||
|
return redirect()->route('paymentResult',$data);
|
||||||
|
}else{
|
||||||
|
return $this->successResponse($data);
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
@ -525,10 +514,17 @@ class StripeController extends Controller
|
||||||
'status' => strtolower($intent->status)
|
'status' => strtolower($intent->status)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()->route('paymentResult', [
|
$data = [
|
||||||
'message' => "Payment ".$transaction->status,
|
'message' => "Payment ".$transaction->status,
|
||||||
'status' => 0
|
'status' => 0
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if($returnView){
|
||||||
|
return redirect()->route('paymentResult', $data);
|
||||||
|
}else{
|
||||||
|
return $this->errorResponse($data);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,363 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Enums\PaymentMethod;
|
||||||
|
use App\Enums\PaymentTransactionStatus;
|
||||||
|
use App\Models\PaymentAggregator;
|
||||||
|
use App\Models\PaymentTransaction;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
|
use GuzzleHttp\MessageFormatter;
|
||||||
|
use GuzzleHttp\Middleware;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Lang;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class YnoteOrangeController extends Controller
|
||||||
|
{
|
||||||
|
private $client;
|
||||||
|
private $timeout = 60; //In seconds
|
||||||
|
private $isSyncRequest = false ;// Async request
|
||||||
|
|
||||||
|
private $username = 'iJ7hLnkD8sYddWGV2ZzT7bbsKQMa';
|
||||||
|
private $password = 'gglK1uIj8WGyVUcCEimoI_Cm0o4a';
|
||||||
|
private $channelUserMsisdn = '659923684';
|
||||||
|
private $PIN = '1468';
|
||||||
|
private $X_AUTH_TOKEN = 'WU5PVEVIRUFEOllOT1RFSEVBRDIwMjA=';
|
||||||
|
|
||||||
|
private $baseURL = 'https://api-s1.orange.cm';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Create a client with a base URI
|
||||||
|
$this->client = new Client([
|
||||||
|
'base_uri' => $this->baseURL,
|
||||||
|
'timeout' => $this->timeout,
|
||||||
|
'http_errors' => false,
|
||||||
|
'verify' => false, // Disable SSL Certification verification
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/ynote/methods",
|
||||||
|
* summary="Afficher la liste des methodes de paiment de Ynote",
|
||||||
|
* tags={"Ynote"},
|
||||||
|
* security={{"api_key":{}}},
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="OK",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* ref="#/components/schemas/ApiResponse",
|
||||||
|
* example = {
|
||||||
|
* "status" : 200,
|
||||||
|
* "response" : {"hasWebview": true, "methods": {"Orange": "Orange"}},
|
||||||
|
* "error":null
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function getMethods()
|
||||||
|
{
|
||||||
|
return $this->successResponse([
|
||||||
|
'hasWebview' => true,
|
||||||
|
'methods' => [
|
||||||
|
'Orange' => 'Orange'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Init payment and provide iLink World checkout page to handle payment
|
||||||
|
*/
|
||||||
|
public function initPay(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
// 'aggregator_id' => 'required|integer|exists:payment_aggregators,id',
|
||||||
|
'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',
|
||||||
|
'customer_country' => 'required|string|size:2',
|
||||||
|
'reason' => 'required|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$aggregator = PaymentAggregator::where('name','like','%ynote%')->firstOrFail();
|
||||||
|
|
||||||
|
$transaction_id = $this->getTransactionID();
|
||||||
|
$payment_method = 'Orange';
|
||||||
|
$customer_phone_number = $request->input('customer_phone_number');
|
||||||
|
if(str_contains($customer_phone_number,'+237')){
|
||||||
|
$customer_phone_number = substr($customer_phone_number,4);
|
||||||
|
}
|
||||||
|
|
||||||
|
do{
|
||||||
|
$payment_token = Str::random(64);
|
||||||
|
}while(PaymentTransaction::where('payment_token', $payment_token)->exists());
|
||||||
|
|
||||||
|
|
||||||
|
$payment_url = route('checkout',['payment_token' => $payment_token]);
|
||||||
|
|
||||||
|
PaymentTransaction::create([
|
||||||
|
'aggregator_id' => $aggregator->id,
|
||||||
|
"currency" => $request->input('currency'),
|
||||||
|
"transaction_id" => $transaction_id,
|
||||||
|
"amount" => $request->input('amount'),
|
||||||
|
"payment_method" => $payment_method,
|
||||||
|
"payment_url" => $payment_url,
|
||||||
|
'payment_token' => $payment_token,
|
||||||
|
'status' => PaymentTransactionStatus::INITIATED,
|
||||||
|
"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'),
|
||||||
|
"payment_endpoint" => route('ynote.checkoutPay'),
|
||||||
|
"payment_verify_endpoint" => route('ynote.status'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->successResponse([
|
||||||
|
'message' => 'Payment initiated',
|
||||||
|
'payment_url' => $payment_url
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkoutPay(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'payment_token' => 'required|string|exists:payment_transactions,payment_token',
|
||||||
|
'phone_number' => 'required|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$token = $request->input('payment_token');
|
||||||
|
$transaction = PaymentTransaction::where('payment_token', $token)
|
||||||
|
->where('status', PaymentTransactionStatus::INITIATED)->firstOrFail();
|
||||||
|
|
||||||
|
|
||||||
|
$customer_phone_number = $request->input('phone_number');
|
||||||
|
if(str_contains($customer_phone_number,'+237')){
|
||||||
|
$customer_phone_number = substr($customer_phone_number,4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get Access Token
|
||||||
|
$accessTokenResponse = $this->client->post('/token', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Basic '.base64_encode($this->username.':'.$this->password),
|
||||||
|
],
|
||||||
|
'form_params' => [
|
||||||
|
'grant_type' => 'client_credentials',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$responseBody = json_decode($accessTokenResponse->getBody()->getContents());
|
||||||
|
|
||||||
|
if ($accessTokenResponse->getStatusCode() == 200) {
|
||||||
|
|
||||||
|
$accessToken = $responseBody->access_token;
|
||||||
|
|
||||||
|
// Init Payment
|
||||||
|
$initResponse = $this->client->post('/omcoreapis/1.0.2/mp/init', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Bearer '.$accessToken,
|
||||||
|
'X-AUTH-TOKEN' => $this->X_AUTH_TOKEN
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$responseBody = json_decode($initResponse->getBody()->getContents());
|
||||||
|
|
||||||
|
if ($initResponse->getStatusCode() == 200) {
|
||||||
|
|
||||||
|
$payToken = $responseBody->data->payToken;
|
||||||
|
|
||||||
|
// Make Payment
|
||||||
|
$makeResponse = $this->client->post('/omcoreapis/1.0.2/mp/pay', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Bearer ' . $accessToken,
|
||||||
|
'X-AUTH-TOKEN' => $this->X_AUTH_TOKEN
|
||||||
|
],
|
||||||
|
'json' => [
|
||||||
|
'notifUrl' => 'http://28f8-102-244-222-34.ngrok-free.app/ynote/webhook' ,// route('ynote.webhook'),
|
||||||
|
'channelUserMsisdn' => $this->channelUserMsisdn,
|
||||||
|
'pin' => $this->PIN,
|
||||||
|
'amount' => ''.intval(ceil(floatval($transaction->amount))),
|
||||||
|
'subscriberMsisdn' => $customer_phone_number,
|
||||||
|
'orderId' => $transaction->transaction_id,
|
||||||
|
'description' => $transaction->reason,
|
||||||
|
'payToken' => $payToken
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$responseBody = json_decode($makeResponse->getBody()->getContents());
|
||||||
|
if ($makeResponse->getStatusCode() == 200) {
|
||||||
|
|
||||||
|
$transaction->update([
|
||||||
|
'aggregator_payment_ref' => $responseBody->data->txnid,
|
||||||
|
'aggregator_payment_token' => $payToken,
|
||||||
|
'status' => strtoupper($responseBody->data->status),
|
||||||
|
"customer_phone_number" => $customer_phone_number,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('checkout',['payment_token' => $token]);
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
//If error regenerate transaction id to avoid 'Numero de commande deja utilisé'
|
||||||
|
$transaction->update([
|
||||||
|
'transaction_id' => $this->getTransactionID()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($responseBody->error)){
|
||||||
|
//Convert into single line
|
||||||
|
session()->flash('error',str_replace(array("\n", "\r"), '',$responseBody->error_description));
|
||||||
|
return redirect()->route('checkout',['payment_token' => $token]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error(json_encode($responseBody));
|
||||||
|
session()->flash('error',__('errors.unexpected_error'));
|
||||||
|
return redirect()->route('checkout',['payment_token' => $token]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function capturePaymentResult(Request $request)
|
||||||
|
{
|
||||||
|
Log::info("capture");
|
||||||
|
Log::warning(json_encode($request->all()));
|
||||||
|
|
||||||
|
$this->validate($request, [
|
||||||
|
'txnid' => 'required|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$transaction = PaymentTransaction::where('aggregator_payment_ref',$request->input('txnid'))->first();
|
||||||
|
return $this->getPaymentStatus($transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaymentStatus(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'transaction_id' => 'required|string|exists:payment_transactions,transaction_id',
|
||||||
|
'verify_btn' => 'nullable|boolean'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$transaction = PaymentTransaction::where('transaction_id',$request->input('transaction_id'))->first();
|
||||||
|
$verify_btn = $request->input('verify_btn');
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Si le paiement fait plus de 5 min on l'annule
|
||||||
|
if($transaction->status == PaymentTransactionStatus::PENDING && $transaction->created_at->diffInMinutes(Carbon::now()) > 5){
|
||||||
|
$transaction->update([
|
||||||
|
'status' => PaymentTransactionStatus::CANCELLED
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Access Token
|
||||||
|
$accessTokenResponse = $this->client->post('/token', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Basic '.base64_encode($this->username.':'.$this->password),
|
||||||
|
],
|
||||||
|
'form_params' => [
|
||||||
|
'grant_type' => 'client_credentials',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$responseBody = json_decode($accessTokenResponse->getBody()->getContents());
|
||||||
|
|
||||||
|
if ($accessTokenResponse->getStatusCode() == 200) {
|
||||||
|
|
||||||
|
$accessToken = $responseBody->access_token;
|
||||||
|
|
||||||
|
$response = $this->client->get('/omcoreapis/1.0.2/mp/paymentstatus/'.$transaction->aggregator_payment_token, [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Bearer '.$accessToken,
|
||||||
|
'X-AUTH-TOKEN' => $this->X_AUTH_TOKEN
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$responseData = json_decode($response->getBody()->getContents());
|
||||||
|
$responseCode = $response->getStatusCode();
|
||||||
|
|
||||||
|
Log::info(json_encode($responseData));
|
||||||
|
Log::info(json_encode($responseCode));
|
||||||
|
Log::info(json_encode([
|
||||||
|
'Authorization' => 'Bearer '.$accessToken,
|
||||||
|
'X-AUTH-TOKEN' => $this->X_AUTH_TOKEN
|
||||||
|
]));
|
||||||
|
|
||||||
|
Log::info(json_encode($transaction->aggregator_payment_token));
|
||||||
|
|
||||||
|
Log::info("Veriication de paement");
|
||||||
|
if ($responseCode == 200) {
|
||||||
|
|
||||||
|
$status = strtoupper($responseData->data->status);
|
||||||
|
if(str_contains($status,'SUCCESS')){
|
||||||
|
$status = PaymentTransactionStatus::ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$transaction->update([
|
||||||
|
'status' => $status,
|
||||||
|
'payment_date' => $responseData->data->transaction_date ?? null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::info("Get Ynote Payment Status Error");
|
||||||
|
Log::info($e);
|
||||||
|
$transaction->update([
|
||||||
|
'status' => PaymentTransactionStatus::REFUSED
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($verify_btn){
|
||||||
|
return redirect()->route('checkout',['payment_token' => $transaction->payment_token]);
|
||||||
|
}else {
|
||||||
|
Log::warning($transaction->status);
|
||||||
|
if ($transaction->status == PaymentTransactionStatus::ACCEPTED) {
|
||||||
|
return [
|
||||||
|
'message' => "Payment accepted",
|
||||||
|
'status' => 1,
|
||||||
|
'refresh' => true,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
'message' => "Payment failed",
|
||||||
|
'status' => 0,
|
||||||
|
'refresh' => $transaction->status == PaymentTransactionStatus::PENDING
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -127,6 +127,8 @@ class YoomeeV2Controller extends Controller
|
||||||
"customer_country" => $request->input('customer_country'),
|
"customer_country" => $request->input('customer_country'),
|
||||||
"customer_state" => $request->input('customer_state'),
|
"customer_state" => $request->input('customer_state'),
|
||||||
"customer_zip_code" => $request->input('customer_zip_code'),
|
"customer_zip_code" => $request->input('customer_zip_code'),
|
||||||
|
"payment_endpoint" => route('yoomee.v2.checkoutPay'),
|
||||||
|
"payment_verify_endpoint" => route('yoomee.v2.status'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $this->successResponse([
|
return $this->successResponse([
|
||||||
|
@ -333,15 +335,11 @@ class YoomeeV2Controller extends Controller
|
||||||
$status = strtoupper($responseData->transaction_status);
|
$status = strtoupper($responseData->transaction_status);
|
||||||
if($status == 'SUCCESS'){
|
if($status == 'SUCCESS'){
|
||||||
$status = PaymentTransactionStatus::ACCEPTED;
|
$status = PaymentTransactionStatus::ACCEPTED;
|
||||||
}else{
|
|
||||||
if(str_starts_with($status,'C')){
|
|
||||||
$status = PaymentTransactionStatus::REFUSED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->update([
|
$transaction->update([
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'payment_date' => $responseData->transaction_date ?? null,
|
'payment_date' => $responseData->data->transaction_date ?? null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,27 +372,4 @@ class YoomeeV2Controller extends Controller
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function merchantRedirect(Request $request)
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->validate($request, [
|
|
||||||
'transaction_id' => 'required|string|exists:payment_transactions,transaction_id'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$transaction = PaymentTransaction::where('transaction_id',$request->input('transaction_id'))->first();
|
|
||||||
|
|
||||||
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
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,6 @@ class VerifyCsrfToken {
|
||||||
protected function tokensMatch($request) {
|
protected function tokensMatch($request) {
|
||||||
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
|
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
|
||||||
|
|
||||||
Log::info($token);
|
|
||||||
Log::error($request->session()->token());
|
|
||||||
|
|
||||||
if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
|
if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
|
||||||
$token = $this->encrypter->decrypt($header);
|
$token = $this->encrypter->decrypt($header);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,8 @@ class PaymentTransaction extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'payment_transactions';
|
protected $table = 'payment_transactions';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $dates = [
|
||||||
|
'payment_date'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,7 @@ return [
|
||||||
'stripe_secret' => env('STRIPE_SECRET', ''),
|
'stripe_secret' => env('STRIPE_SECRET', ''),
|
||||||
'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', ''),
|
'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', ''),
|
||||||
'stripe_account' => env('STRIPE_ACCOUNT', ''),
|
'stripe_account' => env('STRIPE_ACCOUNT', ''),
|
||||||
|
'flw_secret_key' => env('FLW_SECRET_KEY', ''),
|
||||||
|
'ynote_username' => env('YNOTE_USERNAME', ''),
|
||||||
|
'ynote_password' => env('YNOTE_PASSWORD', ''),
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('payment_transactions', function (Blueprint $table) {
|
||||||
|
$table->dateTime('payment_date')->nullable()->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('payment_transactions', function (Blueprint $table) {
|
||||||
|
$table->string('payment_date')->nullable()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('payment_transactions', function (Blueprint $table) {
|
||||||
|
$table->string('aggregator_payment_token')->after('aggregator_payment_ref')->nullable();
|
||||||
|
$table->string('payment_endpoint')->after('status')->nullable();
|
||||||
|
$table->string('payment_verify_endpoint')->after('payment_endpoint')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('payment_transactions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['aggregator_payment_token','payment_endpoint','payment_verify_endpoint']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -6,6 +6,6 @@ return [
|
||||||
'service_unavailable' => 'Service unavailable',
|
'service_unavailable' => 'Service unavailable',
|
||||||
'timeout' => "The server did not receive a complete response within the timeout period. Please Try again later",
|
'timeout' => "The server did not receive a complete response within the timeout period. Please Try again later",
|
||||||
'network_not_taken' => "Network not taken into account",
|
'network_not_taken' => "Network not taken into account",
|
||||||
'service_unavailable_try_later' => "Service not available. please try again later"
|
'service_unavailable_try_later' => "Service not available. please try again later",
|
||||||
|
'minimum_amount_required' => "Transaction amount is less than the minimum authorized amount"
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
//https://gist.github.com/Ladinstar/4655e57bd25099c553956280270b3c83
|
||||||
|
return [
|
||||||
|
"account_closed" => "The customer's bank account has been closed",
|
||||||
|
"account_already_exists" => "Account with that email already exists",
|
||||||
|
"account_country_invalid_address" => "The country of the account or business address is invalid for the account's country",
|
||||||
|
"account_error_country_change_requires_additional_steps" => "Your account has already onboarded as a Connect platform",
|
||||||
|
"account_information_mismatch" => "Account information mismatches with one another",
|
||||||
|
"account_invalid" => "Invalid account ID",
|
||||||
|
"account_number_invalid" => "The bank account number provided is invalid (e.g., missing digits)",
|
||||||
|
"amount_too_large" => "The specified amount is greater than the maximum amount allowed. Use a lower amount and try again",
|
||||||
|
"amount_too_small" => "The specified amount is less than the minimum amount allowed. Use a higher amount and try again",
|
||||||
|
"api_key_expired" => "The API key provided has expired",
|
||||||
|
"authentication_required" => "Authentication required for this action",
|
||||||
|
"balance_insufficient" => "Insufficient balance to perform the requested action",
|
||||||
|
"bank_account_bad_routing_numbers" => "The bank account is known to not support the currency in question",
|
||||||
|
"bank_account_declined" => "The bank account provided can not be used to charge, either because it is not verified yet or it is not supported",
|
||||||
|
"debit_not_authorized" => "The customer has notified their bank that this payment was unauthorized.",
|
||||||
|
"card_declined" => "The card has been declined",
|
||||||
|
"card_decline_rate_limit_exceeded" => "This card has been declined too many times. You can try to charge this card again after 24 hours",
|
||||||
|
"cardholder_phone_number_required" => "You must have a phone number on file for Issuing Cardholders who will be creating EU cards",
|
||||||
|
"expired_card" => "The card has expired. Check the expiration date or use a different card.",
|
||||||
|
"incorrect_cvc" => "The card's security code is incorrect. Check the card's address or use a different card.",
|
||||||
|
"incorrect_address" => "The card's address is incorrect. Check the card's address or use a different card.",
|
||||||
|
"incorrect_zip" => "The card's postal code is incorrect. Check the card's postal code or use a different card.",
|
||||||
|
"insufficient_funds" => "The customer's account has insufficient funds to cover this payment.",
|
||||||
|
"invalid_charge_amount" => "The specified amount is invalid",
|
||||||
|
"invalid_cvc" => "The card's security code is invalid. Check the card's security code or use a different card.",
|
||||||
|
"invalid_expiry_month" => "The card's expiration month is incorrect. Check the expiration date or use a different card.",
|
||||||
|
"invalid_expiry_year" => "The card's expiration year is incorrect. Check the expiration date or use a different card.",
|
||||||
|
"invalid_number" => "The card number is invalid. Check the card details or use a different card.",
|
||||||
|
"processing_error" => "An error occurred while processing the card. Try again later or with a different payment method.",
|
||||||
|
"generic_decline" => "The card has been declined for an unknown reason",
|
||||||
|
"lost_card" => "Payment has been declined, as the bank card has been reported lost.",
|
||||||
|
"merchant_blacklist" => "The payment has been refused, because it matches an entry in the blocklist",
|
||||||
|
"not_permitted" => "The payment is not authorized",
|
||||||
|
"try_again_later" => "The card has been refused for an unknown reason.",
|
||||||
|
"stolen_card" => "Payment has been refused because the bank card has been reported stolen.",
|
||||||
|
"pin_try_exceeded" => "The number of authorized attempts to enter the PIN code has been exceeded.",
|
||||||
|
"offline_pin_required" => "The card has been refused, as it requires a PIN code.",
|
||||||
|
"online_or_offline_pin_required" => "The card has been refused because it requires a PIN code.",
|
||||||
|
"fraudulent" => "The payment has been refused because it has been identified as potentially fraudulent.",
|
||||||
|
"currency_not_supported" => "The specified currency is not supported by this bank card.",
|
||||||
|
"card_velocity_exceeded" => "The customer has exceeded the balance or credit limit available on their bank card.",
|
||||||
|
"card_not_supported" => "This type of payment is not supported by this bank card.",
|
||||||
|
"call_issuer" => "The card has been declined for an unknown reason.",
|
||||||
|
"approve_with_id" => "It is not possible to authorize the payment",
|
||||||
|
"duplicate_transaction" => "A transaction for the same amount with the same credit card information was submitted just recently.",
|
||||||
|
"issuer_not_available" => "The card issuer cannot be reached, so the payment cannot be authorized.",
|
||||||
|
"new_account_information_available" => "The bank card, or the account to which it is connected, is invalid.",
|
||||||
|
"no_action_taken" => "The card has been declined for an unknown reason.",
|
||||||
|
"pickup_card" => "The customer cannot use this card to make this payment (it may have been reported lost or stolen).",
|
||||||
|
"withdrawal_count_limit_exceeded" => "The customer has exceeded the balance or credit limit available on his bank card.",
|
||||||
|
"transaction_not_allowed" => "The card has been refused for an unknown reason.",
|
||||||
|
"testmode_decline" => "The card used is a test card"
|
||||||
|
];
|
|
@ -6,5 +6,6 @@ return [
|
||||||
'service_unavailable' => 'Service non disponible',
|
'service_unavailable' => 'Service non disponible',
|
||||||
'timeout' => "Le serveur n'a pas reçu de réponse complete dans le délai imparti. Essayer plus tard",
|
'timeout' => "Le serveur n'a pas reçu de réponse complete dans le délai imparti. Essayer plus tard",
|
||||||
'network_not_taken' => "Réseau non pris en compte",
|
'network_not_taken' => "Réseau non pris en compte",
|
||||||
'service_unavailable_try_later' => "Service non disponible. Veuillez réessayer plus tard"
|
'service_unavailable_try_later' => "Service non disponible. Veuillez réessayer plus tard",
|
||||||
|
'minimum_amount_required' => "Le montant de la transaction est inférieur au montant minimal autorisé"
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
//https://gist.github.com/Ladinstar/4655e57bd25099c553956280270b3c83
|
||||||
|
return [
|
||||||
|
"account_closed" => "Le compte bancaire du client a été clôturé",
|
||||||
|
"account_already_exists" => "Le compte avec cet email existe déjà",
|
||||||
|
"account_country_invalid_address" => "Le pays de l'adresse du compte ou de l'entreprise n'est pas valide pour le pays du compte",
|
||||||
|
"account_error_country_requires_additional_steps" => "Your account has already onboarded as a Connect platform",
|
||||||
|
"account_information_mismatch" => "Les informations du compte ne correspondent pas entre elles",
|
||||||
|
"account_invalid" => "ID de compte invalide",
|
||||||
|
"account_number_invalid" => "Le numéro de compte bancaire fourni n'est pas valide (par exemple, chiffres manquants)",
|
||||||
|
"amount_too_large" => "Le montant spécifié est supérieur au montant maximum autorisé. Utilisez un montant inférieur et réessayez",
|
||||||
|
"amount_too_small" => "Le montant spécifié est inférieur au montant minimum autorisé. Utilisez un montant plus élevé et réessayez",
|
||||||
|
"api_key_expired" => "La clé API fournie a expiré",
|
||||||
|
"authentication_required" => "Authentification requise pour cette action",
|
||||||
|
"balance_insufficient" => "Solde insuffisant pour effectuer l'action demandée",
|
||||||
|
"bank_account_bad_routing_numbers" => "Le compte bancaire est connu pour ne pas supporter la devise en question",
|
||||||
|
"bank_account_declined" => "Le compte bancaire fourni ne peut pas être utilisé pour débiter, soit parce qu'il n'est pas encore vérifié, soit parce qu'il n'est pas pris en charge",
|
||||||
|
"debit_not_authorized" => "Le client a notifié à sa banque que ce paiement n'était pas autorisé",
|
||||||
|
"card_declined" => "La carte a été refusée",
|
||||||
|
"card_decline_rate_limit_exceeded" => "Cette carte a été refusée trop souvent. Vous pouvez essayer de recharger cette carte après 24 heures",
|
||||||
|
"cardholder_phone_number_required" => "Vous devez disposer d'un numéro de téléphone pour les titulaires de cartes qui créeront des cartes UE",
|
||||||
|
"expired_card" => "La carte a expiré. Vérifiez la date d'expiration ou utilisez une autre carte",
|
||||||
|
"incorrect_cvc" => "Le code de sécurité de la carte est incorrect. Vérifiez l'adresse de la carte ou utilisez une autre carte",
|
||||||
|
"incorrect_address" => "L'adresse de la carte est incorrecte. Vérifiez l'adresse de la carte ou utilisez une autre carte.",
|
||||||
|
"incorrect_zip" => "Le code postal de la carte est incorrect. Vérifiez le code postal de la carte ou utilisez une autre carte.",
|
||||||
|
"insufficient_funds" => "Le compte du client n'est pas suffisamment approvisionné pour couvrir ce paiement",
|
||||||
|
"invalid_charge_amount" => "Le montant spécifié n'est pas valide",
|
||||||
|
"invalid_cvc" => "Le code de sécurité de la carte n'est pas valide. Vérifiez le code de sécurité de la carte ou utilisez une autre carte",
|
||||||
|
"invalid_expiry_month" => "Le mois d'expiration de la carte est incorrect. Vérifiez la date d'expiration ou utilisez une autre carte.",
|
||||||
|
"invalid_expiry_year" => "L'année d'expiration de la carte est incorrecte. Vérifiez la date d'expiration ou utilisez une autre carte.",
|
||||||
|
"invalid_number" => "Le numéro de la carte n'est pas valide. Vérifiez les détails de la carte ou utilisez une autre carte.",
|
||||||
|
"processing_error" => "Une erreur s'est produite lors du traitement de la carte. Réessayez plus tard ou avec une autre méthode de paiement.",
|
||||||
|
"generic_decline" => "La carte a été refusée pour une raison inconnue",
|
||||||
|
"lost_card" => "Le paiement a été refusé, car la carte bancaire a été déclarée perdue.",
|
||||||
|
"merchant_blacklist" => "Le paiement a été refusé, car il correspond à une entrée de la liste de blocage",
|
||||||
|
"not_permitted" => "Le paiement n'est pas autorisé.",
|
||||||
|
"try_again_later" => "La carte a été refusée pour une raison inconnue.",
|
||||||
|
"stolen_card" => "Le paiement a été refusé, car la carte bancaire a été déclarée volée.",
|
||||||
|
"pin_try_exceeded" => "Le nombre de tentatives autorisées de saisie du code PIN a été dépassé.",
|
||||||
|
"offline_pin_required" => "La carte a été refusée, car elle nécessite un code PIN.",
|
||||||
|
"online_or_offline_pin_required" => "La carte a été refusée, car elle nécessite un code PIN.",
|
||||||
|
"fraudulent" => "Le paiement a été refusé car identifié comme potentiellement frauduleux.",
|
||||||
|
"currency_not_supported" => "La devise spécifiée n'est pas prise en charge par cette carte bancaire.",
|
||||||
|
"card_velocity_exceeded" => "Le client a dépassé le solde ou la limite de crédit disponible sur sa carte bancaire.",
|
||||||
|
"card_not_supported" => "Ce type de paiement n'est pas pris en charge par cette carte bancaire.",
|
||||||
|
"call_issuer" => "La carte a été refusée pour une raison inconnue.",
|
||||||
|
"approve_with_id" => "Il n'est pas possible d'autoriser le paiement",
|
||||||
|
"duplicate_transaction" => "Une transaction du même montant avec les mêmes informations de carte bancaire a été soumise tout récemment.",
|
||||||
|
"issuer_not_available" => "Il n'est pas possible de joindre l'émetteur de la carte, donc d'autoriser le paiement.",
|
||||||
|
"new_account_information_available" => "La carte bancaire, ou le compte auquel elle est connectée, n'est pas valide.",
|
||||||
|
"no_action_taken" => "La carte a été refusée pour une raison inconnue.",
|
||||||
|
"pickup_card" => "Le client ne peut pas utiliser cette carte pour effectuer ce paiement (il est possible qu'elle ait été déclarée perdue ou volée).",
|
||||||
|
"withdrawal_count_limit_exceeded" => "Le client a dépassé le solde ou la limite de crédit disponible sur sa carte bancaire.",
|
||||||
|
"transaction_not_allowed" => "La carte a été refusée pour une raison inconnue.",
|
||||||
|
"testmode_decline" => "La carte utilisée est une carte de test"
|
||||||
|
];
|
|
@ -187,7 +187,7 @@
|
||||||
</div>
|
</div>
|
||||||
<hr class="ml-2 mr-2">
|
<hr class="ml-2 mr-2">
|
||||||
<div class="desk-body">
|
<div class="desk-body">
|
||||||
<form id="payment_form" name="begin_form" method="POST" action="{{route('yoomee.v2.checkoutPay')}}">
|
<form id="payment_form" name="begin_form" method="POST" action="{{$paymentEndpoint}}">
|
||||||
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
||||||
<input type="hidden" name="payment_token" value="{{ $payment_token }}">
|
<input type="hidden" name="payment_token" value="{{ $payment_token }}">
|
||||||
<div class="desk-content">
|
<div class="desk-content">
|
||||||
|
|
|
@ -213,7 +213,7 @@
|
||||||
<div class="desk-action p-3">
|
<div class="desk-action p-3">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12 pb-2 text-center">
|
<div class="col-md-12 pb-2 text-center">
|
||||||
<a href="{{route('yoomee.v2.merchantRedirect',['transaction_id' => $transaction_id])}}"
|
<a href="{{route('webPaymentRedirection',['transaction_id' => $transaction_id])}}"
|
||||||
class="btn btn-clear btn-block" id="closeCinetPaySeamlessModal">
|
class="btn btn-clear btn-block" id="closeCinetPaySeamlessModal">
|
||||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor"
|
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor"
|
||||||
stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"
|
stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<title>Payment webhook</title>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
// Afin de de permettre a la webview frontend de recuperer la reponse de paiement
|
||||||
|
var responseData = JSON.stringify({!! json_encode($data) !!});
|
||||||
|
|
||||||
|
// for webview flutter mobile
|
||||||
|
try{
|
||||||
|
window.ReactNativeWebView.postMessage(responseData);
|
||||||
|
}catch (e) {
|
||||||
|
console.log("Unable to post message on messageHandler", e)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -186,7 +186,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="ml-2 mr-2">
|
<hr class="ml-2 mr-2">
|
||||||
<form method="POST" action="{{route('yoomee.v2.verify')}}">
|
<form method="POST" action="{{$paymentVerifyEndpoint}}">
|
||||||
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
||||||
<input type="hidden" name="transaction_id" value="{{ $transaction_id }}">
|
<input type="hidden" name="transaction_id" value="{{ $transaction_id }}">
|
||||||
<input type="hidden" name="verify_btn" value="1">
|
<input type="hidden" name="verify_btn" value="1">
|
||||||
|
@ -267,7 +267,7 @@
|
||||||
var message = '<a href="" class="btn btn-next btn-block">Vérifier votre paiement <span id="timer"></span></a>';
|
var message = '<a href="" class="btn btn-next btn-block">Vérifier votre paiement <span id="timer"></span></a>';
|
||||||
startTimer($countdownDuration, display, '.requestNewCode', message, true);
|
startTimer($countdownDuration, display, '.requestNewCode', message, true);
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
var url = "{{route('yoomee.v2.verify')}}";
|
var url = "{{$paymentVerifyEndpoint}}";
|
||||||
var raw = JSON.stringify({
|
var raw = JSON.stringify({
|
||||||
"_token" : "{{ app('request')->session()->get('_token') }}",
|
"_token" : "{{ app('request')->session()->get('_token') }}",
|
||||||
"transaction_id": "{{$transaction_id}}"
|
"transaction_id": "{{$transaction_id}}"
|
||||||
|
@ -298,7 +298,7 @@
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log({e});
|
console.log({e});
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
)();
|
)();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -12,18 +12,34 @@
|
||||||
| and give it the Closure to call when that URI is requested.
|
| and give it the Closure to call when that URI is requested.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$router->get('/', function (){
|
||||||
|
return "yes payment service";
|
||||||
|
});
|
||||||
/**
|
/**
|
||||||
* Session endpoints
|
* Session endpoints
|
||||||
*/
|
*/
|
||||||
$router->group(['middleware' => 'session'], function () use ($router) {
|
$router->group(['middleware' => 'session'], function () use ($router) {
|
||||||
|
|
||||||
|
$router->get('webPaymentRedirection', ['as' => 'webPaymentRedirection', 'uses' => 'PaymentController@webPaymentRedirection']);
|
||||||
|
|
||||||
|
|
||||||
// $router->get('/', function (){
|
// $router->get('/', function (){
|
||||||
// return 'Payment Service';
|
// return 'Payment Service';
|
||||||
// });
|
// });
|
||||||
$router->get('checkout/{payment_token}', ['as' => 'checkout', 'uses' => 'PaymentController@checkout']);
|
$router->get('checkout/{payment_token}', ['as' => 'checkout', 'uses' => 'PaymentController@checkout']);
|
||||||
$router->post('checkoutPay', ['as' => 'yoomee.v2.checkoutPay', 'uses' => 'YoomeeV2Controller@checkoutPay','middleware' => 'csrf']);
|
$router->post('checkoutPay', ['as' => 'yoomee.v2.checkoutPay', 'uses' => 'YoomeeV2Controller@checkoutPay','middleware' => 'csrf']);
|
||||||
$router->post('status', ['as' => 'yoomee.v2.verify', 'uses' => 'YoomeeV2Controller@getPaymentStatus']);
|
$router->post('status', ['as' => 'yoomee.v2.verify', 'uses' => 'YoomeeV2Controller@getPaymentStatus']);
|
||||||
$router->get('merchantRedirect', ['as' => 'yoomee.v2.merchantRedirect', 'uses' => 'YoomeeV2Controller@merchantRedirect']);
|
|
||||||
|
/**
|
||||||
|
* Ynote
|
||||||
|
*/
|
||||||
|
$router->group(['prefix' => 'ynote'], function () use ($router) {
|
||||||
|
$router->post('checkoutPay', ['as' => 'ynote.checkoutPay', 'uses' => 'YnoteOrangeController@checkoutPay','middleware' => 'csrf']);
|
||||||
|
$router->post('status', ['as' => 'ynote.status', 'uses' => 'YnoteOrangeController@getPaymentStatus']);
|
||||||
|
$router->get('merchantRedirect', ['as' => 'ynote.merchantRedirect', 'uses' => 'YnoteOrangeController@merchantRedirect']);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stripe Endpoints
|
* Stripe Endpoints
|
||||||
|
@ -41,6 +57,9 @@ $router->addRoute(['GET','POST'],'/yoomee/v2/webhook', ['as' => 'yoomee.v2.webho
|
||||||
$router->addRoute(['GET','POST'],'/cinetpay/webhook', ['as' => 'cinetpay.webhook' , 'uses' => 'CinetpayController@capturePaymentResult']);
|
$router->addRoute(['GET','POST'],'/cinetpay/webhook', ['as' => 'cinetpay.webhook' , 'uses' => 'CinetpayController@capturePaymentResult']);
|
||||||
$router->addRoute(['GET','POST'],'/cinetpay/transfert/webhook', ['as' => 'cinetpay.transfert.webhook' , 'uses' => 'CinetpayController@captureTransfertResult']);
|
$router->addRoute(['GET','POST'],'/cinetpay/transfert/webhook', ['as' => 'cinetpay.transfert.webhook' , 'uses' => 'CinetpayController@captureTransfertResult']);
|
||||||
$router->addRoute(['GET','POST'],'/stripe/webhook', ['as' => 'stripe.webhook' , 'uses' => 'StripeController@capturePaymentResult']);
|
$router->addRoute(['GET','POST'],'/stripe/webhook', ['as' => 'stripe.webhook' , 'uses' => 'StripeController@capturePaymentResult']);
|
||||||
|
$router->addRoute(['GET','POST'],'/flutterwave/webhook', ['as' => 'flutterwave.webhook' , 'uses' => 'FlutterwaveController@capturePaymentResult']);
|
||||||
|
$router->addRoute(['GET','POST'],'/flutterwave/transfert/webhook', ['as' => 'flutterwave.transfert.webhook' , 'uses' => 'FlutterwaveController@captureTransfertResult']);
|
||||||
|
$router->addRoute(['GET','POST'],'/ynote/webhook', ['as' => 'ynote.webhook' , 'uses' => 'YnoteOrangeController@capturePaymentResult']);
|
||||||
|
|
||||||
$router->addRoute(['GET','POST'],'/paymentResult', ['as' => 'paymentResult' , 'uses' => 'PaymentController@paymentResult']);
|
$router->addRoute(['GET','POST'],'/paymentResult', ['as' => 'paymentResult' , 'uses' => 'PaymentController@paymentResult']);
|
||||||
|
|
||||||
|
@ -69,6 +88,17 @@ $router->group(['middleware' => 'auth'], function () use ($router) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ynote Orange Endpoints
|
||||||
|
*/
|
||||||
|
$router->group(['prefix' => 'ynote'], function () use ($router) {
|
||||||
|
$router->get('methods',['as' => 'ynote.methods', 'uses' => 'YnoteOrangeController@getMethods']);
|
||||||
|
$router->addRoute(['GET','POST'],'pay', ['as' => 'ynote.pay', 'uses' => 'YnoteOrangeController@pay']);
|
||||||
|
$router->addRoute(['GET','POST'],'initPay', ['as' => 'ynote.initPay', 'uses' => 'YnoteOrangeController@initPay']);
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cinetpay Endpoints
|
* Cinetpay Endpoints
|
||||||
*/
|
*/
|
||||||
|
@ -79,6 +109,16 @@ $router->group(['middleware' => 'auth'], function () use ($router) {
|
||||||
$router->get('checkBalance',['as' => 'cinetpay.check-balance', 'uses' => 'CinetpayController@checkBalance']);
|
$router->get('checkBalance',['as' => 'cinetpay.check-balance', 'uses' => 'CinetpayController@checkBalance']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flutterwave Endpoints
|
||||||
|
*/
|
||||||
|
$router->group(['prefix' => 'flutterwave'], function () use ($router) {
|
||||||
|
$router->get('methods',['as' => 'flutterwave.methods', 'uses' => 'FlutterwaveController@getMethods']);
|
||||||
|
$router->addRoute(['GET','POST'],'pay',['as' => 'flutterwave.pay', 'uses' => 'FlutterwaveController@pay']);
|
||||||
|
$router->post('payOut',['as' => 'flutterwave.payout', 'uses' => 'FlutterwaveController@payOut']);
|
||||||
|
$router->get('checkBalance',['as' => 'flutterwave.check-balance', 'uses' => 'FlutterwaveController@checkBalance']);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stripe Endpoints
|
* Stripe Endpoints
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue