advancelearn/manage-payment-and-orders

Orders and payments management system in Laravel and the feature of adding sales functionality for each model

2.1.0 2023-09-27 13:21 UTC

This package is auto-updated.

Last update: 2024-10-30 02:11:02 UTC


README

#Advancelearn manage-payment-order

advancelearn-otp-auth

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require

Introduction

This package was developed in collaboration with a Sadratech team member and AdvanceLearn. This package aims to create and manage various aspects related to user orders and payments. It includes tracking the number of products and tagging all steps of the user's purchase order." This package is currently under active development and there are plans to add a shopping voucher module in the future, pending support and feasibility.

By installing this package and during the next steps, tables of address, country, province, city, order items, order registration steps, order shipping cost, inventory and price, orders, payments will be created for you. And with the help of seder, you value some tables and you can easily have the country of Iran along with its provinces and cities in your database.

Installation

You can install the package with Composer.

composer require advancelearn/manage-payment-and-orders

Config

After installation, please add its provider to your config folder in the app file to complete and configure the package:

 \Advancelearn\ManagePaymentAndOrders\ManagePayOrderServiceProvider::class,

Then run this command to import and make the package tables public

php artisan vendor:publish

Select the row number of this title from among the tags and enter it

  Tag: AdvanceLearnManagePayAndOrder-migrations ...............

By entering the tag number of the image above, these tables will be added to the tables folder of your program

img.png

Then enter the following command to add tables in your database

php artisan migrate

###Now you need to follow these steps to initialize Audits in the program

php artisan vendor:publish

Select the row number of this title from among the tags and enter it

Tag: AdvanceLearnManagePayAndOrder-seeds .....

Enter the commands in order according to the picture

img.png

Adding the value for the table of order stages in the database until we can use the ID of these records when updating according to each stage of the order we wanted.

Important

