js.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package js
  2. import (
  3. context2 "context"
  4. "fmt"
  5. "github.com/silenceper/wechat/v2/credential"
  6. "github.com/silenceper/wechat/v2/officialaccount/context"
  7. "github.com/silenceper/wechat/v2/util"
  8. )
  9. // Js struct
  10. type Js struct {
  11. *context.Context
  12. credential.JsTicketHandle
  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. // NewJs init
  22. func NewJs(context *context.Context) *Js {
  23. js := new(Js)
  24. js.Context = context
  25. jsTicketHandle := credential.NewDefaultJsTicket(context.AppID, credential.CacheKeyOfficialAccountPrefix, context.Cache)
  26. js.SetJsTicketHandle(jsTicketHandle)
  27. return js
  28. }
  29. // SetJsTicketHandle 自定义js ticket取值方式
  30. func (js *Js) SetJsTicketHandle(ticketHandle credential.JsTicketHandle) {
  31. js.JsTicketHandle = ticketHandle
  32. }
  33. // GetConfig 获取jssdk需要的配置参数
  34. // uri 为当前网页地址
  35. func (js *Js) GetConfig(uri string) (config *Config, err error) {
  36. return js.GetConfigContext(context2.Background(), uri)
  37. }
  38. // GetConfigContext 新方法,允许传入上下文,避免协程泄漏
  39. func (js *Js) GetConfigContext(ctx context2.Context, uri string) (config *Config, err error) {
  40. var accessToken string
  41. // 类型断言,如果断言成功,调用安全的 GetAccessTokenContext 方法
  42. if ctxHandle, ok := js.Context.AccessTokenHandle.(credential.AccessTokenContextHandle); ok {
  43. accessToken, err = ctxHandle.GetAccessTokenContext(ctx)
  44. } else {
  45. // 如果没有实现 AccessTokenContextHandle 接口,调用旧的 GetAccessToken 方法
  46. accessToken, err = js.Context.GetAccessToken()
  47. }
  48. if err != nil {
  49. return
  50. }
  51. var ticketStr string
  52. // 类型断言 jsTicket
  53. if ticketCtxHandle, ok := js.JsTicketHandle.(credential.JsTicketContextHandle); ok {
  54. ticketStr, err = ticketCtxHandle.GetTicketContext(ctx, accessToken)
  55. } else {
  56. // 如果没有实现 JsTicketContextHandle 接口,调用旧的 GetTicket 方法
  57. ticketStr, err = js.GetTicket(accessToken)
  58. }
  59. if err != nil {
  60. return
  61. }
  62. nonceStr := util.RandomStr(16)
  63. timestamp := util.GetCurrTS()
  64. str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", ticketStr, nonceStr, timestamp, uri)
  65. sigStr := util.Signature(str)
  66. config = new(Config)
  67. config.AppID = js.AppID
  68. config.NonceStr = nonceStr
  69. config.Timestamp = timestamp
  70. config.Signature = sigStr
  71. return
  72. }