|
@@ -1,6 +1,7 @@
|
|
package wechat
|
|
package wechat
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "bytes"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"eta/eta_mini_ht_api/common/component/config"
|
|
"eta/eta_mini_ht_api/common/component/config"
|
|
logger "eta/eta_mini_ht_api/common/component/log"
|
|
logger "eta/eta_mini_ht_api/common/component/log"
|
|
@@ -10,13 +11,16 @@ import (
|
|
"eta/eta_mini_ht_api/common/utils/client"
|
|
"eta/eta_mini_ht_api/common/utils/client"
|
|
"fmt"
|
|
"fmt"
|
|
"io"
|
|
"io"
|
|
|
|
+ "io/ioutil"
|
|
|
|
+ "net/http"
|
|
"net/url"
|
|
"net/url"
|
|
"sync"
|
|
"sync"
|
|
)
|
|
)
|
|
|
|
|
|
const (
|
|
const (
|
|
- baseURL = "https://api.weixin.qq.com"
|
|
|
|
- codeAPI = "/sns/jscode2session"
|
|
|
|
|
|
+ baseURL = "https://api.weixin.qq.com"
|
|
|
|
+ codeAPI = "/sns/jscode2session"
|
|
|
|
+ accessTokenApi = "/cgi-bin/token"
|
|
)
|
|
)
|
|
const (
|
|
const (
|
|
// WeChatServerError 微信服务器错误时返回返回消息
|
|
// WeChatServerError 微信服务器错误时返回返回消息
|
|
@@ -147,6 +151,23 @@ func code2url(appID, secret, code string) (string, error) {
|
|
|
|
|
|
return url.String(), nil
|
|
return url.String(), nil
|
|
}
|
|
}
|
|
|
|
+func accessToken2url(appID, secret string) (string, error) {
|
|
|
|
+
|
|
|
|
+ url, err := url.Parse(baseURL + accessTokenApi)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return "", err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ query := url.Query()
|
|
|
|
+
|
|
|
|
+ query.Set("appid", appID)
|
|
|
|
+ query.Set("secret", secret)
|
|
|
|
+ query.Set("grant_type", "client_credential")
|
|
|
|
+
|
|
|
|
+ url.RawQuery = query.Encode()
|
|
|
|
+
|
|
|
|
+ return url.String(), nil
|
|
|
|
+}
|
|
|
|
|
|
type WxUserInfo struct {
|
|
type WxUserInfo struct {
|
|
OpenId string `json:"openid"`
|
|
OpenId string `json:"openid"`
|
|
@@ -157,6 +178,97 @@ type WxUserInfo struct {
|
|
ErrMsg string
|
|
ErrMsg string
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+type QRCodeRequest struct {
|
|
|
|
+ Path string `json:"path"`
|
|
|
|
+ Width int `json:"width,omitempty"`
|
|
|
|
+ AutoColor bool `json:"auto_color,omitempty"`
|
|
|
|
+ LineColor struct {
|
|
|
|
+ R int `json:"r"`
|
|
|
|
+ G int `json:"g"`
|
|
|
|
+ B int `json:"b"`
|
|
|
|
+ } `json:"line_color,omitempty"`
|
|
|
|
+ IsHyaline bool `json:"is_hyaline,omitempty"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (cli *Client) GenerateQRCode(code, path string) ([]byte, error) {
|
|
|
|
+ wechatConf, ok := config.GetConfig(contants.WECHAT).(*config.WechatConfig)
|
|
|
|
+ if !ok {
|
|
|
|
+ return nil, exception.New(exception.WeChatIllegalRequest)
|
|
|
|
+ }
|
|
|
|
+ accessToken, err := getAccessToken(wechatConf.GetAppid(), wechatConf.GetSecret(), code)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ api := fmt.Sprintf("%s%s?access_token=%s", baseURL, "/cgi-bin/wxaapp/createwxaqrcode", accessToken)
|
|
|
|
+ reqBody := QRCodeRequest{
|
|
|
|
+ Path: path,
|
|
|
|
+ Width: 430,
|
|
|
|
+ AutoColor: true,
|
|
|
|
+ LineColor: struct {
|
|
|
|
+ R int `json:"r"`
|
|
|
|
+ G int `json:"g"`
|
|
|
|
+ B int `json:"b"`
|
|
|
|
+ }{
|
|
|
|
+ R: 0,
|
|
|
|
+ G: 0,
|
|
|
|
+ B: 0,
|
|
|
|
+ },
|
|
|
|
+ IsHyaline: false,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jsonData, err := json.Marshal(reqBody)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ resp, err := http.Post(api, "application/json", bytes.NewBuffer(jsonData))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ defer resp.Body.Close()
|
|
|
|
+
|
|
|
|
+ if resp.StatusCode != 200 {
|
|
|
|
+ body, _ := ioutil.ReadAll(resp.Body)
|
|
|
|
+ return nil, fmt.Errorf("failed to generate QR code: %s", body)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ qrCodeBytes, err := ioutil.ReadAll(resp.Body)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return qrCodeBytes, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func getAccessToken(appid, secret, code string) (string, error) {
|
|
|
|
+ api, err := accessToken2url(appid, secret)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return "", exception.New(exception.WeChatIllegalRequest)
|
|
|
|
+ }
|
|
|
|
+ resp, err := http.Get(api)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return "", err
|
|
|
|
+ }
|
|
|
|
+ defer resp.Body.Close()
|
|
|
|
+
|
|
|
|
+ body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return "", err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var result map[string]interface{}
|
|
|
|
+ err = json.Unmarshal(body, &result)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return "", err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if accessToken, ok := result["access_token"].(string); ok {
|
|
|
|
+ return accessToken, nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return "", fmt.Errorf("failed to get access token: %s", string(body))
|
|
|
|
+}
|
|
|
|
+
|
|
// Login 小程序登录
|
|
// Login 小程序登录
|
|
func (cli *Client) GzhLogin(code string) (wxUser WxUser, err error) {
|
|
func (cli *Client) GzhLogin(code string) (wxUser WxUser, err error) {
|
|
if code == "" {
|
|
if code == "" {
|