Building e-commerce application with Laravel 5.8 and Billplz payment.

neonexxa
10 min readApr 5, 2019

--

Just another simpler way to pay with Laravel ..

Not so much a-z but i hope i can help you get started.

I assume you already knew Laravel. If not well verse, the least with php basic syntax is enough ..

Part 1 : Setting up the application

Like the essence of common Laravel application — i assumed you had your laravel-installer library ready at your very finger tip, if not well then just run anywhere within your cmd/terminal composer global require laravel/installer and you can continue onwards —

Lets create our e-commerce application folder by running,

laravel new ecommerce

After a few seconds , we should have our project folder ready. Let’s continue setting up the basic necessity, and some of ours .

cd ecommercephp artisan make:auth && php artisan make:model Product -mrc && php artisan make:model Purchase -mrc

On this quick tutorial we gonna need only 2 extra modules which is

Product to hold our product list and ..

Purchase to hold our customer purchases.

Change it to your setting accordingly.

Alright lets quickly set up the rest of the items. As common Laravel application, do be reminded to set your database configuration in the .env file (within your project folder) .

Last but not least, before we begin crafting the database schema. Let’s quickly look up our schema structure in the database/migrationsfolder and paste the necessary items. You should be seeing something like this in the migration file

Products migration file

the up() function

public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->nullable();
$table->string('pic')->nullable();
$table->string('desc')->nullable();
$table->string('price')->nullable();
$table->string('payment_link')->nullable();
$table->timestamps();
});
}

the down() function

public function down()
{
Schema::dropIfExists('products');
}

Purchases migration file

the up() function

public function up()
{
Schema::create('purchases', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('bill_id');
$table->timestamps();
});
Schema::table('purchases', function (Blueprint $table) {
$table->biginteger('user_id')->unsigned();
$table->biginteger('product_id')->unsigned();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('product_id')
->references('id')
->on('products')
->onDelete('cascade');
});
}

the down() function

public function down()
{
Schema::table('purchases', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropColumn('user_id');
$table->dropForeign(['product_id']);
$table->dropColumn('product_id');
});
Schema::dropIfExists('purchases');
}

We are almost finishing the setup, only 2 more steps to go ..

Run the migration command

php artisan migrate

If all things well set, you should be seeing something like below ..

Your database is ready, should be able to view it using any tools like phpmyadmin/sequelpro etc.

Finally , we need to set up our Model relationship. Like any other structured relationship i hope you are well verse with terms like Eloquent. If not, well afraid none as I’m not gonna bust your head with any unnecessary complicated explanation.

As you can see our “Purchases” migration has some sort of sequel like foreign key. Thus on the Laravel side, we also have to tell it to understand the relationship that the sequel have so that it does not head-bumps into each other relationship.

Enough talking, let us get to the actual task. In the app folder we should see the very model that we created earlier.

  • Product.php
  • Purchase.php
  • User.php

Edit each of it accordingly. Below should be some references incase you miss-out the steps.

Product.php

class Product extends Model
{
//
protected $fillable = [
'name','pic','desc','price','payment_link',
];
public function purchases()
{
return $this->hasMany('App\Purchase');
}
}

Purchase.php

class Purchase extends Model
{
//
protected $fillable = [
'bill_id','user_id','product_id',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}

User.php

class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function purchases()
{
return $this->hasMany('App\Purchase');
}
}

Ps side notes : don’t just copy and paste it, i suggest you be quite thorough with it

Well done!! You are now ready with all the basics to continue on the next part.

Part 2: User and Payment

Ok before begin to create our product we need to have an access first . let us create just one for us to login .

Be sure to generate your application key before serve your Laravel on the browser.

php artisan key:generate && php artisan serve
standard Laravel application build up

Click the register button and sign up our user .

Alright , once we have sign up, we should be able to get our access straight away to the Laravel home page. You might want to list out your products here, but we will get to that later in Part 4.

Now let’s get some payment services to use along with your system.

“A good application is quite useless if it can’t generate money” — most old man said.

Well i am gonna publish an article later on comparison of each payment services. Thus meanwhile, i’m just gonna pick 1 and since i’m living in the asian country called Malaysia, the common payment gateway used is either Billplz or SenangPay ..

Well … we give credit to those company. In this tutorial, I’m gonna use Billplz. As you can see on Billplz Dashboard, each payment services has its own perks , billplz payment structure dissolved into 3 parts

  • Normal Bills
  • Open Bills
  • Mass Bills

I’m not gonna dive into each of it as that will waste our time, i will just explain it briefly here:

Normal bills is when you issue the bill, when people paid/ due, the bill is closed.

Open bills is when you open the bill and people can pay many times to that bill. This is usually comes handy in situation like public donation etc..

Mass bills is when you have to make massive transactions , well … i never quite get this part since i never had to make a massive transaction that requires me to use this. — maybe you can explore this part and share it to us.

Alright then, for our part, we gonna be using the Normal bills. In billplz structure, you need to define the collection prior issuing the bills. This is to acknowledge which collection this bills belongs_to. Thus, in our application, each of our product will be having its own collection, and each of the purchases of that product will be the bills of the collection .

As example below we gonna create one product (collection) and issue a purchase (bill) of that product .

Go to your https://www.billplz.com/enterprise/billing and click the button “Create Collection” it should ask you to enter the collection title .

Put in “Apple” and enter.

Next click on the created collection and add a bill .

Key in the necessary item. Just charge any amount you want for now and enter. You should be able to view the bills afterwards . The best thing about billplz is that it allow you to use the fpx services right out of the box, as you can see below you can do the direct banking transaction with billplz.

In order for the fpx to work well, be sure to verify your bank account with billplz

