sms_service.go 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package service
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io/ioutil"
  6. "net/http"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "Xcx_New/utils"
  11. "github.com/astaxie/beego"
  12. )
  13. type SMSServiceError struct {
  14. Err string
  15. }
  16. func (e *SMSServiceError) Error() string {
  17. return e.Err
  18. }
  19. /* public */
  20. // 发送验证码短信
  21. func SMSSendVerificationCode(mobile string) error {
  22. if len(mobile) == 0 {
  23. return &SMSServiceError{Err: "手机号为空"}
  24. }
  25. if err := checkVerificationCodeSMSLimit(mobile); err != nil {
  26. return err
  27. }
  28. code_str := utils.RandomNumberString(6)
  29. templateID, _ := beego.AppConfig.Int("sms_verification_code_templateid")
  30. _, _, _, err := singleSendMessageUseUCPaas(templateID, []string{code_str}, mobile)
  31. if err == nil {
  32. redisClient := RedisClient()
  33. defer redisClient.Close()
  34. cur_date := time.Now().Format("2006-01-02")
  35. redisClient.Set(redisClient.Context(),"xt_modify_pwd_"+mobile, code_str, time.Minute*10)
  36. redisClient.Incr(redisClient.Context(),"xt_modify_pwd_" + mobile + "_" + cur_date).Result()
  37. }
  38. return err
  39. }
  40. // 成为机构管理员的邀请短信
  41. func SMSSendInviteMobileToJoinOrgAdmin(name string, mobile string, password string) error {
  42. if len(mobile) == 0 {
  43. return &SMSServiceError{Err: "手机号为空"}
  44. }
  45. if len(password) == 0 {
  46. _, _, _, err := singleSendMessageUseUCPaas(332784, []string{name, mobile}, mobile)
  47. return err
  48. } else {
  49. _, _, _, err := singleSendMessageUseUCPaas(332783, []string{name, mobile, password}, mobile)
  50. return err
  51. }
  52. }
  53. /* private */
  54. // 检查验证码短信请求限制
  55. func checkVerificationCodeSMSLimit(mobile string) error {
  56. redisClient := RedisClient()
  57. defer redisClient.Close()
  58. cur_date := time.Now().Format("2006-01-02")
  59. moblie_count, _ := redisClient.Get(redisClient.Context(),"xt_modify_pwd_" + mobile + "_" + cur_date).Result()
  60. moblie_count_int, _ := strconv.Atoi(moblie_count)
  61. if moblie_max := 5; moblie_count_int >= moblie_max {
  62. return &SMSServiceError{Err: "当前手机号发送短信超过限制"}
  63. }
  64. return nil
  65. }
  66. /* 最底层的短信平台创建模板和发送短信的函数 */
  67. // 获取短信平台信息
  68. func getSMSConfig() (string, string, string) {
  69. return beego.AppConfig.String("sms_appId"),
  70. beego.AppConfig.String("sms_sid"),
  71. beego.AppConfig.String("sms_token")
  72. }
  73. // 用云之讯群发模板短信
  74. // 返回值为发送了 n 条短信
  75. func batchSendMessageUseUCPaas(templateID int, params []string, mobiles []string) (int, []interface{}, error) {
  76. sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms_batch"
  77. mobileStr := strings.Join(mobiles, ",")
  78. appID, sid, token := getSMSConfig()
  79. requestParams := make(map[string]interface{})
  80. requestParams["appid"] = appID
  81. requestParams["sid"] = sid
  82. requestParams["token"] = token
  83. requestParams["templateid"] = strconv.Itoa(templateID)
  84. requestParams["mobile"] = mobileStr
  85. if params != nil && len(params) != 0 {
  86. paramStr := strings.Join(params, ",")
  87. requestParams["param"] = paramStr
  88. }
  89. paramsBytes, _ := json.Marshal(requestParams)
  90. resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes))
  91. if requestErr != nil {
  92. utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr)
  93. return 0, nil, requestErr
  94. }
  95. defer resp.Body.Close()
  96. body, ioErr := ioutil.ReadAll(resp.Body)
  97. if ioErr != nil {
  98. utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr)
  99. return 0, nil, ioErr
  100. }
  101. var respJSON map[string]interface{}
  102. utils.InfoLog(string(body))
  103. if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil {
  104. utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err)
  105. return 0, nil, err
  106. }
  107. if respJSON["code"].(string) != "000000" {
  108. msg := respJSON["msg"].(string)
  109. utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg)
  110. return 0, nil, &SMSServiceError{"短信平台模板群发接口请求失败"}
  111. } else {
  112. utils.SuccessLog("短信发送成功 report: %v", respJSON["report"])
  113. if len(mobiles) > 1 {
  114. count, _ := strconv.Atoi(respJSON["count_sum"].(string))
  115. return count, respJSON["report"].([]interface{}), nil
  116. } else {
  117. return 1, nil, nil
  118. }
  119. }
  120. }
  121. // 用云之讯单发模板短信
  122. // 返回值分别是 是否成功,code,msg,error
  123. func singleSendMessageUseUCPaas(templateID int, params []string, mobile string) (bool, string, string, error) {
  124. sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms"
  125. appID, sid, token := getSMSConfig()
  126. requestParams := make(map[string]interface{})
  127. requestParams["appid"] = appID
  128. requestParams["sid"] = sid
  129. requestParams["token"] = token
  130. requestParams["templateid"] = strconv.Itoa(templateID)
  131. requestParams["mobile"] = mobile
  132. if params != nil && len(params) != 0 {
  133. paramStr := strings.Join(params, ",")
  134. requestParams["param"] = paramStr
  135. }
  136. paramsBytes, _ := json.Marshal(requestParams)
  137. resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes))
  138. if requestErr != nil {
  139. utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr)
  140. return false, "", "", requestErr
  141. }
  142. defer resp.Body.Close()
  143. body, ioErr := ioutil.ReadAll(resp.Body)
  144. if ioErr != nil {
  145. utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr)
  146. return false, "", "", ioErr
  147. }
  148. var respJSON map[string]interface{}
  149. utils.InfoLog(string(body))
  150. if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil {
  151. utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err)
  152. return false, "", "", err
  153. }
  154. if respJSON["code"].(string) != "000000" {
  155. msg := respJSON["msg"].(string)
  156. utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg)
  157. return false, "", "", &SMSServiceError{"短信平台模板群发接口请求失败"}
  158. } else {
  159. utils.SuccessLog("短信发送成功")
  160. return true, respJSON["code"].(string), respJSON["msg"].(string), nil
  161. }
  162. }