How to Quickly Add an SMS OTP Flow to Your Laravel Project

July 30, 2021 · Muhammad Fathur Rahman

Creating a complete OTP (one-time password) flow from scratch can be quite time-consuming. To avoid wasting, we’ll use our own GetOTP so you can add a fast and simple OTP flow to a Laravel project.

Using very little code, you’ll be able to set up your SMS OTP flow in 9 simple steps.

But first:

What you will need?

Some basic information

What you will need

  1. Clone this Laravel project repo – LaraWallet
  2. Follow the README.md to set it up
  3. Once the project is up, you can register a new account. Make sure to use a real mobile number so we can receive the OTP via SMS

Some Basic Information

  1. The sample project that we cloned is a simple Wallet app called LaraWallet. The user can transfer credits to another registered user.
  2. Right now, when the user clicks on the Submit button, Credit Transfer Request will be automatically successful, the user’s credit will be deducted, and the receivers credit will increase.
  3. For this how-to, let’s improve the application by adding an SMS OTP verification when the user clicks on the Submit button. The Credit Transfer will only be successful when using a valid OTP.

How to Add an SMS OTP Flow in 9 Simple Steps

The best thing about using GetOTP is that it will save you a lot of time. It’s a fast and convenient OTP flow that you can set up with just a few lines of code.

Here are the steps:

  1. Building the SMS OTP feature
  2. Storing the GetOTP config
  3. Preparing the required parameters for GetOTP API
  4. Add an OTP reference to Credit Transfer Requests
  5. On submit, perform HTTP API call to GetOTP endpoint
  6. Prepare the callback
  7. Prepare the success and failure pages
  8. Enable public access and update env
  9. Test the new SMS OTP feature

1. Building the SMS OTP feature

  1. Instead of building an SMS OTP flow from scratch, let’s save time and resources by using our GetOTP service
  2. GetOTP will provide an OTP API that we can use to implement the SMS OTP. Let’s start byregistering a free account

2. Storing the GetOTP config

  1. It’s a good practice to store third party applications config in a separate config file
  2. Let’s create config/getotp.php
  3. We want to add the GetOTP API endpoint, API key and API token inside the config
  4. Next, let’s add GetOTP config key value to  .env
  5. We’ll update the GETOTP_API_KEY and GETOTP_API_TOKEN value later in Step 8
  6. Once ready, don’t forget to clear the config cache php artisan config:cache

3. Preparing the required parameters for GetOTP API

Now we’re ready to add the SMS OTP feature to our application

  1. GetOTP API requires 3 parameters in order to work properly
  2. callback_url – LaraWallet POST API endpoint, where GetOTP can update the OTP status whether it fails or succeeds
  3. success_redirect_url – LaraWallet url, where GetOTP can redirect the user to this url if the OTP verification is successful
  4. fail_redirect_url – LaraWallet url, where GetOTP can redirect the user to this url if the OTP verification is successful
  5. Add new methods inside CreditTransferController.php
  6. Routes for the GETOTP redirect inside web.php.
  7. For the callback_url routes, we need to add the route inside api.php

4. Add an OTP reference to Credit Transfer Requests

  1. Since we’ll use SMS OTP to verify the Credit Transfer process, we need to store the otp_id and otp_secret as references inside the credit_transfer_requests table.
  2. Let’s create a new migration to add otp_id php artisan make:migration add_otp_reference_to_credit_transfer_requests --table=credit_transfer_requests
  3. Migration code
  4. Don’t forget to run php artisan migrate to migrate the new columns
  5. Next we need to edit the model CreditTransferRequest.php and the columns to a fillable property

5. On submit, perform HTTP API call to GetOTP endpoint

  1. Before the Credit Transfer request can be completed, we’ll perform the verification via SMS OTP
  2. To perform the API call using Laravel, we need to install an HTTP Client. Just run this on the terminal
    composer require guzzlehttp/guzzle
  3. Edit the store() method inside CreditTransferController.php. There are a lot of things going on here:
    • We removed the completeCreditTransfer() because we want the request to be verified using SMS OTP before it completes.
    • We perform the HTTP call with POST method to GetOTP API endpoint. Authentication is needed and you can use your API key.
    • We need to supply these parameters to the HTTP client: callback_url, success_redirect_url, fail_redirect_url, channel and phone_sms
    • phone_sms requires the user mobile number, and must be appended with + string at the front
    • If the HTTP call to GetOTPI API is successful, GetOTP will return otp_id, otp_secret and link inside the API response
    • We use the otp_id and otp_secret from the API response to update the OTP reference
    • Then we’ll redirect user to the provided link
    • Put the HTTP call inside try catch block, so we can handle the exception in the case of GetOTP API returning an error
    • We also log the response and the error for easier debugging

    6. Prepare the callback

    Right now the otpCallback() method does not process anything useful except echo.

    1. Update the otpCallback() method to perform business logic if the OTP is successful or failed.
    2. Once the user enters the correct or incorrect OTP, GetOTP will perform the HTTP call to the callback url to update the status

    7. Prepare the success and failure pages

    We need to redirect the user to the success page if the Credit Transfer is successful, or to failed page if Credit Transfer fails.

    1. Update the otpSuccess() to return a success page. We also check if the status have not been updated yet by otpCallback(), and if not, we call the completeCreditTransfer() method
    2. Update the otpFailed() to return a failed page. We also check if the status have not been updated yet by otpCallback(), and if not, we call the failedCreditTransfer() method

    8. Enable public access and update env

    We are done with the coding part. However, there are still some final touches to do.

    1. Since GetOTP is a hosted API, the service can’t reach our app in a local development server. So we must make sure our application can be publicly accessed
    2. If you are using Laravel Valet, you can make your app public by running valet share. More info here
    3. If you are using Laragon on Windows, follow this tutorial to publicly share your application https://laragon.org/docs/quick-share.html
    4. Once our application can be publicly accessed, copy the public URL
    5. Login to your GetOTP members area, and create a new API key
    6. Update the .env file to set the new application URL and also the API key and API token
    7. Next, clear the config cache php artisan config:cache

    9. Test the new SMS OTP feature

    Finally, we’re ready to test the new SMS OTP feature for LaraWallet

    1. Visit the public URL on our browser: http://3c2ff6c7b019.ngrok.io
    2. Login and Submit the Credit Transfer
    3. We should see the SMS OTP form
    4. And we should receive an SMS that contains the OTP code
    5. Enter the correct OTP code, and we’ll be redirected to a success page
    6. Enter the invalid OTP code 5 times, and we’ll be redirected to a failed page

    Conclusion

    And that’s it! Now you have a functional SMS OTP flow ready to use.

    If you have any questions, feel free to contact us and we’ll answer right away.

    Sources:

    Source code

    Commits

    Initial version before implementing SMS OTP

Tags :

2021 how to