正在显示
7 个修改的文件
包含
163 行增加
和
9 行删除
| @@ -6,7 +6,7 @@ require ( | @@ -6,7 +6,7 @@ require ( | ||
| 6 | github.com/astaxie/beego v1.10.0 | 6 | github.com/astaxie/beego v1.10.0 |
| 7 | github.com/go-sql-driver/mysql v1.4.1 | 7 | github.com/go-sql-driver/mysql v1.4.1 |
| 8 | github.com/prometheus/client_golang v1.1.0 | 8 | github.com/prometheus/client_golang v1.1.0 |
| 9 | - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 | 9 | + github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect |
| 10 | gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1 | 10 | gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1 |
| 11 | google.golang.org/appengine v1.6.2 // indirect | 11 | google.golang.org/appengine v1.6.2 // indirect |
| 12 | ) | 12 | ) |
| @@ -65,6 +65,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= | @@ -65,6 +65,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= | ||
| 65 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= | 65 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= |
| 66 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= | 66 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= |
| 67 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | 67 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= |
| 68 | +github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= | ||
| 68 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | 69 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= |
| 69 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | 70 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= |
| 70 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | 71 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
| @@ -89,8 +90,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 | @@ -89,8 +90,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 | ||
| 89 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= | 90 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= |
| 90 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | 91 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= |
| 91 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | 92 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
| 93 | +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | ||
| 92 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | 94 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
| 93 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | 95 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= |
| 96 | +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= | ||
| 94 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | 97 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= |
| 95 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | 98 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= |
| 96 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | 99 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= |
services/datastore/database.go
0 → 100644
services/datastore/memory.go
0 → 100644
services/filestore/file.go
0 → 100644
| 1 | +package filestore | ||
| 2 | + | ||
| 3 | +//IFileStore TODO文件存储相关 | ||
| 4 | +type IFileStore interface { | ||
| 5 | + Auth() error //在获取文件前进行对请求进行检查 | ||
| 6 | + ReadFile() (string, error) //实际获取文件操作 | ||
| 7 | + StoreFile() (string, error) //实际存储文件操作 | ||
| 8 | + DeleteFile() error | ||
| 9 | +} | ||
| 10 | + | ||
| 11 | +// type LocalFileStore struct { | ||
| 12 | +// } | ||
| 13 | + | ||
| 14 | +// type XXXFileStore struct { | ||
| 15 | +// } |
| @@ -3,22 +3,34 @@ package sms | @@ -3,22 +3,34 @@ package sms | ||
| 3 | import ( | 3 | import ( |
| 4 | "encoding/json" | 4 | "encoding/json" |
| 5 | "errors" | 5 | "errors" |
| 6 | + "fmt" | ||
| 7 | + "regexp" | ||
| 8 | + | ||
| 9 | + "github.com/astaxie/beego" | ||
| 10 | + "github.com/astaxie/beego/httplib" | ||
| 6 | ) | 11 | ) |
| 7 | 12 | ||
| 13 | +//ISmsServe 短信服务接口协议 | ||
| 8 | type ISmsServe interface { | 14 | type ISmsServe interface { |
| 9 | Send() error //调用远端接口发送短信 | 15 | Send() error //调用远端接口发送短信 |
| 10 | TextContent(v ...interface{}) (string, error) //构建短信文本内容 | 16 | TextContent(v ...interface{}) (string, error) //构建短信文本内容 |
| 11 | ValidReturn() (string, error) //检查调用远端接口后的返回内容,可用于记日志等操作 | 17 | ValidReturn() (string, error) //检查调用远端接口后的返回内容,可用于记日志等操作 |
| 18 | + Name() string | ||
| 12 | } | 19 | } |
| 13 | 20 | ||
| 21 | +//SmsServe 生产线上使用的短信服务 | ||
| 14 | type SmsServe struct { | 22 | type SmsServe struct { |
| 15 | - ToPhone string | ||
| 16 | - UseTpl string | ||
| 17 | - smsContent string //非导出 | ||
| 18 | - serveReturn *YunPainReturn //非导出 | 23 | + ToPhone string //对方的电话号码 |
| 24 | + UseTpl string //使用的短信模板 | ||
| 25 | + smsContent string //非导出,最终发送的短信内容 | ||
| 26 | + serveReturn *YunPianReturn //非导出,调用远端接口后的响应内容 | ||
| 19 | } | 27 | } |
| 20 | 28 | ||
| 21 | -type YunPainReturn struct { | 29 | +var ( |
| 30 | + _ ISmsServe = &SmsServe{} | ||
| 31 | +) | ||
| 32 | + | ||
| 33 | +type YunPianReturn struct { | ||
| 22 | Code int `json:"code"` //0代表发送成功,其他code代表出错,详细见"返回值说明"页面 | 34 | Code int `json:"code"` //0代表发送成功,其他code代表出错,详细见"返回值说明"页面 |
| 23 | Msg string `json:"msg"` //例如""发送成功"",或者相应错误信息 | 35 | Msg string `json:"msg"` //例如""发送成功"",或者相应错误信息 |
| 24 | Count int `json:"count"` //发送成功短信的计费条数(计费条数:70个字一条,超出70个字时按每67字一条计费) | 36 | Count int `json:"count"` //发送成功短信的计费条数(计费条数:70个字一条,超出70个字时按每67字一条计费) |
| @@ -36,17 +48,34 @@ func NewSmsServe(toPhone string, useTpl string) *SmsServe { | @@ -36,17 +48,34 @@ func NewSmsServe(toPhone string, useTpl string) *SmsServe { | ||
| 36 | } | 48 | } |
| 37 | 49 | ||
| 38 | //Send 短信服务发送动作 | 50 | //Send 短信服务发送动作 |
| 51 | +//实现接口 ISmsServe | ||
| 39 | func (s *SmsServe) Send() error { | 52 | func (s *SmsServe) Send() error { |
| 40 | if len(s.ToPhone) == 0 { | 53 | if len(s.ToPhone) == 0 { |
| 41 | return nil | 54 | return nil |
| 42 | } | 55 | } |
| 43 | - //TODO | 56 | + //校验号码合法性/^1[3456789][0-9]{9}$/ |
| 57 | + ok, err := regexp.MatchString(`^1[3456789][0-9]{9}$`, s.ToPhone) | ||
| 58 | + if !ok { | ||
| 59 | + return fmt.Errorf("ToPhone err:%w", err) | ||
| 60 | + } | ||
| 44 | //发送短信 | 61 | //发送短信 |
| 62 | + var ( | ||
| 63 | + resp *YunPianReturn | ||
| 64 | + ) | ||
| 65 | + post := httplib.Post(beego.AppConfig.String("yunpian_sms_sdk_url")) | ||
| 66 | + post.Param("apikey", beego.AppConfig.String("yunpian_app_key")) | ||
| 67 | + post.Param("mobile", s.ToPhone) | ||
| 68 | + post.Param("text", s.smsContent) | ||
| 69 | + if err := post.ToJSON(&resp); err != nil { | ||
| 70 | + return fmt.Errorf("parse yunpian response err:%w ", err) | ||
| 71 | + } | ||
| 45 | //获取并设置返回值 | 72 | //获取并设置返回值 |
| 73 | + s.serveReturn = resp | ||
| 46 | return nil | 74 | return nil |
| 47 | } | 75 | } |
| 48 | 76 | ||
| 49 | // TextContent 短信正文内容设置 | 77 | // TextContent 短信正文内容设置 |
| 78 | +//实现接口 ISmsServe | ||
| 50 | func (s *SmsServe) TextContent(v ...interface{}) (string, error) { | 79 | func (s *SmsServe) TextContent(v ...interface{}) (string, error) { |
| 51 | tpl, err := getSmsTpl(s.UseTpl) | 80 | tpl, err := getSmsTpl(s.UseTpl) |
| 52 | if err != nil { | 81 | if err != nil { |
| @@ -61,6 +90,7 @@ func (s *SmsServe) TextContent(v ...interface{}) (string, error) { | @@ -61,6 +90,7 @@ func (s *SmsServe) TextContent(v ...interface{}) (string, error) { | ||
| 61 | } | 90 | } |
| 62 | 91 | ||
| 63 | //ValidReturn 校验调用远端接口后返回的响应内容 | 92 | //ValidReturn 校验调用远端接口后返回的响应内容 |
| 93 | +//实现接口 ISmsServe | ||
| 64 | func (s *SmsServe) ValidReturn() (string, error) { | 94 | func (s *SmsServe) ValidReturn() (string, error) { |
| 65 | if s.serveReturn == nil { | 95 | if s.serveReturn == nil { |
| 66 | return "", errors.New("serveReturn is nil") | 96 | return "", errors.New("serveReturn is nil") |
| @@ -71,3 +101,69 @@ func (s *SmsServe) ValidReturn() (string, error) { | @@ -71,3 +101,69 @@ func (s *SmsServe) ValidReturn() (string, error) { | ||
| 71 | } | 101 | } |
| 72 | return string(str), nil | 102 | return string(str), nil |
| 73 | } | 103 | } |
| 104 | + | ||
| 105 | +func (s *SmsServe) Name() string { | ||
| 106 | + return "SmsServe" | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +//DevSmsServe 开发调试使用的短信服务 | ||
| 110 | +type DevSmsServe struct { | ||
| 111 | + ToPhone string //对方的电话号码 | ||
| 112 | + UseTpl string //使用的短信模板 | ||
| 113 | + smsContent string //非导出,最终发送的短信内容 | ||
| 114 | + serveReturn string //非导出,调用远端接口后的响应内容 | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +var ( | ||
| 118 | + _ ISmsServe = &DevSmsServe{} | ||
| 119 | +) | ||
| 120 | + | ||
| 121 | +func NewDevSmsServe(toPhone string, useTpl string) *DevSmsServe { | ||
| 122 | + return &DevSmsServe{ | ||
| 123 | + ToPhone: toPhone, | ||
| 124 | + UseTpl: useTpl, | ||
| 125 | + serveReturn: "", | ||
| 126 | + } | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +//Send 实现接口 ISmsServe | ||
| 130 | +func (s *DevSmsServe) Send() error { | ||
| 131 | + return nil | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +//TextContent 实现接口 ISmsServe | ||
| 135 | +func (s *DevSmsServe) TextContent(v ...interface{}) (string, error) { | ||
| 136 | + tpl, err := getSmsTpl(s.UseTpl) | ||
| 137 | + if err != nil { | ||
| 138 | + return "", err | ||
| 139 | + } | ||
| 140 | + t, err := tpl.ParseTpl(v) | ||
| 141 | + if err != nil { | ||
| 142 | + return "", err | ||
| 143 | + } | ||
| 144 | + s.smsContent = t | ||
| 145 | + return t, nil | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +//ValidReturn 实现接口 ISmsServe | ||
| 149 | +func (s *DevSmsServe) ValidReturn() (string, error) { | ||
| 150 | + return "ok", nil | ||
| 151 | +} | ||
| 152 | + | ||
| 153 | +func (s *DevSmsServe) Name() string { | ||
| 154 | + return "DevSmsServe" | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +//SendSms 发送短信调用出口 TODO | ||
| 158 | +func SendSms(phone string, code string, param ...interface{}) error { | ||
| 159 | + var serve ISmsServe | ||
| 160 | + serve = NewSmsServe(phone, code) | ||
| 161 | + // serve = NewDevSmsServe(phone, code) | ||
| 162 | + | ||
| 163 | + _, err := serve.TextContent(param) | ||
| 164 | + if err != nil { | ||
| 165 | + return err | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + return serve.Send() | ||
| 169 | +} |
| 1 | package sms | 1 | package sms |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | + "bytes" | ||
| 4 | "errors" | 5 | "errors" |
| 5 | "fmt" | 6 | "fmt" |
| 7 | + "html/template" | ||
| 6 | ) | 8 | ) |
| 7 | 9 | ||
| 8 | type ISmsTpl interface { | 10 | type ISmsTpl interface { |
| @@ -13,6 +15,9 @@ type ISmsTpl interface { | @@ -13,6 +15,9 @@ type ISmsTpl interface { | ||
| 13 | //注册短信模板 | 15 | //注册短信模板 |
| 14 | var smsTpl = map[string]ISmsTpl{ | 16 | var smsTpl = map[string]ISmsTpl{ |
| 15 | "10001": SmsTpl{"【云片网】您的验证码是%s", 1}, | 17 | "10001": SmsTpl{"【云片网】您的验证码是%s", 1}, |
| 18 | + "10002": SmsTplUseHtml{ | ||
| 19 | + `【买买买信息科技】{{.Code}}({{.AppName}}手机验证码,请完成验证),如非本人操作,请忽略本短信`, | ||
| 20 | + "10002"}, | ||
| 16 | } | 21 | } |
| 17 | 22 | ||
| 18 | const ( | 23 | const ( |
| @@ -21,8 +26,8 @@ const ( | @@ -21,8 +26,8 @@ const ( | ||
| 21 | ) | 26 | ) |
| 22 | 27 | ||
| 23 | type SmsTpl struct { | 28 | type SmsTpl struct { |
| 24 | - Formate string | ||
| 25 | - ParamNum int | 29 | + Formate string //模板字符串 |
| 30 | + ParamNum int //模板限定参数数量 | ||
| 26 | } | 31 | } |
| 27 | 32 | ||
| 28 | var ( | 33 | var ( |
| @@ -42,6 +47,35 @@ func (t SmsTpl) String() string { | @@ -42,6 +47,35 @@ func (t SmsTpl) String() string { | ||
| 42 | return t.Formate | 47 | return t.Formate |
| 43 | } | 48 | } |
| 44 | 49 | ||
| 50 | +//SmsTplUseHtml 以html模板方式构建短信模板 | ||
| 51 | +type SmsTplUseHtml struct { | ||
| 52 | + Formate string //模板字符串 | ||
| 53 | + Name string | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +var ( | ||
| 57 | + _ ISmsTpl = SmsTplUseHtml{} | ||
| 58 | +) | ||
| 59 | + | ||
| 60 | +func (t SmsTplUseHtml) ParseTpl(v ...interface{}) (string, error) { | ||
| 61 | + var param interface{} | ||
| 62 | + if len(v) > 0 { | ||
| 63 | + param = v[0] | ||
| 64 | + } | ||
| 65 | + tpl, err := template.New(t.Name).Parse(t.Formate) | ||
| 66 | + if err != nil { | ||
| 67 | + return "", err | ||
| 68 | + } | ||
| 69 | + btTpl := bytes.NewBuffer(nil) | ||
| 70 | + if err = tpl.Execute(btTpl, param); err != nil { | ||
| 71 | + return "", err | ||
| 72 | + } | ||
| 73 | + return btTpl.String(), nil | ||
| 74 | +} | ||
| 75 | +func (t SmsTplUseHtml) String() string { | ||
| 76 | + return t.Formate | ||
| 77 | +} | ||
| 78 | + | ||
| 45 | //getSmsTpl 获取样板 | 79 | //getSmsTpl 获取样板 |
| 46 | //TODO 待优化 | 80 | //TODO 待优化 |
| 47 | func getSmsTpl(code string) (ISmsTpl, error) { | 81 | func getSmsTpl(code string) (ISmsTpl, error) { |
-
请 注册 或 登录 后发表评论