mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-12 08:42:28 +08:00
Merge branch 'master' into master
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,3 +25,4 @@ _testmain.go
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode/
|
.vscode/
|
||||||
vendor/*/
|
vendor/*/
|
||||||
|
.idea/
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
|
- 1.11.x
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.7.x
|
|
||||||
- 1.6.x
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- memcached
|
- memcached
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ type Reply struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
注意:`retrun nil`表示什么也不做
|
注意:`return nil`表示什么也不做
|
||||||
|
|
||||||
#### 回复文本消息
|
#### 回复文本消息
|
||||||
```go
|
```go
|
||||||
|
|||||||
7
cache/redis.go
vendored
7
cache/redis.go
vendored
@@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/garyburd/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Redis redis cache
|
//Redis redis cache
|
||||||
@@ -45,6 +45,11 @@ func NewRedis(opts *RedisOpts) *Redis {
|
|||||||
return &Redis{pool}
|
return &Redis{pool}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SetConn 设置conn
|
||||||
|
func (r *Redis) SetConn(conn *redis.Pool) {
|
||||||
|
r.conn = conn
|
||||||
|
}
|
||||||
|
|
||||||
//Get 获取一个值
|
//Get 获取一个值
|
||||||
func (r *Redis) Get(key string) interface{} {
|
func (r *Redis) Get(key string) interface{} {
|
||||||
conn := r.conn.Get()
|
conn := r.conn.Get()
|
||||||
|
|||||||
76
context/qy_access_token.go
Normal file
76
context/qy_access_token.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//qyAccessTokenURL 获取access_token的接口
|
||||||
|
qyAccessTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"
|
||||||
|
)
|
||||||
|
|
||||||
|
//ResQyAccessToken struct
|
||||||
|
type ResQyAccessToken struct {
|
||||||
|
util.CommonError
|
||||||
|
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int64 `json:"expires_in"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetQyAccessTokenLock 设置读写锁(一个appID一个读写锁)
|
||||||
|
func (ctx *Context) SetQyAccessTokenLock(l *sync.RWMutex) {
|
||||||
|
ctx.accessTokenLock = l
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetQyAccessToken 获取access_token
|
||||||
|
func (ctx *Context) GetQyAccessToken() (accessToken string, err error) {
|
||||||
|
ctx.accessTokenLock.Lock()
|
||||||
|
defer ctx.accessTokenLock.Unlock()
|
||||||
|
|
||||||
|
accessTokenCacheKey := fmt.Sprintf("qy_access_token_%s", ctx.AppID)
|
||||||
|
val := ctx.Cache.Get(accessTokenCacheKey)
|
||||||
|
if val != nil {
|
||||||
|
accessToken = val.(string)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//从微信服务器获取
|
||||||
|
var resQyAccessToken ResQyAccessToken
|
||||||
|
resQyAccessToken, err = ctx.GetQyAccessTokenFromServer()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
accessToken = resQyAccessToken.AccessToken
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetQyAccessTokenFromServer 强制从微信服务器获取token
|
||||||
|
func (ctx *Context) GetQyAccessTokenFromServer() (resQyAccessToken ResQyAccessToken, err error) {
|
||||||
|
log.Printf("GetQyAccessTokenFromServer")
|
||||||
|
url := fmt.Sprintf(qyAccessTokenURL, ctx.AppID, ctx.AppSecret)
|
||||||
|
var body []byte
|
||||||
|
body, err = util.HTTPGet(url)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(body, &resQyAccessToken)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resQyAccessToken.ErrCode != 0 {
|
||||||
|
err = fmt.Errorf("get qy_access_token error : errcode=%v , errormsg=%v", resQyAccessToken.ErrCode, resQyAccessToken.ErrMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
qyAccessTokenCacheKey := fmt.Sprintf("qy_access_token_%s", ctx.AppID)
|
||||||
|
expires := resQyAccessToken.ExpiresIn - 1500
|
||||||
|
err = ctx.Cache.Set(qyAccessTokenCacheKey, resQyAccessToken.AccessToken, time.Duration(expires)*time.Second)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -184,13 +184,6 @@ func (material *Material) DeleteMaterial(mediaID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var resDeleteMaterial util.CommonError
|
|
||||||
err = json.Unmarshal(response, &resDeleteMaterial)
|
return util.DecodeWithCommonError(response, "DeleteMaterial")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if resDeleteMaterial.ErrCode != 0 {
|
|
||||||
return fmt.Errorf("DeleteMaterial error : errcode=%v , errmsg=%v", resDeleteMaterial.ErrCode, resDeleteMaterial.ErrMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ const (
|
|||||||
type Media struct {
|
type Media struct {
|
||||||
util.CommonError
|
util.CommonError
|
||||||
|
|
||||||
Type MediaType `json:"type"`
|
Type MediaType `json:"type"`
|
||||||
MediaID string `json:"media_id"`
|
MediaID string `json:"media_id"`
|
||||||
ThumbMediaID string `json:"thumb_media_id"`
|
ThumbMediaID string `json:"thumb_media_id"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//MediaUpload 临时素材上传
|
//MediaUpload 临时素材上传
|
||||||
|
|||||||
45
menu/menu.go
45
menu/menu.go
@@ -134,15 +134,8 @@ func (menu *Menu) SetMenu(buttons []*Button) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var commError util.CommonError
|
|
||||||
err = json.Unmarshal(response, &commError)
|
return util.DecodeWithCommonError(response, "SetMenu")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if commError.ErrCode != 0 {
|
|
||||||
return fmt.Errorf("SetMenu Error , errcode=%d , errmsg=%s", commError.ErrCode, commError.ErrMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetMenu 获取菜单配置
|
//GetMenu 获取菜单配置
|
||||||
@@ -180,15 +173,8 @@ func (menu *Menu) DeleteMenu() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var commError util.CommonError
|
|
||||||
err = json.Unmarshal(response, &commError)
|
return util.DecodeWithCommonError(response, "GetMenu")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if commError.ErrCode != 0 {
|
|
||||||
return fmt.Errorf("GetMenu Error , errcode=%d , errmsg=%s", commError.ErrCode, commError.ErrMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddConditional 添加个性化菜单
|
//AddConditional 添加个性化菜单
|
||||||
@@ -208,15 +194,8 @@ func (menu *Menu) AddConditional(buttons []*Button, matchRule *MatchRule) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var commError util.CommonError
|
|
||||||
err = json.Unmarshal(response, &commError)
|
return util.DecodeWithCommonError(response, "AddConditional")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if commError.ErrCode != 0 {
|
|
||||||
return fmt.Errorf("AddConditional Error , errcode=%d , errmsg=%s", commError.ErrCode, commError.ErrMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//DeleteConditional 删除个性化菜单
|
//DeleteConditional 删除个性化菜单
|
||||||
@@ -235,15 +214,8 @@ func (menu *Menu) DeleteConditional(menuID int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var commError util.CommonError
|
|
||||||
err = json.Unmarshal(response, &commError)
|
return util.DecodeWithCommonError(response, "DeleteConditional")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if commError.ErrCode != 0 {
|
|
||||||
return fmt.Errorf("DeleteConditional Error , errcode=%d , errmsg=%s", commError.ErrCode, commError.ErrMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//MenuTryMatch 菜单匹配
|
//MenuTryMatch 菜单匹配
|
||||||
@@ -286,7 +258,6 @@ func (menu *Menu) GetCurrentSelfMenuInfo() (resSelfMenuInfo ResSelfMenuInfo, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(string(response))
|
|
||||||
err = json.Unmarshal(response, &resSelfMenuInfo)
|
err = json.Unmarshal(response, &resSelfMenuInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ type MixMessage struct {
|
|||||||
//基本消息
|
//基本消息
|
||||||
MsgID int64 `xml:"MsgId"`
|
MsgID int64 `xml:"MsgId"`
|
||||||
Content string `xml:"Content"`
|
Content string `xml:"Content"`
|
||||||
|
Recognition string `xml:"Recognition"`
|
||||||
PicURL string `xml:"PicUrl"`
|
PicURL string `xml:"PicUrl"`
|
||||||
MediaID string `xml:"MediaId"`
|
MediaID string `xml:"MediaId"`
|
||||||
Format string `xml:"Format"`
|
Format string `xml:"Format"`
|
||||||
@@ -82,15 +83,15 @@ type MixMessage struct {
|
|||||||
URL string `xml:"Url"`
|
URL string `xml:"Url"`
|
||||||
|
|
||||||
//事件相关
|
//事件相关
|
||||||
Event EventType `xml:"Event"`
|
Event EventType `xml:"Event"`
|
||||||
EventKey string `xml:"EventKey"`
|
EventKey string `xml:"EventKey"`
|
||||||
Ticket string `xml:"Ticket"`
|
Ticket string `xml:"Ticket"`
|
||||||
Latitude string `xml:"Latitude"`
|
Latitude string `xml:"Latitude"`
|
||||||
Longitude string `xml:"Longitude"`
|
Longitude string `xml:"Longitude"`
|
||||||
Precision string `xml:"Precision"`
|
Precision string `xml:"Precision"`
|
||||||
MenuID string `xml:"MenuId"`
|
MenuID string `xml:"MenuId"`
|
||||||
Status string `xml:"Status"`
|
Status string `xml:"Status"`
|
||||||
SessionFrom string `xml:"SessionFrom"`
|
SessionFrom string `xml:"SessionFrom"`
|
||||||
|
|
||||||
ScanCodeInfo struct {
|
ScanCodeInfo struct {
|
||||||
ScanType string `xml:"ScanType"`
|
ScanType string `xml:"ScanType"`
|
||||||
|
|||||||
95
oauth/qy_oauth.go
Normal file
95
oauth/qy_oauth.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package oauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
qyRedirectOauthURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&agentid=%s&state=%s#wechat_redirect"
|
||||||
|
qyUserInfoURL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s"
|
||||||
|
qyUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail"
|
||||||
|
)
|
||||||
|
|
||||||
|
//GetQyRedirectURL 获取企业微信跳转的url地址
|
||||||
|
func (oauth *Oauth) GetQyRedirectURL(redirectURI, agentid, scope, state string) (string, error) {
|
||||||
|
//url encode
|
||||||
|
urlStr := url.QueryEscape(redirectURI)
|
||||||
|
return fmt.Sprintf(qyRedirectOauthURL, oauth.AppID, urlStr, scope, agentid, state), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//QyUserInfo 用户授权获取到用户信息
|
||||||
|
type QyUserInfo struct {
|
||||||
|
util.CommonError
|
||||||
|
|
||||||
|
UserID string `json:"UserId"`
|
||||||
|
DeviceID string `json:"DeviceId"`
|
||||||
|
UserTicket string `json:"user_ticket"`
|
||||||
|
ExpiresIn int64 `json:"expires_in"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetQyUserInfoByCode 根据code获取企业user_info
|
||||||
|
func (oauth *Oauth) GetQyUserInfoByCode(code string) (result QyUserInfo, err error) {
|
||||||
|
qyAccessToken, e := oauth.GetQyAccessToken()
|
||||||
|
if e != nil {
|
||||||
|
err = e
|
||||||
|
return
|
||||||
|
}
|
||||||
|
urlStr := fmt.Sprintf(qyUserInfoURL, qyAccessToken, code)
|
||||||
|
var response []byte
|
||||||
|
response, err = util.HTTPGet(urlStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(response, &result)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.ErrCode != 0 {
|
||||||
|
err = fmt.Errorf("GetQyUserInfoByCode error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//QyUserDetail 到用户详情
|
||||||
|
type QyUserDetail struct {
|
||||||
|
util.CommonError
|
||||||
|
|
||||||
|
UserID string `json:"UserId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Gender string `json:"gender"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
QrCode string `json:"qr_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetQyUserDetailUserTicket 根据user_ticket获取到用户详情
|
||||||
|
func (oauth *Oauth) GetQyUserDetailUserTicket(userTicket string) (result QyUserDetail, err error) {
|
||||||
|
var qyAccessToken string
|
||||||
|
qyAccessToken, err = oauth.GetQyAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("%s?access_token=%s", qyUserDetailURL, qyAccessToken)
|
||||||
|
var response []byte
|
||||||
|
response, err = util.PostJSON(uri, map[string]string{
|
||||||
|
"user_ticket": userTicket,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(response, &result)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.ErrCode != 0 {
|
||||||
|
err = fmt.Errorf("GetQyUserDetailUserTicket Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
*context.Context
|
*context.Context
|
||||||
|
|
||||||
|
debug bool
|
||||||
|
|
||||||
openID string
|
openID string
|
||||||
|
|
||||||
messageHandler func(message.MixMessage) *message.Reply
|
messageHandler func(message.MixMessage) *message.Reply
|
||||||
@@ -40,6 +42,11 @@ func NewServer(context *context.Context) *Server {
|
|||||||
return srv
|
return srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDebug set debug field
|
||||||
|
func (srv *Server) SetDebug(debug bool) {
|
||||||
|
srv.debug = debug
|
||||||
|
}
|
||||||
|
|
||||||
//Serve 处理微信的请求消息
|
//Serve 处理微信的请求消息
|
||||||
func (srv *Server) Serve() error {
|
func (srv *Server) Serve() error {
|
||||||
if !srv.Validate() {
|
if !srv.Validate() {
|
||||||
@@ -65,6 +72,9 @@ func (srv *Server) Serve() error {
|
|||||||
|
|
||||||
//Validate 校验请求是否合法
|
//Validate 校验请求是否合法
|
||||||
func (srv *Server) Validate() bool {
|
func (srv *Server) Validate() bool {
|
||||||
|
if srv.debug {
|
||||||
|
return true
|
||||||
|
}
|
||||||
timestamp := srv.Query("timestamp")
|
timestamp := srv.Query("timestamp")
|
||||||
nonce := srv.Query("nonce")
|
nonce := srv.Query("nonce")
|
||||||
signature := srv.Query("signature")
|
signature := srv.Query("signature")
|
||||||
|
|||||||
51
user/user.go
51
user/user.go
@@ -9,7 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
userInfoURL = "https://api.weixin.qq.com/cgi-bin/user/info"
|
userInfoURL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"
|
||||||
|
updateRemarkURL = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=%s"
|
||||||
)
|
)
|
||||||
|
|
||||||
//User 用户管理
|
//User 用户管理
|
||||||
@@ -28,20 +29,20 @@ func NewUser(context *context.Context) *User {
|
|||||||
type Info struct {
|
type Info struct {
|
||||||
util.CommonError
|
util.CommonError
|
||||||
|
|
||||||
Subscribe int32 `json:"subscribe"`
|
Subscribe int32 `json:"subscribe"`
|
||||||
OpenID string `json:"openid"`
|
OpenID string `json:"openid"`
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
Sex int32 `json:"sex"`
|
Sex int32 `json:"sex"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
Province string `json:"province"`
|
Province string `json:"province"`
|
||||||
Language string `json:"language"`
|
Language string `json:"language"`
|
||||||
Headimgurl string `json:"headimgurl"`
|
Headimgurl string `json:"headimgurl"`
|
||||||
SubscribeTime int32 `json:"subscribe_time"`
|
SubscribeTime int32 `json:"subscribe_time"`
|
||||||
UnionID string `json:"unionid"`
|
UnionID string `json:"unionid"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
GroupID int32 `json:"groupid"`
|
GroupID int32 `json:"groupid"`
|
||||||
TagidList []string `json:"tagid_list"`
|
TagidList []int32 `json:"tagid_list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetUserInfo 获取用户基本信息
|
//GetUserInfo 获取用户基本信息
|
||||||
@@ -52,7 +53,7 @@ func (user *User) GetUserInfo(openID string) (userInfo *Info, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uri := fmt.Sprintf("%s?access_token=%s&openid=%s&lang=zh_CN", userInfoURL, accessToken, openID)
|
uri := fmt.Sprintf(userInfoURL, accessToken, openID)
|
||||||
var response []byte
|
var response []byte
|
||||||
response, err = util.HTTPGet(uri)
|
response, err = util.HTTPGet(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,3 +70,21 @@ func (user *User) GetUserInfo(openID string) (userInfo *Info, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateRemark 设置用户备注名
|
||||||
|
func (user *User) UpdateRemark(openID, remark string) (err error) {
|
||||||
|
var accessToken string
|
||||||
|
accessToken, err = user.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uri := fmt.Sprintf(updateRemarkURL, accessToken)
|
||||||
|
var response []byte
|
||||||
|
response, err = util.PostJSON(uri, map[string]string{"openid": openID, "remark": remark})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.DecodeWithCommonError(response, "UpdateRemark")
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// CommonError 微信返回的通用错误json
|
// CommonError 微信返回的通用错误json
|
||||||
type CommonError struct {
|
type CommonError struct {
|
||||||
ErrCode int64 `json:"errcode"`
|
ErrCode int64 `json:"errcode"`
|
||||||
ErrMsg string `json:"errmsg"`
|
ErrMsg string `json:"errmsg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeWithCommonError 将返回值按照CommonError解析
|
||||||
|
func DecodeWithCommonError(response []byte, apiName string) (err error) {
|
||||||
|
var commError CommonError
|
||||||
|
err = json.Unmarshal(response, &commError)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if commError.ErrCode != 0 {
|
||||||
|
return fmt.Errorf("%s Error , errcode=%d , errmsg=%s", apiName, commError.ErrCode, commError.ErrMsg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
"github.com/silenceper/wechat/material"
|
"github.com/silenceper/wechat/material"
|
||||||
"github.com/silenceper/wechat/menu"
|
"github.com/silenceper/wechat/menu"
|
||||||
"github.com/silenceper/wechat/oauth"
|
"github.com/silenceper/wechat/oauth"
|
||||||
|
"github.com/silenceper/wechat/pay"
|
||||||
"github.com/silenceper/wechat/server"
|
"github.com/silenceper/wechat/server"
|
||||||
"github.com/silenceper/wechat/template"
|
"github.com/silenceper/wechat/template"
|
||||||
"github.com/silenceper/wechat/user"
|
"github.com/silenceper/wechat/user"
|
||||||
"github.com/silenceper/wechat/pay"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wechat struct
|
// Wechat struct
|
||||||
@@ -27,9 +27,9 @@ type Config struct {
|
|||||||
AppSecret string
|
AppSecret string
|
||||||
Token string
|
Token string
|
||||||
EncodingAESKey string
|
EncodingAESKey string
|
||||||
PayMchID string //支付 - 商户 ID
|
PayMchID string //支付 - 商户 ID
|
||||||
PayNotifyURL string //支付 - 接受微信支付结果通知的接口地址
|
PayNotifyURL string //支付 - 接受微信支付结果通知的接口地址
|
||||||
PayKey string //支付 - 商户后台设置的支付 key
|
PayKey string //支付 - 商户后台设置的支付 key
|
||||||
Cache cache.Cache
|
Cache cache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user