package mp import ( "errors" "fmt" "io/ioutil" "net/http" "net/url" "time" "zhiyuan/models" "zhiyuan/pkg/app" "zhiyuan/pkg/config" "zhiyuan/pkg/utils" "zhiyuan/services/form" "zhiyuan/services/weixin" ) type Client struct { Account *models.Weixin } func NewClient(wxID int) (*Client, error) { weixinInfo, _ := weixin.GetOne(map[string]interface{}{"id": wxID}, nil, nil) return &Client{ Account: weixinInfo, }, nil } func (c *Client) GetAccessToken() (string, error) { rc, err := utils.HttpGet(&http.Client{}, config.Cfg.App.ProductionUrl+"api/weixin/access_token/"+utils.ToStr(c.Account.ID), nil) if err != nil { return "", err } p, err := ioutil.ReadAll(rc) if err != nil { return "", err } var response app.ResponseData utils.JsonDecode(p).To(&response) if response.Code != 200 { return "", errors.New(response.Msg) } return utils.ToStr(response.Data.(map[string]interface{})["access_token"]), nil } func (c *Client) RefreshAccessToken() AccessTokenResponse { currentTime := utils.ToInt(time.Now().Unix()) if c.Account.AccessToken != "" && c.Account.AccessTokenExpiresIn > 0 && currentTime < c.Account.AccessTokenExpiresIn+c.Account.AccessTokenUpdatedAt { return AccessTokenResponse{ AccessToken: c.Account.AccessToken, ExpiresIn: c.Account.AccessTokenExpiresIn, } } baseUrl := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s" url := fmt.Sprintf(baseUrl, c.Account.AppID, c.Account.AppSecret) rc, err := utils.HttpGet(&http.Client{}, url, nil) if err != nil { return AccessTokenResponse{ErrCode: 1, ErrMsg: "http get error"} } p, err := ioutil.ReadAll(rc) if err != nil { return AccessTokenResponse{ErrCode: 1, ErrMsg: "http read error"} } var response AccessTokenResponse utils.JsonDecode(p).To(&response) if response.AccessToken != "" && response.ErrCode == 0 { weixinForm := form.WeixinEditToken{ AccessToken: response.AccessToken, AccessTokenExpiresIn: response.ExpiresIn, } weixin.EditToken(weixinForm, c.Account.ID) } return response } func (c *Client) GetOauthUrl(scope string, retUrl string) (string, error) { baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=" + scope + "&state=STATE#wechat_redirect" url := fmt.Sprintf(baseUrl, c.Account.AppID, url.QueryEscape(config.Cfg.App.ProductionUrl+retUrl)) return url, nil } func (c *Client) GetOauthUrls(scope string, retUrl string) (string, error) { baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=" + scope + "&state=STATE#wechat_redirect" url := fmt.Sprintf(baseUrl, c.Account.AppID, url.QueryEscape(retUrl)) return url, nil } func (c *Client) GetOauthToken(code string) OauthTokenResponse { baseUrl := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" url := fmt.Sprintf(baseUrl, c.Account.AppID, c.Account.AppSecret, code) rc, err := utils.HttpGet(&http.Client{}, url, nil) if err != nil { return OauthTokenResponse{ErrCode: 1, ErrMsg: "http get error"} } p, err := ioutil.ReadAll(rc) if err != nil { return OauthTokenResponse{ErrCode: 1, ErrMsg: "http read error"} } var response OauthTokenResponse utils.JsonDecode(p).To(&response) return response } func (c *Client) GetUserInfo(accessToken string, openid string) UserInfo { baseUrl := "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" url := fmt.Sprintf(baseUrl, accessToken, openid) rc, err := utils.HttpGet(&http.Client{}, url, nil) if err != nil { return UserInfo{ErrCode: 1, ErrMsg: "http get error"} } p, err := ioutil.ReadAll(rc) if err != nil { return UserInfo{ErrCode: 1, ErrMsg: "http read error"} } var response UserInfo utils.JsonDecode(p).To(&response) return response } func (c *Client) GetJsTicket() (string, error) { rc, err := utils.HttpGet(&http.Client{}, config.Cfg.App.ProductionUrl+"api/weixin/jsapi_ticket/"+utils.ToStr(c.Account.ID), nil) fmt.Println(config.Cfg.App.ProductionUrl + "api/weixin/jsapi_ticket/" + utils.ToStr(c.Account.ID)) p, err := ioutil.ReadAll(rc) if err != nil { return "", err } var response app.ResponseData utils.JsonDecode(p).To(&response) if response.Code != 200 { return "", errors.New(response.Msg) } return utils.ToStr(response.Data.(map[string]interface{})["ticket"]), nil } func (c *Client) RefreshJsapiTicket() JsapiTicketResponse { currentTime := utils.ToInt(time.Now().Unix()) if c.Account.JsapiTicket != "" && c.Account.JsapiTicketExpiresIn > 0 && currentTime < c.Account.JsapiTicketExpiresIn+c.Account.JsapiTicketUpdatedAt { return JsapiTicketResponse{ Ticket: c.Account.JsapiTicket, ExpiresIn: c.Account.JsapiTicketExpiresIn, } } baseUrl := "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi" accessToken, err := c.GetAccessToken() if err != nil { fmt.Println(err) return JsapiTicketResponse{ErrCode: 1, ErrMsg: "http get error"} } url := fmt.Sprintf(baseUrl, accessToken) fmt.Println(url) rc, err := utils.HttpGet(&http.Client{}, url, nil) if err != nil { return JsapiTicketResponse{ErrCode: 1, ErrMsg: "http get error"} } p, err := ioutil.ReadAll(rc) if err != nil { return JsapiTicketResponse{ErrCode: 1, ErrMsg: "http read error"} } var response JsapiTicketResponse utils.JsonDecode(p).To(&response) if response.Ticket != "" && response.ErrCode == 0 { weixinForm := form.WeixinEditJsapi{ JsapiTicket: response.Ticket, JsapiTicketExpiresIn: response.ExpiresIn, } weixin.EditJsapi(weixinForm, c.Account.ID) } return response } func (c *Client) GetJsapiParam(requestUrl string) (JsapiReturn, error) { requestUrl, _ = url.QueryUnescape(requestUrl) nonceStr := utils.RandomStr() timestamp := time.Now().Unix() ticket, err := c.GetJsTicket() if err != nil { return JsapiReturn{}, err } formatStr := "jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s" formatStr = fmt.Sprintf(formatStr, ticket, nonceStr, utils.ToStr(timestamp), requestUrl) fmt.Println(formatStr) return JsapiReturn{ AppID: c.Account.AppID, NonceStr: nonceStr, Timestamp: utils.ToInt(timestamp), Signature: utils.SHA1(formatStr), }, nil } func (c *Client) SendTemplateMessage(touser string, template_id string, url string, data map[string]interface{}) (interface{}, error) { baseUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s&type=jsapi" accessToken, err := c.GetAccessToken() if err != nil { return nil, err } urls := fmt.Sprintf(baseUrl, accessToken) datas := map[string]interface{}{ "touser": touser, "template_id": template_id, "data": data, } if url != "" { datas["url"] = url } var ret interface{} err = utils.HttpPostJSON(&http.Client{}, urls, http.Header{}, datas, &ret) if err != nil { return nil, err } return ret, err }