Now you must be wondering this, “Do i have issue this manually when someone wanted to buy item from my store? Do i have to go to the dashboard and create the collection every time i wanted to add a product to my store? oh thats gonna be pain in the a**.” — the answer is no, that is where Laravel library helps you.

“The best part about Laravel being open source is the community become bigger and larger. Thus there are so many out there developing tools and library to help power up the frameworks. I am sure that each payment services out there would already have many supporting Laravel package for it, if not, at least one must be there. “

As for billplz, there are plenty of it already . It should not render you incapable to proceed further with your application.

Well since i’m a notorious developer , i prefer to use my own library https://packagist.org/packages/neonexxa/billplz-wrapper .

Just as according to the guide there, by this moment its version is around v1.7 .

Run below command .

composer require neonexxa/billplz-wrapper

Add billplz secret key to your .env file in the project folder, should be able to get your billplz secret key here https://www.billplz.com/enterprise/setting

As written in the package guide, edit your .env appropriately

in your config/app.php add below to your service provider class

Neonexxa\BillplzWrapperV3\BillplzServiceProvider::class,

Be sure to clear out the config cache before serve your application again.

composer dump-autoload && php artisan config:cache && php artisan cache:clear && php artisan vendor:publish --provider="Neonexxa\BillplzWrapperV3\BillplzServiceProvider"

Part 3: Add an item to our store or product

Recap: As previously we had created this so called (collection) item to sell . How do we wired it out with our Laravel? ..

First we have to add an item into our product table , oh well, Im not gonna guide you on this part as you sure well expert even better on this i assumed. You can go directly to your database/tools to do so like mysql/sequelpro/phpmyadmin or other tools to your database and add the product directly there.

How ever i will show you the Laravel way to do so.

In order to generate/add our items in store as clean as we can, we gonna need a seeder class for our Model. Yea right, go ahead and run

php artisan make:seeder ProductTableSeeder

We should be able to see the file seeder generated in our database/seedsfolder . Open our ProductTableSeeder.php

At the top include our Model Class,

use App\Product;

And for the run() function be sure to copy the “collection id” from your item/collection created in billplz , it should be located below the item name as per the image earlier this part. Paste it in the“payment_link” parameter.

public function run()
{
//
$products = [
["name"=>"Apple","pic"=>"https://www.kofixlabs.co/logo.png","desc"=>"Our Apple","price"=>"1","payment_link"=>"rtvgkhf3"],
];
Product::insert($products);
}

Below is the example incase you were confuse

Thus our seeder class is completed, you can add more product later but for now its enough. Now we need to call our seeder class from the Db seeder . Add below into our run() function in database/seeds/DatabaseSeeder.php .

$this->call(ProductTableSeeder::class);

then run below command and it should seed without a hatch..

php artisan db:seed

Well done, now let’s see what we have done. We have a user, we have a product, we have a payment services. All thats left is to see our product on the web and buy it .

Part 4: Show our product

Well, as all standard practice of the Laravel practitioners around the world. You should list your item under the index of ProductController, however we gonna skip the practice and jump a bit fast as to get you the item listed quickly.

In your app/Https/Controllers/HomeController.php index() function

public function index()
{
$products = \App\Product::all();
return view(‘home’,compact(‘products’));
}

adjust it like the above to pass our product list to the front page. Thus from our view resources/views/home.blade.php , can grab any type of “card” you want, but i will use the default bootstrap card https://getbootstrap.com/docs/4.0/components/card/

@foreach($products as $product)
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{$product->pic}}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{$product->name}}</h5>
<p class="card-text">{{$product->desc}}</p>
<a class="btn btn-primary" href="#"
onclick="event.preventDefault();
document.getElementById('newbill-form{{$product->id}}').submit();">
Buy RM {{$product->price}}
</a>
<form id="newbill-form{{$product->id}}" action="{{ route('purchase.store') }}" method="POST" style="display: none;">
@csrf
<input type="hidden" name="product" value="{{$product->id}}">
</form>
</div>
</div>
@endforeach

Replace the card existing with this one . Your view file should look something like this.

There we go!! We have our very first product listed.

Part 5: Buy the product

Buying a product in the system means we have to issue a bill. So by default, every time a customer buy a product we issue a new bill.

In order to do that, we had to create a link or route that will generate a new bill on each request of the product.

How do we create a bill?

As refer to the guide, just call our classes at the top of the PurchaseController . Add these classes there.

use Neonexxa\BillplzWrapperV3\BillplzBill;
use App\Product;
use Auth;

In our ProductController store() function

        //
$params = $request->all();
$product = Purchase::find($params['product']);
// from the guide
$res0 = new BillplzBill;
$res0->collection_id = $product->payment_link;
$res0->description = "New BIll";
$res0->email = Auth::user()->email;
$res0->name = Auth::user()->name;
$res0->amount = $product->price*100;
$res0->callback_url = "yourwebsite@example.com";
// and other optional params
$res0 = $res0->create_bill();
list($rhead ,$rbody, $rurl) = explode("\n\r\n", $res0);
$bplz_result = json_decode($rurl);

// Store the bill into our purchases
$purchase = new Purchase;
$purchase->user_id = Auth::user()->id;
$purchase->product_id = $product->id;
$purchase->bill_id = $bplz_result->id;
$purchase->save();
return redirect($bplz_result->url);

Well done!! it should redirect the user to the payment on the click of the button.

Alright then, from here on i believe you can continue onwards. Im not gonna guide until the “thank you” page hehe, but you should have that somewhere in your mind.

If by any chance anyone reading this, and having troubles, feel free to ask .. and i’m sorry for the bad story telling.

Our project repo for your references : https://github.com/neonexxa/ecommerce

Best of luck, adios!!

--

--