作者 yangfu
package sms
import (
"ability/protocol"
"github.com/astaxie/beego"
"github.com/astaxie/beego/httplib"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"encoding/json"
"errors"
)
type ISmsService interface {
Send(request *protocol.SmsCodeRequest) (err error)
type ISmsServe interface {
Send() error //调用远端接口发送短信
TextContent(v ...interface{}) (string, error) //构建短信文本内容
ValidReturn() (string, error) //检查调用远端接口后的返回内容,可用于记日志等操作
}
type YunPianSmsService struct{}
type SmsServe struct {
ToPhone string
UseTpl string
smsContent string //非导出
serveReturn *YunPainReturn //非导出
}
func assertImplement() {
var _ ISmsService = (*YunPianSmsService)(nil)
type YunPainReturn struct {
Code int `json:"code"` //0代表发送成功,其他code代表出错,详细见"返回值说明"页面
Msg string `json:"msg"` //例如""发送成功"",或者相应错误信息
Count int `json:"count"` //发送成功短信的计费条数(计费条数:70个字一条,超出70个字时按每67字一条计费)
Mobile string `json:"string"` //发送手机号
Fee float64 `json:"fee"` //扣费金额,单位:元,类型:双精度浮点型/double
Sid int64 `json:"sid"` //短信id,64位整型
}
//发送
func NewSmsServe(toPhone string, useTpl string) *SmsServe {
return &SmsServe{
ToPhone: toPhone,
UseTpl: useTpl,
serveReturn: nil,
}
}
func (s *YunPianSmsService) Send(request *protocol.SmsCodeRequest) (err error) {
var (
resp *YunPianResponse
)
log.Debug("[sms] mobile:", request.Phone, " content:", request.Content)
if beego.BConfig.RunMode != "prod" {
return
//Send 短信服务发送动作
func (s *SmsServe) Send() error {
if len(s.ToPhone) == 0 {
return nil
}
post := httplib.Post(beego.AppConfig.String("yunpian_sms_sdk_url"))
post.Param("apikey", beego.AppConfig.String("yunpian_app_key"))
post.Param("mobile", request.Phone)
post.Param("text", request.Content)
if err = post.ToJSON(&resp); err != nil {
return
//TODO
//发送短信
//获取并设置返回值
return nil
}
// TextContent 短信正文内容设置
func (s *SmsServe) TextContent(v ...interface{}) (string, error) {
tpl, err := getSmsTpl(s.UseTpl)
if err != nil {
return "", err
}
if resp.Code != 0 || resp.Mobile != request.Phone {
log.Error("yunpian send sms code:", resp.Code, " error msg:", resp.Msg)
err = common.NewErrorWithMsg(1, resp.Msg)
t, err := tpl.ParseTpl(v)
if err != nil {
return "", err
}
return nil
s.smsContent = t
return t, nil
}
type YunPianResponse struct {
Code int `json:"code"` //0代表发送成功,其他code代表出错,详细见"返回值说明"页面
Msg string `json:"msg"` //例如""发送成功"",或者相应错误信息
Count int `json:"count"` //发送成功短信的计费条数(计费条数:70个字一条,超出70个字时按每67字一条计费)
Mobile string `json:"string"` //发送手机号
Fee float64 `json:"fee"` //扣费金额,单位:元,类型:双精度浮点型/double
Sid int64 `json:"sid"` //短信id,64位整型
//ValidReturn 校验调用远端接口后返回的响应内容
func (s *SmsServe) ValidReturn() (string, error) {
if s.serveReturn == nil {
return "", errors.New("serveReturn is nil")
}
str, _ := json.Marshal(s.serveReturn)
if s.serveReturn.Code != 0 || s.serveReturn.Mobile != s.ToPhone {
return string(str), errors.New("send sms fail")
}
return string(str), nil
}
... ...
package sms
import (
"errors"
"fmt"
)
type ISmsTpl interface {
ParseTpl(v ...interface{}) (string, error)
String() string
}
//注册短信模板
var smsTpl = map[string]ISmsTpl{
"10001": SmsTpl{"【云片网】您的验证码是%s", 1},
}
const (
TplNotExit string = "tpl not exit"
TplFormateErr string = "tpl formate error"
)
type SmsTpl struct {
Formate string
ParamNum int
}
var (
_ ISmsTpl = SmsTpl{}
)
//ParseTpl 根据传参填充模板内容
func (t SmsTpl) ParseTpl(v ...interface{}) (string, error) {
if len(v) < t.ParamNum {
return "", errors.New(TplFormateErr)
}
return fmt.Sprintf(t.String(), v), nil
}
//String 返回模板字符串
func (t SmsTpl) String() string {
return t.Formate
}
//getSmsTpl 获取样板
//TODO 待优化
func getSmsTpl(code string) (ISmsTpl, error) {
if tpl, ok := smsTpl[code]; ok {
return tpl, nil
}
return nil, errors.New(TplNotExit)
}
... ...
package sms
import (
"ability/protocol"
"errors"
"github.com/astaxie/beego"
"github.com/astaxie/beego/httplib"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
)
type ISmsService interface {
Send(request *protocol.SmsCodeRequest) (err error)
GetSmsTpl(code string, content ...interface{}) (string, error)
}
type YunPianSmsService struct{}
func assertImplement() {
var _ ISmsService = (*YunPianSmsService)(nil)
}
//发送
func (s *YunPianSmsService) Send(request *protocol.SmsCodeRequest) (err error) {
var (
resp *YunPianResponse
)
log.Debug("[sms] mobile:", request.Phone, " content:", request.Content)
if beego.BConfig.RunMode != "prod" {
return
}
post := httplib.Post(beego.AppConfig.String("yunpian_sms_sdk_url"))
post.Param("apikey", beego.AppConfig.String("yunpian_app_key"))
post.Param("mobile", request.Phone)
post.Param("text", request.Content)
if err = post.ToJSON(&resp); err != nil {
return
}
if resp.Code != 0 || resp.Mobile != request.Phone {
log.Error("yunpian send sms code:", resp.Code, " error msg:", resp.Msg)
err = common.NewErrorWithMsg(1, resp.Msg)
}
return nil
}
func (s *YunPianSmsService) GetSmsTpl(code string, content ...interface{}) (string, error) {
// if data, ok := yunPianSmsTpl[code]; !ok {
// return fmt.Sprintf(data, content...), nil
// }
return "", errors.New("GetSmsTpl err,code=" + code)
}
type YunPianResponse struct {
Code int `json:"code"` //0代表发送成功,其他code代表出错,详细见"返回值说明"页面
Msg string `json:"msg"` //例如""发送成功"",或者相应错误信息
Count int `json:"count"` //发送成功短信的计费条数(计费条数:70个字一条,超出70个字时按每67字一条计费)
Mobile string `json:"string"` //发送手机号
Fee float64 `json:"fee"` //扣费金额,单位:元,类型:双精度浮点型/double
Sid int64 `json:"sid"` //短信id,64位整型
}
... ...