feat: add route to calculate fees
This commit is contained in:
parent
457df41c9c
commit
81796c15bb
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
|
||||||
|
abstract class PaymentType
|
||||||
|
{
|
||||||
|
const CASH_IN = 'CASH_IN'; // Les remboursements ou recharges vers des clients
|
||||||
|
const CASH_OUT = 'CASH_OUT'; // Les paiements effectués par les clients
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Enums\PaymentTransactionStatus;
|
use App\Enums\PaymentTransactionStatus;
|
||||||
|
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;
|
||||||
|
@ -147,4 +148,59 @@ class PaymentController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFees(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'amount' => 'required|numeric|min:0',
|
||||||
|
'country_id' => 'required|integer|exists:countries,id',
|
||||||
|
'payment_type' => 'required|string|in:CASH_IN,CASH_OUT',
|
||||||
|
'payment_method' => 'required|string|in:CARD,WALLET',
|
||||||
|
'payment_channel' => 'nullable|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$fees = 0;
|
||||||
|
|
||||||
|
$amount = $request->input('amount');
|
||||||
|
$paymentChannel = $request->input('payment_channel');
|
||||||
|
$paymentMethod = $request->input('payment_method');
|
||||||
|
$paymentType = $request->input('payment_type');
|
||||||
|
$countryId = $request->input('country_id');
|
||||||
|
$country = Country::where('id', $countryId)->firstOrFail();
|
||||||
|
$countryCode = $country->code_country;
|
||||||
|
|
||||||
|
|
||||||
|
if($paymentMethod == 'CARD'){
|
||||||
|
$aggregator = PaymentAggregator::where('name','like','%stripe%')->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($paymentMethod == 'WALLET'){
|
||||||
|
$aggregator = PaymentAggregator::where('status',1)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($aggregator)){
|
||||||
|
$rate = $aggregator->rates()->where('country', $countryCode)->orWhere('country','ALL')->where('type', $paymentType)
|
||||||
|
->where('method', $paymentMethod)->when($paymentChannel, function ($q) use($paymentChannel){
|
||||||
|
return $q->where('channel',$paymentChannel);
|
||||||
|
})->first();
|
||||||
|
|
||||||
|
if(!empty($rate)){
|
||||||
|
if(!empty($rate->fixed_fees)){
|
||||||
|
$targetCurrency = $country->currency->code;
|
||||||
|
$sourceCurrency = $targetCurrency;
|
||||||
|
if(!empty($rate->fixed_fees_currency)){
|
||||||
|
$sourceCurrency = $rate->fixed_fees_currency;
|
||||||
|
}
|
||||||
|
$fixed_fees = $this->toMoneyAmount($rate->fixed_fees, $sourceCurrency, $targetCurrency);
|
||||||
|
$fees = (($amount - $fixed_fees) * $rate->rate / 100 ) + $fixed_fees;
|
||||||
|
}else{
|
||||||
|
$fees = $amount * $rate->rate / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->successResponse(['fees' => round($fees, 2)]);
|
||||||
|
}else {
|
||||||
|
return $this->errorResponse("Aggregateur non disponible");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Reliese Model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Country
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property string $code_dial
|
||||||
|
* @property string $name
|
||||||
|
* @property string $code_country
|
||||||
|
* @property float $longitude
|
||||||
|
* @property float $latitude
|
||||||
|
* @property int $idCurrency
|
||||||
|
*
|
||||||
|
* @property Currency $currency
|
||||||
|
* @property Collection|Admin[] $admins
|
||||||
|
* @property Collection|ConfigGame[] $config_games
|
||||||
|
* @property Collection|Identification[] $identifications
|
||||||
|
* @property Collection|WalletIlinkTransaction[] $wallet_ilink_transactions
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Country extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'countries';
|
||||||
|
public $timestamps = false;
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'longitude' => 'float',
|
||||||
|
'latitude' => 'float',
|
||||||
|
'idCurrency' => 'int'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'code_dial',
|
||||||
|
'name',
|
||||||
|
'code_country',
|
||||||
|
'longitude',
|
||||||
|
'latitude',
|
||||||
|
'idCurrency'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function currency()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Currency::class, 'idCurrency');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Reliese Model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Currency
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property string $code
|
||||||
|
* @property int $numeric
|
||||||
|
* @property string $symbol
|
||||||
|
* @property string $name_en
|
||||||
|
* @property string $name_fr
|
||||||
|
*
|
||||||
|
* @property Collection|Country[] $countries
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Currency extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'currencies';
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'numeric' => 'int'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'code',
|
||||||
|
'numeric',
|
||||||
|
'symbol',
|
||||||
|
'name_en',
|
||||||
|
'name_fr'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function countries()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Country::class, 'idCurrency');
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,4 +8,8 @@ class PaymentAggregator extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'payment_aggregators';
|
protected $table = 'payment_aggregators';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
public function rates(){
|
||||||
|
return $this->hasMany(PaymentAggregatorRate::class,'aggregator_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class PaymentAggregatorRate extends Model
|
||||||
|
{
|
||||||
|
//
|
||||||
|
protected $table = 'payment_aggregator_rates';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
}
|
|
@ -3,7 +3,17 @@
|
||||||
|
|
||||||
namespace App\Traits;
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Models\Country;
|
||||||
|
use Brick\Math\RoundingMode;
|
||||||
|
use Brick\Money\Context\AutoContext;
|
||||||
|
use Brick\Money\Context\CashContext;
|
||||||
|
use Brick\Money\CurrencyConverter;
|
||||||
|
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
|
||||||
|
use Brick\Money\ExchangeRateProvider\PDOProvider;
|
||||||
|
use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration;
|
||||||
|
use Brick\Money\Money;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use PDO;
|
||||||
|
|
||||||
trait Helper
|
trait Helper
|
||||||
{
|
{
|
||||||
|
@ -18,8 +28,40 @@ trait Helper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convertir vers le multiple de 5 le plus proche
|
// Convertir vers le multiple de 5 le plus proche
|
||||||
function roundUpToAny($n,$x=5) {
|
function roundUpToAny($n, $x = 5)
|
||||||
return (ceil($n)%$x === 0) ? ceil($n) : round(($n+$x/2)/$x)*$x;
|
{
|
||||||
|
return (ceil($n) % $x === 0) ? ceil($n) : round(($n + $x / 2) / $x) * $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function convertMoney($amount, $sourceCurrency, $targetCurrency)
|
||||||
|
{
|
||||||
|
// set to whatever your rates are relative to
|
||||||
|
$baseCurrency = 'USD';
|
||||||
|
|
||||||
|
// use your own credentials, or re-use your existing PDO connection
|
||||||
|
$pdo = new PDO('mysql:host=' . env('DB_HOST') . ';dbname=' . env('DB_DATABASE'), env('DB_USERNAME'), env('DB_PASSWORD'));
|
||||||
|
|
||||||
|
$configuration = new PDOProviderConfiguration(
|
||||||
|
tableName: 'exchange_rate',
|
||||||
|
exchangeRateColumnName: 'exchange_rate',
|
||||||
|
sourceCurrencyCode: $baseCurrency,
|
||||||
|
targetCurrencyColumnName: 'target_currency'
|
||||||
|
);
|
||||||
|
|
||||||
|
// this provider loads exchange rates from your database
|
||||||
|
$provider = new PDOProvider($pdo, $configuration);
|
||||||
|
|
||||||
|
// this provider calculates exchange rates relative to the base currency
|
||||||
|
$provider = new BaseCurrencyProvider($provider, $baseCurrency);
|
||||||
|
|
||||||
|
$converter = new CurrencyConverter($provider);
|
||||||
|
$sourceMoney = Money::of(round($amount, 2), $sourceCurrency, new AutoContext());
|
||||||
|
return $converter->convert($sourceMoney, $targetCurrency, null, RoundingMode::UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toMoneyAmount($amount, $sourceCurrency, $targetCurrency)
|
||||||
|
{
|
||||||
|
return $this->convertMoney($amount, $sourceCurrency, $targetCurrency)->getAmount()->toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.0",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
|
"brick/money": "^0.8.0",
|
||||||
"cknow/laravel-money": "^7.0",
|
"cknow/laravel-money": "^7.0",
|
||||||
"darkaonline/swagger-lume": "^9.0",
|
"darkaonline/swagger-lume": "^9.0",
|
||||||
"doctrine/dbal": "^3.6",
|
"doctrine/dbal": "^3.6",
|
||||||
|
@ -15,7 +16,8 @@
|
||||||
"illuminate/session": "^9.52",
|
"illuminate/session": "^9.52",
|
||||||
"laravel/lumen-framework": "^9.0",
|
"laravel/lumen-framework": "^9.0",
|
||||||
"propaganistas/laravel-phone": "^5.0",
|
"propaganistas/laravel-phone": "^5.0",
|
||||||
"stripe/stripe-php": "^10.13"
|
"stripe/stripe-php": "^10.13",
|
||||||
|
"ext-pdo": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "81090437c0e646c7e1df7fd291f0a3ac",
|
"content-hash": "4835260236c50e25a136ef532dcb5875",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
|
@ -61,6 +61,64 @@
|
||||||
],
|
],
|
||||||
"time": "2023-01-15T23:15:59+00:00"
|
"time": "2023-01-15T23:15:59+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "brick/money",
|
||||||
|
"version": "0.8.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/brick/money.git",
|
||||||
|
"reference": "b530ab64d7f85fdfd5858cde8c57f2f587c8aab8"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/brick/money/zipball/b530ab64d7f85fdfd5858cde8c57f2f587c8aab8",
|
||||||
|
"reference": "b530ab64d7f85fdfd5858cde8c57f2f587c8aab8",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"brick/math": "~0.10.1 || ~0.11.0",
|
||||||
|
"ext-json": "*",
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"brick/varexporter": "~0.3.0",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-pdo": "*",
|
||||||
|
"php-coveralls/php-coveralls": "^2.2",
|
||||||
|
"phpunit/phpunit": "^9.4.3",
|
||||||
|
"vimeo/psalm": "5.4.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-intl": "Required to format Money objects"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Brick\\Money\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Money and currency library",
|
||||||
|
"keywords": [
|
||||||
|
"brick",
|
||||||
|
"currency",
|
||||||
|
"money"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/brick/money/issues",
|
||||||
|
"source": "https://github.com/brick/money/tree/0.8.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/BenMorel",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-01-15T23:59:01+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "cknow/laravel-money",
|
"name": "cknow/laravel-money",
|
||||||
"version": "v7.1.0",
|
"version": "v7.1.0",
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?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::create('payment_aggregator_rates', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('aggregator_id');
|
||||||
|
$table->string('country')->comment("ALL : Pour tous les pays");
|
||||||
|
$table->string('type')->comment("Cash In or Cash Out");
|
||||||
|
$table->string('method')->comment("Methode de paiements");
|
||||||
|
$table->string('channel')->nullable()->comment("Canal ou Reseau concerné");
|
||||||
|
$table->decimal('rate')->default(0)->comment("Taux de commission");
|
||||||
|
$table->decimal('fixed_fees')->nullable()->comment("Frais fixe");
|
||||||
|
$table->string('fixed_fees_currency')->nullable()->comment("Monnaie des frais fixes");
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('payment_aggregator_rates');
|
||||||
|
}
|
||||||
|
};
|
|
@ -53,6 +53,7 @@ $router->group(['middleware' => 'auth'], function () use ($router) {
|
||||||
$router->post('pay','PaymentController@pay');
|
$router->post('pay','PaymentController@pay');
|
||||||
$router->get('checkStatus/{transaction_id}','PaymentController@checkStatus');
|
$router->get('checkStatus/{transaction_id}','PaymentController@checkStatus');
|
||||||
$router->post('payOut','PaymentController@payOut');
|
$router->post('payOut','PaymentController@payOut');
|
||||||
|
$router->get('fees','PaymentController@getFees');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yoomee Endpoints
|
* Yoomee Endpoints
|
||||||
|
|
Loading…
Reference in New Issue