02 . 02 . Go之Gin+Vue开发一个线上外卖应用(集成第三方发送短信和xorm生成存储数据库表)
集成第三方发送短信
介绍
用户登录

用户登录有两种方式:  短信登录,密码登录
短信登录是使用手机号和验证码进行登录
短信平台
很多云平台,比如阿里云,腾讯云,七牛云等云厂商,向程序开发者提供了短信验证码套餐服务。借助云平台的短信服务,程序开发者可以非常简单方便的将短信服务集成到自己的程序中。
我们以接入和集成阿里云的短信服务sdk为例, 如果需要申请腾讯云短信服务可以看我另外写的一篇blog,使用两者都差不多
https://www.cnblogs.com/you-men/p/13088949.html
阿里云短信服务集成-登录阿里云
登录阿里云
登录阿里云:https://www.aliyun.com/
选择短信服务模块:https://www.aliyun.com/product/sms
注明:云平台的短信服务是收费的,有不同类别的套餐。开发者可以按照自己的需求进行选择。如下图:

Go短信服务SDK
可以访问https://api.aliyun.com/?spm=5176.12207334.0.0.54d71cbe3NE29f#/?product=Dysmsapi&lang=GO查看go语言版本的短信服务sdk代码。
安装阿里云GO SDK
go get github.com/aliyun/alibaba-cloud-sdk-go
创建签名和短信模板
在使用go sdk集成短息服务之前,需要首先创建短信签名和短信模板。
签名:短信签名是短信服务提供的一种快捷、方便的个性化签名方式。当发送短信时,短信平台会根据设置,在短信内容里附加个性签名,再发送给指定手机号码。比如,下图红框中的"招商银行”就是这条短信的签名,用以标识发送者的类别等内容。

在阿里云后台的短信服务控制面板的左侧功能栏中,选择国内消息,如下图所示,然后选择签名管理的TAB,然后选择添加签名,可以创建新的短信签名。如下图:



短信模板:短信模版,即具体发送的短信内容。短信模版可以支持验证码、短信通知、推广短信三种模式。验证码和短信通知,通过变量替换实现个性短信定制。
与创建签名同理,可以在模板管理TAB中,选择添加模板,用来创建新的短信模板。创建完成后,会进行审核。

创建成功后的短信模板CODE需要记住,后续会使用到

在短信服务管理平台的概览界面,可以选择AccessKey按钮进行创建集成短信服务所需要的AccessKey和AccessKeySecret。

程序中集成短信服务
client, err := dysmsapi.NewClientWithAccessKey(smsConfig.RegionId, smsConfig.AppKey, smsConfig.AppSecret)
	if err != nil {
		toolbox.Error(err.Error())
		return ""
	}
	request := dysmsapi.CreateSendSmsRequest()
	request.Scheme = "https"
	request.SignName = smsConfig.SignName
	request.TemplateCode = smsConfig.TemplateCode
	request.PhoneNumbers = phone
	par, err := json.Marshal(map[string]interface{}{
		"code": code,
	})
	request.TemplateParam = string(par)
	response, err := client.SendSms(request)
	fmt.Println( response)
	if err != nil {
		toolbox.Error(err.Error())
		return ""
	}
