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 ""
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM