go service access SMS verification code function (connected to Alibaba Cloud platform)

Introduction

SMS verification code is still a relatively common function, and there are already very mature solutions. This article introduces the SMS service of docking with Alibaba Cloud. A text message costs about two cents.

The basic process is:

  1. Go to the corresponding cloud platform to apply for permission, and the approximate cost is similar.
  2. Connect according to official documents and integrate into your own system

Let’s briefly talk about the business logic of the verification code. Points to note:

  1. SMS verification code validity period control, the setting here is 5minutes
  2. Randomly generated 6verification code
  3. The same mobile phone can only send a verification code once per minute.
  4. The same mobile phone number can only cache one verification code. If the previous verification code has not expired, it will be overwritten directly.

Alibaba Cloud platform service docking

The documentation related to Alibaba Cloud is quite complete. Just follow it. Here is a brief introduction.

  1. Register an Alibaba Cloud account
  2. Apply for SMS service test permission and bind a test mobile phone number
  3. Conduct a message sending test based on the information obtained after the application AccessKeyId, AccessKeySecret, SignName, and so on. The official example is as follows:TemplateCode
    Please add image description

The importance of documentation should be done well even if you have the energy to do your own projects.

go code implementation

Test code, the local memory cache is used here, it is useless redis. When using the following code, pay attention to the replacement marks TODO.

SmsOperationA is given interfaceto facilitate subsequent docking with other platforms. The code directory structure is as follows:

- verifyCode
	- aliyun.go
	- sms.go

sms.go

package verifyCode

import (
	"fmt"
	"math/rand"
	"time"
)

type SmsOperation interface {
    
    
	SendVerificationCode(phoneNumber string) error
	CheckVerificationCode(phoneNumber, verificationCode string) error
}

func NewSms() SmsOperation {
    
    
	return getAliyunEntity()
}

// 创建6位随机数
func CreateRandCode() string {
    
    
	return fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
}

aliyun.go

The cache here can be a separate module

package verifyCode

import (
	"errors"
	openapi "github.com/alibabacloud-go/darabonba-openapi/client"
	dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v2/client"
	aliyunUtil "github.com/alibabacloud-go/tea-utils/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/patrickmn/go-cache"
	"sync"
	"time"
)

type aliyun struct {
    
    
	verificationCodeCache    *cache.Cache // 验证码 5 分钟过期
	verificationCodeReqCache *cache.Cache // 一分钟内只能发送一次验证码
}

var (
	aliyunOnce   sync.Once
	aliyunEntity *aliyun
)

func getAliyunEntity() *aliyun {
    
    
	aliyunOnce.Do(func() {
    
    
		aliyunEntity = new(aliyun)
		aliyunEntity.verificationCodeReqCache = cache.New(time.Minute, time.Minute)
		aliyunEntity.verificationCodeCache = cache.New(time.Minute*5, time.Minute*5)
	})
	return aliyunEntity
}

func (this *aliyun) SendVerificationCode(phoneNumber string) (err error) {
    
    
	// 验证是否可以获取验证码(1分钟有效期)
	_, found := this.verificationCodeReqCache.Get(phoneNumber)
	if found {
    
    
		err = errors.New("请勿重复发送验证码")
		return
	}

	// 生成验证码
	verifyCode := CreateRandCode()

	// 发送短信
	err = this.SendSms(this.getVerifyCodeReq(phoneNumber, verifyCode))
	if err != nil {
    
    
		return
	}

	// 验证码加入缓存
	this.verificationCodeReqCache.SetDefault(phoneNumber, 1)
	this.verificationCodeCache.SetDefault(phoneNumber, verifyCode)

	return
}

func (this *aliyun) CheckVerificationCode(phoneNumber, verificationCode string) (err error) {
    
    
	cacheCode, found := this.verificationCodeCache.Get(phoneNumber)
	if !found {
    
    
		err = errors.New("验证码已失效")
		return
	}

	cc, sure := cacheCode.(string)
	if !sure {
    
    
		err = errors.New("内部服务出错")
		return
	}
	if cc != verificationCode {
    
    
		err = errors.New("验证码输入错误")
		return
	}
	return
}

// 可以上官网查看示例 https://next.api.aliyun.com/api/Dysmsapi/2017-05-25/SendSms?params={}

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
func (*aliyun) CreateClient(accessKeyId *string, accessKeySecret *string) (_result *dysmsapi20170525.Client, _err error) {
    
    
	config := &openapi.Config{
    
    
		// 您的 AccessKey ID
		AccessKeyId: accessKeyId,
		// 您的 AccessKey Secret
		AccessKeySecret: accessKeySecret,
	}
	// 访问的域名
	config.Endpoint = tea.String("dysmsapi.aliyuncs.com")
	_result = &dysmsapi20170525.Client{
    
    }
	_result, _err = dysmsapi20170525.NewClient(config)
	return _result, _err
}

func (this *aliyun) SendSms(req dysmsapi20170525.SendSmsRequest) (_err error) {
    
    
	// TODO your key,from config
	client, _err := this.CreateClient(tea.String("key id"), tea.String("key secret"))
	if _err != nil {
    
    
		return _err
	}

	defer func() {
    
    
		if r := tea.Recover(recover()); r != nil {
    
    
			_err = r
		}
	}()

	runtime := &aliyunUtil.RuntimeOptions{
    
    }
	result, _err := client.SendSmsWithOptions(&req, runtime)
	if _err != nil {
    
    
		return _err
	}

	if *result.Body.Code != "OK" {
    
    
		_err = errors.New(result.String())
		return
	}

	return _err
}

func (this *aliyun) getVerifyCodeReq(phoneNumber, code string) (req dysmsapi20170525.SendSmsRequest) {
    
    
	// TODO SignName TemplateCode
	req = dysmsapi20170525.SendSmsRequest{
    
    
		SignName:      tea.String("SignName"),
		TemplateCode:  tea.String("TemplateCode"),
		PhoneNumbers:  tea.String(phoneNumber),
		TemplateParam: tea.String(`{"code":"` + code + `"}`),
	}
	return
}

Summarize

  1. You should read the documentation of the connected SMS sending platform to learn the basic usage.
  2. Verification code caching, if it is a small business and does not have a large amount of data, sessionjust put it in the service cache. If it is a distributed service or the amount of data is large, it is best to put it redisin storage, which is a very mature solution.
  3. Pay attention to protecting yourself from malicious attacks. After all, every text message you send is worth money.

reference

Alibaba Cloud's
best practice for sending SMS sample SMS verification codes

Guess you like

Origin blog.csdn.net/DisMisPres/article/details/125564649