Saturday, November 14, 2020

Laravel stripe payment gateway integration with Laravel 7

Today, I want to share with you how to integrate stripe payment gateway in Laravel 7. we will use stripe/stripe-php composer library for stripe payment gateway. we will make RS100 charge using Stripe payment gateway Integration.

Stripe is a US company allowing businesses to accept payments over the Internet. It operates in 25 countries and powers 100,000+ businesses.Stripe payments allow you to get paid with all major cards from customers around the world on the web or in mobile apps.

I will give you an example from scratch to implement a stripe payment gateway in Laravel 7 applications. In this tutorial, we are going to use stripe js v3 and stripe intent to make the payment. You just need to follow each and every step to get paid.

Requirments

  • Stripe Account
  • A system with installed composer
  • Basic idea of PHP and Laravel

STEP – 1 Install fresh Laravel Project by using the below command just open the command prompt and copy paste the below code.

composer create-project --prefer-dist laravel/laravel Stripe

STEP – 2 Install stripe via composer again go to your command and write the below code

composer require stripe/stripe-php

STEP – 3 Create your stripe Account

Stripe Account Dashboard

STEP- 4 Get your stripe key and secret you will find those things in your stripe dashboard, Just copy the publishable key and secret key and paste to the safe place we will use those later.

Stripe Dashboard

STEP – 5 Create a CheckoutController Using the following Command.

php artisan make:controller CheckoutController

STEP – 6 Go to web.php and the following code in that file

Route::get('checkout','CheckoutController@checkout');
Route::post('checkout','CheckoutController@afterpayment')->name('checkout.credit-card');

STEP – 7 Go CheckoutController.php add the below code

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CheckoutController extends Controller
{
    public function checkout()
    {   
        // Enter Your Stripe Secret
        \Stripe\Stripe::setApiKey('use-your-stripe-key-here');
        		
		$amount = 100;
		$amount *= 100;
        $amount = (int) $amount;
        
        $payment_intent = \Stripe\PaymentIntent::create([
			'description' => 'Stripe Test Payment',
			'amount' => $amount,
			'currency' => 'INR',
			'description' => 'Payment From Codehunger',
			'payment_method_types' => ['card'],
		]);
		$intent = $payment_intent->client_secret;

		return view('checkout.credit-card',compact('intent'));

    }

    public function afterPayment()
    {
        echo 'Payment Has been Received';
    }
}

STEP – 8 Create blade file credit-card.blade.php under resources/views/checkout/credit-card.blade.php and add the below code.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Stripe Payment</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
    @php
        $stripe_key = 'put your publishable key here';
    @endphp
    <div class="container" style="margin-top:10%;margin-bottom:10%">
        <div class="row justify-content-center">
            <div class="col-md-12">
                <div class="">
                    <p>You will be charged rs 100</p>
                </div>
                <div class="card">
                    <form action="{{route('checkout.credit-card')}}"  method="post" id="payment-form">
                        @csrf                    
                        <div class="form-group">
                            <div class="card-header">
                                <label for="card-element">
                                    Enter your credit card information
                                </label>
                            </div>
                            <div class="card-body">
                                <div id="card-element">
                                <!-- A Stripe Element will be inserted here. -->
                                </div>
                                <!-- Used to display form errors. -->
                                <div id="card-errors" role="alert"></div>
                                <input type="hidden" name="plan" value="" />
                            </div>
                        </div>
                        <div class="card-footer">
                          <button
                          id="card-button"
                          class="btn btn-dark"
                          type="submit"
                          data-secret="{{ $intent }}"
                        > Pay </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    <script src="https://js.stripe.com/v3/"></script>
    <script>
        // Custom styling can be passed to options when creating an Element.
        // (Note that this demo uses a wider set of styles than the guide below.)

        var style = {
            base: {
                color: '#32325d',
                lineHeight: '18px',
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: 'antialiased',
                fontSize: '16px',
                '::placeholder': {
                    color: '#aab7c4'
                }
            },
            invalid: {
                color: '#fa755a',
                iconColor: '#fa755a'
            }
        };
    
        const stripe = Stripe('{{ $stripe_key }}', { locale: 'en' }); // Create a Stripe client.
        const elements = stripe.elements(); // Create an instance of Elements.
        const cardElement = elements.create('card', { style: style }); // Create an instance of the card Element.
        const cardButton = document.getElementById('card-button');
        const clientSecret = cardButton.dataset.secret;
    
        cardElement.mount('#card-element'); // Add an instance of the card Element into the `card-element` <div>.
    
        // Handle real-time validation errors from the card Element.
        cardElement.addEventListener('change', function(event) {
            var displayError = document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent = event.error.message;
            } else {
                displayError.textContent = '';
            }
        });
    
        // Handle form submission.
        var form = document.getElementById('payment-form');
    
        form.addEventListener('submit', function(event) {
            event.preventDefault();
    
        stripe.handleCardPayment(clientSecret, cardElement, {
                payment_method_data: {
                    //billing_details: { name: cardHolderName.value }
                }
            })
            .then(function(result) {
                console.log(result);
                if (result.error) {
                    // Inform the user if there was an error.
                    var errorElement = document.getElementById('card-errors');
                    errorElement.textContent = result.error.message;
                } else {
                    console.log(result);
                    form.submit();
                }
            });
        });
    </script>
</body>
</html>

STEP – 9 visit this URL from your system – http://localhost/crud/public/checkout you will get view something like below.

Payment-view
Payment View

STEP – 10 Enter the below test card detail to make a test payment

Card Number - 4242 4242 4242 4242 EXP - 12/32 CVV - 123 ZIP - 12345

STEP – 11 After the successful payment you can check your stripe dashboard for the payment confirmation.

payment-confirmation-dashboard

Payment Confirmation Dashboard


 

https://codehunger.in/laravel-stripe-payment-gateway-integration-with-laravel-7/


Thursday, November 12, 2020

Dynamic vue from desing

 class Errors {

    /**
     * Create a new Errors instance.
     */
    constructor() {
        this.errors = {};
    }


    /**
     * Determine if an errors exists for the given field.
     *
     * @param {string} field
     */
    has(field) {
        return this.errors.hasOwnProperty(field);
    }


    /**
     * Determine if we have any errors.
     */
    any() {
        return Object.keys(this.errors).length > 0;
    }


    /**
     * Retrieve the error message for a field.
     *
     * @param {string} field
     */
    get(field) {
        if (this.errors[field]) {
            return this.errors[field][0];
        }
    }


    /**
     * Record the new errors.
     *
     * @param {object} errors
     */
    record(errors) {
        this.errors = errors;
    }


    /**
     * Clear one or all error fields.
     *
     * @param {string|null} field
     */
    clear(field) {
        if (field) {
            delete this.errors[field];

            return;
        }

        this.errors = {};
    }
}


class Form {
    /**
     * Create a new Form instance.
     *
     * @param {object} data
     */
    constructor(data) {
        this.originalData = data;

        for (let field in data) {
            this[field] = data[field];
        }

        this.errors = new Errors();
    }


    /**
     * Fetch all relevant data for the form.
     */
    data() {
        let data = {};

        for (let property in this.originalData) {
            data[property] = this[property];
        }

        return data;
    }


    /**
     * Reset the form fields.
     */
    reset() {
        for (let field in this.originalData) {
            this[field] = '';
        }

        this.errors.clear();
    }


    /**
     * Send a POST request to the given URL.
     * .
     * @param {string} url
     */
    post(url) {
        return this.submit('post', url);
    }


    /**
     * Send a PUT request to the given URL.
     * .
     * @param {string} url
     */
    put(url) {
        return this.submit('put', url);
    }


    /**
     * Send a PATCH request to the given URL.
     * .
     * @param {string} url
     */
    patch(url) {
        return this.submit('patch', url);
    }


    /**
     * Send a DELETE request to the given URL.
     * .
     * @param {string} url
     */
    delete(url) {
        return this.submit('delete', url);
    }


    /**
     * Submit the form.
     *
     * @param {string} requestType
     * @param {string} url
     */
    submit(requestType, url) {
        return new Promise((resolve, reject) => {
            axios[requestType](url, this.data())
                .then(response => {
                    this.onSuccess(response.data);

                    resolve(response.data);
                })
                .catch(error => {
                    this.onFail(error.response.data);

                    reject(error.response.data);
                });
        });
    }


    /**
     * Handle a successful form submission.
     *
     * @param {object} data
     */
    onSuccess(data) {
        alert(data.message); // temporary

        this.reset();
    }


    /**
     * Handle a failed form submission.
     *
     * @param {object} errors
     */
    onFail(errors) {
        this.errors.record(errors);
    }
}


new Vue({
    el: '#app',

    data: {
        form: new Form({
            name: '',
            description: ''
        })
    },

    methods: {
        onSubmit() {
            this.form.post('/projects')
                .then(response => alert('Wahoo!'));
        }
    }
});

<form method="POST" action="/projects" @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
    <div class="control">
        <label for="name" class="label">Project Name:</label>
        
        <input type="text" id="name" name="name" class="input" v-model="form.name"> 

        <span class="help is-danger" v-if="form.errors.has('name')" v-text="form.errors.get('name')"></span>
    </div>

    <div class="control">
        <label for="description" class="label">Project Description:</label>
        
        <input type="text" id="description" name="description" class="input" v-model="form.description">

        <span class="help is-danger" v-if="form.errors.has('description')" v-text="form.errors.get('description')"></span>
    </div>

    <div class="control">
        <button class="button is-primary" :disabled="form.errors.any()">Create</button>
    </div>
