qr.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package basic
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "reflect"
  6. "time"
  7. "github.com/silenceper/wechat/v2/util"
  8. )
  9. const (
  10. qrCreateURL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s"
  11. getQRImgURL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"
  12. )
  13. const (
  14. actionID = "QR_SCENE"
  15. actionStr = "QR_STR_SCENE"
  16. actionLimitID = "QR_LIMIT_SCENE"
  17. actionLimitStr = "QR_LIMIT_STR_SCENE"
  18. )
  19. // Request 临时二维码
  20. type Request struct {
  21. ExpireSeconds int64 `json:"expire_seconds,omitempty"`
  22. ActionName string `json:"action_name"`
  23. ActionInfo struct {
  24. Scene struct {
  25. SceneStr string `json:"scene_str,omitempty"`
  26. SceneID int `json:"scene_id,omitempty"`
  27. } `json:"scene"`
  28. } `json:"action_info"`
  29. }
  30. // Ticket 二维码 ticket
  31. type Ticket struct {
  32. util.CommonError `json:",inline"`
  33. Ticket string `json:"ticket"`
  34. ExpireSeconds int64 `json:"expire_seconds"`
  35. URL string `json:"url"`
  36. }
  37. // GetQRTicket 获取二维码 Ticket
  38. func (basic *Basic) GetQRTicket(tq *Request) (t *Ticket, err error) {
  39. accessToken, err := basic.GetAccessToken()
  40. if err != nil {
  41. return
  42. }
  43. uri := fmt.Sprintf(qrCreateURL, accessToken)
  44. response, err := util.PostJSON(uri, tq)
  45. if err != nil {
  46. err = fmt.Errorf("get qr ticket failed, %s", err)
  47. return
  48. }
  49. t = new(Ticket)
  50. err = json.Unmarshal(response, &t)
  51. if err != nil {
  52. return
  53. }
  54. if t.ErrMsg != "" {
  55. err = fmt.Errorf("get qr_ticket error : errcode=%v , errormsg=%v", t.ErrCode, t.ErrMsg)
  56. return
  57. }
  58. return
  59. }
  60. // ShowQRCode 通过 ticket 换取二维码
  61. func ShowQRCode(tk *Ticket) string {
  62. return fmt.Sprintf(getQRImgURL, tk.Ticket)
  63. }
  64. // NewTmpQrRequest 新建临时二维码请求实例
  65. func NewTmpQrRequest(exp time.Duration, scene interface{}) *Request {
  66. var (
  67. tq = &Request{
  68. ExpireSeconds: int64(exp.Seconds()),
  69. }
  70. ok bool
  71. )
  72. switch reflect.ValueOf(scene).Kind() {
  73. case reflect.String:
  74. tq.ActionName = actionStr
  75. if tq.ActionInfo.Scene.SceneStr, ok = scene.(string); !ok {
  76. panic("scene must be string")
  77. }
  78. case reflect.Int, reflect.Int8, reflect.Int16,
  79. reflect.Int32, reflect.Int64,
  80. reflect.Uint, reflect.Uint8, reflect.Uint16,
  81. reflect.Uint32, reflect.Uint64:
  82. tq.ActionName = actionID
  83. if tq.ActionInfo.Scene.SceneID, ok = scene.(int); !ok {
  84. panic("scene must be int")
  85. }
  86. default:
  87. }
  88. return tq
  89. }
  90. // NewLimitQrRequest 新建永久二维码请求实例
  91. func NewLimitQrRequest(scene interface{}) *Request {
  92. var (
  93. tq = &Request{}
  94. ok bool
  95. )
  96. switch reflect.ValueOf(scene).Kind() {
  97. case reflect.String:
  98. tq.ActionName = actionLimitStr
  99. if tq.ActionInfo.Scene.SceneStr, ok = scene.(string); !ok {
  100. panic("scene must be string")
  101. }
  102. case reflect.Int, reflect.Int8, reflect.Int16,
  103. reflect.Int32, reflect.Int64,
  104. reflect.Uint, reflect.Uint8, reflect.Uint16,
  105. reflect.Uint32, reflect.Uint64:
  106. tq.ActionName = actionLimitID
  107. if tq.ActionInfo.Scene.SceneID, ok = scene.(int); !ok {
  108. panic("scene must be int")
  109. }
  110. default:
  111. }
  112. return tq
  113. }