个人商城系统开源(发送手机验证码!)

原文地址:个人商城系统开源(发送手机验证码!) - Pleasure的博客

下面是正文内容:

前言

由于近期实在没有什么话题可写和一些有趣的项目教程可以分享。所以我只能决定将我自己亲手编写的一个迷你迷你商城系统进行开源。

也就是放在我博客右边的"我的另一个网站"(由于实在没什么生意只能开源了,充当教材)

开始分享一些前后端全栈的内容,希望对你们有所帮助。

虽然是迷你的商城系统,但是由于要实现每一部分各自的功能还是非常复杂的,比如用户的注册登录,手机号邮箱的绑定,充值支付功能的实现等等。

所以在这里我会花一周的时间按照功能进行划分来逐块解释,也好水一周的文章。顺便可以迁个站,整理一下代码。

看之前还是麻烦大家点点关注,谢谢!(就不选仅粉丝可见了)

如果在实现上存在什么问题,可以联系我。

正文

预先准备

通过API发送测试验证码短信(个人认证)-阿里云帮助中心

阿里云的账号,已在工信部备案的域名

首先在个人产品免费试用页面领取这个100条免费国内短信发送包。

在短信服务控制台申请资质,签名,以及短信模版。在工作日时间中大概需要一两个小时左右的时间,还是挺快的。

关于如何调用短信模版和签名进行发送,可以参考下面官方给出的SDK使用范例。

SendSms_短信服务_API调试-阿里云OpenAPI开发者门户

短信服务_SDK中心-阿里云OpenAPI开发者门户

注意!我在源码里使用的是SDKV1.0的版本,因为V2.0的版本涉及到阿里云OpenAPI的调用,虽然安全性高,但是操作难度也更高。

需要注意的事,短信验证码也是属于个人的财产需要做好保护。防止被别人盗刷。

在开始之前还需要将上面下载的官方SDK放在网站的根目录下,并修改下面文件中的accesskeyid和accesskeysecret为自己的账号内容。

正式调用(源码)

现在就是在商城系统的源码中正式嵌入短信验证的功能------用于账户手机的绑定以及密码的重置。

还是主要有四个文件,phoneregister.php,phone.php,phonecheck.php,phoneaction.php

phoneregister.php,前端展示页面

P.S. 为了防止短信验证码被盗刷,一般在发送按钮按钮处会添加一个验证码验证(人机验证)。这里我采取的是最基础的JavaSprint前端验证,但由于JS可以被浏览器禁用等原因而无法起到验证的作用,所以现如今的验证码都主要采取后端验证的方式,而这又要涉及到API的调用等更加复杂的操作,所以这里就不进行折腾了。

<?php
session_start();
$phone = isset($_SESSION['phone']) ? $_SESSION['phone'] : '';
if (isset($_SESSION['username'])) { ?>
  <!DOCTYPE html>
  <html>

  <head>
    <title>手机注册或更新</title>
    <meta name="content-type" ; charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    <meta name="generator" content="Jekyll v4.0.1">
    <link rel="icon" href="../picture/avatar2.jpg" type="image">
    <link href="../bootstrap.css" rel="stylesheet">
    <link href="../loginsystem/signin.css" rel="stylesheet">
    <style>
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }
    </style>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
  </head>

  <body class="text-center">
    <div class="form-signin" id="signinform">
      <img class="mb-4" src="../picture/avatar2.jpg" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal">Please register/change here</h1><br>

      <form class="form-signin" id="loginform" action="./phone.php" method="post">
        <div style="display: flex; align-items: center;">
          <input type="phone" id="phone" class="form-control" name="phone" required="required" value="<?php echo $phone ?>" placeholder="Phone Number" required autofocus>
          <button class="btn btn-md btn-secondary" id="buttonfirst" type="button" name="send">Send</button>
        </div>
      </form>
      <div class="modal fade" id="captchaModal" tabindex="-1" aria-labelledby="captchaModalLabel" aria-hidden="true">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title" id="captchaModalLabel">验证码</h5>
            </div>
            <div class="modal-body">
              <div id="rotateWrap" style="margin-top:50px;">

              </div>
            </div>
          </div>
        </div>
      </div>
      <p>
        <?php
        $err = isset($_GET["err"]) ? $_GET["err"] : "";
        switch ($err) {
          case 8:
            echo "发送成功!";
            break;

          case 9:
            echo "发送失败!";
            break;

          case 12:
            echo "该手机号已被注册!";
            break;

          case 14:
            echo "手机号格式错误!";
            break;

          case 15:
            echo "请等待1分钟后再试!";
            break;
        }
        ?>
      </p>
      <form class="form-signin" id="loginform" action="./phonecheck.php" method="post">
        <div style="display: flex; align-items: center;">
          <input type="text" id="verification2" class="form-control" name="verification2" required="required" value="" placeholder="Verification Code" required autofocus>
          <button class="btn btn-md btn-secondary" id="buttonfirst" type="submit" name="send">Sure</button>
        </div>
      </form>
      <p>
        <?php
        $err = isset($_GET["err"]) ? $_GET["err"] : "";
        switch ($err) {
          case 10:
            echo "验证成功!";
            header('Refresh: 1; URL=../index.php');
            exit();
            break;

          case 11:
            echo "手机号更新成功!";
            header('Refresh: 1; URL=../index.php');
            exit();
            break;

          case 16:
            echo "验证失败!";
            break;
        }
        ?>
      </p>
    </div>
  </body>
  <script src="../jqRotateVerify.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
    var myRotateVerify;
    var isVerified = false; // 添加一个变量来记录滑块验证是否通过
    var shouldSubmit = false; // 添加一个变量来跟踪是否应该提交表单

    $(document).ready(function() {
      $('#buttonfirst').click(function() {
        $('#captchaModal').modal('show');
        myRotateVerify.resetSlide();
      });

      $('#loginform').submit(function(e) {
        var phone = $('#phone').val();
        if (!/^1[3-9]\d{9}$/.test(phone)) {
          window.location.replace("phoneregister.php?err=14");
          return false;
        } else if (!isVerified) { // 检查滑块验证是否通过
          e.preventDefault();
        } else if (shouldSubmit) { // 如果应该提交表单,则允许表单提交
          return true;
        } else {
          e.preventDefault();
          $('#buttonfirst').click(); // 触发滑块验证
        }
      });
    });

    $(function() {
      myRotateVerify = new RotateVerify('#rotateWrap', {
        initText: '滑动将图片转正', //默认
        slideImage: ['../image/1.jpg', '../image/2.jpg', '../image/3.jpg'], //arr  [imgsrc1,imgsrc2] 或者str 'imgsrc1'
        slideAreaNum: 10, // 误差范围角度 +- 10(默认)
        getSuccessState: function(res) { //验证通过 返回  true;
          if (res) {
            isVerified = true; // 当滑块验证通过时,更新 isVerified 变量的值
            shouldSubmit = true; // 设置应该提交表单的标志为 true
            $('#loginform').submit(); // 提交表单
            $('#captchaModal').modal('hide');
          }
        }
      })
    });
  </script>

  </html>
