jssdk.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package jssdk
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "time"
  6. "github.com/yaotian/gowechat/util"
  7. "github.com/yaotian/gowechat/wxcontext"
  8. )
  9. const getTicketURL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi"
  10. // Js struct
  11. type Js struct {
  12. *wxcontext.Context
  13. }
  14. // Config 返回给用户jssdk配置信息
  15. type Config struct {
  16. AppID string `json:"app_id"`
  17. Timestamp int64 `json:"timestamp"`
  18. NonceStr string `json:"nonce_str"`
  19. Signature string `json:"signature"`
  20. }
  21. //JsString wx.config中的配置
  22. func (c *Config) JsString() (str string) {
  23. return fmt.Sprintf(`
  24. appId: "%s",
  25. timestamp: '%d',
  26. nonceStr: '%s',
  27. signature: '%s',`, c.AppID, c.Timestamp, c.NonceStr, c.Signature)
  28. }
  29. // resTicket 请求jsapi_tikcet返回结果
  30. type resTicket struct {
  31. util.CommonError
  32. Ticket string `json:"ticket"`
  33. ExpiresIn int64 `json:"expires_in"`
  34. }
  35. //NewJs init
  36. func NewJs(context *wxcontext.Context) *Js {
  37. js := new(Js)
  38. js.Context = context
  39. return js
  40. }
  41. //GetConfig 获取jssdk需要的配置参数
  42. //uri 为当前网页地址
  43. func (js *Js) GetConfig(url string) (config *Config, err error) {
  44. config = new(Config)
  45. var ticketStr string
  46. ticketStr, err = js.GetTicket()
  47. if err != nil {
  48. return
  49. }
  50. nonceStr := util.RandomStr(16)
  51. timestamp := util.GetCurrTs()
  52. str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", ticketStr, nonceStr, timestamp, url)
  53. sigStr := util.Signature(str)
  54. config.AppID = js.AppID
  55. config.NonceStr = nonceStr
  56. config.Timestamp = timestamp
  57. config.Signature = sigStr
  58. return
  59. }
  60. //GetTicket 获取jsapi_tocket
  61. func (js *Js) GetTicket() (ticketStr string, err error) {
  62. js.GetJsAPITicketLock().Lock()
  63. defer js.GetJsAPITicketLock().Unlock()
  64. //先从cache中取
  65. jsAPITicketCacheKey := fmt.Sprintf("jsapi_ticket_%s", js.AppID)
  66. val := js.Cache.Get(jsAPITicketCacheKey)
  67. if val != nil {
  68. ticketStr = val.(string)
  69. return
  70. }
  71. var ticket resTicket
  72. ticket, err = js.getTicketFromServer()
  73. if err != nil {
  74. return
  75. }
  76. ticketStr = ticket.Ticket
  77. return
  78. }
  79. //getTicketFromServer 强制从服务器中获取ticket
  80. func (js *Js) getTicketFromServer() (ticket resTicket, err error) {
  81. var accessToken string
  82. accessToken, err = js.GetAccessToken()
  83. if err != nil {
  84. return
  85. }
  86. var response []byte
  87. url := fmt.Sprintf(getTicketURL, accessToken)
  88. response, err = util.HTTPGet(url)
  89. err = json.Unmarshal(response, &ticket)
  90. if err != nil {
  91. return
  92. }
  93. if ticket.ErrCode != 0 {
  94. err = fmt.Errorf("getTicket Error : errcode=%d , errmsg=%s", ticket.ErrCode, ticket.ErrMsg)
  95. return
  96. }
  97. jsAPITicketCacheKey := fmt.Sprintf("jsapi_ticket_%s", js.AppID)
  98. expires := ticket.ExpiresIn - 1500
  99. err = js.Cache.Put(jsAPITicketCacheKey, ticket.Ticket, time.Duration(expires)*time.Second)
  100. return
  101. }