附近小店
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.
 
 
 

298 lines
7.5 KiB

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