</form>


Tuesday, November 10, 2020

Stripe payment gateway intregation process


<button id="checkout-button">Checkout</button>

<script src="https://js.stripe.com/v3/"></script>
    <script src="{{ asset('js/app.js') }}"></script>
    <script type="text/javascript">
        // Create an instance of the Stripe object with your publishable API key
        var stripe = Stripe('pk_test_51Hl77PKBzirhUGIcEQ0WvzMnWDLNHuT5dJ19DXvrATFr8SFcgzcjTAc1anvLqX8GRY36vnovlZYyR4LZZvnwkJrA00fzBPjbh2');
        var checkoutButton = document.getElementById('checkout-button');
  
        checkoutButton.addEventListener('click', function() {
          // Create a new Checkout Session using the server-side endpoint you
          // created in step 3.
          
          axios.post('/create-checkout-session', {})
          .then(function(response) {
            return stripe.redirectToCheckout({ sessionId: response.data });
          })
          .then(function(result) {

            
            // If `redirectToCheckout` fails due to a browser or network
            // error, you should display the localized error message to your
            // customer using `error.message`.
            if (result.error) {
              alert(result.error.message);
            }
          })
          .catch(function(error) {
            console.error('Error:', error);
          });
        });
      </script>



Route::post('create-checkout-session', 'CheckoutController@checkoutSession')->name('checkout.session')->middleware('auth');

Route::get('success', 'CheckoutController@success')->middleware('auth'); 

Route::post('create-checkout-session', 'CheckoutController@checkoutSession')->name('checkout.session')->middleware('auth');
Route::get('success', 'CheckoutController@success')->middleware('auth');


public function checkoutSession()
    {

        \Stripe\Stripe::setApiKey(config('services.stripe.key'));

        $session = \Stripe\Checkout\Session::create([
            'payment_method_types' => ['card'],
            'line_items'           => [[
                'price_data' => [
                    'currency'     => 'usd',
                    'product_data' => [
                        'name' => 'T-shirt',
                    ],
                    'unit_amount'  => 2000,
                ],
                'quantity'   => 1,
            ]],
            'mode'                 => 'payment',
            'success_url'          => 'http://localhost:8000/success?session_id={CHECKOUT_SESSION_ID}',
            'cancel_url'           => 'http://localhost:8000/success',
        ]);

        return $session->id;

        return response()->json(['id' => $session->id]);

        //->withStatus(200)
    }

    public function success(Request $request)
    {
        $stripe = new \Stripe\StripeClient(
            config('services.stripe.key')
        );
        $returndata = $stripe->checkout->sessions->retrieve(
            $request->session_id,
            []
        );

        dd($returndata);
    }

    public function afterPayment()
    {
        echo 'Payment Has been Received';
    }


Sunday, November 8, 2020

What Actually is Vue.set?

 Reactivity in VueJS is one of THE core features that any developer needs to understand and completely harness to fully grasp the power of the framework. Vue.set is an API call that will fit nicely in your toolbelt for building more powerful applications. Let's go ahead and learn about it together.

Talking about Vue.set is talking about reactivity, so prepare yourself for some theory on this one. However, as always, it doesn’t need to be something hard or boring. Find your avocados and chips, make some guacamole, and let’s dip right in.

Data and Reactivity

Whenever you create a data() property function inside a Vue component and return the object back, Vue does a lot of things behind the scenes to hook everything up inside your component and to make it reactive.

export default {
  data() {
   return {
     red: 'hot',
     chili: 'peppers'
   }
  }
}
Js

The first thing that Vue will do here with our awesome awesome awesome RHCP data, is walk through each of the properties of the return { } object, and create a unique getter and setter for each one. The nitty gritty of how this actually happens is beyond the scope of this article, but Vue Mastery has a very nice video explaining this in detail.

The purpose of creating these is so that when you access these properties inside your code, by doing this.red for example, or when setting them with this.red = "hotter", you are actually calling these getters and setters that Vue created for you.

Inside this magical land of SETGET, Vue hooks up your computer properties, watchers, props, data, etc. to become reactive. In super simple terms, a function is called that updates the whole shebang every time the setter is changed.

The Pitfall

Awesome! This is what we love about Vue, right? Its amazing reactivity and under-the-hood power. But there is a dark side here that needs to be explored.

Let’s change our data a little bit and see what happens when we start trying to work with dynamic data.

