mini.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package wechat
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/url"
  7. "time"
  8. "git.chuangxin1.com/cx/myth"
  9. "git.chuangxin1.com/cx/myth/cache"
  10. )
  11. func keyMini(appid string) string {
  12. return "wechat:mini:client:" + appid
  13. }
  14. func keyMiniToken(appid string) string {
  15. return "wechat:mini:client:token:" + appid
  16. }
  17. // NewMiniClient new mini client
  18. func NewMiniClient(appID, appSecret string) *MiniClient {
  19. key := keyMini(appID)
  20. if v, ok := memcache.Load(key); ok {
  21. return v.(*MiniClient)
  22. }
  23. c := &MiniClient{AppID: appID, AppSecret: appSecret, UseCacheToken: true}
  24. memcache.Store(key, c)
  25. return c
  26. }
  27. // TokenKey token key in cache
  28. func (mc *MiniClient) TokenKey() string {
  29. return keyMiniToken(mc.AppID)
  30. }
  31. // GetMiniOpenID get openid by code
  32. func (mc *MiniClient) GetMiniOpenID(frm FormCode) (s MiniSession, err error) {
  33. uri := BaseURL + "/sns/jscode2session?"
  34. args := url.Values{}
  35. args.Add("grant_type", "authorization_code")
  36. args.Add("appid", mc.AppID)
  37. args.Add("secret", mc.AppSecret)
  38. args.Add("js_code", frm.Code)
  39. uri += args.Encode()
  40. var jq *myth.JSONQuery
  41. if jq, err = getJSON(uri); err == nil {
  42. s.OpenID, err = jq.String(`openid`)
  43. s.SessionKey, _ = jq.String(`session_key`)
  44. s.UnionID, _ = jq.String(`unionid`)
  45. }
  46. return
  47. }
  48. // getToken get token
  49. func (mc *MiniClient) getToken() (token string, err error) {
  50. if mc.UseCacheToken {
  51. key := keyMiniToken(mc.AppID)
  52. var ct ClientToken
  53. s := ``
  54. //now := time.Now().Unix()
  55. s, err = cache.Get(key)
  56. if err != nil {
  57. return
  58. }
  59. err = json.Unmarshal([]byte(s), &ct)
  60. if err != nil {
  61. return
  62. }
  63. token = ct.AccessToken
  64. return
  65. }
  66. now := time.Now().Unix()
  67. if mc.LastTokenTime > 0 {
  68. if now-mc.LastTokenTime < TokenExpires {
  69. token = mc.AccessToken
  70. return
  71. }
  72. }
  73. token, err = mc.UpdateToken()
  74. return
  75. }
  76. func (mc *MiniClient) UpdateToken() (token string, err error) {
  77. now := time.Now().Unix()
  78. uri := BaseURL + "/cgi-bin/token?"
  79. args := url.Values{}
  80. args.Add("grant_type", "client_credential")
  81. args.Add("appid", mc.AppID)
  82. args.Add("secret", mc.AppSecret)
  83. uri += args.Encode()
  84. var jq *myth.JSONQuery
  85. jq, err = getJSON(uri)
  86. if err != nil {
  87. return
  88. }
  89. key := keyMiniToken(mc.AppID)
  90. mc.LastTokenTime = now
  91. mc.AccessToken, err = jq.String(`access_token`)
  92. token = mc.AccessToken
  93. k := keyMini(mc.AppID)
  94. memcache.Store(k, mc)
  95. ct := ClientToken{AppID: mc.AppID, AccessToken: mc.AccessToken, LastTokenTime: now}
  96. bs, _ := json.Marshal(ct)
  97. cache.Set(key, string(bs), 0)
  98. return
  99. }
  100. // TemplateList /cgi-bin/wxopen/template/list
  101. func (mc *MiniClient) TemplateList(offset, count int) (body []byte, err error) {
  102. uri := BaseURL + "/cgi-bin/wxopen/template/list?"
  103. if mc.AccessToken, err = mc.getToken(); err != nil {
  104. return
  105. }
  106. args := url.Values{}
  107. args.Add("access_token", mc.AccessToken)
  108. uri += args.Encode()
  109. params := make(map[string]interface{})
  110. params["offset"] = offset
  111. params["count"] = count
  112. var msg myth.HTTPMessage
  113. msg, err = postJSON(uri, params)
  114. if err == nil {
  115. body = msg.Body
  116. }
  117. /*
  118. data, err := json.Marshal(params)
  119. if err != nil {
  120. return
  121. }
  122. body, err = postJSONBody(uri, data)
  123. // */
  124. return
  125. }
  126. // MiniPhoneInfo 手机信息
  127. type MiniPhoneInfo struct {
  128. ResponseMsg
  129. PhoneInfo struct {
  130. PhoneNumber string `json:"phoneNumber"`
  131. PurePhoneNumber string `json:"purePhoneNumber"`
  132. CountryCode string `json:"countryCode"`
  133. Watermark struct {
  134. Timestamp int64 `json:"timestamp"`
  135. AppID string `json:"appid"`
  136. } `json:"watermark"`
  137. } `json:"phone_info"`
  138. }
  139. // GetPhoneInfo 获取手机信息 /wxa/business/getuserphonenumber
  140. func (mc *MiniClient) GetPhoneInfo(frm FormCode) (res MiniPhoneInfo, err error) {
  141. uri := BaseURL + "/wxa/business/getuserphonenumber?"
  142. if mc.AccessToken, err = mc.getToken(); err != nil {
  143. return
  144. }
  145. args := url.Values{}
  146. args.Add("access_token", mc.AccessToken)
  147. uri += args.Encode()
  148. var msg myth.HTTPMessage
  149. msg, err = postJSON(uri, frm)
  150. if err != nil {
  151. return
  152. }
  153. err = msg.JSON(&res)
  154. if err != nil {
  155. return
  156. }
  157. if res.ErrCode != 0 {
  158. err = fmt.Errorf("%s uri: %s", res.ErrMsg, uri)
  159. }
  160. return
  161. }
  162. // TemplateSend /cgi-bin/message/wxopen/template/send
  163. func (mc *MiniClient) TemplateSend(template MiniTemplateMessage) (res TemplateResponse, err error) {
  164. uri := BaseURL + "/cgi-bin/message/wxopen/template/send?"
  165. if mc.AccessToken, err = mc.getToken(); err != nil {
  166. return
  167. }
  168. args := url.Values{}
  169. args.Add("access_token", mc.AccessToken)
  170. uri += args.Encode()
  171. var msg myth.HTTPMessage
  172. msg, err = postJSON(uri, template)
  173. if err != nil {
  174. return
  175. }
  176. err = msg.JSON(&res)
  177. if err != nil {
  178. return
  179. }
  180. if !res.Ok() {
  181. err = errors.New(res.ErrMsg)
  182. return
  183. }
  184. return
  185. }
  186. // UniformSend /cgi-bin/message/wxopen/template/uniform_send
  187. func (mc *MiniClient) UniformSend(template MiniUniformMessage) (res TemplateResponse, err error) {
  188. uri := BaseURL + "/cgi-bin/message/wxopen/template/uniform_send?"
  189. if mc.AccessToken, err = mc.getToken(); err != nil {
  190. return
  191. }
  192. args := url.Values{}
  193. args.Add("access_token", mc.AccessToken)
  194. uri += args.Encode()
  195. var msg myth.HTTPMessage
  196. msg, err = postJSON(uri, template)
  197. if err != nil {
  198. return
  199. }
  200. err = msg.JSON(&res)
  201. if err != nil {
  202. return
  203. }
  204. if !res.Ok() {
  205. err = errors.New(res.ErrMsg)
  206. return
  207. }
  208. return
  209. }