package service import ( "bytes" "encoding/json" "io/ioutil" "net/http" "strconv" "strings" "time" "wsc-go/utils" "github.com/astaxie/beego" ) type SMSServiceError struct { Err string } func (e *SMSServiceError) Error() string { return e.Err } /* public */ // 发送验证码短信 func SMSSendVerificationCode(mobile string) error { if len(mobile) == 0 { return &SMSServiceError{Err: "手机号为空"} } if err := checkVerificationCodeSMSLimit(mobile); err != nil { return err } code_str := utils.RandomNumberString(6) templateID, _ := beego.AppConfig.Int("sms_verification_code_templateid") _, _, _, err := singleSendMessageUseUCPaas(templateID, []string{code_str}, mobile) if err == nil { redisClient := RedisClient() defer redisClient.Close() cur_date := time.Now().Format("2006-01-02") redisClient.Set("xt_modify_pwd_"+mobile, code_str, time.Minute*10) redisClient.Incr("xt_modify_pwd_" + mobile + "_" + cur_date).Result() } return err } // 成为机构管理员的邀请短信 func SMSSendInviteMobileToJoinOrgAdmin(name string, mobile string, password string) error { if len(mobile) == 0 { return &SMSServiceError{Err: "手机号为空"} } if len(password) == 0 { _, _, _, err := singleSendMessageUseUCPaas(332784, []string{name, mobile}, mobile) return err } else { _, _, _, err := singleSendMessageUseUCPaas(332783, []string{name, mobile, password}, mobile) return err } } /* private */ // 检查验证码短信请求限制 func checkVerificationCodeSMSLimit(mobile string) error { redisClient := RedisClient() defer redisClient.Close() cur_date := time.Now().Format("2006-01-02") moblie_count, _ := redisClient.Get("xt_modify_pwd_" + mobile + "_" + cur_date).Result() moblie_count_int, _ := strconv.Atoi(moblie_count) if moblie_max := 5; moblie_count_int >= moblie_max { return &SMSServiceError{Err: "当前手机号发送短信超过限制"} } return nil } /* 最底层的短信平台创建模板和发送短信的函数 */ // 获取短信平台信息 func getSMSConfig() (string, string, string) { return beego.AppConfig.String("sms_appId"), beego.AppConfig.String("sms_sid"), beego.AppConfig.String("sms_token") } // 用云之讯群发模板短信 // 返回值为发送了 n 条短信 func batchSendMessageUseUCPaas(templateID int, params []string, mobiles []string) (int, []interface{}, error) { sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms_batch" mobileStr := strings.Join(mobiles, ",") appID, sid, token := getSMSConfig() requestParams := make(map[string]interface{}) requestParams["appid"] = appID requestParams["sid"] = sid requestParams["token"] = token requestParams["templateid"] = strconv.Itoa(templateID) requestParams["mobile"] = mobileStr if params != nil && len(params) != 0 { paramStr := strings.Join(params, ",") requestParams["param"] = paramStr } paramsBytes, _ := json.Marshal(requestParams) resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes)) if requestErr != nil { utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr) return 0, nil, requestErr } defer resp.Body.Close() body, ioErr := ioutil.ReadAll(resp.Body) if ioErr != nil { utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr) return 0, nil, ioErr } var respJSON map[string]interface{} utils.InfoLog(string(body)) if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil { utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err) return 0, nil, err } if respJSON["code"].(string) != "000000" { msg := respJSON["msg"].(string) utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg) return 0, nil, &SMSServiceError{"短信平台模板群发接口请求失败"} } else { utils.SuccessLog("短信发送成功 report: %v", respJSON["report"]) if len(mobiles) > 1 { count, _ := strconv.Atoi(respJSON["count_sum"].(string)) return count, respJSON["report"].([]interface{}), nil } else { return 1, nil, nil } } } // 用云之讯单发模板短信 // 返回值分别是 是否成功,code,msg,error func singleSendMessageUseUCPaas(templateID int, params []string, mobile string) (bool, string, string, error) { sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms" appID, sid, token := getSMSConfig() requestParams := make(map[string]interface{}) requestParams["appid"] = appID requestParams["sid"] = sid requestParams["token"] = token requestParams["templateid"] = strconv.Itoa(templateID) requestParams["mobile"] = mobile if params != nil && len(params) != 0 { paramStr := strings.Join(params, ",") requestParams["param"] = paramStr } paramsBytes, _ := json.Marshal(requestParams) resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes)) if requestErr != nil { utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr) return false, "", "", requestErr } defer resp.Body.Close() body, ioErr := ioutil.ReadAll(resp.Body) if ioErr != nil { utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr) return false, "", "", ioErr } var respJSON map[string]interface{} utils.InfoLog(string(body)) if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil { utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err) return false, "", "", err } if respJSON["code"].(string) != "000000" { msg := respJSON["msg"].(string) utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg) return false, "", "", &SMSServiceError{"短信平台模板群发接口请求失败"} } else { utils.SuccessLog("短信发送成功") return true, respJSON["code"].(string), respJSON["msg"].(string), nil } }