Last active
December 23, 2022 15:00
-
-
Save sahilkashyap64/b2d2db0999b3d540d2578da9a0f728c0 to your computer and use it in GitHub Desktop.
Laravel QR login using polling like whatsapp with memecache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//api doc : https://documenter.getpostman.com/view/6553325/UUy39SJv | |
//article: https://dev.to/sahilkashyap64/qr-login-in-php-2pgf | |
Route::post('/login/create/qrcode', 'Admin\QRLoginTwoController@CreateQrcodeAction');//creates QR and save it as png | |
Route::post('/login/mobile/scan/qrcode', 'Admin\QRLoginTwoController@mobileScanQrcodeAction');//gets scaned by phone with key passed in header | |
Route::post('/login/qrcodedoLogin', 'Admin\QRLoginTwoController@qrcodeDoLoginAction'); //this url is used when qr code is scanned successfully | |
Route::post('/login/scan/qrcode', 'Admin\QRLoginTwoController@isScanQrcodeAction'); //Check whether the code has been scanned | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@extends('frontend/partials/master') | |
@section('top-stylesheets') | |
@include('frontend.partials.sidenavRegisterAndLoginCSS') | |
@endsection | |
@section('stylesheets') | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="{{ asset('frontend/qr/jquery.qrcode-0.11.0.min.js') }}" ></script> | |
<style> | |
.alert.alert-position { | |
position: absolute; | |
width: 100%; | |
z-index: 1040; | |
} | |
</style> | |
@endsection | |
@section('stylesheets-bottom') | |
@include('frontend.partials.sidenavRegisterAndLoginJS') | |
<script type="text/javascript"> | |
// Check whether the login has been confirmed | |
function is_loginfun(){ | |
var key = $('#key').val(); | |
console.log("is_login called"); | |
$.ajax({ | |
type: "POST" , | |
dataType: "json" , | |
url: "web/login/entry/login" , | |
data:{ | |
key:key , | |
"_token":"{{ csrf_token() }}" | |
}, | |
headers: {'x-csrf-token': '{{ csrf_token() }}'}, | |
success:function(data) { | |
if (data.status==1 ){ | |
var uid = data.jwt; | |
var user = data.user; | |
console.log("user",user); | |
// var sign = data.sign; | |
// Cancel timed tasks and clear cookies | |
clearInterval($('#is_login' ).val ()); | |
$( '#is_login').val('' ); | |
// Hide the successful scanning code | |
// $('.barcode-container.scanned .status.scanned, .barcode-container.scanned .mask' ).hide(); | |
// | |
// Confirmed pop-up $('.confirmed,.mask' ).show(); | |
// Confirm login at a time of 1 second | |
console.log("login successfull",uid); | |
$('.qrcode-img').attr('src',''); | |
alert("login successfull",uid); | |
$('#thelogindata').text(uid) | |
window.location.href = '/'; | |
} else if (data.status==2 ){ | |
// Cancel timed tasks and clear cookies | |
clearInterval($('#is_login').val()); | |
$('#is_login').val('' ); | |
alert(data.msg); | |
} | |
} | |
}); | |
} | |
// Check whether the code has been scanned | |
function is_sacn_qrcode(){ | |
var key = $('#key').val(); | |
console.log("is_sacn_qrcode called"); | |
//return; | |
$.ajax({ | |
type: "POST" , | |
dataType: "json" , | |
url: "api/login/scan/qrcode" , | |
data:{ | |
key:key | |
}, | |
success: function(data){ | |
if(data.status==1){ | |
// Scan code successfully | |
// $('.barcode-container.scanned .status.scanned, .barcode-container.scanned .mask' ).show() ; | |
// Cancel timing tasks and clear cookies | |
clearInterval($('#timing').val()); | |
$( '#timing').val(''); | |
// // close the pop-up window at a timing of 2 seconds | |
// setTimeout(function(){ | |
// $('.qrcode').hide( ); | |
// }, 2000); | |
// Check whether the login has been confirmed | |
var is_login = setInterval(function() { | |
is_loginfun(); | |
},3000); | |
$('#is_login').val(is_login); | |
// $.cookie('is_login', is_login); | |
} else if(data.status==2 ){ | |
$('.timeout,.mask').show(); | |
// Cancel timing tasks and clear cookies | |
clearInterval($('#timing').val()); | |
$('#timing').val(''); | |
} | |
} | |
}); | |
} | |
$(document).ready(function() { | |
$('.scanqrcode').click(function(){ | |
// Request QR code | |
$.ajax({ | |
type: "POST" , | |
dataType: "json" , | |
url: "api/login/create/qrcode" , | |
headers: {'x-csrf-token': '{{ csrf_token() }}'}, | |
success:function(data){ | |
if(data.status == 1) { | |
var qrcodeimg=data.msg; | |
// of Put in hidden The Key Domain | |
$('#key').val(data.key); | |
console.log("key",data.key); | |
// Replace the QR code | |
$('.qrcode-img').attr('src',qrcodeimg); | |
//Trigger timed task, check whether it has been Scan code | |
var inter = setInterval(function() { | |
is_sacn_qrcode(); | |
},3000); | |
$('#timing').val(inter); | |
} | |
} | |
}); | |
}); | |
}); | |
$("#my_form").submit(function(event){ | |
event.preventDefault(); //prevent default action | |
var zipnumber = $("[name='zip']"); | |
// alert(zip); exit; | |
$.ajax({ | |
url:"{{ route('ajax-check') }}", | |
type:"GET", | |
data:{zip: zipnumber.val()}, | |
dataType: 'json', | |
success: function (data) { | |
$('#card-button').prop('disabled', false); | |
$('#ziphelp').html('<p style="color:green">'+data.message+' <a href="javascript:void(0)" onclick="openNavReg();"style="padding: 0;">Start Your Trial Now!</a></p>'); | |
}, | |
error:function(xhr, status, error){ | |
if(xhr.status==404) { | |
// alert('status:' + xhr.status + ', status text: ' + xhr.responseText); | |
$('#card-button').prop('disabled', true); | |
$('#ziphelp').html('<p style="color:red">'+xhr.responseJSON.message+' Our apologies, your location is outside of the streamly service area. Please call 1111111111 for more information.</p>'); | |
} | |
// coupon was invalid, clear input so it doesn't get posted if user doesn't input a new valid coupon | |
} | |
}); | |
}); | |
</script> | |
<style> | |
nav#mainNav { | |
background-color: #004E92; | |
} | |
body{ | |
background: #F9F9F9 0% 0% no-repeat padding-box; | |
} | |
.page-section { | |
padding: 8rem 0; | |
} | |
ul.setting-card { | |
margin: 0 auto; | |
list-style: none; | |
box-shadow: 0px 3px 6px #00000029; | |
padding: 0; | |
} | |
ul.setting-card li:first-child { | |
font-weight: bold; | |
background: #004E92 0% 0% no-repeat padding-box; | |
padding: 12px 34px; | |
letter-spacing: 0.24px; | |
color: #FFFFFF; | |
border-top-right-radius: 6px; | |
border-top-left-radius: 6px; | |
} | |
ul.setting-card { | |
margin: 0 auto; | |
color: #5E5E5E; | |
} | |
.col-centered { | |
margin: 0 auto; | |
position: relative; | |
} | |
ul.setting-card li:not(:first-child) { | |
padding: 12px 34px; | |
letter-spacing: 0.24px; | |
} | |
.light-brown{ | |
color: #989898; | |
} | |
.account-save-btn { | |
background: #C4C4C4 0% 0% no-repeat padding-box; | |
border-radius: 6px; | |
} | |
.account-cancel-btn { | |
border: 1px solid #707070; | |
border-radius: 6px; | |
} | |
.cancel-subscription { | |
display: block; | |
text-align: right; | |
color: #CF0000; | |
} | |
i.fa.fa-trash { | |
cursor: pointer; | |
} | |
i.fa.fa-edit { | |
cursor: pointer; | |
} | |
.modal-dialog { | |
min-height: calc(100vh - 60px); | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
overflow: auto; | |
} | |
.modal-body { | |
position: relative; | |
flex: 1 1 auto; | |
padding: 3rem 5rem; | |
} | |
.modal-body p{ | |
letter-spacing: 0.24px; | |
color: #5E5E5E; | |
} | |
</style> | |
@endsection | |
@section('content') | |
@if(session()->has('message')) | |
<div class="alert alert-success alert-dismissible "> | |
<button type="button" class="close" data-dismiss="alert">×</button> | |
{{ session()->get('message') }} | |
</div> | |
@endif | |
@include('frontend.partials.sidenavRegisterAndLogin') | |
<section class="page-section"> | |
<div class="container"> | |
<h2 class="section-heading text-center">QR code</h2> | |
<div class="row setting-cards"> | |
<div class="col-centered col-md-8"> | |
<ul class="setting-card"> | |
<li class="text-center"><button class="scanqrcode">Login with QR</button></li> | |
<li class="text-center"> | |
<p id="thelogindata"></p> | |
<img class="qrcode-img" src="" /> | |
<input type="hidden" id="key"> | |
<input type="hidden" id="timing" value="timing"> | |
<input type="hidden" id="is_login" value="is_login "></li> | |
</ul> | |
</div> | |
</div> | |
@if ($errors->any()) | |
<div class="alert alert-danger"> | |
<ul> | |
@foreach ($errors->all() as $error) | |
<li>{{ $error }}</li> | |
@endforeach | |
</ul> | |
</div> | |
@endif | |
</div> | |
</section><section class="page-section"> | |
</section> | |
@endsection | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Admin; | |
use App\Http\Controllers\Controller; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Str; | |
use Illuminate\Support\Facades\Cache; | |
use SimpleSoftwareIO\QrCode\Facades\QrCode; | |
use Memcache; | |
use Illuminate\Support\Facades\Auth; | |
class QRLoginTwoController extends Controller | |
{ | |
// QR code should be only avilable for non logged in user | |
public function qr() | |
{ | |
if (Auth::check()) | |
{ | |
return "you are already logged in, open it in incognito mode"; | |
} | |
else | |
{ | |
return view('frontend.drm.qr'); | |
} | |
} | |
//QR scanner only avilable for logged in user | |
public function qrscanner() | |
{ | |
if (Auth::check()) | |
{ | |
$login = true; | |
return view('frontend.drm.qrscanner', compact('login')); | |
} | |
return redirect()->route('home'); | |
} | |
public function CreateQrcodeAction() | |
{ | |
$url = 'http://' . $_SERVER['HTTP_HOST']; // Get the current url | |
// dd($url); | |
$http = $url . '/api/login/mobile/scan/qrcode'; // Verify the url method of scanning code | |
$key = Str::random(30); //$this->getRandom(30); // The key value stored in memcache, a random 32-bit string | |
$random = mt_rand(1000000000, 9999999999); //random integer | |
$_SESSION['qrcode_name'] = $key; // Save the key as the name of the picture in the session | |
$forhash = substr($random, 0, 2); | |
$sgin_data = HashUserID($forhash); // The basic algorithm for generating the sign string | |
$sgin = strrev(substr($key, 0, 2)) . $sgin_data; // Intercept the first two digits and reverse them | |
$value = $http . '?key=' . $key . '&type=1'; // Two-dimensional Code content | |
$pngImage = QrCode::format('png') | |
// ->merge(public_path('frontend/img/streamly-logo.png'), 0.3, true) | |
->size(300) | |
->errorCorrection('H') | |
->generate($value, public_path('assets/img/qrcodeimg/' . $key . '.png')); | |
$return = array( | |
'status' => 0, | |
'msg' => '' | |
); | |
$qr = public_path('assets/img/qrcodeimg/' . $key . '.png'); | |
if (!file_exists($qr)) | |
{ | |
$return = array( | |
'status' => 0, | |
'msg' => '' | |
); | |
return response()->json($return, 404); | |
// return "no found qr img"; | |
} | |
$qr = asset('assets/img/qrcodeimg/' . $key . '.png'); | |
$mem = new \Memcache(); | |
$mem->connect('127.0.0.1', 11211); | |
$res = json_encode(array( | |
'sign' => $sgin, | |
'type' => 0 | |
)); | |
// store in memcache, expiration time is three minutes | |
$mem->set($key, $res, 0, 180); // 180 | |
$return = array( | |
'status' => 1, | |
'msg' => $qr, | |
'key' => $key | |
); | |
return response()->json($return, 200); | |
} | |
// Mobile device scan code | |
public function mobileScanQrcodeAction(Request $request) | |
{ | |
$key = $_GET['key']; | |
$url = 'http://' . $_SERVER['HTTP_HOST']; | |
$agent = $_SERVER["HTTP_USER_AGENT"]; | |
$headerpasscode = $request->header('userpasscode'); | |
$http = $url . '/api/login/qrcodedoLogin'; // Return to confirm the login link | |
$mem = new \Memcache(); | |
$mem->connect('127.0.0.1', 11211); | |
$data = json_decode($mem->get($key) , true); | |
if (empty($data)) | |
{ | |
$return = array( | |
'status' => 2, | |
'msg' => 'expired' | |
); | |
return response()->json($return, 200); | |
} | |
$data['type'] = 1; // Increase the type value to determine whether the code has been scanned | |
$res = json_encode($data); | |
$mem->set($key, $res, 0, 180); | |
$http = $http . '?key=' . $key . '&type=scan&login=' . $headerpasscode . '&sign=' . $data['sign']; | |
$return = array( | |
'status' => 1, | |
'msg' => $http | |
); | |
return response()->json($return, 200); | |
} | |
/* * | |
* Log in after the client scans the code | |
* $sign passes the identification when the client scans the code, and compares it with the memcache | |
* $key is the key passed in the QR code on the web page | |
* $uid The user id sent by scanning the code after the client logs in | |
* @return void | |
*/ | |
public function qrcodeDoLoginAction(Request $request) | |
{ | |
$login = $_GET['login']; //jwt or passcode | |
$key = $_GET['key']; | |
$sign = $_GET['sign']; | |
$mem = new \Memcache(); | |
$mem->connect('127.0.0.1', 11211); | |
$data = json_decode($mem->get($key) , true); // Remove the value of memcache | |
if (empty($data)) | |
{ | |
$return = array( | |
'status' => 2, | |
'msg' => 'expired' | |
); | |
return response()->json($return, 200); | |
} | |
else | |
{ | |
if (!isset($data['sign'])) | |
{ | |
$return = array( | |
'status' => 0, | |
'msg' => 'Sign notset' | |
); | |
} | |
if ($data['sign'] != $sign) | |
{ // Verify delivery Sign | |
$return = array( | |
'status' => 0, | |
'msg' => 'Verification Error' | |
); | |
// return $this ->createJsonResponse( $return ); | |
return response()->json($return, 403); | |
} | |
else | |
{ | |
if ($login) | |
{ // Mobile phone scan code webpage login, save the user name in memcache | |
$data['jwt'] = $login; | |
$res = json_encode($data); | |
$mem->set($key, $res, 0, 180); | |
$return = array( | |
'status' => 1, | |
'msg' => 'Login successful' | |
); | |
// return $this ->createJsonResponse( $return ); | |
return response()->json($return, 200); | |
} | |
else | |
{ | |
$return = array( | |
'status' => 0, | |
'msg' => 'Please pass the correct user information' | |
); | |
// return $this ->createJsonResponse( $return ); | |
return response()->json($return, 401); | |
} | |
} | |
} | |
} | |
/* * | |
* Check whether the code has been scanned, this checked by polling, | |
* it looks for the key, the filename, | |
*/ | |
public function isScanQrcodeAction(Request $request) | |
{ | |
$key = $request['key']; | |
$mem = new \Memcache(); | |
$mem->connect('127.0.0.1', 11211); | |
$data = json_decode($mem->get($key) , true); | |
if (empty($data)) | |
{ | |
$return = array( | |
'status' => 2, | |
'msg' => 'expired' | |
); | |
} | |
else | |
{ | |
if ($data['type']) | |
{ | |
$return = array( | |
'status' => 1, | |
'msg' => 'success' | |
); | |
} | |
else | |
{ | |
$return = array( | |
'status' => 0, | |
'msg' => '' | |
); | |
} | |
} | |
return response()->json($return, 200); | |
// return $this->createJsonResponse( $return ); | |
} | |
public function loginEntry(Request $request) | |
{ | |
$key=$request['key']; | |
if (empty($key)){ | |
$return = array ('status'=>2,'msg'=>'key not provided' ); | |
return response()->json($return, 200); | |
} | |
$mem = new \Memcache(); | |
$mem->connect('127.0.0.1',11211); | |
$data = json_decode($mem->get($key),true); | |
// $passcode=$data['login']; | |
if (empty($data)){ | |
$return = array ('status'=>2,'msg'=>'expired' ); | |
return response()->json($return, 200); | |
} else { | |
if (isset($data['jwt'])){ | |
$userid=UnHashUserID($data['jwt']); | |
$user = Auth::loginUsingId($userid, true); | |
$return = array ('status'=>1,'msg'=>'success','jwt'=>$data['jwt'],'user'=>$user ); | |
return response()->json($return, 200); | |
} else { | |
$return = array ('status'=>0,'msg'=>'','data'=>$data ); | |
return response()->json($return, 400); | |
} | |
} | |
// Use passcode to login and return the object in reposne or jWT | |
// extract memcache and the login var jwt/passcode | |
//use passcode to login and return the jwt | |
} | |
} | |
?> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@extends('frontend/partials/master') | |
@section('top-stylesheets') | |
@include('frontend.partials.sidenavRegisterAndLoginCSS') | |
@endsection | |
@section('stylesheets') | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<style> | |
.alert.alert-position { | |
position: absolute; | |
width: 100%; | |
z-index: 1040; | |
} | |
</style> | |
@endsection | |
@section('stylesheets-bottom') | |
@include('frontend.partials.sidenavRegisterAndLoginJS') | |
<script type="text/javascript"> | |
</script> | |
<style> | |
nav#mainNav { | |
background-color: #004E92; | |
} | |
body{ | |
background: #F9F9F9 0% 0% no-repeat padding-box; | |
} | |
.page-section { | |
padding: 8rem 0; | |
} | |
ul.setting-card { | |
margin: 0 auto; | |
list-style: none; | |
box-shadow: 0px 3px 6px #00000029; | |
padding: 0; | |
} | |
ul.setting-card li:first-child { | |
font-weight: bold; | |
background: #004E92 0% 0% no-repeat padding-box; | |
padding: 12px 34px; | |
letter-spacing: 0.24px; | |
color: #FFFFFF; | |
border-top-right-radius: 6px; | |
border-top-left-radius: 6px; | |
} | |
ul.setting-card { | |
margin: 0 auto; | |
color: #5E5E5E; | |
} | |
.col-centered { | |
margin: 0 auto; | |
position: relative; | |
} | |
ul.setting-card li:not(:first-child) { | |
padding: 12px 34px; | |
letter-spacing: 0.24px; | |
} | |
.light-brown{ | |
color: #989898; | |
} | |
.account-save-btn { | |
background: #C4C4C4 0% 0% no-repeat padding-box; | |
border-radius: 6px; | |
} | |
.account-cancel-btn { | |
border: 1px solid #707070; | |
border-radius: 6px; | |
} | |
.cancel-subscription { | |
display: block; | |
text-align: right; | |
color: #CF0000; | |
} | |
i.fa.fa-trash { | |
cursor: pointer; | |
} | |
i.fa.fa-edit { | |
cursor: pointer; | |
} | |
.modal-dialog { | |
min-height: calc(100vh - 60px); | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
overflow: auto; | |
} | |
.modal-body { | |
position: relative; | |
flex: 1 1 auto; | |
padding: 3rem 5rem; | |
} | |
.modal-body p{ | |
letter-spacing: 0.24px; | |
color: #5E5E5E; | |
} | |
</style> | |
@endsection | |
@section('content') | |
@if(session()->has('message')) | |
<div class="alert alert-success alert-dismissible "> | |
<button type="button" class="close" data-dismiss="alert">×</button> | |
{{ session()->get('message') }} | |
</div> | |
@endif | |
@include('frontend.partials.sidenavRegisterAndLogin') | |
<section class="page-section"> | |
<div class="container"> | |
<h2 class="section-heading text-center">QR code scanner</h2> | |
<div class="row setting-cards"> | |
<div class="col-centered col-md-8"> | |
<ul class="setting-card"> | |
<li class="text-center"> | |
<?php $hashedid= HashUserID(Auth::user()->id); ?> | |
<p>passcode: {{$hashedid}}</p> | |
<p>Name: {{Auth::user()->name}}</p> | |
<p>Email: {{Auth::user()->email}}</p> | |
</li> | |
<li class="text-center"> | |
<div id="qr-reader" ></div> | |
<div id="qr-reader-results"></div> | |
<p id="login_mobile_scan_qrcode"></p> | |
<p id="qrcodedoLogin"></p></li> | |
</ul> | |
</div> | |
</div> | |
@if ($errors->any()) | |
<div class="alert alert-danger"> | |
<ul> | |
@foreach ($errors->all() as $error) | |
<li>{{ $error }}</li> | |
@endforeach | |
</ul> | |
</div> | |
@endif | |
</div> | |
</section><section class="page-section"> | |
</section> | |
@endsection | |
</body> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="{{ asset('frontend/qr/html5-qrcode.min.js') }}" ></script> | |
<script> | |
function qrcodedoLogin(param){ | |
var url = param; | |
console.log("qrcodedoLogin called",url); | |
$.ajax({ | |
type: "POST" , | |
dataType: "json" , | |
url: url , | |
data:{ | |
//key:key | |
}, | |
success:function(data) { | |
if (data.status==1 ){ | |
var qrcodeloginurl = data.msg; | |
//scan successfull url recieved | |
$('#qrcodedoLogin').text("QR Loggin successfully"); | |
// console.log("qrcodeloginurl",qrcodeloginurl); | |
//qrcodedoLogin(qrcodeloginurl); | |
} else if (data.status==2 ){ | |
//couldn't do login | |
// alert(data.msg); | |
$('#qrcodedoLogin').text(data.msg); | |
} | |
} | |
}); | |
} | |
function login_mobile_scan_qrcode(param){ | |
var url = param; | |
// console.log("login_mobile_scan_qrcode called",url); | |
$.ajax({ | |
type: "POST" , | |
dataType: "json" , | |
url: url , | |
headers: { 'userpasscode': '{{$hashedid}}' }, | |
data:{ | |
//key:key | |
}, | |
success:function(data) { | |
if (data.status==1 ){ | |
var qrcodeloginurl = data.msg; | |
//scan successfull url recieved | |
console.log("qrcodeloginurl",qrcodeloginurl); | |
$('#login_mobile_scan_qrcode').text("QR scanned successfully"); | |
qrcodedoLogin(qrcodeloginurl); | |
} else if(data.status==2 ){ | |
// error found | |
$('#login_mobile_scan_qrcode').text(data.msg); | |
} | |
} | |
}); | |
} | |
function docReady(fn) { | |
// see if DOM is already available | |
if (document.readyState === "complete" | |
|| document.readyState === "interactive") { | |
// call on next available tick | |
setTimeout(fn, 1); | |
} else { | |
document.addEventListener("DOMContentLoaded", fn); | |
} | |
} | |
docReady(function () { | |
var resultContainer = document.getElementById('qr-reader-results'); | |
var lastResult, countResults = 0; | |
function onScanSuccess(decodedText, decodedResult) { | |
if (decodedText !== lastResult) { | |
++countResults; | |
lastResult = decodedText; | |
// Handle on success condition with the decoded message. | |
console.log(`Scan result ${decodedText}`, decodedResult); | |
login_mobile_scan_qrcode(decodedText); | |
} | |
} | |
var html5QrcodeScanner = new Html5QrcodeScanner( | |
"qr-reader", { fps: 10, qrbox: 250 }); | |
html5QrcodeScanner.render(onScanSuccess); | |
}); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
Route::get('/qrtesting2', 'Admin\QRLoginTwoController@qr'); //shows the QR cde on screen | |
Route::get('/qrscanner', 'Admin\QRLoginTwoController@qrscanner');// scan the qr code | |
Route::post('web/login/entry/login', 'Admin\QRLoginTwoController@loginEntry');//Check whether the login has been confirmed ,and return the token in response and redirect | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment