智盟项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
6.7 KiB

  1. package mob
  2. import (
  3. "applet/app/db"
  4. "applet/app/e"
  5. "applet/app/lib/sms"
  6. "applet/app/utils"
  7. "applet/app/utils/logx"
  8. "bytes"
  9. "crypto/cipher"
  10. "crypto/des"
  11. "crypto/md5"
  12. "encoding/base64"
  13. "encoding/hex"
  14. "encoding/json"
  15. "errors"
  16. "fmt"
  17. "io/ioutil"
  18. "net/http"
  19. "sort"
  20. "time"
  21. "github.com/gin-gonic/gin"
  22. "github.com/tidwall/gjson"
  23. )
  24. const base string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  25. // Mob is mob sdk
  26. var Mob *SDK
  27. // MobMap is 每个站长都要有自己的mob 对象
  28. var MobMap map[string]*SDK
  29. // Init 初始化
  30. func Init() {
  31. // 后续可能要传请求的上下文来获取对应的配置
  32. // mob 目前都是我们来管理每个站长的app 所以使用template 库
  33. //fmt.Println("Mob SDK init ....")
  34. ch := make(chan struct{}) // 只是做信号标志的话 空struct 更省点资源
  35. MobMap = make(map[string]*SDK)
  36. // 初始化
  37. for k, e := range db.DBs {
  38. m := db.SysCfgGetWithDb(e, k, "third_app_push_set")
  39. if m == "" {
  40. fmt.Printf("masterid:%s 找不到推送配置", k)
  41. continue
  42. }
  43. key := gjson.Get(m, "mobAppKey").String()
  44. secret := gjson.Get(m, "mobAppSecret").String()
  45. if key == "" || secret == "" {
  46. fmt.Println(k + ":mob no config")
  47. continue
  48. }
  49. // fmt.Println(k, key, secret)
  50. mob := new(SDK)
  51. mob.AppKey = key
  52. mob.AppSecret = secret
  53. MobMap[k] = mob
  54. fmt.Println(k + ":mob config success")
  55. }
  56. go func() {
  57. ch <- struct{}{}
  58. }()
  59. // 定时任务
  60. go func(MobMap map[string]*SDK, ch chan struct{}) {
  61. <-ch
  62. ticker := time.NewTicker(time.Duration(time.Second * 15))
  63. //每 15s 一次更新一次mob 配置
  64. for range ticker.C {
  65. for k, e := range db.DBs {
  66. if err := e.Ping(); err != nil {
  67. logx.Info(err)
  68. continue
  69. }
  70. m := db.SysCfgGetWithDb(e, k, "third_app_push_set")
  71. if m == "" {
  72. fmt.Printf("masterid:%s 找不到推送配置", k)
  73. continue
  74. }
  75. key := gjson.Get(m, "mobAppKey").String()
  76. secret := gjson.Get(m, "mobAppSecret").String()
  77. if key == "" || secret == "" {
  78. fmt.Println(k + ":mob no config")
  79. continue
  80. }
  81. // fmt.Println(k, key, secret)
  82. mob := new(SDK)
  83. mob.AppKey = key
  84. mob.AppSecret = secret
  85. MobMap[k] = mob
  86. // fmt.Println(k + ":mob config success")
  87. }
  88. }
  89. }(MobMap, ch)
  90. }
  91. // GetMobSDK is 获取mob 的sdk
  92. func GetMobSDK(mid string) (*SDK, error) {
  93. return &SDK{AppKey: "30dc33054b635", AppSecret: "396e98c293130c9976fb7428b6b434d6"}, nil
  94. }
  95. // SDK is mob_push 的sdk
  96. type SDK struct {
  97. AppKey string
  98. AppSecret string
  99. }
  100. // MobFreeLogin is 秒验
  101. func (s *SDK) MobFreeLogin(args map[string]interface{}) (string, error) {
  102. var url string = "http://identify.verify.mob.com/auth/auth/sdkClientFreeLogin"
  103. // https://www.mob.com/wiki/detailed/?wiki=miaoyan_for_fuwuduan_mianmifuwuduanjieru&id=78
  104. //加appkey
  105. args["appkey"] = s.AppKey
  106. //加签名
  107. args["sign"] = generateSign(args, s.AppSecret)
  108. b, err := json.Marshal(args)
  109. if err != nil {
  110. return "", logx.Warn(err)
  111. }
  112. // 发送请求
  113. respBody, err := httpPostBody(url, b)
  114. if err != nil {
  115. return "", logx.Warn(err)
  116. }
  117. // 反序列化
  118. ret := struct {
  119. Status int `json:"status"`
  120. Error string `json:"error"`
  121. Res interface{} `json:"res"`
  122. }{}
  123. // 要拿 ret 里面 Res 再解密
  124. if err := json.Unmarshal(respBody, &ret); err != nil {
  125. return "", logx.Warn(err)
  126. }
  127. //fmt.Println(ret)
  128. // ret里面的Res 反序列化为结构体
  129. res := struct {
  130. IsValid int `json:"isValid"`
  131. Phone string `json:"phone"`
  132. }{}
  133. // 判断是否返回正确 状态码
  134. if ret.Status == 200 {
  135. decode, _ := base64Decode([]byte(ret.Res.(string)))
  136. decr, _ := desDecrypt(decode, []byte(s.AppSecret)[0:8])
  137. if err := json.Unmarshal(decr, &res); err != nil {
  138. return "", logx.Warn(err)
  139. }
  140. }
  141. // 有效则拿出res 里的电话号码
  142. if res.IsValid == 1 {
  143. return res.Phone, nil
  144. }
  145. // Status 不等于200 则返回空
  146. return "", fmt.Errorf("Mob error , status code %v ", ret.Status)
  147. }
  148. // MobSMS is mob 的短信验证
  149. func (s *SDK) MobSMS(c *gin.Context, args map[string]interface{}) (bool, error) {
  150. // mob 的短信验证
  151. // https://www.mob.com/wiki/detailed/?wiki=SMSSDK_for_yanzhengmafuwuduanxiaoyanjiekou&id=23
  152. url := "https://webapi.sms.mob.com/sms/verify"
  153. //加appkey
  154. args["appkey"] = s.AppKey
  155. fmt.Println(args)
  156. //fmt.Println(args)
  157. // 发送请求
  158. respBody, err := utils.CurlPost(url, args, nil)
  159. if err != nil {
  160. fmt.Println(err)
  161. return false, logx.Warn(err)
  162. }
  163. fmt.Println("=======================mob")
  164. fmt.Println("mob", string(respBody))
  165. code := gjson.GetBytes(respBody, "status").Int()
  166. if code == 468 {
  167. return false, errors.New("验证码错误")
  168. }
  169. if code != 200 {
  170. utils.FilePutContents("sms", string(respBody))
  171. return false, errors.New("验证码错误~")
  172. }
  173. return true, nil
  174. }
  175. func pkcs5UnPadding(origData []byte) []byte {
  176. length := len(origData)
  177. // 去掉最后一个字节 unpadding 次
  178. unpadding := int(origData[length-1])
  179. return origData[:(length - unpadding)]
  180. }
  181. func desDecrypt(crypted, key []byte) ([]byte, error) {
  182. block, err := des.NewCipher(key)
  183. if err != nil {
  184. return nil, err
  185. }
  186. blockMode := cipher.NewCBCDecrypter(block, []byte("00000000"))
  187. origData := make([]byte, len(crypted))
  188. // origData := crypted
  189. blockMode.CryptBlocks(origData, crypted)
  190. origData = pkcs5UnPadding(origData)
  191. // origData = ZeroUnPadding(origData)
  192. return origData, nil
  193. }
  194. func base64Decode(src []byte) ([]byte, error) {
  195. var coder *base64.Encoding
  196. coder = base64.NewEncoding(base)
  197. return coder.DecodeString(string(src))
  198. }
  199. func httpPostBody(url string, msg []byte) ([]byte, error) {
  200. resp, err := http.Post(url, "application/json;charset=utf-8", bytes.NewBuffer(msg))
  201. if err != nil {
  202. return []byte(""), err
  203. }
  204. defer resp.Body.Close()
  205. body, err := ioutil.ReadAll(resp.Body)
  206. return body, err
  207. }
  208. func generateSign(request map[string]interface{}, secret string) string {
  209. ret := ""
  210. var keys []string
  211. for k := range request {
  212. keys = append(keys, k)
  213. }
  214. sort.Strings(keys)
  215. for _, k := range keys {
  216. ret = ret + fmt.Sprintf("%v=%v&", k, request[k])
  217. }
  218. ret = ret[:len(ret)-1] + secret
  219. md5Ctx := md5.New()
  220. md5Ctx.Write([]byte(ret))
  221. cipherStr := md5Ctx.Sum(nil)
  222. return hex.EncodeToString(cipherStr)
  223. }
  224. func Check(c *gin.Context, phone, zone, validCode string, ok1 bool) (bool, error) {
  225. smsPlatform := sms.GetSmsPlatform(c)
  226. if smsPlatform == "mob" {
  227. mob1, errr := GetMobSDK(c.GetString("master_id"))
  228. if errr != nil {
  229. return false, e.NewErr(400, "mob配置错误")
  230. }
  231. send := map[string]interface{}{
  232. "phone": phone,
  233. "zone": zone,
  234. "code": validCode,
  235. }
  236. if zone == "" {
  237. send["zone"] = "86"
  238. }
  239. c.Set("not_deduction_doing", "1")
  240. ok, err := mob1.MobSMS(c, send)
  241. fmt.Println(ok)
  242. if err != nil {
  243. fmt.Println(err)
  244. return false, e.NewErr(400, "验证码校验错误")
  245. }
  246. return ok, nil
  247. }
  248. return ok1, nil
  249. }