<?php
} else {
  header('Location: ./index1.html');
  exit;
}
?>

phone.php,用于调用SDK发送短信

<?php
require "../aliyun-dysms-php-sdk/api_demo/SmsDemo.php";

ini_set('session.cookie_lifetime', 300);
session_start();

$cooldownSeconds = 60; // 冷却时间为120秒
$lastSentTime = isset($_SESSION['last_sent_time']) ? $_SESSION['last_sent_time'] : 0;
$currentTime = time();

if ($currentTime - $lastSentTime < $cooldownSeconds) {
       header("Location:phoneregister.php?err=15");
       exit;
}

$phone = $_POST['phone'];
$_SESSION['phone'] = $phone;

$username = $_SESSION['username'];
require "../conn.php";
$stmt = $conn->prepare("SELECT phone FROM phone WHERE phone = ? AND username != ?");
$stmt->bind_param("ss", $phone, $username);
$stmt->execute();
$res1 = $stmt->get_result();
$phone2 = $res1->fetch_assoc();
if ($phone2) {
       header("Location:phoneregister.php?err=12");
       exit;
}

$code = rand(111111, 999999);
$send = SmsDemo::sendSms($phone, $code);

if ($send->Code == "OK") {
       header("Location:phoneregister.php?err=8");

       $_SESSION['last_sent_time'] = $currentTime;
       $_SESSION['code'] = $code;
       $_SESSION['phone'] = $_POST["phone"];
} else {
       header("Location:phoneregister.php?err=9");
}

phonecheck.php,用于验证用户输入的验证码是否正确。

<?php
session_start();

$userInputCode = $_POST['verification2'];
$code = $_SESSION['code']; 
$phone = $_SESSION['phone'];
// 进行验证

if ((int)$userInputCode === (int)$code) { 
   header("Location:phoneaction.php");
   exit;
} else {
   header("Location:phoneregister.php?err=16");
}
?>

phoneaction.php,验证成功后向数据库相应账户插入手机号

<?php
session_start();
$username = $_SESSION['username'];
$phone = $_SESSION['phone'];

require "../conn.php";
$stmt = $conn->prepare("SELECT phone FROM phone WHERE phone = ?");
$stmt->bind_param("s", $phone);
$stmt->execute();
$ret = $stmt->get_result();
$num = $ret->num_rows;
if ($num < 1) {
    $stmt1 = $conn->prepare("INSERT INTO phone (phone, username) VALUES (?, ?)");
    $stmt1->bind_param("ss", $phone, $username);
    $stmt1->execute();
    header("Location:phoneregister.php?err=10");
} else {
    $stmt2 = $conn->prepare("UPDATE phone SET phone = ? WHERE username = ?");
    $stmt2->bind_param("ss", $username, $phone);
    $stmt2->execute();
    header("Location:phoneregister.php?err=11");
}

效果展示

可以看到已经接收成功了。

尾声

大致的流程如上,由于时间较为久远,可能忽略了一些具体的细节。但至少在源码的测试中是可行的,大家结合代码的具体语境进行使用吧。

网站源码下载地址:

https://download.csdn.net/download/2302_79791164/88922823

后面几天可能会视情况上传一个个人下载链接,如果有需要的话大家点个关注耐心等待一下。

相关推荐
啊松同学2 分钟前
【Java】设计模式——工厂模式
java·后端·设计模式
枫叶_v31 分钟前
【SpringBoot】20 同步调用、异步调用、异步回调
java·spring boot·后端
神夜大侠1 小时前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱1 小时前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
PC端游爱好者1 小时前
手机怎么玩steam游戏?随时随地远程串流玩steam游戏教程
游戏·macos·智能手机·电脑
AORO_BEIDOU1 小时前
抢抓5G机遇,AORO A23防爆手机如何直击园区巡检挑战?
大数据·5g·智能手机·信息与通信
柯南二号1 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72931 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲2 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6
王解2 小时前
【模块化大作战】Webpack如何搞定CommonJS与ES6混战(3)
前端·webpack·es6