123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- package youngee_talent_service
- import (
- "bytes"
- "crypto/sha256"
- "crypto/tls"
- "encoding/base64"
- "encoding/json"
- "fmt"
- openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
- dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v4/client"
- util "github.com/alibabacloud-go/tea-utils/v2/service"
- "github.com/alibabacloud-go/tea/tea"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/net/ghttp"
- uuid "github.com/satori/go.uuid"
- "io/ioutil"
- "math/rand"
- "net/http"
- "net/url"
- "strings"
- "time"
- "youngmini_server/app/model/youngee_talent_model"
- "youngmini_server/app/utils"
- )
- // 无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
- const WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\""
- // 无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
- const AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""
- type SendcodeReq struct {
- Phone string `json:"phone"`
- }
- // 接口调用此函数
- func SendSmsCode(r *ghttp.Request) *TalentHttpResult {
- l := SendcodeReq{}
- err := r.ParseForm(&l)
- if err != nil {
- return &TalentHttpResult{Code: -1, Msg: "请求体解析失败"}
- }
- vcode := GetCode()
- err = SendCodeImpAli(l.Phone, vcode)
- if err != nil {
- return &TalentHttpResult{Code: -1, Msg: "短信发送失败"}
- }
- //验证码存redis
- _ = SetRedis(l.Phone, vcode)
- return &TalentHttpResult{Code: 0, Msg: "sendSmsCodeSuccess", Data: vcode}
- }
- func SetRedis(phone string, vcode string) error {
- _, err := g.Redis().Do("SETEX", getRedisKey(phone), 120, vcode) //第三个参数以秒为单位
- if err != nil {
- fmt.Println("redis存储错误")
- }
- return nil
- }
- func getRedisKey(phone string) string {
- return fmt.Sprintf("%s%s", "c_user:", phone)
- }
- // 发送验证码具体实现
- //func SendCodeImp(phone string, vcode string) error {
- // //必填,请参考"开发准备"获取如下数据,替换为实际值
- // apiAddress := "https://smsapi.cn-south-1.myhuaweicloud.com:443/sms/batchSendSms/v1" //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
- // appKey := "NETTvTJJie9ax03v9K5T4DFB9EV6" //APP_Key
- // appSecret := "txi9kXIrxW0dVNMyAulrJf7XFNP7" //APP_Secret
- // sender := "8823022707732" //国内短信签名通道号或国际/港澳台短信通道号
- // templateId := "7103cdd480d14d0aa8c68954a7dbeb6e" //模板ID
- //
- // //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
- // //国际/港澳台短信不用关注该参数
- // signature := "样叽" //签名名称
- //
- // //必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
- // receiver := "+86" + phone //短信接收人号码
- //
- // //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
- // statusCallBack := ""
- //
- // /*
- // * 选填,使用无变量模板时请赋空值 string templateParas = "";
- // * 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为"[\"369751\"]"
- // * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为"[\"3\",\"人民公园正门\"]"
- // * 模板中的每个变量都必须赋值,且取值不能为空
- // * 查看更多模板和变量规范:产品介绍>模板和变量规范
- // */
- // templateParas := "[\"" + vcode + "\"]" //模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
- // // templateParas := "[\"12345678\"]" //模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
- //
- // body := buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, signature)
- // headers := make(map[string]string)
- // headers["Content-Type"] = "application/x-www-form-urlencoded"
- // headers["Authorization"] = AUTH_HEADER_VALUE
- // headers["X-WSSE"] = buildWsseHeader(appKey, appSecret)
- // resp, err := post(apiAddress, []byte(body), headers)
- // if err != nil {
- // return err
- // }
- // fmt.Println(resp)
- // return nil
- //}
- func SendCodeImpAli(phone string, vcode string) error {
- // 1. 创建客户端
- config := &openapi.Config{
- AccessKeyId: tea.String("LTAI5tDfTQeZ2ufN8mhsWQNA"),
- AccessKeySecret: tea.String("DKLd2hGbmJPcNki8p6VlU6mV2HXVvO"),
- Endpoint: tea.String("dysmsapi.aliyuncs.com"),
- }
- client, err := dysmsapi20170525.NewClient(config)
- if err != nil {
- return fmt.Errorf("创建客户端失败: %v", err)
- }
- // 2. 准备请求
- sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
- PhoneNumbers: tea.String(phone),
- SignName: tea.String("北京智子时空科技"),
- TemplateCode: tea.String("SMS_481650308"),
- TemplateParam: tea.String(fmt.Sprintf(`{"code":"%s"}`, vcode)),
- }
- // 3. 发送请求
- runtime := &util.RuntimeOptions{}
- resp, err := client.SendSmsWithOptions(sendSmsRequest, runtime)
- if err != nil {
- // 错误处理
- if sdkErr, ok := err.(*tea.SDKError); ok {
- var data interface{}
- if err := json.NewDecoder(strings.NewReader(tea.StringValue(sdkErr.Data))).Decode(&data); err == nil {
- if m, ok := data.(map[string]interface{}); ok {
- if recommend, exists := m["Recommend"]; exists {
- return fmt.Errorf("短信发送失败: %s, 建议: %v", tea.StringValue(sdkErr.Message), recommend)
- }
- }
- }
- return fmt.Errorf("短信发送失败: %s", tea.StringValue(sdkErr.Message))
- }
- return fmt.Errorf("短信发送失败: %v", err)
- }
- // 4. 响应
- fmt.Printf("短信发送成功,响应: %v\n", resp)
- return nil
- }
- func buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, signature string) string {
- param := "from=" + url.QueryEscape(sender) + "&to=" + url.QueryEscape(receiver) + "&templateId=" + url.QueryEscape(templateId)
- if templateParas != "" {
- param += "&templateParas=" + url.QueryEscape(templateParas)
- }
- if statusCallBack != "" {
- param += "&statusCallback=" + url.QueryEscape(statusCallBack)
- }
- if signature != "" {
- param += "&signature=" + url.QueryEscape(signature)
- }
- return param
- }
- func post(url string, param []byte, headers map[string]string) (string, error) {
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
- }
- client := &http.Client{Transport: tr}
- req, err := http.NewRequest("POST", url, bytes.NewBuffer(param))
- if err != nil {
- return "", err
- }
- for key, header := range headers {
- req.Header.Set(key, header)
- }
- resp, err := client.Do(req)
- defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return "", err
- }
- return string(body), nil
- }
- func buildWsseHeader(appKey, appSecret string) string {
- var cTime = time.Now().Format("2006-01-02T15:04:05Z")
- var nonce = uuid.NewV4().String()
- nonce = strings.ReplaceAll(nonce, "-", "")
- h := sha256.New()
- h.Write([]byte(nonce + cTime + appSecret))
- passwordDigestBase64Str := base64.StdEncoding.EncodeToString(h.Sum(nil))
- return fmt.Sprintf(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, cTime)
- }
- // 随机生成6位数验证码
- func GetCode() string {
- rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
- vcode := fmt.Sprintf("%06v", rnd.Int31n(1000000))
- return vcode
- }
- type ChangeReq struct {
- Phone string `json:"phone"`
- Vcode string `json:"vcode"`
- }
- // 更换手机号
- func ChangePhone(r *ghttp.Request) *TalentHttpResult {
- tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
- if err != nil {
- return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
- }
- l := ChangeReq{}
- err = r.ParseForm(&l)
- if err != nil {
- fmt.Printf("前端数据解析错误")
- }
- //手机号是否被绑定
- existingTalent := &youngee_talent_model.TalentInfo{}
- record, err := g.DB().Model(existingTalent).Where("talent_phone_number = ?", l.Phone).One()
- if err != nil {
- fmt.Println("查询错误:", err)
- return &TalentHttpResult{Code: -3, Msg: "查询失败"}
- }
- // 检查是否找到了记录
- if record != nil {
- fmt.Println("手机号已存在:", record["talent_phone_number"])
- return &TalentHttpResult{Code: -1, Msg: "手机号已绑定"}
- } else {
- VcodeKey := fmt.Sprintf("%s%s", "c_user:", l.Phone)
- Vcode, _ := g.Redis().DoVar("GET", VcodeKey)
- //验证码正确
- if Vcode.String() == l.Vcode {
- //修改youngee_talent_info表中手机号
- _, err := g.DB().Model(existingTalent).Where("id=?", tid).Update(g.Map{"talent_phone_number": l.Phone})
- if err != nil {
- fmt.Println("更新失败")
- return &TalentHttpResult{Code: -4, Msg: "手机号更新失败"}
- }
- return &TalentHttpResult{Code: 0, Msg: "更新成功"}
- } else {
- return &TalentHttpResult{Code: -2, Msg: "验证码错误"}
- }
- }
- }
|