顾客找回密码功能
This commit is contained in:
parent
2e577bbd8c
commit
6ee3aacc0f
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* Notification.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author TL <mengwb@opencart.cn>
|
||||
* @created 2022-07-07 10:52:57
|
||||
* @modified 2022-07-07 10:52:57
|
||||
*/
|
||||
|
||||
namespace Beike\Libraries;
|
||||
|
||||
|
||||
class Notification
|
||||
{
|
||||
/**
|
||||
* @param string $code
|
||||
* @param string $message
|
||||
* @param string $type email|telephone
|
||||
* @return bool
|
||||
*/
|
||||
public static function verifyCode(string $code, string $message, string $type): bool
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* VerifyCode.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author Edward Yang <yangjin@opencart.cn>
|
||||
* @created 2022-07-07 15:22:18
|
||||
* @modified 2022-07-07 15:22:18
|
||||
*/
|
||||
|
||||
namespace Beike\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class VerifyCode extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['account', 'code'];
|
||||
}
|
||||
|
||||
|
|
@ -28,16 +28,24 @@ class CustomerRepo
|
|||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $customer
|
||||
* @param $data
|
||||
* @return bool|int
|
||||
*/
|
||||
public static function update($id, $data)
|
||||
public static function update($customer, $data)
|
||||
{
|
||||
if (!$customer instanceof Customer) {
|
||||
$customer = Customer::query()->findOrFail($customer);
|
||||
}
|
||||
if (isset($data['password'])) {
|
||||
$data['password'] = Hash::make($data['password']);
|
||||
}
|
||||
return Customer::query()->find($id)->update($data);
|
||||
return $customer->update($data);
|
||||
}
|
||||
|
||||
public static function findByEmail($email)
|
||||
{
|
||||
return Customer::query()->where('email', $email)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* VerifyCodeRepo.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author Edward Yang <yangjin@opencart.cn>
|
||||
* @created 2022-07-07 15:22:05
|
||||
* @modified 2022-07-07 15:22:05
|
||||
*/
|
||||
|
||||
namespace Beike\Repositories;
|
||||
|
||||
|
||||
use Beike\Models\VerifyCode;
|
||||
|
||||
class VerifyCodeRepo
|
||||
{
|
||||
/**
|
||||
* 创建一个记录
|
||||
* @param $data
|
||||
* @return int
|
||||
*/
|
||||
public static function create($data)
|
||||
{
|
||||
$verifyCode = VerifyCode::query()->create($data);
|
||||
return $verifyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public static function find($id)
|
||||
{
|
||||
return VerifyCode::query()->find($id);
|
||||
}
|
||||
|
||||
public static function findByAccount($account)
|
||||
{
|
||||
return VerifyCode::query()->where('account', $account)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return void
|
||||
*/
|
||||
public static function delete($id)
|
||||
{
|
||||
$verifyCode = VerifyCode::query()->find($id);
|
||||
if ($verifyCode) {
|
||||
$verifyCode->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
/**
|
||||
* ForgottenController.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author TL <mengwb@opencart.cn>
|
||||
* @created 2022-07-06 15:39:08
|
||||
* @modified 2022-07-06 15:39:08
|
||||
*/
|
||||
|
||||
namespace Beike\Shop\Http\Controllers\Account;
|
||||
|
||||
use Beike\Shop\Services\AccountService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ForgottenController
|
||||
{
|
||||
/**
|
||||
* 找回密码页面
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('account/forgotten');
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收email地址,生成验证码发送到邮件地址
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function sendVerifyCode(Request $request)
|
||||
{
|
||||
AccountService::sendVerifyCodeForForgotten($request->get('email'), 'email');
|
||||
return json_success('验证码已发送,请查看并输入验证码');
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收验证码和新密码、确认密码,验证验证码是否正确、密码和确认密码是否相等,然后修改密码
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function changePassword(ForgottenRequest $request)
|
||||
{
|
||||
AccountService::verifyAndChangePassword($request->get('code'), $request->get('account'), $request->get('password'));
|
||||
|
||||
return json_success('密码已修改');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Beike\Shop\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ForgottenRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'password' => 'required|confirmed',
|
||||
];
|
||||
}
|
||||
|
||||
public function attributes()
|
||||
{
|
||||
return [
|
||||
'password' => '密码'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Beike\Models\Customer;
|
||||
use Beike\Shop\Http\Controllers\Account\AddressController;
|
||||
use Beike\Shop\Http\Controllers\Account\ForgottenController;
|
||||
use Beike\Shop\Http\Controllers\Account\OrderController;
|
||||
use Beike\Shop\Http\Controllers\ZoneController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
|
@ -40,6 +41,9 @@ Route::prefix('/')
|
|||
Route::get('register', [RegisterController::class, 'index'])->name('register.index');
|
||||
Route::post('register', [RegisterController::class, 'store'])->name('register.store');
|
||||
Route::get('logout', [LogoutController::class, 'index'])->name('logout');
|
||||
Route::get('forgotten', [ForgottenController::class, 'index'])->name('forgotten.index');
|
||||
Route::post('forgotten/send_code', [ForgottenController::class, 'sendVerifyCode'])->name('forgotten.send_code');
|
||||
Route::post('forgotten/password', [ForgottenController::class, 'changePassword'])->name('forgotten.password');
|
||||
Route::resource('countries.zones', ZoneController::class);
|
||||
|
||||
Route::middleware('shop_auth:' . Customer::AUTH_GUARD)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@
|
|||
namespace Beike\Shop\Services;
|
||||
|
||||
|
||||
use Beike\Libraries\Notification;
|
||||
use Beike\Models\Customer;
|
||||
use Beike\Repositories\CustomerRepo;
|
||||
use Beike\Repositories\VerifyCodeRepo;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AccountService
|
||||
{
|
||||
|
|
@ -38,4 +42,54 @@ class AccountService
|
|||
|
||||
return CustomerRepo::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码通过$type方式,type为email或telephone
|
||||
* @param $email
|
||||
* @param $type
|
||||
* @return void
|
||||
*/
|
||||
public static function sendVerifyCodeForForgotten($email, $type) {
|
||||
$code = str_pad(mt_rand(10, 999999), 6, '0', STR_PAD_LEFT);
|
||||
|
||||
VerifyCodeRepo::create([
|
||||
'account' => $email,
|
||||
'code' => $code,
|
||||
]);
|
||||
|
||||
Log::info("找回密码验证码:{$code}");
|
||||
|
||||
Notification::verifyCode($code, "您的验证码是%s,该验证码仅用于找回密码。", $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证验证码是否正确,并修改密码为新密码
|
||||
* @param $code
|
||||
* @param $account
|
||||
* @param $password
|
||||
* @param $type $account类型,email代表$account为邮箱地址,telephone代表$account为手机号码
|
||||
* @return void
|
||||
*/
|
||||
public static function verifyAndChangePassword($code, $account, $password, $type = 'email')
|
||||
{
|
||||
$verifyCode = VerifyCodeRepo::findByAccount($account);
|
||||
if ($verifyCode->created_at->addMinutes(10) < Carbon::now()) {
|
||||
$verifyCode->delete();
|
||||
throw new \Exception("您的验证码已过期(10分钟),请重新获取");
|
||||
}
|
||||
|
||||
if ($verifyCode->code != $code) {
|
||||
throw new \Exception("您的验证码错误");
|
||||
}
|
||||
|
||||
if ($type == 'email') {
|
||||
$customer = CustomerRepo::findByEmail($account);
|
||||
} elseif ($type == 'telephone') {
|
||||
throw new \Exception("暂不支持手机号码找回密码");
|
||||
} else {
|
||||
throw new \Exception("找回密码类型错误");
|
||||
}
|
||||
CustomerRepo::update($customer, ['password' => $password]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class VerifyCode extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('verify_codes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('account', 256);
|
||||
$table->string('code', 16);
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('verify_codes');
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<div class="row">
|
||||
|
||||
<x-shop-sidebar/>
|
||||
<x-hop-sidebars/>
|
||||
|
||||
<div class="col-12 col-md-9">
|
||||
@if (\Session::has('success'))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
@extends('layout.master')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<h1>找回密码</h1>
|
||||
<form action="{{ route('shop.register.store') }}" method="post">
|
||||
@csrf
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="email">邮箱</span>
|
||||
</div>
|
||||
<input type="text" name="register[email]" class="form-control" value="{{ old('register.email') }}" placeholder="邮箱地址">
|
||||
</div>
|
||||
@error('register.email')
|
||||
<x-admin::form.error :message="$message"/>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="password">密码</span>
|
||||
</div>
|
||||
<input type="password" name="register[password]" class="form-control" placeholder="密码">
|
||||
</div>
|
||||
@error('register.password')
|
||||
<x-admin::form.error :message="$message"/>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if (session('error'))
|
||||
<div class="alert alert-success">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-block mb-4">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
Loading…
Reference in New Issue