Implement iLink World checkout page to handle Yoomee provider
|
@ -17,6 +17,8 @@ DB_PASSWORD=vps@2017GA
|
|||
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
ACCEPTED_KEYS=U14YhuyFhweMeYpIYj8Ft2jm4cVgbMzD
|
||||
|
||||
|
@ -34,3 +36,5 @@ CINETPAY_API_KEY=176445314662bebd39b1b6f8.42908045
|
|||
CINETPAY_SECRET_KEY=140983310662e79736e8ae45.38146680
|
||||
CINETPAY_SITE_ID=862736
|
||||
CINETPAY_API_URL=https://api-checkout.cinetpay.com/v2/
|
||||
|
||||
RECEIVER_NAME="Commune X"
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Enums;
|
|||
|
||||
abstract class PaymentTransactionState
|
||||
{
|
||||
const INITIATED = 'INITIATED';
|
||||
const ACCEPTED = 'ACCEPTED';
|
||||
const PENDING = 'PENDING';
|
||||
const PENDING_OTP = 'PENDING_OTP';
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\PaymentTransactionState;
|
||||
use App\Models\PaymentAggregator;
|
||||
use App\Models\PaymentTransaction;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
|
@ -41,7 +44,7 @@ class PaymentController extends Controller
|
|||
case 'yoomee':
|
||||
return app(YoomeeController::class)->pay($request);
|
||||
case 'yoomeev2':
|
||||
return app(YoomeeV2Controller::class)->pay($request);
|
||||
return app(YoomeeV2Controller::class)->initPay($request);
|
||||
case 'cinetpay':
|
||||
return app(CinetpayController::class)->pay($request);
|
||||
default:
|
||||
|
@ -57,4 +60,29 @@ class PaymentController extends Controller
|
|||
return $this->errorResponse($request->all());
|
||||
}
|
||||
}
|
||||
|
||||
public function checkout(Request $request, $payment_token)
|
||||
{
|
||||
$transaction = PaymentTransaction::where('payment_token',$payment_token)->firstOrFail();
|
||||
|
||||
$transaction_id = $transaction->transaction_id;
|
||||
$method = $transaction->payment_method;
|
||||
$amount = money($transaction->amount, $transaction->currency)->format(app()->getLocale());
|
||||
$receiver = config('variables.receiver_name');
|
||||
$receiver_logo = asset('assets/images/logo.jpeg');
|
||||
|
||||
|
||||
if($transaction->state == PaymentTransactionState::INITIATED){
|
||||
return view('checkout',compact('payment_token','method','amount', 'receiver','receiver_logo'));
|
||||
}
|
||||
|
||||
if($transaction->state == PaymentTransactionState::PENDING){
|
||||
return view('verify-payment',compact('transaction_id','method','amount', 'receiver','receiver_logo'));
|
||||
}
|
||||
|
||||
$status = $transaction->state == PaymentTransactionState::ACCEPTED;
|
||||
|
||||
|
||||
return view('payment-status',compact('transaction_id','method','amount', 'receiver','receiver_logo','status'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Enums\PaymentTransactionState;
|
|||
use App\Models\PaymentTransaction;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
@ -66,13 +67,139 @@ class YoomeeV2Controller extends Controller
|
|||
$methods[] = $method;
|
||||
}
|
||||
return $this->successResponse([
|
||||
'hasWebview' => false,
|
||||
'hasWebview' => true,
|
||||
'methods' => $methods
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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',
|
||||
'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);
|
||||
}
|
||||
|
||||
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' => $request->input('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,
|
||||
'state' => PaymentTransactionState::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'),
|
||||
]);
|
||||
|
||||
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('state', PaymentTransactionState::INITIATED)->firstOrFail();
|
||||
|
||||
|
||||
$customer_phone_number = $request->input('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' => $transaction->payment_method,
|
||||
'order_app_id' => config('variables.yoomee_app_id'),
|
||||
'order_ext_id' => $transaction->transaction_id,
|
||||
"order_base_amount" => $transaction->amount,
|
||||
"order_currency" => $transaction->currency,
|
||||
"order_description" => $transaction->reason,
|
||||
"order_wait_final_status" => $this->isSyncRequest
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
if ($createResponse->getStatusCode() == 400) {
|
||||
$createResponse = json_decode($createResponse->getBody()->getContents());
|
||||
|
||||
if(!empty($createResponse->error)){
|
||||
//If error regenerate transaction id to avoid 'Numero de commande deja utilisé'
|
||||
$transaction->update([
|
||||
'transaction_id' => $this->getTransactionID()
|
||||
]);
|
||||
//Convert into single line
|
||||
session()->flash('error',str_replace(array("\n", "\r"), '',$createResponse->error_description));
|
||||
return redirect()->route('checkout',['payment_token' => $token]);
|
||||
}
|
||||
|
||||
$transaction->update([
|
||||
'aggregator_payment_ref' => $createResponse->transaction_number,
|
||||
'payment_date' => $createResponse->transaction_date,
|
||||
'state' => strtoupper($createResponse->transaction_status),
|
||||
"customer_phone_number" => $customer_phone_number,
|
||||
]);
|
||||
|
||||
redirect()->route('checkout',['payment_token' => $token]);
|
||||
|
||||
}
|
||||
|
||||
session()->flash('error',__('errors.unexpected_error'));
|
||||
return redirect()->route('checkout',['payment_token' => $token]);
|
||||
}
|
||||
|
||||
|
||||
public function pay(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
|
@ -129,7 +256,7 @@ class YoomeeV2Controller extends Controller
|
|||
"amount" => $createResponse->transaction_amount,
|
||||
'payment_date' => $createResponse->transaction_date,
|
||||
"payment_method" => $payment_method,
|
||||
'payment_token' => Str::random(32),
|
||||
'payment_token' => Str::random(64),
|
||||
'state' => strtoupper($createResponse->transaction_status),
|
||||
"reason" => $request->input('reason'),
|
||||
"customer_id" => $request->input('customer_id'),
|
||||
|
@ -170,9 +297,24 @@ class YoomeeV2Controller extends Controller
|
|||
return $this->getPaymentStatus($transaction);
|
||||
}
|
||||
|
||||
private function getPaymentStatus(PaymentTransaction $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->state == PaymentTransactionState::PENDING && $transaction->created_at->diffInMinutes(Carbon::now()) > 5){
|
||||
$transaction->update([
|
||||
'state' => PaymentTransactionState::CANCELLED
|
||||
]);
|
||||
}
|
||||
$response = $this->client->post('status/v1', [
|
||||
'json' => [
|
||||
'order_merchant' => config('variables.yoomee_username'),
|
||||
|
@ -213,6 +355,35 @@ class YoomeeV2Controller extends Controller
|
|||
|
||||
}
|
||||
|
||||
if ($transaction->state == PaymentTransactionState::ACCEPTED) {
|
||||
return [
|
||||
'message' => "Payment accepted",
|
||||
'status' => 1,
|
||||
'refresh' => 1,
|
||||
];
|
||||
} else {
|
||||
if($verify_btn){
|
||||
return redirect()->route('checkout',['payment_token' => $transaction->payment_token]);
|
||||
}else{
|
||||
return [
|
||||
'message' => "Payment failed",
|
||||
'status' => 0
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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->state == PaymentTransactionState::ACCEPTED) {
|
||||
return redirect()->route('paymentResult', [
|
||||
'transaction_id' => $transaction->transaction_id,
|
||||
|
@ -225,7 +396,6 @@ class YoomeeV2Controller extends Controller
|
|||
'status' => 0
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
|
||||
class VerifyCsrfToken {
|
||||
|
||||
/**
|
||||
* The encrypter implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
protected $encrypter;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Encrypter $encrypter) {
|
||||
$this->encrypter = $encrypter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Session\TokenMismatchException
|
||||
*/
|
||||
public function handle($request, Closure $next) {
|
||||
if ($this->isReading($request) || $this->tokensMatch($request)) {
|
||||
$request->session()->regenerateToken();
|
||||
return $this->addCookieToResponse($request, $next($request));
|
||||
}
|
||||
|
||||
throw new TokenMismatchException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the session and input CSRF tokens match.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function tokensMatch($request) {
|
||||
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
|
||||
|
||||
if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
|
||||
$token = $this->encrypter->decrypt($header);
|
||||
}
|
||||
|
||||
return $request->session()->token() == $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the CSRF token to the response cookies.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function addCookieToResponse($request, $response) {
|
||||
$response->headers->setCookie(
|
||||
new Cookie('XSRF-TOKEN', $request->session()->token(), time() + 60 * 120, '/', null, false, false)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the HTTP request uses a ‘read’ verb.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function isReading($request) {
|
||||
return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);
|
||||
}
|
||||
|
||||
}
|
|
@ -60,6 +60,7 @@ $app->singleton(
|
|||
*/
|
||||
|
||||
$app->configure('app');
|
||||
$app->configure('session');
|
||||
$app->configure('swagger-lume');
|
||||
$app->configure('variables');
|
||||
/*
|
||||
|
@ -80,7 +81,9 @@ $app->middleware([
|
|||
$app->routeMiddleware([
|
||||
// 'auth' => App\Http\Middleware\Authenticate::class,
|
||||
'docs' => App\Http\Middleware\SecureApiDocs::class,
|
||||
'auth' => App\Http\Middleware\AuthenticateAccess::class
|
||||
'auth' => App\Http\Middleware\AuthenticateAccess::class,
|
||||
'session' => \Illuminate\Session\Middleware\StartSession::class,
|
||||
'csrf' => \App\Http\Middleware\VerifyCsrfToken::class
|
||||
]);
|
||||
|
||||
/*
|
||||
|
@ -94,11 +97,19 @@ $app->routeMiddleware([
|
|||
|
|
||||
*/
|
||||
|
||||
// $app->register(App\Providers\AppServiceProvider::class);
|
||||
$app->register(App\Providers\AppServiceProvider::class);
|
||||
// $app->register(App\Providers\AuthServiceProvider::class);
|
||||
// $app->register(App\Providers\EventServiceProvider::class);
|
||||
$app->register(App\Providers\EventServiceProvider::class);
|
||||
$app->register(Flipbox\LumenGenerator\LumenGeneratorServiceProvider::class);
|
||||
$app->register(\SwaggerLume\ServiceProvider::class);
|
||||
|
||||
$app->singleton(Illuminate\Session\SessionManager::class, function () use ($app) {
|
||||
return $app->loadComponent('session', Illuminate\Session\SessionServiceProvider::class, 'session');
|
||||
});
|
||||
|
||||
$app->singleton('session.store', function () use ($app) {
|
||||
return $app->loadComponent('session', Illuminate\Session\SessionServiceProvider::class, 'session.store');
|
||||
});
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Load The Application Routes
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
"license": "MIT",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"ext-json": "*",
|
||||
"cknow/laravel-money": "^7.0",
|
||||
"darkaonline/swagger-lume": "^9.0",
|
||||
"flipbox/lumen-generator": "^9.1",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"laravel/lumen-framework": "^9.0"
|
||||
"illuminate/session": "^8.83",
|
||||
"laravel/lumen-framework": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "dynamodb", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
|
||||
'expire_on_close' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path('framework/sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'sessions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While using one of the framework's cache driven session backends you may
|
||||
| list a cache store that should be used for these sessions. This value
|
||||
| must match with one of the application's configured cache "stores".
|
||||
|
|
||||
| Affects: "apc", "dynamodb", "memcached", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => env('SESSION_STORE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [2, 100],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => '/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. You are free to modify this option if needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" since this is a secure default value.
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
*/
|
||||
|
||||
'same_site' => 'lax',
|
||||
|
||||
];
|
|
@ -4,6 +4,7 @@ return [
|
|||
'app_env' => env('APP_ENV', 'local'),
|
||||
'app_debug' => env('APP_DEBUG', true),
|
||||
'swagger_docs_token' => env('SWAGGER_DOCS_TOKEN', true),
|
||||
'receiver_name' => env('RECEIVER_NAME', 'iLink World'),
|
||||
'yoomee_merchant_code' => env('YOOMEE_MERCHANT_CODE', ''),
|
||||
'yoomee_api_url' => env('YOOMEE_API_URL', ''),
|
||||
'yoomee_api_v2_url' => env('YOOMEE_API_V2_URL', ''),
|
||||
|
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,616 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="fr" data-kantu="1">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Effectuer un paiement - {{__('providers.'.$method)}}</title>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="csrf-token" content="">
|
||||
<link rel="icon" href="{{asset('assets/images/favicon.ico')}}">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" href="{{asset('assets/app.css')}}">
|
||||
|
||||
<style>
|
||||
.option-content1::after {
|
||||
left: 42%;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
#page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loading {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
background-position: center;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%)
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7 {
|
||||
0% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: translate(12px, 80px) scale(1);
|
||||
}
|
||||
75% {
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-r {
|
||||
0% {
|
||||
transform: translate(148px, 80px) scale(1):
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-c {
|
||||
0% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
25% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
50% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
75% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
100% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
background: var(--loader-color1);
|
||||
animation: ldio-5owbnf6l9j7 1.2048192771084336s infinite cubic-bezier(0, 0.5, 0.5, 1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(1) {
|
||||
background: var(--loader-color2);
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
animation: ldio-5owbnf6l9j7-r 0.3012048192771084s infinite cubic-bezier(0, 0.5, 0.5, 1), ldio-5owbnf6l9j7-c 1.2048192771084336s infinite step-start;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(2) {
|
||||
animation-delay: -0.3012048192771084s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(3) {
|
||||
animation-delay: -0.6024096385542168s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(4) {
|
||||
animation-delay: -0.9036144578313252s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(5) {
|
||||
animation-delay: -1.2048192771084336s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.loadingio-spinner-ellipsis-99po1h19hjs {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
transform: translateZ(0) scale(1);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 0 0; /* see note above */
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
.toggle-content {
|
||||
display: none;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: height 350ms ease-in-out, opacity 750ms ease-in-out;
|
||||
}
|
||||
|
||||
.toggle-content.is-visible {
|
||||
display: block;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body id="body">
|
||||
<div id="loading">
|
||||
<div class="loadingio-spinner-ellipsis-99po1h19hjs">
|
||||
<div class="ldio-5owbnf6l9j7">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page" class="container">
|
||||
<div class="row h-100 justify-content-center">
|
||||
<div class="col-md-8 col-lg-6 my-auto">
|
||||
<div class="desk bg-white shadow-sm">
|
||||
<div class="desk-head">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="">
|
||||
<div class="media align-items-center">
|
||||
<div class="media-head">
|
||||
<img src="{{$receiver_logo}}" class="rounded media-body mr-2 marchand-logo" alt="{{$receiver}}">
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p class="marchand-name p-0 m-0">{{$receiver}}</p>
|
||||
<h4 class="due-amount p-0 m-0">{{$amount}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="ml-2 mr-2">
|
||||
<div class="desk-body">
|
||||
<form id="payment_form" name="begin_form" method="POST" action="{{route('yoomee.v2.checkoutPay')}}">
|
||||
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
||||
<input type="hidden" name="payment_token" value="{{ $payment_token }}">
|
||||
<div class="desk-content">
|
||||
<p class="text-center">Payer avec</p>
|
||||
<div class="choose-payment-type">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60px" height="60px" viewBox="0 0 100 100">
|
||||
<g transform="translate(-2978 2535)">
|
||||
<rect width="100" height="100" transform="translate(2978 -2535)" fill="var()" opacity="0.003"></rect>
|
||||
<g transform="translate(2403.753 -3004.222)">
|
||||
<path d="M65.889,1.928H12.373A5.964,5.964,0,0,0,6.427,7.874V91.122a5.964,5.964,0,0,0,5.946,5.946H65.889a5.964,5.964,0,0,0,5.946-5.946V7.874A5.964,5.964,0,0,0,65.889,1.928ZM39.131,92.774a4.625,4.625,0,1,1,4.625-4.625A4.625,4.625,0,0,1,39.131,92.774ZM65.889,79.23H12.373V13.821H65.889Z" transform="translate(584.82 469.294)" fill="var(--cinetpay1)"></path>
|
||||
<path d="M21.585,0V3.6H0V7.2H21.585v3.6l7.2-5.4ZM7.2,14.39,0,19.787l7.2,5.4v-3.6H28.78v-3.6H7.2Z" transform="translate(609.43 500.731)" fill=" var(--cinetpay1)"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<p class="descrip" style="font-size:medium; margin-top: 5px">{{__('providers.'.$method)}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade active show" id="mobile-money" role="tabpanel" aria-labelledby="mobile-money-tab">
|
||||
<div class="option-content1">
|
||||
<div class="p-1">
|
||||
<div class="desk-form">
|
||||
<div class="phone-input form-group">
|
||||
<label class="input-title input-phone" for="phone_number">
|
||||
Numéro de téléphone
|
||||
</label>
|
||||
<div class="iti iti--allow-dropdown iti--separate-dial-code">
|
||||
<div class="iti__flag-container">
|
||||
<div class="iti__selected-flag" role="combobox"
|
||||
aria-controls="iti-0__country-listbox"
|
||||
aria-owns="iti-0__country-listbox"
|
||||
aria-expanded="false" tabindex="0"
|
||||
title="Cameroon (Cameroun): +237"
|
||||
aria-activedescendant="iti-0__item-cm">
|
||||
<div class="iti__flag iti__cm"></div>
|
||||
<div class="iti__selected-dial-code">+237</div>
|
||||
<div class="iti__arrow"></div>
|
||||
</div>
|
||||
<ul class="iti__country-list iti__hide"
|
||||
id="iti-0__country-listbox" role="listbox"
|
||||
aria-label="List of countries">
|
||||
<li class="iti__country iti__standard iti__active"
|
||||
tabindex="-1" id="iti-0__item-cm" role="option"
|
||||
data-dial-code="237" data-country-code="cm"
|
||||
aria-selected="true">
|
||||
<div class="iti__flag-box">
|
||||
<div class="iti__flag iti__cm"></div>
|
||||
</div>
|
||||
<span class="iti__country-name">Cameroon (Cameroun)</span><span
|
||||
class="iti__dial-code">+237</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="tel" id="phone_number" name="phone_number"
|
||||
class="form-control input-tel" value="" autofocus
|
||||
required autocomplete="off"
|
||||
data-intl-tel-input-id="0"
|
||||
style="padding-left: 94px;" minlength="9" maxlength="9"
|
||||
placeholder="6 71 23 45 67">
|
||||
</div>
|
||||
<img id="payment-method-icon" width="2rem"
|
||||
alt="payment method logo"
|
||||
src="{{url('assets/images/default.png')}}">
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-12 px-0">
|
||||
<div>
|
||||
<p id="methodscm" class="payment-method-box operator-box">
|
||||
@if(str_contains(strtolower($method),'orange'))
|
||||
<img
|
||||
src="{{url('assets/images/orange.png')}}"
|
||||
class="rounded mx-1 payment-method-logo"
|
||||
alt="ORANGE">
|
||||
@elseif(str_contains(strtolower($method),'mtn'))
|
||||
<img
|
||||
src="{{url('assets/images/mtn.png')}}"
|
||||
class="rounded mx-1 payment-method-logo"
|
||||
alt="MTN">
|
||||
@elseif(str_contains(strtolower($method),'yoomee'))
|
||||
<img
|
||||
src="{{url('assets/images/yoomee.png')}}"
|
||||
class="rounded mx-1 payment-method-logo"
|
||||
alt="yoomee">
|
||||
@elseif(str_contains(strtolower($method),'express'))
|
||||
<img
|
||||
src="{{url('assets/images/express-union.png')}}"
|
||||
class="rounded mx-1 payment-method-logo"
|
||||
alt="express">
|
||||
@else
|
||||
<img
|
||||
src="{{url('assets/images/default.png')}}"
|
||||
class="rounded mx-1 payment-method-logo"
|
||||
alt="default">
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="desk-action p-3" id="desk-action">
|
||||
<button type="submit" class="btn btn-next btn-block" id="del">
|
||||
Payer {{$amount}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@include('footer')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{asset('assets/sweetalert2/sweetalert2.all.min.js')}}"></script>
|
||||
<script src="{{asset('assets/app.js')}}"></script>
|
||||
<script>
|
||||
|
||||
document.addEventListener('readystatechange', function (event) {
|
||||
if (event.target.readyState === 'complete') {
|
||||
ready();
|
||||
}
|
||||
});
|
||||
|
||||
function ready() {
|
||||
setTimeout(function () {
|
||||
fadeIn(document.getElementById('page'))
|
||||
}, 217)
|
||||
fadeOut(document.getElementById('loading'));
|
||||
}
|
||||
|
||||
// ** FADE OUT FUNCTION **
|
||||
function fadeOut(el) {
|
||||
el.style.opacity = 1;
|
||||
(function fade() {
|
||||
if ((el.style.opacity -= .1) < 0) {
|
||||
el.style.display = "none";
|
||||
} else {
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// ** FADE IN FUNCTION **
|
||||
function fadeIn(el, display) {
|
||||
el.style.opacity = 0;
|
||||
el.style.display = display || "block";
|
||||
(function fade() {
|
||||
var val = parseFloat(el.style.opacity);
|
||||
if (!((val += .1) > 1)) {
|
||||
el.style.opacity = val;
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
function empty(item) {
|
||||
return (item === undefined || item === null || item === false || item === '');
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('readystatechange', function (event) {
|
||||
if (event.target.readyState === 'complete') {
|
||||
disableButtonOnSubmit();
|
||||
}
|
||||
});
|
||||
function disableButtonOnSubmit() {
|
||||
var form = document.getElementById('payment_form');
|
||||
var submitButton = document.getElementById('del');
|
||||
form.addEventListener('submit', function () {
|
||||
submitButton.disabled = true;
|
||||
setTimeout(function () {
|
||||
submitButton.disabled = false;
|
||||
}, 15000)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
|
||||
@if(session('error'))
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: "{{session('error')}}",
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
})
|
||||
@endif
|
||||
|
||||
function initializeIntelInput() {
|
||||
try {
|
||||
if (empty(window.intlTelInput) && intlTelInput) {
|
||||
window.intlTelInput = intlTelInput;
|
||||
}
|
||||
|
||||
var phoneNumberInput = document.querySelector("#phone_number");
|
||||
|
||||
var iti = window.intlTelInput(phoneNumberInput, {
|
||||
hiddenInput: "phone_number",
|
||||
onlyCountries: ["cm"],
|
||||
placeholderNumberType: "MOBILE",
|
||||
initialCountry: 'cm',
|
||||
localizedCountries: {"cd": "Congo RDC"},
|
||||
separateDialCode: true,
|
||||
utilsScript: "/assets/utils.js",
|
||||
customPlaceholder: function (selectedCountryPlaceholder, selectedCountryData) {
|
||||
if (selectedCountryData.iso2 === 'ci') {
|
||||
return '01 23 45 67 89';
|
||||
} else {
|
||||
return selectedCountryPlaceholder;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var countryJsData = iti.getSelectedCountryData();
|
||||
var countryJs = 'cm';
|
||||
if (!empty(countryJsData) && !empty(countryJsData.iso2)) {
|
||||
countryJs = countryJsData.iso2;
|
||||
getMobileMoneyPaymentMethodLogo(iti);
|
||||
}
|
||||
|
||||
var methodCountry = document.getElementById("methods" + countryJs);
|
||||
showCurrentLogos(methodCountry);
|
||||
|
||||
phoneNumberInput.addEventListener('countrychange', function (e) {
|
||||
const methodCountry = document.getElementById("methods" + iti.getSelectedCountryData().iso2)
|
||||
showCurrentLogos(methodCountry);
|
||||
getMobileMoneyPaymentMethodLogo(iti);
|
||||
});
|
||||
|
||||
|
||||
phoneNumberInput.addEventListener('paste', function (e) {
|
||||
getMobileMoneyPaymentMethodLogo(iti);
|
||||
});
|
||||
phoneNumberInput.addEventListener('keyup', function (e) {
|
||||
getMobileMoneyPaymentMethodLogo(iti);
|
||||
});
|
||||
|
||||
if (!empty(phoneNumberInput)) {
|
||||
setInputFilter(phoneNumberInput, function (value) {
|
||||
return /^\d*\.?\d*$/.test(value.replace(/\s/g, ''));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var countryData = iti.getSelectedCountryData()
|
||||
var countryIso = countryData.iso2;
|
||||
var phoneNumber = phoneNumberInput.value.replace("+" + iti.dialCode, "").trim();
|
||||
displayPaymentMethodLogo(countryIso, phoneNumber);
|
||||
return true;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
function getMobileMoneyPaymentMethodLogo(itiEvent) {
|
||||
var countryData = itiEvent.getSelectedCountryData()
|
||||
var countryIso = countryData.iso2;
|
||||
var phoneNumber = itiEvent.getNumber().replace("+" + countryData.dialCode, "").trim();
|
||||
return displayPaymentMethodLogo(countryIso, phoneNumber);
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
initializeIntelInput();
|
||||
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", initializeIntelInput);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
if (!String.prototype.startsWith) {
|
||||
Object.defineProperty(String.prototype, 'startsWith', {
|
||||
value: function (search, rawPos) {
|
||||
var pos = rawPos > 0 ? rawPos | 0 : 0;
|
||||
return this.substring(pos, pos + search.length) === search;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var paymentMethods = {
|
||||
"bf": {
|
||||
"regex": [],
|
||||
"prefixes": [{
|
||||
"values": ["55", "64", "65", "66", "67", "74", "75", "76", "77"],
|
||||
"name": "orange"
|
||||
}, {"values": ["51", "53", "60", "61", "62", "63", "70", "71", "72", "73"], "name": "moov"}],
|
||||
"max_digits": 8,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"bj": {
|
||||
"regex": [],
|
||||
"prefixes": [{
|
||||
"values": ["51", "52", "53", "54", "61", "62", "66", "67", "69", "90", "91", "96", "97"],
|
||||
"name": "mtn"
|
||||
}, {"values": ["60", "63", "64", "65", "94", "95", "98", "99"], "name": "moov"}],
|
||||
"max_digits": 8,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"cd": {
|
||||
"regex": [],
|
||||
"prefixes": [{
|
||||
"values": ["80", "84", "85", "89"],
|
||||
"currencies": ["CDF", "USD"],
|
||||
"name": "orange"
|
||||
}, {
|
||||
"currencies": ["CDF", "USD"],
|
||||
"values": ["97", "99"],
|
||||
"name": "airtel"
|
||||
}, {
|
||||
"values": ["81", "82", "83", "081", "082", "080", "083"],
|
||||
"currencies": ["CDF", "USD"],
|
||||
"name": "mpesa"
|
||||
}],
|
||||
"max_digits": 10,
|
||||
"currencies": ["CDF", "USD"]
|
||||
},
|
||||
"ci": {
|
||||
"regex": [{
|
||||
"values": "^[0,4,5,6,7,8,9]{1}[7,8,9]\\d{0,8}",
|
||||
"name": "orange"
|
||||
}, {
|
||||
"values": "^[0,4,5,6,7,8,9]{1}[4,5,6]\\d{0,8}",
|
||||
"name": "mtn"
|
||||
}, {"values": "^[0,4,5,6,7,8,9]{1}[0,1,2,3]{1}\\d{0,8}", "name": "moov"}],
|
||||
"prefixes": [],
|
||||
"max_digits": 10,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"cm": {
|
||||
"regex": [],
|
||||
"prefixes": [
|
||||
{
|
||||
"values": ["690", "691", "692", "693", "694", "695", "696", "697", "698", "699", "655", "656", "657", "658", "659"],
|
||||
"name": "orange"
|
||||
},
|
||||
{
|
||||
"values": ["680", "681", "682", "683", "684", "685", "686", "687", "688", "689", "650", "651", "652", "653", "654", "678"],
|
||||
"name": "mtn"
|
||||
},
|
||||
{
|
||||
"values": ["230", "231", "232" , "233" , "240","241","242"],
|
||||
"name": "yoomee"
|
||||
}
|
||||
],
|
||||
"max_digits": 10,
|
||||
"currencies": ["XAF"]
|
||||
},
|
||||
"ml": {
|
||||
"regex": [],
|
||||
"prefixes": [{"values": ["65", "66", "67", "68", "69", "95", "96", "97", "98", "99"], "name": "moov"}],
|
||||
"max_digits": 10,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"ne": {
|
||||
"regex": [],
|
||||
"prefixes": [{"values": ["86", "87", "88", "89", "96", "97", "98", "99"], "name": "airtel"}],
|
||||
"max_digits": 8,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"sn": {
|
||||
"regex": [],
|
||||
"prefixes": [{"values": ["77", "78"], "name": "orange"}, {
|
||||
"values": ["65", "66", "76"],
|
||||
"name": "freemoney"
|
||||
}, {"values": ["70"], "name": "expresso"}],
|
||||
"max_digits": 10,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"tg": {
|
||||
"regex": [],
|
||||
"prefixes": [{
|
||||
"values": ["79", "96", "97", "98", "99"],
|
||||
"name": "moov"
|
||||
}, {"values": ["70", "90", "91", "92", "93"], "name": "tmoney"}],
|
||||
"max_digits": 10,
|
||||
"currencies": ["XOF"]
|
||||
},
|
||||
"gn": {
|
||||
"regex": [],
|
||||
"prefixes": [{"values": ["610", "611", "62"], "name": "orange"}, {"values": ["66"], "name": "mtn"}],
|
||||
"max_digits": 8,
|
||||
"currencies": ["GNF"]
|
||||
}
|
||||
};
|
||||
|
||||
function displayPaymentMethodLogo(country, phoneNumber) {
|
||||
var countriesPaymentMethods = paymentMethods[country.toLowerCase()];
|
||||
var logosPath = '/assets/images/';
|
||||
var logo = 'default';
|
||||
if (countriesPaymentMethods !== undefined) {
|
||||
var countriesPaymentMethodsRegexEntries = countriesPaymentMethods['regex'];
|
||||
var countriesPaymentMethodsValuesEntries = countriesPaymentMethods['prefixes'];
|
||||
if (typeof countriesPaymentMethodsRegexEntries !== undefined && countriesPaymentMethodsRegexEntries.length > 0) {
|
||||
for (var regexItem of countriesPaymentMethodsRegexEntries) {
|
||||
if (new RegExp(regexItem.values).test(phoneNumber) && phoneNumber.length <= countriesPaymentMethods['max_digits']) {
|
||||
logo = regexItem.name;
|
||||
document.getElementById("payment-method-icon").src = logosPath + logo + '.png';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof countriesPaymentMethodsValuesEntries !== undefined && countriesPaymentMethodsValuesEntries.length > 0) {
|
||||
for (var prefixItem of countriesPaymentMethodsValuesEntries) {
|
||||
var prefixes = prefixItem['values'];
|
||||
for (var prefix of prefixes) {
|
||||
if (phoneNumber.startsWith(prefix) && phoneNumber.length <= countriesPaymentMethods['max_digits']) {
|
||||
logo = prefixItem['name'];
|
||||
document.getElementById("payment-method-icon").src = logosPath + logo + '.png';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById("payment-method-icon").src = logosPath + 'default.png';
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<p class="text-center pt-2">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" stroke="var(--lockStroke)" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||
</svg>
|
||||
<span style="color: var(--secured-by-text)">Sécurisé par </span>
|
||||
<strong class="text-cinetpay">
|
||||
<span style="color: #6787B1">iLink World</span>
|
||||
</strong>
|
||||
</p>
|
|
@ -0,0 +1,280 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="fr" data-kantu="1">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Paiement {{$status ? 'réussi' : 'échoué'}} - {{__('providers.'.$method)}}</title>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="csrf-token" content="">
|
||||
<link rel="icon" href="{{asset('assets/images/favicon.ico')}}">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" href="{{asset('assets/app.css')}}">
|
||||
|
||||
<style>
|
||||
.option-content1::after {
|
||||
left: 42%;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
#page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loading {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
background-position: center;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%)
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7 {
|
||||
0% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: translate(12px, 80px) scale(1);
|
||||
}
|
||||
75% {
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-r {
|
||||
0% {
|
||||
transform: translate(148px, 80px) scale(1):
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-c {
|
||||
0% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
25% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
50% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
75% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
100% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
background: var(--loader-color1);
|
||||
animation: ldio-5owbnf6l9j7 1.2048192771084336s infinite cubic-bezier(0, 0.5, 0.5, 1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(1) {
|
||||
background: var(--loader-color2);
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
animation: ldio-5owbnf6l9j7-r 0.3012048192771084s infinite cubic-bezier(0, 0.5, 0.5, 1), ldio-5owbnf6l9j7-c 1.2048192771084336s infinite step-start;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(2) {
|
||||
animation-delay: -0.3012048192771084s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(3) {
|
||||
animation-delay: -0.6024096385542168s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(4) {
|
||||
animation-delay: -0.9036144578313252s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(5) {
|
||||
animation-delay: -1.2048192771084336s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.loadingio-spinner-ellipsis-99po1h19hjs {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
transform: translateZ(0) scale(1);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 0 0; /* see note above */
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
.toggle-content {
|
||||
display: none;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: height 350ms ease-in-out, opacity 750ms ease-in-out;
|
||||
}
|
||||
|
||||
.toggle-content.is-visible {
|
||||
display: block;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body id="body">
|
||||
<div id="loading">
|
||||
<div class="loadingio-spinner-ellipsis-99po1h19hjs">
|
||||
<div class="ldio-5owbnf6l9j7">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page" class="container">
|
||||
<div class="row h-100 justify-content-center">
|
||||
<div class="col-md-8 col-lg-6 my-auto">
|
||||
<div class="desk bg-white shadow-sm">
|
||||
<div class="desk-head">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="">
|
||||
<div class="media align-items-center">
|
||||
<div class="media-head">
|
||||
<img src="{{$receiver_logo}}" class="rounded media-body mr-2 marchand-logo" alt="{{$receiver}}">
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p class="marchand-name p-0 m-0">{{$receiver}}</p>
|
||||
<h4 class="due-amount p-0 m-0">{{$amount}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="ml-2 mr-2">
|
||||
<div class="desk-body">
|
||||
<div class="desk-content">
|
||||
@if($status)
|
||||
<div class="desk-animation">
|
||||
<img alt="failed_icon" height="85" width="85"
|
||||
src="{{asset('assets/images/success.png')}}">
|
||||
</div>
|
||||
<p class="text-center my-4">Votre paiement a réussi</p>
|
||||
@else
|
||||
<div class="desk-animation">
|
||||
<img alt="failed_icon" height="85" width="85"
|
||||
src="{{asset('assets/images/failed.png')}}">
|
||||
</div>
|
||||
<p class="text-center my-4">Votre paiement a échoué</p>
|
||||
@endif
|
||||
|
||||
<div class="">
|
||||
{{-- <p class="p-2 text-center">--}}
|
||||
{{-- Contacter <a href="https://checkout.cinetpay.com/payment/reclamation">--}}
|
||||
{{-- le support--}}
|
||||
{{-- </a>--}}
|
||||
{{-- </p>--}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="desk-action p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-12 pb-2 text-center">
|
||||
<a href="{{route('yoomee.v2.merchantRedirect',['transaction_id' => $transaction_id])}}"
|
||||
class="btn btn-clear btn-block" id="closeCinetPaySeamlessModal">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor"
|
||||
stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="css-i6dzq1">
|
||||
<polyline points="15 18 9 12 15 6"></polyline>
|
||||
</svg>
|
||||
Retourner sur le site
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('footer')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
document.addEventListener('readystatechange', function (event) {
|
||||
if (event.target.readyState === 'complete') {
|
||||
ready();
|
||||
}
|
||||
});
|
||||
|
||||
function ready() {
|
||||
setTimeout(function () {
|
||||
fadeIn(document.getElementById('page'))
|
||||
}, 217)
|
||||
fadeOut(document.getElementById('loading'));
|
||||
}
|
||||
|
||||
// ** FADE OUT FUNCTION **
|
||||
function fadeOut(el) {
|
||||
el.style.opacity = 1;
|
||||
(function fade() {
|
||||
if ((el.style.opacity -= .1) < 0) {
|
||||
el.style.display = "none";
|
||||
} else {
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// ** FADE IN FUNCTION **
|
||||
function fadeIn(el, display) {
|
||||
el.style.opacity = 0;
|
||||
el.style.display = display || "block";
|
||||
(function fade() {
|
||||
var val = parseFloat(el.style.opacity);
|
||||
if (!((val += .1) > 1)) {
|
||||
el.style.opacity = val;
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
function empty(item) {
|
||||
return (item === undefined || item === null || item === false || item === '');
|
||||
}
|
||||
</script>
|
||||
<script src="{{asset('assets/app.js')}}"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,306 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="fr" data-kantu="1">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vérification du paiement - {{__('providers.'.$method)}}</title>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="csrf-token" content="">
|
||||
<link rel="icon" href="{{asset('assets/images/favicon.ico')}}">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" href="{{asset('assets/app.css')}}">
|
||||
|
||||
<style>
|
||||
.option-content1::after {
|
||||
left: 42%;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
#page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loading {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
background-position: center;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%)
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7 {
|
||||
0% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(12px, 80px) scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: translate(12px, 80px) scale(1);
|
||||
}
|
||||
75% {
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-r {
|
||||
0% {
|
||||
transform: translate(148px, 80px) scale(1):
|
||||
}
|
||||
100% {
|
||||
transform: translate(148px, 80px) scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ldio-5owbnf6l9j7-c {
|
||||
0% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
25% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
50% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
75% {
|
||||
background: var(--loader-color2)
|
||||
}
|
||||
100% {
|
||||
background: var(--loader-color1)
|
||||
}
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
transform: translate(80px, 80px) scale(1);
|
||||
background: var(--loader-color1);
|
||||
animation: ldio-5owbnf6l9j7 1.2048192771084336s infinite cubic-bezier(0, 0.5, 0.5, 1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(1) {
|
||||
background: var(--loader-color2);
|
||||
transform: translate(148px, 80px) scale(1);
|
||||
animation: ldio-5owbnf6l9j7-r 0.3012048192771084s infinite cubic-bezier(0, 0.5, 0.5, 1), ldio-5owbnf6l9j7-c 1.2048192771084336s infinite step-start;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(2) {
|
||||
animation-delay: -0.3012048192771084s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(3) {
|
||||
animation-delay: -0.6024096385542168s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(4) {
|
||||
animation-delay: -0.9036144578313252s;
|
||||
background: var(--loader-color1);
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div:nth-child(5) {
|
||||
animation-delay: -1.2048192771084336s;
|
||||
background: var(--loader-color2);
|
||||
}
|
||||
|
||||
.loadingio-spinner-ellipsis-99po1h19hjs {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
transform: translateZ(0) scale(1);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 0 0; /* see note above */
|
||||
}
|
||||
|
||||
.ldio-5owbnf6l9j7 div {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
.toggle-content {
|
||||
display: none;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: height 350ms ease-in-out, opacity 750ms ease-in-out;
|
||||
}
|
||||
|
||||
.toggle-content.is-visible {
|
||||
display: block;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body id="body">
|
||||
<div id="loading">
|
||||
<div class="loadingio-spinner-ellipsis-99po1h19hjs">
|
||||
<div class="ldio-5owbnf6l9j7">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page" class="container">
|
||||
<div class="row h-100 justify-content-center">
|
||||
<div class="col-md-8 col-lg-6 my-auto">
|
||||
<div class="desk bg-white shadow-sm">
|
||||
<div class="desk-head">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="">
|
||||
<div class="media align-items-center">
|
||||
<div class="media-head">
|
||||
<img src="{{$receiver_logo}}" class="rounded media-body mr-2 marchand-logo" alt="{{$receiver}}">
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p class="marchand-name p-0 m-0">{{$receiver}}</p>
|
||||
<h4 class="due-amount p-0 m-0">{{$amount}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="ml-2 mr-2">
|
||||
<form method="POST" action="{{route('yoomee.v2.verify')}}">
|
||||
<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">
|
||||
<input type="hidden" name="transaction_id" value="{{ $transaction_id }}">
|
||||
<input type="hidden" name="verify_btn" value="1">
|
||||
<div class="desk-body">
|
||||
<div class="desk-content">
|
||||
<p class="text-center">Vérification du paiement</p>
|
||||
<div class="desk-info">
|
||||
<p class="p-2 text-center">
|
||||
Veuillez confirmer le paiement en saisissant votre code PIN sur votre telephone.
|
||||
</p>
|
||||
</div>
|
||||
<p id="time">02:01</p>
|
||||
</div>
|
||||
<div class="desk-action p-3 requestNewCode">
|
||||
<button type="submit"
|
||||
class="btn btn-next btn-block">
|
||||
Vérifier votre paiement <span id="timer"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@include('footer')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{asset('assets/sweetalert2/sweetalert2.all.min.js')}}"></script>
|
||||
<script src="{{asset('assets/app.js')}}"></script>
|
||||
<script>
|
||||
document.addEventListener('readystatechange', function (event) {
|
||||
if (event.target.readyState === 'complete') {
|
||||
ready();
|
||||
}
|
||||
});
|
||||
|
||||
function ready() {
|
||||
setTimeout(function () {
|
||||
fadeIn(document.getElementById('page'))
|
||||
}, 217)
|
||||
fadeOut(document.getElementById('loading'));
|
||||
}
|
||||
|
||||
// ** FADE OUT FUNCTION **
|
||||
function fadeOut(el) {
|
||||
el.style.opacity = 1;
|
||||
(function fade() {
|
||||
if ((el.style.opacity -= .1) < 0) {
|
||||
el.style.display = "none";
|
||||
} else {
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// ** FADE IN FUNCTION **
|
||||
function fadeIn(el, display) {
|
||||
el.style.opacity = 0;
|
||||
el.style.display = display || "block";
|
||||
(function fade() {
|
||||
var val = parseFloat(el.style.opacity);
|
||||
if (!((val += .1) > 1)) {
|
||||
el.style.opacity = val;
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
function empty(item) {
|
||||
return (item === undefined || item === null || item === false || item === '');
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
(
|
||||
window.onload = function () {
|
||||
var $countdownDuration = parseInt('121');
|
||||
var display = document.querySelector('#time');
|
||||
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);
|
||||
var myHeaders = new Headers();
|
||||
var url = "{{route('yoomee.v2.verify')}}";
|
||||
var raw = JSON.stringify({
|
||||
"transaction_id": "{{$transaction_id}}"
|
||||
});
|
||||
|
||||
var requestOptions = {
|
||||
body: raw,
|
||||
headers: myHeaders,
|
||||
method: "POST",
|
||||
redirect: "follow"
|
||||
};
|
||||
|
||||
setInterval(function () {
|
||||
try {
|
||||
myHeaders.append("Content-Type", "application/json");
|
||||
fetch(url, requestOptions)
|
||||
.then(function (result) {
|
||||
return result.json();
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.refresh) {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
.catch(function (caughtError) {
|
||||
console.log({caughtError})
|
||||
});
|
||||
} catch (e) {
|
||||
console.log({e});
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
)();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -12,6 +12,18 @@
|
|||
| and give it the Closure to call when that URI is requested.
|
||||
|
|
||||
*/
|
||||
/**
|
||||
* Session endpoints
|
||||
*/
|
||||
$router->group(['middleware' => 'session'], function () use ($router) {
|
||||
// $router->get('/', function (){
|
||||
// return 'Payment Service';
|
||||
// });
|
||||
$router->get('checkout/{payment_token}', ['as' => 'checkout', 'uses' => 'PaymentController@checkout']);
|
||||
$router->post('checkoutPay', ['as' => 'yoomee.v2.checkoutPay', 'uses' => 'YoomeeV2Controller@checkoutPay','middleware' => 'csrf']);
|
||||
$router->post('status', ['as' => 'yoomee.v2.verify', 'uses' => 'YoomeeV2Controller@getPaymentStatus', 'middleware' => 'csrf']);
|
||||
$router->get('merchantRedirect', ['as' => 'yoomee.v2.merchantRedirect', 'uses' => 'YoomeeV2Controller@merchantRedirect']);
|
||||
});
|
||||
|
||||
/**
|
||||
* Webhooks
|
||||
|
@ -21,7 +33,7 @@ $router->addRoute(['GET','POST'],'/cinetpay/webhook', ['as' => 'cinetpay.webhook
|
|||
|
||||
$router->addRoute(['GET','POST'],'/paymentResult', ['as' => 'paymentResult' , 'uses' => 'PaymentController@paymentResult']);
|
||||
|
||||
$router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($router) {
|
||||
$router->group(['middleware' => 'auth'], function () use ($router) {
|
||||
|
||||
/**
|
||||
* Entry Endpoints
|
||||
|
@ -44,7 +56,6 @@ $router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($route
|
|||
});
|
||||
|
||||
/**
|
||||
* CinetPay Endpoints
|
||||
*/
|
||||
$router->group(['prefix' => 'cinetpay'], function () use ($router) {
|
||||
$router->get('methods',['as' => 'cinetpay.methods', 'uses' => 'CinetpayController@getMethods']);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|