Here is a Sample Plugin with a Custom payment gateway implemented, you can explore it to understand how it actually work
https://github.com/xgenious-official/nazmart-plugin-sample
First, create a custom module using the artisan command,
php artisan module:make ModuleName
Put this in your custom payment module module.json file
"paymentGateway": {
"name": "Your Payment Gateway Name",
"slug": "payment_gateway_slug",
"tenant": false,
"chargeCustomerMethodNameSpace": "Modules\\TestManage\\Http\\Controllers\\TestManageController",
"chargeCustomerMethodName": "paymentGateway",
"test_mode" : false,
"status" : true,
"extraInfoMarkupBlade" : "payment_blade",
"logo_file" : "payment-logo.png"
}
Put your payment gateway logo_file
in Module > assets > payment-gateway-image and place the logo file name in the module.json
Create extraInfoMarkupBlade
blade file in Module > Resource > views > payment-gateway-view and place the blade file name in the module.json, if any extra information is needed while checkout
extraInfoMarkupBlade
the file looks like this,
<div class="form-group single-input mt-4">
<label for="ali">AliPay ID Here</label>
<input type="text" name="ali_id"
class="form-control form--control mt-2"
placeholder="Ali ID" id="ali">
<label for="ali1">Ali Express Code Here</label>
<input type="text" name="ali_express_code"
class="form-control form--control mt-2"
placeholder="Ali Express Code" id="ali1">
<label for="ali2">Ali Transaction Attachment</label>
<input type="file" name="ali_attachment"
class="form-control form--control mt-2"
placeholder="Transaction ID" accept="image/*" id="ali2">
</div>
Create a Controller or PHP class and include its namespace in the module.json file
Create a charge customer method inside the class and include the method name in the JSON file like this,
In the chargeCustomerMethod
take an array-type parameter and you will find the payment details in it to continue your logic.
The chargeCustomerMethod
will look like this,
public function customChargeCustomer($args){
// $args has the payment details along with request information
// Your code
}
You can update your current payment details from the database like this,
// For Landlord
PaymentLogs::find($args['payment_details']['id'])->update([
'transaction_id' => $args['request']['ali_id'] ?? '',
'attachments' => $args['request']['ali_express_code'] ?? '',
'status' => 'complete',
'payment_status' => 'complete',
'updated_at' => Carbon::now()
]);
// For Tenant
ProductOrder::find($args['order_id'])->update([
'payment_status' => 'success'
]);
To create tenant use this functions according to your logic,
public function tenant_create_event_with_credential_mail($order_id)
{
$log = PaymentLogs::findOrFail($order_id);
if (empty($log))
{
abort(462,__('Does not exist, Tenant does not exists'));
}
$user = User::where('id', $log->user_id)->first();
$tenant = Tenant::find($log->tenant_id);
if (!empty($log) && $log->payment_status == 'complete' && is_null($tenant)) {
event(new TenantRegisterEvent($user, $log->tenant_id, get_static_option('default_theme')));
try {
$raw_pass = get_static_option_central('tenant_admin_default_password') ??'12345678';
$credential_password = $raw_pass;
$credential_email = $user->email;
$credential_username = get_static_option_central('tenant_admin_default_username') ?? 'super_admin';
Mail::to($credential_email)->send(new TenantCredentialMail($credential_username, $credential_password));
} catch (\Exception $e) {
}
} else if (!empty($log) && $log->payment_status == 'complete' && !is_null($tenant) && $log->is_renew == 0) {
try {
$raw_pass = get_static_option_central('tenant_admin_default_password') ??'12345678';
$credential_password = $raw_pass;
$credential_email = $user->email;
$credential_username = get_static_option_central('tenant_admin_default_username') ?? 'super_admin';
Mail::to($credential_email)->send(new TenantCredentialMail($credential_username, $credential_password));
} catch (\Exception $exception) {
$message = $exception->getMessage();
if(str_contains($message,'Access denied')){
abort(463,__('Database created failed, Make sure your database user has permission to create database'));
}
}
}
return true;
}
public function updateTenant(){
\DB::table('tenants')->where('id', $tenant->id)->update([
'renew_status' => $renew_status = is_null($tenant->renew_status) ? 0 : $tenant->renew_status+1,
'is_renew' => $renew_status == 0 ? 0 : 1,
'start_date' => $payment_log->start_date,
'expire_date' => get_plan_left_days($payment_log->package_id, $tenant->expire_date)
]);
}
Before proceeding to the success page wrap the order-id,
$id = random_int(100000,999999).$charge_data->id.random_int(100000,999999);
return redirect()->route('landlord.frontend.order.payment.success', $id);
Payment gateway sidebar menu for admin
Add the below code inside the paymentGateway
. The admin_settings
accepts an array, so you can add multiple menu items inside the menu_item
. Examples are the following,
"admin_settings": {
"menu_item": [
{
"id" : "test-settings-menu-submenu",
"label": "Test Payment Menu",
"route": "tenant.admin.activity.log",
"tenantRoute": "tenant.admin.newsletter",
"permissions": ["general-settings-page-settings"]
}
]
}
This menu can be used for both landlord and tenant. The route for landlord and tenant is separate. route
for the landlord and tenantRoute
for the tenant. The menu can be enabled or disabled for the
landlord or tenant by changing these two attribute show_admin_landlord
and show_admin_tenant
The full file for the payment gateway inside the module.json will look like something this,
{
"name": "TestManage",
"alias": "testmanage",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\TestManage\\Providers\\TestManageServiceProvider"
],
"aliases": {},
"files": [],
"requires": [],
"nazmartMetaData": {
"style": [],
"admin_settings": {
"menu_item": [
{
"id" : "test-settings-menu",
"label": "Test Menu",
"route": "tenant.admin.newsletter",
"tenantRoute": "tenant.admin.newsletter",
"parent": null,
"permissions": ["general-settings-page-settings", "general-settings-site-identity"],
"icon": "mdi mdi-settings"
},
{
"id" : "test-settings-menu-submenu",
"label": "Test Sub Menu",
"route": "tenant.admin.activity.log",
"parent": "test-settings-menu",
"permissions": ["general-settings-page-settings"]
}
]
},
"header_hook": [],
"footer_hook": [],
"pageBuilderAddon": [
"Modules\\TestManage\\Http\\PageBuilder\\Addons\\TestAddon"
],
"widgetBuilderAddon": [
"Modules\\TestManage\\Http\\WidgetBuilder\\Widgets\\FooterAbout"
],
"paymentGateway": {
"name": "AliPay",
"slug": "alipay",
"tenant": true,
"show_admin_landlord": true,
"show_admin_tenant": true,
"chargeCustomerMethodNameSpace": "Modules\\TestManage\\Http\\Controllers\\TestManageController",
"chargeCustomerMethodName": "paymentGateway",
"test_mode" : false,
"status" : true,
"extraInfoMarkupBlade" : "ali_pay",
"logo_file" : "ali-pay.png",
"admin_settings": {
"menu_item": [
{
"id" : "test-settings-menu-submenu",
"label": "Test Payment Menu",
"route": "tenant.admin.activity.log",
"tenantRoute": "tenant.admin.newsletter",
"permissions": ["general-settings-page-settings"]
}
]
}
}
}
}