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

news2024/10/6 6:51:49

原文地址:个人商城系统开源(发送手机验证码!) - 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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3 模型评估

3 模型评估 在测试AI系统中的模型训练和评估阶段,需要使用准备好的数据集对AI模型进行训练和评估。在训练过程中,应该对模型进行监控和调整,以确保模型的准确性和效果。在评估过程中,需要使用测试数据集对模型进行测试,以验证模型的准确性和效果。模型的评估也分为离线评…

通过一篇文章带你玩转git和GitHub

Git和Github的基本用法 前言一、Git和Github的基本用法背景下载安装安装 git for windows安装 tortoise gitgit安装过程中的一些选项 tortoise git汉化教程下载tortoise git汉化安装包安装tortoise git汉化安装包 三、使用 Github 创建项目注册账号创建项目下载项目到本地 四、…

视频批量混剪剪辑,批量剪辑批量剪视频,探店带货系统,精细化顺序混剪,故事影视解说,视频处理大全,精细化顺序混剪,多场景裂变,多视频混剪

前言 工具的产生源于dy出的火山引擎的云视频混剪制作是按分钟数收费的&#xff0c;这个软件既能实现正常混剪也能避免二次收费。属于FFMPEG合成的。 欢迎大家给一些好的建议和功能&#xff0c;回复可见&#xff0c;附加了一些天卡&#xff0c;周卡&#xff0c;请大家不要一人占…

【C++】函数模板和类模板

目录 1.泛型编程 2.函数模板 2.1函数模板的定义格式 2.2函数模板的实例化 2.3函数模板参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 3.3模板的分离编译 1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段…

新一代 Git 工具,AI 赋能!深度集成、简化操作 | 开源日报 No.194

gitbutlerapp/gitbutler Stars: 7.2k License: NOASSERTION gitbutler 是一个基于 Git 的版本控制客户端。旨在为现代工作流程构建一个全新的 Git 分支管理工具。 虚拟分支&#xff1a;可以同时在多个分支上工作&#xff0c;而无需不断切换分支简化提交管理&#xff1a;通过拖…

如何转行成为产品经理?

转行NPDP也是很合适的一条发展路径&#xff0c;之后从事新产品开发相关工作~ 一、什么是NPDP&#xff1f; NPDP 是产品经理国际资格认证&#xff0c;美国产品开发与管理协会&#xff08;PDMA&#xff09;发起的&#xff0c;是目前国际公认的唯一的新产品开发专业认证&#xff…

stm32普通定时器脉冲计数(发送固定脉冲个数),控制步进电机驱动器

拨码开关设置驱动器&#xff0c;细分 方法思路&#xff1a;用通用定时器TIM2&#xff0c;1ms产生一次中断&#xff1b;在中断里做IO反转&#xff1b; 发送10个脉冲信号

Docker部署SimpleMindMap结合内网穿透实现公网访问本地思维导图

文章目录 1. Docker一键部署思维导图2. 本地访问测试3. Linux安装Cpolar4. 配置公网地址5. 远程访问思维导图6. 固定Cpolar公网地址7. 固定地址访问 SimpleMindMap 是一个可私有部署的web思维导图工具。它提供了丰富的功能和特性&#xff0c;包含插件化架构、多种结构类型&…

【漏洞复现】大华ICC智能物联综合管理平台token弱口令漏洞

Nx01 产品简介 大华智能物联综合管理平台 iConnection Center&#xff08;以下简称&#xff1a;ICC平台&#xff09;&#xff0c;是一套基于智能物联的综合业务管理平台软件&#xff0c;具备强大的后台服务能力&#xff0c;配套了B/S管理员端、C/S客户端、移动APP终端、小程序等…

Java的Writer类详解

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

Tomcat容器经常重启问题排查

报错代码: INFO [Catalina-utility-2] org.apache.catalina.core.StandardContext.reload Reloading Context with name [] has started1.查看内存占用情况:top 可以发现java线程正常情况下占用高达24%的内存资源 2.继续排查:top -Hp 29580 可以发现主要有子线程Catalina-ut…

汉服|高校汉服租赁网站|基于Springboot的高校汉服租赁网站设计与实现(源码+数据库+文档)

高校汉服租赁网站目录 目录 基于Springboot的高校汉服租赁网站设计与实现 一、前言 二、系统设计 三、系统功能设计 1、汉服信息管理 2、汉服租赁管理 3、公告管理 4、公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…

Elasticsearch 通过索引阻塞实现数据保护深入解析

Elasticsearch 是一种强大的搜索和分析引擎&#xff0c;被广泛用于各种应用中&#xff0c;以其强大的全文搜索能力而著称。 不过&#xff0c;在日常管理 Elasticsearch 时&#xff0c;我们经常需要对索引进行保护&#xff0c;以防止数据被意外修改或删除&#xff0c;特别是在进…

关于STM32G070RBTx单片机使用HAL库往flash写数据的过程中死机问题

1.单片机型号:STM32G070RBTx 2.出现的问题 根据库函数FLASH_If_Write()的使用&#xff0c;我们分析往flash写数据的过程是把uint8_t 类型的数据(p_data)以地址的形式强转成uint64类型的&#xff0c;在一包128字节的数据时一次存储8位&#xff0c;存16次(packet_size/8)&#x…

简介:Deep Web和Dark Web

深网和暗网之间的区别是什么&#xff1f; “深网”和“暗网”是不能互换的术语。虽然整个暗网都是暗网的一部分&#xff0c;但反过来却不是这样。简单地说&#xff0c;深度网络是网络中没有被搜索引擎索引的任何部分。这包括在付费墙后面屏蔽其内容的网站、受密码保护的网站&a…

存货计价方式 比较-移动平均和批次计价

SAP常用的存货计价方式有 标准价格移动平均价格批次计价 标准价格常用于制造企业&#xff0c;今天的方案比较主要集中在销售型企业常用的移动平均价和批次计价 批次计价&#xff1a; 移动平均&#xff1a; 两种计价方式的Pros&Cons 比较 批次计价 移动平均优点 1…

韦根协议刷卡原理及代码实现

一、韦根协议原理 韦根接口在门禁行业广泛使用&#xff0c;是一个门禁行业的通信标准&#xff0c;通过两条数据线 DATA0&#xff08;D0&#xff09;和 DATA1 &#xff08;D1&#xff09;发送数据。目前用的最多的是韦根 34 和韦根 26&#xff0c;二者数据格式相同&#xff0c;…

【Python】科研代码学习:二 dataclass,pipeline

【Python】科研代码学习&#xff1a;二 dataclass&#xff0c;pipeline 前言dataclasspipeline 前言 后文需要学习一下 transformers 库&#xff0c;必要时会介绍其他相关的重要库和方法。主要是从源代码、别人的技术文档学习&#xff0c;会更快些。 dataclass Python中的数…

为什么选择Copilot for Microsoft365而不是Copilot Pro

最近很多小伙伴都用上了copilot&#xff0c;开始感受copilot在生产力工具中发挥的作用与带来的提升。 询问比较多的就是商业企业版的Copilot for Microsoft 365和个人家庭版的Copilot Pro有什么区别&#xff1f; 这篇文章一定会让你在两者之间选择最合适你的那个。 一、价格…