In the next step, you have to set the values of these three tables for your user and your product (the user's address, the amount of the model that will be known as the product, and the amount of costs due to the type of shipment)

img_7.png

this table adm_addresses example:

img.png

this table adm_inventories example:

img_8.png

this table adm_shippings example:

img_9.png

##Create new Order By User Request "In the initial step, it's important to note that we aim to store a user's order within the system. To achieve this, we need to send the required parameters to the 'store' method of the order service package. Upon successful validation of these parameters, we will receive a response containing the order details." We receive and send the requested parameters from the user: $shippingId , $addressId , $description , $items __!!Pay attention to the type of parameters that they should be__

$items = [
    0 => [
        'quantity' => 2,
        "inventory_id" => 1
    ]

];
$shippingId = $request->shippingId; //It can be null
$addressId = (int)$request->addressId;
$newOrder = app('orderFunction')->store($shippingId, $addressId, "test from create new order", $items);
//
return $newOrder;
#params :
# shippingId => Type of shipment,
# $addressId => The address ID stored for the user in the address table ,
# $description => create new order by user example .... ,
# $items =>  Enter the product order number and inventory ID for the corresponding model

add this method for Relationship in your model with Inventory

    public function inventories()
    {
        return $this->morphMany(app('inventory'), 'adm_inventories');
    }

After add RelationShip:

"After integrating your model with the inventory model, it is essential to implement this contract within your model. This allows you to execute various actions, such as sending emails or updating your model, during the successful payment phase. Additionally, you can seamlessly update the Inventory associated with the sold record in your model."

use Advancelearn\ManagePaymentAndOrders\PaymentConfirmationInterface;

class Product extends Model implements PaymentConfirmationInterface
{
    //you're methods or logic
    
    //added this method after implemention:
    public function paymentConfirmation($user_id, $inventory_id, $quantity)
    {
        //you're added logic after paymentConfirmation
    }
}

"Now you have created a new order in the order creation phase, so to redirect the user to the payment gateway, you need to send this order id to this method, you can check whether the order amount has already been paid or not. In case of non-payment, you can redirect the user to the payment gateway."

write this namespace in your class:

use Advancelearn\ManagePaymentAndOrders\Enums\AuditTypes; 
$order = app('order')::findOrFail($orderId);

if ($order->audits->where('id', AuditTypes::PAID)->count()) {
    return response()->json(['errors' => 'Already paid'], 422);
}
    

And finally, send the final order amount to send to the portal:

$invoice = new Invoice;

$invoice->amount($order->payment_price);

And in the same method that the user was sent to the payment portal, you can create a payment for the user with a pending status:

 app('payment')::create
 ([
    'order_id' => $order->id,
    'driver' => $request->input('driver'),
    'transaction_id' => //transactionId from your gateway sent request for pay,
    'amount' => $order->payment_price
]);

And for example, in your callback method that returns from the portal, let's assume that your callback method is called paymentConfirmation.

public function paymentConfirmation(Request $request)
{
    $payment = app('payment')::where('transaction_id', $transactionId)->first();
    $order = app('order')::find($payment->order_id);
     $receipt = //api call gateway for verifyPayment and get response add to this variable
    $this->verifyPayAndConfirm($payment, $order, $request);
//          return redirect('https://example.com?gatewayOrderID=' .
//           $paymentTransaction->OrderId ?? null . '&RRN=' .
//           $paymentTransaction->RRN ?? null);
}

create call method verifyPayAndConfirm:: write this namespace in your class:

use Advancelearn\ManagePaymentAndOrders\Enums\AuditTypes; 
private function verifyPayAndConfirm($receipt, $payment, Request $request): void
{
    $payment->reference_id = $receipt->getReferenceId();
    $payment->transaction = $request->all();
    $payment->driver = $receipt->getDriver();
    $payment->save();
    $order->audits()->attach([AuditTypes::PAID => ['description' => 'Payment was successful']]);
    foreach ($order->items as $item) {
        //this method called fromAnd finally, this
        // method reaches the method that we implemented
        // in the corresponding model of the interface 
        $item->PaymentConfirmation($order->address->user_id);
    }
    return $receipt;
}

##Payment status

You can monitor the status of orders that have been prepared by checking each step where the new status should be documented. You can add a record related to the current stage of the order and you can reference the stage IDs from the adm_audits table.

You can call this method to get all the information about your orders

$paginateCount = 6;
app('orderFunction')->getOrders($paginateCount);

Use this method to display individual information of an order

app('orderFunction')->show($order);

####Pay attention to the type of parameters ####You can use this method to update an order You can create a new record in the adm_shippings table for the types of shipping steps and prices that must be calculated for shipping, and send its ID for calculation in the store or update method. Pay attention to this example.

$shippingId = app('shipping')::find(1)->pluck('id')->first();
$items = [
    0 => [
        'quantity' => 1,
        "inventory_id" => 1,
        "price" => 168000//It can be Nal
    ]
];
$shippingId = $request->shippingId; //can be null
$addressId = $request->addressId;
$auditId = app('audit')::find(2)->toArray();
$orderId = 9;
$update = app('orderFunction')->update($shippingId, $addressId, "update order for test", "2023-09-28 10:01:03", $items, $auditId['id'], $orderId);
#params => shippingId , $addressId , $description , $shippingDate , $items , $auditID , $orderId

##Important Remember that the address ID you enter for updating must be related to the user who made the purchase, because we reach the user from the address in the codes. ####You can use this method to cancel the order By User

$delete =  app('orderFunction')->destroyByUser($orderId);
return $delete;

####You can use this method to cancel the order By Admin

$delete =  app('orderFunction')->destroyByAdmin($orderId);
return $delete;

You can display the list of orders and payments to the admin and to the user who is logged in with the help of these methods and passing the required parameters.

get Orders List Or SingleOrder

return app('orderFunction')->getOrders(); // get Order List for AdminPanel
return app('orderFunction')->singleOrder(5); // get singleOrder for AdminPanel

return app('orderFunction')->ordersOfTheLoggedInUser(); // get user Authenticated Order list
return app('orderFunction')->SingleOrderOfTheLoggedInUser(5); //get user Authenticated singleOrder

get Payments List Or SinglePayment

return app('paymentFunction')->getPayments(); // get PaymentList for AdminPanel

return app('paymentFunction')->singlePayment(1); //get singlePayment for AdminPanel


return app('paymentFunction')->paymentsOfTheLoggedInUser(); //get user Authenticated payment list

return app('paymentFunction')->SinglePaymentsOfTheLoggedInUser(1); //send $paymentId

##keep in mind

"When a user utilizes your User model and you have defined Address relationships for this user, upon creating a new user account in the system, with the assistance of AdmUserObserve in your package, a digital address is generated for the user within the system. In this manner, if the user intends to purchase non-physical products for which shipping costs are irrelevant, we create a digital delivery address in the system for them."

Conclusion

By utilizing this package, there is no need to create separate models for the order and payment processes. Moreover, it allows for the presentation of user information history and the management of these records. For instance, you can perform actions like updating the order status to various types and sections, organizing the order stages (e.g., sending the products, order cancellation, final registration, readiness for shipment), and more—all within a unified framework.