我们通过上述核心代码程序,完成阿里云短信服务的集成。其中:
- SignName:在阿里云后台创建的前名,必传参数。
- TemplateCode:在阿里云后台创建的短信模板ID,必传参数。
- PhoneNumbers:接收短信的手机号码,必传参数。
创建阿里云短信服务sdk的client时,需要传regionID、appKey、accessKeySecret三个参数。regionID表示的是区域ID,可以填写cn-hangzhou。
创建Controller解析请求
无论是短信登录,还是用户名和密码登录,均属于用户功能模块。因此,创建MemberController用于解析用户模块的各个请求:
package controller
import (
	"CloudRestaurant/service"
	"fmt"
	"github.com/gin-gonic/gin"
)
type MemberController struct {}
func (mc *MemberController) Router(engine *gin.Engine)  {
	engine.GET("/api/sendcode",mc.sendSmsCode)
}
// http://localhost:8090/api/sendcode?phone=18621048481
func (mc *MemberController) sendSmsCode(c *gin.Context)  {
	// 发送验证码
	phone,exist := c.GetQuery("phone")
	fmt.Println(phone,"phone --->")
	if !exist {
		c.JSON(200,map[string]interface{}{
			"code":0,
			"msg":"参数解析失败",
		})
		return
	}
	ms := service.MemberService{}
	isSend := ms.Sendcode(phone)
	if isSend {
		c.JSON(200,map[string]interface{}{
			"code":1,
			"msg":"发送成功",
		})
		return
	}
	c.JSON(200,map[string]interface{}{
		"code":0,
		"msg":"发送失败",
	})
}
创建用户控制层程序MemberController,使用GET方法解析客户端发送短信验证码的请求,请求接口为:/api/sendcode,同时指定sendSmsCode方法处理接口请求。
在实际的开发中,程序功能往往是分层来进行开发的,controller层只负责控制和处理接口请求的逻辑,具体的功能调用,往往由另外称为service层的功能服务层来进行实现。
创建service层
在service层中,依然按照模块化开发的理念,将用户模块的服务统一由UserServicej进行提供。因此,创建MemberService,并提供SendCode方法。
package service
import (
	"CloudRestaurant/tool"
	"encoding/json"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
	"github.com/wonderivan/logger"
	"math/rand"
	"time"
)
type MemberService struct {
}
func (ms *MemberService) Sendcode(phone string) bool {
	// 1.产生一个验证码
	code := fmt.Sprintf("%06v",rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
	// 2.调用阿里云服务
	config := tool.GetConfig().Sms
	client, err := dysmsapi.NewClientWithAccessKey(config.RegionId, config.AppKey, config.AppSecret)
	if err != nil {
		logger.Error(err.Error())
		return false
	}
	request := dysmsapi.CreateSendSmsRequest()
	request.Scheme = "https"
	request.SignName = config.SignName
	request.TemplateCode = config.TemplateCode
	request.PhoneNumbers = phone
	par,err := json.Marshal(map[string]interface{}{
		"code":code,
	})
	request.TemplateParam = string(par)
	response,err :=client.SendSms(request)
	fmt.Println(response,"response --->")
	if err != nil {
		logger.Error(err.Error())
		return false
	}
	// 3. 接受返回结果,并判断发送状态
	if response.Code == "OK" {
		return true
	}
	return false
}
测试
在postman中, 使用/api/sendcode接口进行测试,详细url如下:
http://localhost:8090/api/sendcode?phone=13167582436
然后就能在手机端收到验证码

创建数据库和数据表
上面已经接入了第三方的短信服务SDK功能,可以接受短信验证码。在用户接受到验证码以后,输入验证码进行登录,我们需要验证用户输入的验证码是否正确。
因此,我们需要将发送过的验证码通过持久化的方式保存下来,方便我们进行校验。
我们选择通过数据库来存储用户手机验证码。
xorm介绍及安装
在项目开发过程中,我们会使用一些成熟的框架来操作数据库。xorm就是一个比较流行的数据库操作orm框架。
安装xorm
go get github.com/go-xorm/xorm
安装Mysql驱动
go get github.com/go-sql-driver/mysql
连接数据库
在连接数据库之前,首先要创建数据库。在mysql中创建cloudrestaurant数据库:
create database cloudrestaurant;
创建完数据库并安装好xorm库以后,使用xorm进行连接数据库
import (
	"github.com/go-xorm/xorm"
	_ "github.com/go-sql-driver/mysql"
)
database := cfg.Database
conn := database.User + ":" + database.Password + "@tcp(" + database.Host + ":" + database.Port + ")/" + database.DbName + "?charset=" + database.Charset
engine, err := xorm.NewEngine(database.Driver, conn)
if err != nil {
	return nil, err
}
连接数据库有些参数需要自己指定,比如说驱动类型,登录数据库的用户名,密码,数据库名等。将这些变量配置在app.json配置文件中,如下所示:
{
"database": {
    "driver": "mysql",
    "user": "root",
    "password": "12345678",
    "host": "127.0.0.1",
    "port": "3306",
    "db_name": "cloudrestaurant",
    "charset": "utf8mb4",
    "show_sql": true
}
}
在Config结构体中添加对database的解析
type Config struct {
	AppName  string         `json:"app_name"`
	AppMode  string         `json:"app_mode"`
	AppHost  string         `json:"app_host"`
	AppPort  string         `json:"app_port"`
	Database DatabaseConfig `json:"database"`
	Sms      SmsConfig      `json:"sms"`
}
type DatabaseConfig struct {
	Driver   string `json:"driver"`
	User     string `json:"user"`
	Password string `json:"password"`
	Host     string `json:"host"`
	Port     string `json:"port"`
	DbName   string `json:"db_name"`
	Charset  string `json:"charset"`
	ShowSql  bool   `json:"show_sql"`
}
创建SmsCode
要存储验证码,需要在数据库中创建表结构进行存储。我们可以创建SmsCode结构体,并通过tag设置数据库字段约束,具体的SmsCode定义如下:
package model
type SmsCode struct {
	Id         int64  `xorm:"pk autoincr" json:"id"`
	Phone      string `xorm:"varchar(11)" json:"phone"`
	BizId      string `xorm:"varchar(30)" json:"biz_id"`
	Code       string `xorm:"varchar(4)" json:"code"`
	CreateTime int64  `xorm:"bigint" json:"create_time"`
}
通过tag的xorm设置字段数据类型以及约束。
- pk:表示主键
- autoinc:表示自增
- bigint:整形变量
- varchar:字符串类型
Sync2同步生成数据库表
可以调用engine.Sync2方法,将结构体类型同步映射到数据库中,生成数据库表。
err = engine.Sync2(new(model.SmsCode))
	if err != nil {
		return nil, err
}
将验证码数据保存到数据库
在MemberService的SendCode方法,添加保存验证码到数据库的操作:
func (msi *MemberServiceImpl) SendCode(phone string) string {
	code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
	...
	dao := impl.NewMemberDao()
	smsCode := model.SmsCode{Phone: phone, Code: code, BizId: response.BizId, CreateTime: time.Now().Unix()}
	if result := dao.InsertCode(smsCode); result > 0 {
		return code
	}
	return ""
}
02 . 02 . Go之Gin+Vue开发一个线上外卖应用(集成第三方发送短信和xorm生成存储数据库表)的更多相关文章
- 01 . Go之Gin+Vue开发一个线上外卖应用
		项目介绍 我们将开始使用Gin框架开发一个api项目,我们起名为:云餐厅.如同饿了么,美团外卖等生活服务类应用一样,云餐厅是一个线上的外卖应用,应用的用户可以在线浏览商家,商品并下单. 该项目分为客户 ... 
- 03 . Gin+Vue开发一个线上外卖应用(用户数据创建,插入,跨域处理)
		功能和背景介绍 在项目的登录功能中,如果在登录时发现用户名和密码在用户表中不存在,会自动将用户名和密码保存在用户表中,创建一个新的用户. 因此,除了使用手机号和验证码登录以外,还支持使用用户名.密码进 ... 
- 04 . Go+Vue开发一个线上外卖应用(用户名密码和图形验证码)
		图形化验证码生成和验证 功能介绍 在使用用户名和密码登录功能时,需要填写验证码,验证码是以图形化的方式进行获取和展示的. 验证码使用原理 验证码的使用流程和原理为:在服务器端负责生成图形化验证码,并以 ... 
- 05 . Go+Vue开发一个线上外卖应用(Session集成及修改用户头像到Fastdfs)
		用户头像上传 功能介绍 在用户中心中,允许用户更换自己的头像.因此,我们开发上传一张图片到服务器,并保存成为用户的头像. 接口解析 在用户模块的控制器MemberController中,解析头像上传的 ... 
- JavaWeb-SpringBoot_一个类实现腾讯云SDK发送短信
		腾讯云应用列表 传送门 使用Gradle编译项目 传送门 SDK&API:qcloudsms_java 传送门 package com.Gary.sms.controller; import ... 
- 用Vue开发一个实时性时间转换功能,看这篇文章就够了
		前言 最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了.比如咱们今天要聊的这个话题:如何用 ... 
- 用vue开发一个app(4,一个久等了的文章)H5直播平台登录注册(1)
		我上一篇关于vue的文章和这一篇时间隔了有点久了.最近终于写完了. 因为我一直想写个有点实绩的东西,而不是随便写一个教程一样东西.结合最近在项目中学到的经验和我的一点创意. 首先介绍下这是个什么! H ... 
- 2440开发板linux系统移植3G拨号上网收发短信(三)
		一.用text查看模式 下面的“发”是指我敲的命令,“收”是指回车后显示的信息包括其他接收的信息. ~ >: microcom -s 115200 /dev/ttyUSB1 发:at 收:OK ... 
- 用qpython3写一个最简单的发送短信的程序
		到目前为止并没有多少手机应用是用python开发的,不过qpython可以作为一个不错的玩具推荐给大家来玩. 写一个最简单的发送短信的程序,代码如下: #-*-coding:utf8;-*- #qpy ... 
随机推荐
- redis过期策略以及内存淘汰机制(理论+配置)
			一.redis的过期策略: redis的过期策略是:定期删除+惰性删除redis在存储数据时,可能会设置过期时间,而所谓的定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的k ... 
- Hibernate4.3基础知识2
			一.数据库的隔离级别 脏读 不可重复读 幻读 Read uncommited Y Y Y Read commited N Y Y Repeatable read N N Y Serializabl ... 
- sqli-labs第一关 详解
			sqli-labs第一关 方法一:手工注入 方法二:sqlmap工具 两种方式,都可以学学,顺便学会用sqlmap,也是不错的.不多说,我们开始吧 方法一: 来到第一关,图上说我们需要一个数字的参数 ... 
- AD技巧之原理图元器件统一重新编号
			本文将简要介绍Altium Designer中如何进行原理图元器件统一命名,这是Altium Designer软件一个小技巧,在学习和工程实践中,都十分有用的技能. 第一步:打开原理图 第二步:点击& ... 
- Vue路由Hash模式分析
			Vue路由Hash模式分析 Vue-router是Vue的核心组件,主要是作为Vue的路由管理器,Vue-router默认hash模式,即使用URL的Hash来模拟一个完整的URL,当URL改变时页面 ... 
- 实验1:Mininet源码安装和可视化拓扑工具
			一.实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二.实验任务 使用源码安装 Mininet 的 2.3.0d6 版本,并使用可视化拓扑工具生成一个最简拓扑 ... 
- VS2015建立一个完整的c++工程:头文件.h 源文件.cpp,自动生成类
			https://blog.csdn.net/weixin_40539125/article/details/81430801 打开VS2015 ,新建VS win32工程,前面步骤很简单,不再阐述 下 ... 
- 《C++primerplus》第8章练习题
			1.(简单用一下引用变量,没有采用书中的题目)定义一个替身结构体,存储名字(char[])和力量值(int).使用结构体引用作为形参写两个函数,一个不加const,使得能对定义的结构体做修改,另一个加 ... 
- P2652 同花顺
			P2652 同花顺 Link 题目背景 所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续. 题目描述 现在我手里有 \(n\) 张扑克牌,但它们可能并不能凑成同花顺.我现在想知道,最少更换其中 ... 
- YCM 安装小记
			layout: post title: YCM 安装小记 半夜,女朋友在那边抱怨购物车的物品秒无货,我这边刚好成功安装了vim上最难装的插件--YouCompleteMe,内心非常激动,于是本着取之于 ... 
