实现阿里云发送手机验证码功能——golang+redis

使用阿里云短信服务发送手机验证码,并简单结合redis实现验证码有效期功能。本篇侧重于讲解阿里云短信服务,redis相关的知识点后续再补上。

 基础知识

想使用阿里云短信服务,需要先注册一个账号,在此就不过多讲解,可以访问阿里云短信服务官方文档以及具体的阿里云短信服务文档使用指引获取相关的知识点。其完整的流程可以引用官方的使用流程图展示:

 在完成注册,开通短信服务等功能后,可以在短信服务管理平台查看使用信息。成功创建短信签名和模板并通过审核后,可以在模板签名管理查看设置的签名模板。想调试接口可以访问OpenApI Explore快速调用短信服务API。调用短信访问API后返回的具体数据也可以在该页面查看,如下图所示:

功能实现

简单讲完阿里云短信服务的使用基础,下面就给出具体的代码实现,go语言下使用短信服务,需先引入官方的SDK:github.com/aliyun/alibaba-cloud-sdk-go。功能逻辑很简单,就不多描述。

redis连接:

package redis_conn

import(
    "github.com/go-redis/redis"
    "github.com/micro/go-micro/util/log"
)

var RdsConn *redis.Client

func init(){
    // connect redis
    RdsConn = redis.NewClient(&redis.Options{
		Addr:     "127.0.0.1:6379",  //
		Password: "", // no password set
		DB:       0,  // use default DB
	})

    _, err := RdsConn.Ping().Result()
    if err != nil{
        log.Logf("connect redis fail",err)
        panic(err)
    }
}

实现短信发送以及验证功能关键代码:

package handler

import (
    "time"
    "fmt"
    "context"
    "github.com/micro/go-micro/util/log"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
    "encoding/json"
    "github.com/go-redis/redis"

    auth_helper "auth/common"
	auth "auth/proto/auth"
    rds_conn "auth/common/redis_conn"
)


// 短信验证功能
// send verification code to mobile phone
func (e *Auth) SMSAuth(ctx context.Context, req *auth.SMSRequest, rsp *auth.SMSResponse) error{
    phone_num := req.PhoneNum

    if phone_num == ""{
        rsp.Detail="mobile phone number is null"
        return nil
    }
    
    // 下列的accessKeyId以及accessSecret请按实际申请到的填写
    client, err := sdk.NewClientWithAccessKey("cn-hangzhou", "accessKeyId", "accessSecret")
	if err != nil {
        rsp.Detail="connect to SMS server fail"
        return nil
	}
    
    // generate the verification code
    verify_code := auth_helper.GenerateCode()  // 生成6位数字验证码功能
    verify_code_str := fmt.Sprintf("{\"code\":\"%d\"}",verify_code)

    request := requests.NewCommonRequest()
    request.Method = "POST"
    request.Scheme = "https" // https | http
    request.Domain = "dysmsapi.aliyuncs.com"
    request.Version = "2017-05-25"
    request.ApiName = "SendSms"
    request.QueryParams["RegionId"] = "cn-hangzhou"
	
    /*
      接收短信的手机号码。
      格式:
      国内短信:11位手机号码,例如15951955195。
      国际/港澳台消息:国际区号+号码,例如85200000000。
      支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。
      验证码类型短信,建议使用单独发送的方式。
    */
    request.QueryParams["PhoneNumbers"] = phone_num

    /*
      短信签名名称。请在控制台签名管理页面签名名称一列查看。
      必须是已添加、并通过审核的短信签名。
    */
    request.QueryParams["SignName"] = "XX服务"

    /*
      短信模板ID。请在控制台模板管理页面模板CODE一列查看。
      必须是已添加、并通过审核的短信签名;且发送国际/港澳台消息时,请使用国际/港澳台短信模版。
    */
    request.QueryParams["TemplateCode"] = "SMS_XXXXXXXX"

    /*
      短信模板变量对应的实际值,JSON格式。
      如果JSON中需要带换行符,请参照标准的JSON协议处理。
    */
    request.QueryParams["TemplateParam"] = verify_code_str

	response, err := client.ProcessCommonRequest(request)
	if err != nil {
        rsp.Detail=err.Error()
        return nil
	}

    // get the api response result
    send_res := &auth_helper.SMSResponseJson{}
    err = json.Unmarshal(response.GetHttpContentBytes(),&send_res)

    if err != nil{
        rsp.Detail=err.Error()
        return nil
    }

    if send_res.Message != "OK"{
        rsp.Detail=send_res.Message
        return nil
    }

    // 将手机号以及验证码保存到redis中,并设置超时时间
    rds_conn.RdsConn.Set(phone_num, 
    fmt.Sprintf("%d",verify_code), 
    time.Duration(auth_helper.SMS_TIME_OUT) * time.Second).Err()

    rsp.Detail="send SMS successfully"

    return nil
}


func (e *Auth)VerifyCodeAuth(ctx context.Context, req *auth.VerifyCodeAuthRequest, rsp *auth.SMSResponse)error{
    
    // check the request param
    if req.PhoneNum == "" || req.Code == ""{
        rsp.Detail="request parameters not correct"
        return nil
    }

    val, err := rds_conn.RdsConn.Get(req.PhoneNum).Result()  // 获取redis中保存的手机号以及验证码信息

    if err == redis.Nil{
        rsp.Detail="key not exists"
        return nil
    }else if err != nil{
        rsp.Detail="未知错误:"+err.Error()
        return nil
    }

    if val != req.Code{
        rsp.Detail="verification code not correct"
        return nil
    }

    rsp.Detail="verification code passed"

    return nil
}

 


版权声明:本文为DAKESLON原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。