payment adn super attributes
This commit is contained in:
parent
6f5939346a
commit
241f39b99d
|
|
@ -109,7 +109,8 @@
|
|||
"Sarga\\Shop\\": "packages/Sarga/Shop/src",
|
||||
"Sarga\\API\\": "packages/Sarga/API",
|
||||
"Sarga\\Admin\\": "packages/Sarga/Admin/src",
|
||||
"Sarga\\Brand\\": "packages/Sarga/Brand/src"
|
||||
"Sarga\\Brand\\": "packages/Sarga/Brand/src",
|
||||
"Sarga\\Payment\\": "packages/Sarga/Payment"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ return [
|
|||
Sarga\API\Providers\APIServiceProvider::class,
|
||||
Sarga\Admin\Providers\AdminServiceProvider::class,
|
||||
Sarga\Brand\Providers\BrandServiceProvider::class,
|
||||
Sarga\Payment\Providers\PaymentServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -69,12 +69,32 @@ class Product extends JsonResource
|
|||
$this->merge($this->specialPriceInfo()),
|
||||
|
||||
/* super attributes */
|
||||
// $this->mergeWhen($productTypeInstance->isComposite(), [
|
||||
// 'super_attributes' => Attribute::collection($product->super_attributes),
|
||||
// ]),
|
||||
$this->mergeWhen($productTypeInstance->isComposite(), [
|
||||
'super_attributes' => $this->super_attributes,
|
||||
]),
|
||||
];
|
||||
}
|
||||
private function super_attributes(){
|
||||
if(is_countable($this->super_attributes)){
|
||||
return $this->super_attributes->map(function($item, $key){
|
||||
return [
|
||||
'code' => $item->code,
|
||||
'value' => $this->{$item->code},
|
||||
'name' => $item->name,
|
||||
'label' => $item->options->where('id',$this->{$item->code})->first()->admin_name
|
||||
];
|
||||
})->toArray();
|
||||
}else{
|
||||
$item = $this->super_attributes;
|
||||
return [
|
||||
'code' => $item->code,
|
||||
'value' => $this->{$item->code},
|
||||
'name' => $item->name,
|
||||
'label' => $item->options->where('id',$this->{$item->code})->first()->admin_name
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Get special price information.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
return [
|
||||
// 'terminal' => [
|
||||
// 'code' => 'terminal',
|
||||
// 'title' => 'Terminal',
|
||||
// 'description' => 'Card On Delivery',
|
||||
// 'class' => 'Payment\Methods\Terminal',
|
||||
// 'active' => true,
|
||||
// 'sort' => 3,
|
||||
// ],
|
||||
'altynasyr' =>[
|
||||
'code' => 'altynasyr',
|
||||
'title' => 'Altyn Asyr',
|
||||
'description' => 'Altyn Asyr Kartly Töleg',
|
||||
'api_url' => 'https://mpi.gov.tm/payment/rest/',
|
||||
'class' => 'Payment\Methods\AltynAsyr',
|
||||
'active' => false,
|
||||
'sort' => 4
|
||||
],
|
||||
'tfeb' =>[
|
||||
'code' => 'tfeb',
|
||||
'title' =>'TFEB',
|
||||
'description' => 'THE STATE BANK FOR FOREIGN ECONOMIC AFFAIRS OF TURKMENISTAN',
|
||||
'api_url' => 'https://ecomt.tfeb.gov.tm/v1/orders/',
|
||||
'class' => 'Payment\Methods\TFEB',
|
||||
'active' => false,
|
||||
'sort' => 5
|
||||
]
|
||||
];
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
// [
|
||||
// 'key' => 'sales.paymentmethods.terminal',
|
||||
// 'name' => 'Terminal',
|
||||
// 'sort' => 3,
|
||||
// 'fields' => [
|
||||
// [
|
||||
// 'name' => 'title',
|
||||
// 'title' => 'admin::app.admin.system.title',
|
||||
// 'type' => 'depends',
|
||||
// 'depend' => 'active:1',
|
||||
// 'validation' => 'required_if:active,1',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => true,
|
||||
// ], [
|
||||
// 'name' => 'description',
|
||||
// 'title' => 'admin::app.admin.system.description',
|
||||
// 'type' => 'textarea',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => true,
|
||||
// ], [
|
||||
// 'name' => 'instructions',
|
||||
// 'title' => 'admin::app.admin.system.instructions',
|
||||
// 'type' => 'textarea',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => true,
|
||||
// ], [
|
||||
// 'name' => 'generate_invoice',
|
||||
// 'title' => 'admin::app.admin.system.generate-invoice',
|
||||
// 'type' => 'boolean',
|
||||
// 'default_value' => false,
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => false,
|
||||
// ], [
|
||||
// 'name' => 'invoice_status',
|
||||
// 'title' => 'admin::app.admin.system.set-invoice-status',
|
||||
// 'validation' => 'required_if:generate_invoice,1',
|
||||
// 'type' => 'select',
|
||||
// 'options' => [
|
||||
// [
|
||||
// 'title' => 'admin::app.sales.invoices.status-pending',
|
||||
// 'value' => 'pending',
|
||||
// ], [
|
||||
// 'title' => 'admin::app.sales.invoices.status-paid',
|
||||
// 'value' => 'paid',
|
||||
// ],
|
||||
// ],
|
||||
// 'info' => 'admin::app.admin.system.generate-invoice-applicable',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => false,
|
||||
// ], [
|
||||
// 'name' => 'order_status',
|
||||
// 'title' => 'admin::app.admin.system.set-order-status',
|
||||
// 'type' => 'select',
|
||||
// 'options' => [
|
||||
// [
|
||||
// 'title' => 'admin::app.sales.orders.order-status-pending',
|
||||
// 'value' => 'pending',
|
||||
// ], [
|
||||
// 'title' => 'admin::app.sales.orders.order-status-pending-payment',
|
||||
// 'value' => 'pending_payment',
|
||||
// ], [
|
||||
// 'title' => 'admin::app.sales.orders.order-status-processing',
|
||||
// 'value' => 'processing',
|
||||
// ],
|
||||
// ],
|
||||
// 'info' => 'admin::app.admin.system.generate-invoice-applicable',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => false,
|
||||
// ], [
|
||||
// 'name' => 'active',
|
||||
// 'title' => 'admin::app.admin.system.status',
|
||||
// 'type' => 'boolean',
|
||||
// 'validation' => 'required',
|
||||
// 'channel_based' => true,
|
||||
// 'locale_based' => true,
|
||||
// ], [
|
||||
// 'name' => 'sort',
|
||||
// 'title' => 'admin::app.admin.system.sort_order',
|
||||
// 'type' => 'select',
|
||||
// 'options' => [
|
||||
// [
|
||||
// 'title' => '1',
|
||||
// 'value' => 1,
|
||||
// ], [
|
||||
// 'title' => '2',
|
||||
// 'value' => 2,
|
||||
// ], [
|
||||
// 'title' => '3',
|
||||
// 'value' => 3,
|
||||
// ], [
|
||||
// 'title' => '4',
|
||||
// 'value' => 4,
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
[
|
||||
'key' => 'sales.paymentmethods.altynasyr',
|
||||
'name' => 'admin::app.admin.system.altyn-asyr',
|
||||
'sort' => 4,
|
||||
'fields' => [
|
||||
[
|
||||
'name' => 'title',
|
||||
'title' => 'admin::app.admin.system.title',
|
||||
'type' => 'text',
|
||||
'validation' => 'required',
|
||||
'locale_based' => true
|
||||
], [
|
||||
'name' => 'description',
|
||||
'title' => 'admin::app.admin.system.description',
|
||||
'type' => 'textarea',
|
||||
'locale_based' => true
|
||||
], [
|
||||
'name' => 'business_account',
|
||||
'title' => 'admin::app.admin.system.business-account',
|
||||
'type' => 'text',
|
||||
'validation' => 'required'
|
||||
],[
|
||||
'name' => 'account_password',
|
||||
'title' => 'admin::app.account.password',
|
||||
'type' => 'password',
|
||||
'validation' => 'required'
|
||||
], [
|
||||
'name' => 'active',
|
||||
'title' => 'admin::app.admin.system.status',
|
||||
'type' => 'boolean',
|
||||
'validation' => 'required',
|
||||
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'sales.paymentmethods.tfeb',
|
||||
'name' => 'TFEB',
|
||||
'sort' => 5,
|
||||
'fields' => [
|
||||
[
|
||||
'name' => 'title',
|
||||
'title' => 'admin::app.admin.system.title',
|
||||
'type' => 'text',
|
||||
'validation' => 'required',
|
||||
'locale_based' => true
|
||||
], [
|
||||
'name' => 'description',
|
||||
'title' => 'admin::app.admin.system.description',
|
||||
'type' => 'textarea',
|
||||
'locale_based' => true
|
||||
], [
|
||||
'name' => 'client_id',
|
||||
'title' => 'ClientID',
|
||||
'type' => 'text',
|
||||
'validation' => 'required'
|
||||
],[
|
||||
'name' => 'client_secret',
|
||||
'title' => 'Client Secret',
|
||||
'type' => 'text',
|
||||
'validation' => 'required'
|
||||
],[
|
||||
'name' => 'merchant',
|
||||
'title' => 'Merchant',
|
||||
'type' => 'text',
|
||||
'validation' => 'required'
|
||||
],[
|
||||
'name' => 'terminal',
|
||||
'title' => 'Terminal',
|
||||
'type' => 'text',
|
||||
'validation' => 'required'
|
||||
], [
|
||||
'name' => 'active',
|
||||
'title' => 'admin::app.admin.system.status',
|
||||
'type' => 'boolean',
|
||||
'validation' => 'required',
|
||||
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddOrderIdToCartPaymentTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('cart_payment', function (Blueprint $table) {
|
||||
$table->string('order_id')->nullable();
|
||||
// $table->unsignedSmallInteger('OrderStatus')->nullable();
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('cart_payment', function (Blueprint $table) {
|
||||
$table->dropColumn('order_id');
|
||||
// $table->dropColumn('OrderStatus');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace Sarga\Payment\Http\Controllers;
|
||||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Webkul\Checkout\Facades\Cart;
|
||||
use Sarga\Payment\CardPayment\AltynAsyr;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
|
||||
class AltynAsyrController extends Controller
|
||||
{
|
||||
/**
|
||||
* OrderRepository object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $orderRepository;
|
||||
|
||||
/**
|
||||
* @var AltynAsyr object
|
||||
*/
|
||||
protected $altynAsyr;
|
||||
|
||||
public function __construct(OrderRepository $orderRepository, AltynAsyr $altynAsyr)
|
||||
{
|
||||
$this->orderRepository = $orderRepository;
|
||||
$this->altynAsyr = $altynAsyr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to payment gateway
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function redirect(){
|
||||
// register order to payment gateway
|
||||
try{
|
||||
$result = $this->altynAsyr->registerOrder();
|
||||
if($result['errorCode'] == 0){
|
||||
// dd($result);
|
||||
$this->altynAsyr->registerOrderId($result['orderId']);
|
||||
return redirect($result['formUrl']);
|
||||
}
|
||||
else{//if already registered or otkazana w dostupe
|
||||
//todo log
|
||||
session()->flash('error', $result['errorMessage']);
|
||||
}
|
||||
|
||||
}catch (\Exception $exception){
|
||||
//todo Check exception if not connection excepion redirect to login ore somewhere if session expired
|
||||
session()->flash('error', $exception->getMessage());
|
||||
}
|
||||
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Success payment
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function success(){
|
||||
try {
|
||||
$result = $this->altynAsyr->getOrderStatus();
|
||||
|
||||
if ($result['ErrorCode'] == 0) {
|
||||
if ($result['OrderStatus'] == 2) {
|
||||
$order = $this->orderRepository->create(Cart::prepareDataForOrder());
|
||||
//todo save card details to cart->payment
|
||||
Cart::deActivateCart();
|
||||
|
||||
session()->flash('order', $order);
|
||||
|
||||
return redirect()->route('shop.checkout.success');
|
||||
} else {
|
||||
return view('payment::order-status')->with('cart', $this->altynAsyr->getCart());
|
||||
}
|
||||
|
||||
} else {
|
||||
session()->flash('error', trans('payment.unsuccessfull'));
|
||||
}
|
||||
}
|
||||
catch (ConnectException $connectException){
|
||||
session()->flash('error',trans('payment::messages.connection_failed'));
|
||||
}
|
||||
catch (\Exception $exception){
|
||||
session()->flash('error',trans('payment::messages.session_expired'));
|
||||
}
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel payment from gateway
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function cancel(){
|
||||
session()->flash('error', trans('payment::messages.unsuccessfull'));
|
||||
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
public function status(){
|
||||
|
||||
return view('payment::order-status');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 7/26/2019
|
||||
* Time: 18:09
|
||||
*/
|
||||
|
||||
namespace Sarga\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/24/2021
|
||||
* Time: 17:16
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Http\Controllers;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Webkul\Checkout\Facades\Cart;
|
||||
use Sarga\Payment\CardPayment\TFEB;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
|
||||
|
||||
class TFEBController extends Controller
|
||||
{
|
||||
/**
|
||||
* OrderRepository object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $orderRepository;
|
||||
|
||||
/**
|
||||
* @var AltynAsyr object
|
||||
*/
|
||||
protected $teb;
|
||||
|
||||
public function __construct(OrderRepository $orderRepository, TFEB $teb)
|
||||
{
|
||||
$this->guard = request()->has('token') ? 'api' : 'customer';
|
||||
|
||||
auth()->setDefaultDriver($this->guard);
|
||||
|
||||
// $this->middleware('auth:' . $this->guard);
|
||||
|
||||
$this->orderRepository = $orderRepository;
|
||||
$this->teb = $teb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to payment gateway
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function redirect(){
|
||||
// register order to payment gateway
|
||||
try{
|
||||
$result = json_decode($this->teb->registerOrder(),true);
|
||||
Log::info($result);
|
||||
if($result['response']['operationResult'] == 'OPG-00100' && $orderId = $result['response']['orderId']){
|
||||
// dd($result);
|
||||
$this->teb->registerOrderId($orderId);
|
||||
return request()->has('token') ? response()->json(['status' => true, 'redirect_url' => $result['_links']['redirectToCheckout']['href']]):
|
||||
redirect($result['_links']['redirectToCheckout']['href']);
|
||||
}
|
||||
else{//if already registered or otkazana w dostupe
|
||||
//todo log
|
||||
if(request()->has('token')){
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => $result['response']['operationResultDescription']
|
||||
]);
|
||||
}
|
||||
session()->flash('error', $result['response']['operationResultDescription']);
|
||||
}
|
||||
|
||||
}catch (\Exception $exception){
|
||||
//todo Check exception if not connection excepion redirect to login ore somewhere if session expired
|
||||
Log::error($exception);
|
||||
|
||||
if(request()->has('token')){
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => $exception->getMessage()
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
session()->flash('error', $exception->getMessage());
|
||||
}
|
||||
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Success payment
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function complete(){
|
||||
try {
|
||||
$result = json_decode($this->teb->getOrderStatus(),true);
|
||||
|
||||
if ($result['response']['operationResult'] == 'GEN-00000') {
|
||||
$order = $this->orderRepository->create(Cart::prepareDataForOrder());
|
||||
//todo save card details to cart->payment
|
||||
Cart::deActivateCart();
|
||||
|
||||
session()->flash('order', $order);
|
||||
|
||||
return redirect()->route('shop.checkout.success');
|
||||
|
||||
} else {
|
||||
|
||||
session()->flash('error', trans('payment.unsuccessfull'));
|
||||
}
|
||||
}
|
||||
catch (ConnectException $connectException){
|
||||
|
||||
session()->flash('error',trans('payment::messages.connection_failed'));
|
||||
}
|
||||
catch (\Exception $exception){
|
||||
Log::error($exception);
|
||||
|
||||
session()->flash('error',$exception->getMessage());
|
||||
}
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel payment from gateway
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function cancel(){
|
||||
session()->flash('error', trans('payment::messages.unsuccessfull'));
|
||||
|
||||
return redirect()->route('shop.checkout.cart.index');
|
||||
}
|
||||
|
||||
public function status(){
|
||||
|
||||
return view('payment::order-status');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/22/2021
|
||||
* Time: 18:50
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Http\Resoures\Payment;
|
||||
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class Browser extends JsonResource
|
||||
{
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
"AcceptHeader" => "*/*",
|
||||
"IpAddress" => "10.33.27.3",
|
||||
"Language" => "ru-RU",
|
||||
"ScreenColorDepth" => 48,
|
||||
"ScreenHeight" => 1200,
|
||||
"ScreenWidth" => 1900,
|
||||
"UserAgentString" => "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.3"
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/22/2021
|
||||
* Time: 18:33
|
||||
*/
|
||||
|
||||
namespace Sarga\Http\Resoures\Payment;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class Card extends JsonResource
|
||||
{
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
"PAN" => "6015840000000843",
|
||||
"ExpiryDate" => "2401",
|
||||
"SecurityCode2" => "725",
|
||||
"Name" => "John Doe",
|
||||
"TAVV" => null,
|
||||
"IsCardOnFile" => false
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Sarga\Payment\Http\Resoures\Payment;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CartAddress extends JsonResource
|
||||
{
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
"SameAsShipping" => true,
|
||||
"Line1"=> 'L1:'.substr($this->address1,0,47),//Line1 must be max 50 chars
|
||||
"Line2"=> 'L2:'.substr($this->address2,0,47),
|
||||
"PostCode"=> "74000",
|
||||
"City"=> "01",
|
||||
"CountrySubdivision"=> "01",
|
||||
"Country"=> "196"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/22/2021
|
||||
* Time: 18:36
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Http\Resoures\Payment;
|
||||
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class Cusromer extends JsonResource
|
||||
{
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
"Name" => $this->name,
|
||||
"Language" => "en-US",
|
||||
"Email" => $this->phone.'@ozan.com.tm',
|
||||
"HomePhone" => [
|
||||
"cc" => "993",
|
||||
"subscriber" => $this->phone
|
||||
],
|
||||
"MobilePhone" => [
|
||||
"cc" => "993",
|
||||
"subscriber" => $this->phone
|
||||
],
|
||||
"WorkPhone" => null
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/22/2021
|
||||
* Time: 18:24
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Http\Resoures\Payment;
|
||||
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
class Order extends JsonResource
|
||||
{
|
||||
public function getConfigData($field)
|
||||
{
|
||||
return core()->getConfigData('sales.paymentmethods.tfeb.' . $field);
|
||||
}
|
||||
|
||||
public function toArray($request){
|
||||
return [
|
||||
"RequestId" => $this->id,
|
||||
"Environment" => [
|
||||
"Merchant" => [
|
||||
"Id" =>$this->getConfigData('merchant')
|
||||
],
|
||||
"POI" => [
|
||||
"Id" => $this->getConfigData('terminal'),
|
||||
"Language" => "en-US"
|
||||
],
|
||||
"Transport" => [
|
||||
"MerchantFinalResponseUrl" => route('paymentmethod.tfeb.complete',['uid'=>auth()->user()->id]),
|
||||
"ChallengeResponseUrl" => route('paymentmethod.tfeb.complete',['uid'=>auth()->user()->id]),
|
||||
"ChallengeWindowSize" => 3,
|
||||
"ChallengeResponseData"=> null,
|
||||
"ThreeDSMethodNotificationUrl"=> "",
|
||||
"MethodCompletion"=> false,
|
||||
"Consent" => false,
|
||||
"EndpointHostAddress" => "/orders/7b72093d-bb14-45b5-a6ec-a3ca5f6c2731"
|
||||
],
|
||||
"SponsoredMerchant"=> null,
|
||||
"SponsoredMerchantPOI"=> null,
|
||||
"Card" => null,
|
||||
"CardRecipient"=> null,
|
||||
"Customer" => [
|
||||
"Name" => $this->customer_first_name,
|
||||
"Language" => "en-US",
|
||||
"Email" => $this->customer_email.'@ozan.com.tm',
|
||||
"HomePhone" => [
|
||||
"cc" => "993",
|
||||
"subscriber" => $this->customer_email
|
||||
],
|
||||
"MobilePhone" => [
|
||||
"cc" => "993",
|
||||
"subscriber" => $this->customer_email
|
||||
],
|
||||
"WorkPhone" => null
|
||||
],
|
||||
|
||||
"CustomerDevice" => [
|
||||
"Browser" => [
|
||||
"AcceptHeader" => "*/*",
|
||||
"IpAddress" => request()->ip(),
|
||||
"Language" => "en-US",
|
||||
"ScreenColorDepth" => 48,
|
||||
"ScreenHeight" => 1200,
|
||||
"ScreenWidth" => 1900,
|
||||
"UserAgentString" => "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.3"
|
||||
],
|
||||
"MobileApp" => null,
|
||||
],
|
||||
'BillingAddress' => CartAddress::make($this->billing_address),
|
||||
'ShippingAddress' => CartAddress::make($this->shipping_address),
|
||||
|
||||
],
|
||||
"Transaction" => [
|
||||
"InvoiceNumber" => "Acquirer",
|
||||
"Type" => "CRDP",
|
||||
"AdditionalService" => null,
|
||||
"TransactionText" => "ozan online sowda",
|
||||
"TotalAmount" => (double)$this->grand_total,
|
||||
"Currency" => "934",
|
||||
"CurrencyConversion"=> null,
|
||||
"DetailedAmount"=> null,
|
||||
"AirlineItems"=> null,
|
||||
"MerchantOrderId" => $this->id,
|
||||
"AutoComplete" => true,
|
||||
"Instalment"=> null,
|
||||
"MerchantCategoryCode"=> null,
|
||||
"AntiMoneyLaundering"=> [
|
||||
"SenderName"=> $this->customer_first_name,
|
||||
"SenderDateOfBirth"=> null,
|
||||
"SenderPlaceOfBirth"=> null,
|
||||
"NationalIdentifier"=> null,
|
||||
"NationalIdentifierCountry"=> null,
|
||||
"NationalIdentifierExpiry"=> null,
|
||||
"PassportNumber"=> "123-456",
|
||||
"PassportIssuingCountry"=> null,
|
||||
"PassportExpiry"=> "20291/12/01"
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Sarga\Payment\Http\Controllers\AltynAsyrController;
|
||||
use Sarga\Payment\Http\Controllers\TFEBController;
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 7/26/2019
|
||||
* Time: 16:49
|
||||
*/
|
||||
Route::group(['prefix' =>'payment','middleware' => ['web', 'locale', 'theme', 'currency']], function ()
|
||||
{
|
||||
Route::get('altynasyr/redirect', [AltynAsyrController::class,'redirect'])
|
||||
->name('paymentmethod.altynasyr.redirect');
|
||||
|
||||
Route::get('altynasyr/success', [AltynAsyrController::class,'success'])
|
||||
->name('paymentmethod.altynasyr.success');
|
||||
|
||||
Route::get('altynasyr/cancel', [AltynAsyrController::class,'cancel'])
|
||||
->name('paymentmethod.altynasyr.cancel');
|
||||
|
||||
Route::get('tfeb/redirect',[TFEBController::class,'redirect'])
|
||||
->name('paymentmethod.tfeb.redirect');
|
||||
|
||||
Route::get('tfeb/complete', [TFEBController::class,'complete'])
|
||||
->name('paymentmethod.tfeb.complete');
|
||||
|
||||
Route::get('tfeb/cancel', [TFEBController::class,'cancel'])
|
||||
->name('paymentmethod.tfeb.cancel');
|
||||
});
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 7/24/2019
|
||||
* Time: 16:48
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Methods;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Client;
|
||||
use Webkul\Payment\Payment\Payment;
|
||||
|
||||
|
||||
class AltynAsyr extends Payment
|
||||
{
|
||||
protected $code = 'altynasyr';
|
||||
|
||||
public function getRedirectUrl():String
|
||||
{
|
||||
return route('paymentmethod.altynasyr.redirect');
|
||||
}
|
||||
|
||||
private function getApiClient():Client{
|
||||
return new Client([
|
||||
'base_uri' => $this->getConfigData('api_url'),
|
||||
'connect_timeout' => 10,//sec
|
||||
'timeout' => 10,//sec
|
||||
'verify' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function isRegistered(){
|
||||
$payment = $this->getCart()->payment;
|
||||
return (!empty($payment) && !empty($payment->orderId));
|
||||
}
|
||||
|
||||
public function registerOrder(){
|
||||
|
||||
$cart = $this->getCart();
|
||||
$lifeTime = config('session.lifetime',10);//10 minutes
|
||||
|
||||
$client = $this->getApiClient();
|
||||
|
||||
|
||||
$params =[
|
||||
'form_params' => [
|
||||
'userName' => $this->getConfigData('business_account'),//'103161020074',
|
||||
'password' => $this->getConfigData('account_password'),//'E12wKp7a7vD8',
|
||||
'sessionTimeoutSecs' => $lifeTime * 30, //(600 sec)
|
||||
'orderNumber' =>$cart->id . Carbon::now()->timestamp,
|
||||
'currency' => 934,
|
||||
'language' => 'ru',
|
||||
'description'=> "bagisto multivendor {$cart->grand_total}m.",
|
||||
'amount' =>$cart->grand_total * 100,// amount w kopeykah
|
||||
'returnUrl' => route('paymentmethod.altynasyr.success'),
|
||||
'failUrl' => route('paymentmethod.altynasyr.cancel')
|
||||
],
|
||||
];
|
||||
|
||||
return json_decode($client->post('register.do',$params)->getBody(),true);
|
||||
|
||||
}
|
||||
|
||||
public function registerOrderId($orderId){
|
||||
$payment = $this->getCart()->payment;
|
||||
$payment->order_id = $orderId;
|
||||
// dd($payment);
|
||||
// $payment->paymentFormUrl = $formUrl;
|
||||
$payment->save();
|
||||
}
|
||||
|
||||
public function getOrderStatus(){
|
||||
$client = $this->getApiClient();
|
||||
$payment = $this->getCart()->payment;
|
||||
|
||||
$params = [
|
||||
'form_params' => [
|
||||
'userName' => $this->getConfigData('business_account'),//'103161020074',
|
||||
'password' => $this->getConfigData('account_password'),//'E12wKp7a7vD8',
|
||||
'orderId' => $payment->order_id,
|
||||
]
|
||||
];
|
||||
|
||||
return json_decode($client->post('getOrderStatus.do',$params)->getBody(),true);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 9/22/2021
|
||||
* Time: 15:40
|
||||
*/
|
||||
|
||||
namespace Sarga\Payment\Methods;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Sarga\Payment\Http\Resoures\Payment\Order;
|
||||
use Webkul\Payment\Payment\Payment;
|
||||
|
||||
class TFEB extends Payment
|
||||
{
|
||||
|
||||
protected $code = 'tfeb';
|
||||
|
||||
private function getApiClient():Client{
|
||||
return new Client([
|
||||
'base_uri' => $this->getConfigData('api_url'),
|
||||
'connect_timeout' => 55,//sec
|
||||
'timeout' => 55,//sec
|
||||
'verify' => false,
|
||||
'headers' =>[
|
||||
'ClientId' => $this->getConfigData('client_id'),
|
||||
'ClientSecret' => $this->getConfigData('client_secret'),
|
||||
'Accept' => "application/hal+json",
|
||||
"Content-Type" => 'application/json'
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function registerOrder(){
|
||||
|
||||
$client = $this->getApiClient();
|
||||
$cart_order = new Order($this->getCart());
|
||||
$body = $cart_order->toJson();
|
||||
$params =[
|
||||
'body' => $body
|
||||
];
|
||||
|
||||
return $client->post('',$params)->getBody();
|
||||
|
||||
}
|
||||
|
||||
public function getRedirectUrl()
|
||||
{
|
||||
return route('paymentmethod.tfeb.redirect');
|
||||
}
|
||||
|
||||
public function isRegistered(){
|
||||
$payment = $this->getCart()->payment;
|
||||
return (!empty($payment) && !empty($payment->orderId));
|
||||
}
|
||||
|
||||
public function getOrderStatus(){
|
||||
$client = $this->getApiClient();
|
||||
$payment = $this->getCart()->payment;
|
||||
|
||||
return $client->get($payment->order_id)->getBody();
|
||||
}
|
||||
|
||||
public function registerOrderId($orderId){
|
||||
$payment = $this->getCart()->payment;
|
||||
$payment->order_id = $orderId;
|
||||
// dd($payment);
|
||||
// $payment->paymentFormUrl = $formUrl;
|
||||
$payment->save();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Sarga\Payment\Methods;
|
||||
|
||||
use Webkul\Payment\Payment\Payment;
|
||||
|
||||
class Terminal extends Payment
|
||||
{
|
||||
/**
|
||||
* Payment method code
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $code = 'terminal';
|
||||
|
||||
public function getRedirectUrl()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace Sarga\Payment\Providers;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Routing\Router;
|
||||
class PaymentServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(Router $router)
|
||||
{
|
||||
// include __DIR__ . '/../Http/routes.php';
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'payment');
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../Database/migrations');
|
||||
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'payment');
|
||||
}
|
||||
public function register()
|
||||
{
|
||||
$this->mergeConfigFrom(
|
||||
dirname(__DIR__) . '/Config/paymentmethods.php', 'paymentmethods'
|
||||
);
|
||||
$this->mergeConfigFrom(
|
||||
dirname(__DIR__) . '/Config/system.php', 'core'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 8/5/2019
|
||||
* Time: 11:22
|
||||
*/
|
||||
return [
|
||||
'unsuccessfull' => 'Insufficient balance or card credentials you supplied were not correct or did not grant access.',
|
||||
'connection_failed' => 'Unable to connect to bank service. Please try again later!.',
|
||||
'session_expired' => 'Session expired please try again later.',
|
||||
'processing_payment' => 'Your payment is being processed... Please press the refresh button if page doesnt refreshes',
|
||||
'refresh' => 'Refresh'
|
||||
];
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 8/5/2019
|
||||
* Time: 11:22
|
||||
*/
|
||||
return [
|
||||
'unsuccessfull' => 'Недостаточный баланс или учетные данные карты, которые вы указали, были неверными или не давали доступа.',
|
||||
'connection_failed' => 'Невозможно подключиться к банковской услуге. Пожалуйста, повторите попытку позже!.',
|
||||
'session_expired' => 'Срок действия сеанса истек, повторите попытку позже.',
|
||||
'processing_payment' => 'Ваш платеж обрабатывается ... Нажмите кнопку "Обновить", если страница не обновляется.',
|
||||
'refresh' => 'Обновить'
|
||||
];
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: merdan
|
||||
* Date: 8/5/2019
|
||||
* Time: 11:22
|
||||
*/
|
||||
return [
|
||||
'unsuccessfull' => 'Hasabyňyzda ýeterli serişde ýok. Ýa-da kart maglumatlaryňyz nädogry girizdiňiz',
|
||||
'connection_failed' => 'Bank bilen aragatnaşykda säwlik ýüze çykdy. Ýene birsalymdan täzeden synanşyp görmegiňizi haýş edýäris!',
|
||||
'session_expired' => 'Siziň sessiýaňyzyň wagty doldy',
|
||||
'processing_payment' => 'Siziň tölegiňiziň üstünde işlenilýär.... Egerde sahypa täzelenmese. Aşakdaky dügmä basmagyňyzy haýyş edýäris.',
|
||||
'refresh' => 'Täzele'
|
||||
];
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
@extends('shop::layouts.master')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('shop::app.checkout.onepage.title') }}
|
||||
@stop
|
||||
|
||||
@section('content-wrapper')
|
||||
|
||||
<div class="checkout-process">
|
||||
<div class="col-main">
|
||||
<div class="step-content review">
|
||||
<div class="form-container">
|
||||
{{--@if($result['ErrorMessage'])--}}
|
||||
<div class="alert alert-error mb-20">
|
||||
<strong class="text-success">@lang('payment::messages.processing_payment')</strong>
|
||||
<form method="GET" action="{{route('paymentmethod.altynasyr.success')}}">
|
||||
<button type="submit" name="orderId" value="{{$cart->payment->order_id}}">@lang('payment::messages.refresh')</button>
|
||||
</form>
|
||||
</div>
|
||||
{{--@endif--}}
|
||||
<div class="form-header mb-30">
|
||||
<span class="checkout-step-heading">{{ __('shop::app.checkout.onepage.summary') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="address-summary">
|
||||
@if ($billingAddress = $cart->billing_address)
|
||||
<div class="billing-address">
|
||||
<div class="card-title mb-20">
|
||||
<b>{{ __('shop::app.checkout.onepage.billing-address') }}</b>
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<ul>
|
||||
<li class="mb-10">
|
||||
{{ $billingAddress->name }}
|
||||
</li>
|
||||
<li class="mb-10">
|
||||
{{ $billingAddress->address1 }},<br/> {{ $billingAddress->state }}
|
||||
</li>
|
||||
<li class="mb-10">
|
||||
{{ core()->country_name($billingAddress->country) }} {{ $billingAddress->postcode }}
|
||||
</li>
|
||||
|
||||
<span class="horizontal-rule mb-15 mt-15"></span>
|
||||
|
||||
<li class="mb-10">
|
||||
{{ __('shop::app.checkout.onepage.contact') }} : {{ $billingAddress->phone }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($shippingAddress = $cart->shipping_address)
|
||||
<div class="shipping-address">
|
||||
<div class="card-title mb-20">
|
||||
<b>{{ __('shop::app.checkout.onepage.shipping-address') }}</b>
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<ul>
|
||||
<li class="mb-10">
|
||||
{{ $shippingAddress->name }}
|
||||
</li>
|
||||
<li class="mb-10">
|
||||
{{ $shippingAddress->address1 }},<br/> {{ $shippingAddress->state }}
|
||||
</li>
|
||||
<li class="mb-10">
|
||||
{{ core()->country_name($shippingAddress->country) }} {{ $shippingAddress->postcode }}
|
||||
</li>
|
||||
|
||||
<span class="horizontal-rule mb-15 mt-15"></span>
|
||||
|
||||
<li class="mb-10">
|
||||
{{ __('shop::app.checkout.onepage.contact') }} : {{ $shippingAddress->phone }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
@inject ('productImageHelper', 'Webkul\Product\Helpers\ProductImage')
|
||||
|
||||
<div class="cart-item-list mt-20">
|
||||
@foreach ($cart->items as $item)
|
||||
|
||||
<?php
|
||||
$product = $item->product;
|
||||
|
||||
if ($product->type == "configurable")
|
||||
$productBaseImage = $productImageHelper->getProductBaseImage($item->child->product);
|
||||
else
|
||||
$productBaseImage = $productImageHelper->getProductBaseImage($item->product);
|
||||
?>
|
||||
|
||||
<div class="item mb-5" style="margin-bottom: 5px;">
|
||||
<div class="item-image">
|
||||
<img src="{{ $productBaseImage['medium_image_url'] }}" />
|
||||
</div>
|
||||
|
||||
<div class="item-details">
|
||||
|
||||
{!! view_render_event('bagisto.shop.checkout.name.before', ['item' => $item]) !!}
|
||||
|
||||
<div class="item-title">
|
||||
{{ $product->name }}
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.shop.checkout.name.after', ['item' => $item]) !!}
|
||||
{!! view_render_event('bagisto.shop.checkout.price.before', ['item' => $item]) !!}
|
||||
|
||||
<div class="row">
|
||||
<span class="title">
|
||||
{{ __('shop::app.checkout.onepage.price') }}
|
||||
</span>
|
||||
<span class="value">
|
||||
{{ core()->currency($item->base_price) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.shop.checkout.price.after', ['item' => $item]) !!}
|
||||
{!! view_render_event('bagisto.shop.checkout.quantity.before', ['item' => $item]) !!}
|
||||
|
||||
<div class="row">
|
||||
<span class="title">
|
||||
{{ __('shop::app.checkout.onepage.quantity') }}
|
||||
</span>
|
||||
<span class="value">
|
||||
{{ $item->quantity }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.shop.checkout.quantity.after', ['item' => $item]) !!}
|
||||
|
||||
@if ($product->type == 'configurable')
|
||||
{!! view_render_event('bagisto.shop.checkout.options.after', ['item' => $item]) !!}
|
||||
|
||||
<div class="summary" >
|
||||
{{ Cart::getProductAttributeOptionDetails($item->child->product)['html'] }}
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.shop.checkout.options.after', ['item' => $item]) !!}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="order-description mt-20">
|
||||
<div class="pull-left" style="width: 60%; float: left;">
|
||||
<div class="shipping">
|
||||
<div class="decorator">
|
||||
<i class="icon shipping-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="text">
|
||||
{{ core()->currency($cart->selected_shipping_rate->base_price) }}
|
||||
|
||||
<div class="info">
|
||||
{{ $cart->selected_shipping_rate->method_title }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment">
|
||||
<div class="decorator">
|
||||
<i class="icon payment-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="text">
|
||||
{{ core()->getConfigData('sales.paymentmethods.' . $cart->payment->method . '.title') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="pull-right" style="width: 40%; float: left;">
|
||||
<slot name="summary-section"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<div class="row">
|
||||
<p class="text-danger">Some problem occured while connecting with your bank.Please try again later!</p>
|
||||
<p class="text-danger">RESPONSE : {{$message}}</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "merdan/payment",
|
||||
"description": "Local payment methods",
|
||||
"require": {
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "merdiano",
|
||||
"email": "merdan.m@gmail.com"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
Loading…
Reference in New Issue