data() {
  return {
    members: {}
  }
}
Js

Alright, nothing fancy so far. We have a members property of our data into which we want to add band member information. Now for the sake of example, let’s add a method that will pretend to pull some information from a remote HTTP call, that will give us back a JSON object with the band info.

data() {
  return {
    members: {}
  }
},
methods: {
  getMembers() {
   const newMember = {
     name: 'Flea',
     instrument: 'Bass',
     baeLevel: 'A++'
   }; // Some magical method that gives us data got us this sweet info

   // ...
  }
}
Js

Hm. Ok, so looking at this example, let’s stop and think. There are many ways to resolve this current dilemma - how do we add this newMember object into our current members property?

Maybe you’re thinking, let’s turn members into an array and push it. Sure, but that’s cheating because it breaks my CAREFULLY constructed example that I didn’t just make up as I was typing this.

In this scenario, we NEED to have members as an object. Ok, simple - you’d say, let’s just add a new property to the members property, it’s an object after all. In fact, let’s go ahead and make the member’s name the name of the property.

getMembers() {
   const newMember = {
     name: 'Flea',
     instrument: 'Bass',
     baeLevel: 'A++' // Totally important property that we will never use
   }; // Some magical method that gives us data got us this sweet info

   this.members[newMember.name] = newMember;
  }
Js

Lok’tar Ogar!

Except, no, because A. this is not Orgrimmar, and B. we now have a problem.

If you were to run this code on your browser and test it right now, you will see that you are actually pushing this new data into the members data, but this change to the component state will not actually make any of your application re-render.

In a scenario where you are just using this data for some computation, or for some type of internal storage, then doing things this way won’t impact your application. However, and this is a huge HOWEVER, if you are using this data reactively on your app to display some information on your page, or for conditional rendering with v-if or v-else, then things are going to get funky.

Actually Using Vue.set

So now that we understand where the problem is actually coming from, we can learn what is the proper solution. Allow me to introduce you to Vue.set.

Vue.set is a tool that allows us to add a new property to an already reactive object, and makes sure that this new property is ALSO reactive. This completely takes care of the problem that we were experiencing on the other example, because when our new property on members gets set, it will automatically be hooked into Vue’s reactivity system, with all the cool getters/setters and Vue-magic behind the scenes.

A small note is, however, required to understand how this affects arrays. So far, we have only really played around with objects, which are super easy to understand. New prop? Add it with Vue.set if you want it to be reactive. Simple.

Following up with our example, let’s switch things up to use Vue.set instead.

getMembers() {
   const newMember = {
     name: 'Flea',
     instrument: 'Bass',
     baeLevel: 'A++'
   }; // Some magical method that gives us data got us this sweet info

   //this.members[newMember.name] = newMember;
     this.$set(this.members, newMember.name, newMember);
  }
Js

This bit is new - this.$set(this.members, newMember.name, newMember);.

There’s two things I want to mention for this piece of code. I’ve been telling you so far that Vue.set is how we are going to be doing things, but now I’m using this.$set. But fear not - this is only an alias, so it will behave in the exact same way. The cool thing is that you don’t have to import Vue inside your components to use it.

The second thing I want to make note of is the syntax of this function. It takes three parameters.

One is the object or array which we are going to modify (in this case this.members).

A second parameter that points to the property or key of the first object/array that we passed (so newMember.name because we want it to be dynamic).

And finally a third parameter which is the value we want to set into it. (In our case, newMember).

         this.members [newMember.name] = newMember;
//            V               V              V
this.$set(this.members, newMember.name,   newMember);
Js

(P.S. My ASCII skills are not for sale. ^)

But what’s up with array reactivity?

When we create an array inside the initial state, Vue sets it up to be reactive for us. However, Vue is unable to currently detect when you directly assign a value using an index. For example, if we were doing this:

this.membersArray[3] = myNewValue;
Js

Then Vue won’t be able to detect this change, and thus it would not be reactive. Please keep in mind that if you modify arrays with operations like pop, splice, or push, then those operations WILL trigger reactivity on the arrays, so you can safely use those.

In the off case that you need to set an index value directly, we have Vue.set to help us out. Let’s see how that would look on our previous example.

this.$set(this.membersArray, 3, myNewValue)
Js

If you want to read more about all the reactivity caveats, check out this link to the official documentation.

Bonus

Vue’s core team is currently working on Vue 3.0, and recently announced a lot of upcoming changes to the reactivity system that will make our lives easier as developers.

This is all still subject to change at the time of this writing, but the word on the street is that these caveats will no longer be an issue. In other words, in Vue 3.0 you will be safe to forget about these edge cases completely, with the exception of those poor souls that still have to target some old browsers that will not fully support the new reactivity system.