forked from silenceper/wechat
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2c7d3aa
commit 85b0a11
Showing
13 changed files
with
413 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,7 @@ | |
|
||
[官方文档](https://developers.weixin.qq.com/minigame/dev/api-backend/) | ||
|
||
## 快速入门 | ||
## 快速入门 | ||
```go | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,55 @@ | ||
# 微信开放平台 | ||
|
||
状态:开发中 | ||
|
||
[官方文档](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Third_party_platform_appid.html) | ||
|
||
## 快速入门 | ||
## 快速入门 | ||
|
||
```go | ||
wc := wechat.NewWechat() | ||
memory := cache.NewMemory() | ||
cfg := &openplatform.Config{ | ||
AppID: "xxx", | ||
AppSecret: "xxx", | ||
Token: "xxx", | ||
EncodingAESKey: "xxx", | ||
Cache: memory, | ||
} | ||
|
||
//授权的第三方公众号的appID | ||
appID := "xxx" | ||
openPlatform := wc.GetOpenPlatform(cfg) | ||
officialAccount := openPlatform.GetOfficialAccount(appID) | ||
|
||
// 传入request和responseWriter | ||
server := officialAccount.GetServer(req, rw) | ||
//设置接收消息的处理方法 | ||
server.SetMessageHandler(func(msg message.MixMessage) *message.Reply { | ||
if msg.InfoType == message.InfoTypeVerifyTicket { | ||
componentVerifyTicket, err := openPlatform.SetComponentAccessToken(msg.ComponentVerifyTicket) | ||
if err != nil { | ||
log.Println(err) | ||
return nil | ||
} | ||
//debug | ||
fmt.Println(componentVerifyTicket) | ||
rw.Write([]byte("success")) | ||
return nil | ||
} | ||
//handle other message | ||
// | ||
|
||
|
||
return nil | ||
}) | ||
|
||
//处理消息接收以及回复 | ||
err := server.Serve() | ||
if err != nil { | ||
fmt.Println(err) | ||
return | ||
} | ||
//发送回复的消息 | ||
server.Send() | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package config | ||
|
||
import ( | ||
"github.com/silenceper/wechat/v2/cache" | ||
) | ||
|
||
//Config config for 微信开放平台 | ||
type Config struct { | ||
AppID string `json:"app_id"` //appid | ||
AppSecret string `json:"app_secret"` //appsecret | ||
Token string `json:"token"` //token | ||
EncodingAESKey string `json:"encoding_aes_key"` //EncodingAESKey | ||
Cache cache.Cache | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
package context | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/silenceper/wechat/v2/util" | ||
) | ||
|
||
const ( | ||
componentAccessTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token" | ||
getPreCodeURL = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=%s" | ||
queryAuthURL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=%s" | ||
refreshTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=%s" | ||
getComponentInfoURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=%s" | ||
getComponentConfigURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=%s" | ||
) | ||
|
||
// ComponentAccessToken 第三方平台 | ||
type ComponentAccessToken struct { | ||
AccessToken string `json:"component_access_token"` | ||
ExpiresIn int64 `json:"expires_in"` | ||
} | ||
|
||
// GetComponentAccessToken 获取 ComponentAccessToken | ||
func (ctx *Context) GetComponentAccessToken() (string, error) { | ||
accessTokenCacheKey := fmt.Sprintf("component_access_token_%s", ctx.AppID) | ||
val := ctx.Cache.Get(accessTokenCacheKey) | ||
if val == nil { | ||
return "", fmt.Errorf("cann't get component access token") | ||
} | ||
return val.(string), nil | ||
} | ||
|
||
// SetComponentAccessToken 通过component_verify_ticket 获取 ComponentAccessToken | ||
func (ctx *Context) SetComponentAccessToken(verifyTicket string) (*ComponentAccessToken, error) { | ||
body := map[string]string{ | ||
"component_appid": ctx.AppID, | ||
"component_appsecret": ctx.AppSecret, | ||
"component_verify_ticket": verifyTicket, | ||
} | ||
respBody, err := util.PostJSON(componentAccessTokenURL, body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
at := &ComponentAccessToken{} | ||
if err := json.Unmarshal(respBody, at); err != nil { | ||
return nil, err | ||
} | ||
|
||
accessTokenCacheKey := fmt.Sprintf("component_access_token_%s", ctx.AppID) | ||
expires := at.ExpiresIn - 1500 | ||
if err := ctx.Cache.Set(accessTokenCacheKey, at.AccessToken, time.Duration(expires)*time.Second); err != nil { | ||
return nil, nil | ||
} | ||
return at, nil | ||
} | ||
|
||
// GetPreCode 获取预授权码 | ||
func (ctx *Context) GetPreCode() (string, error) { | ||
cat, err := ctx.GetComponentAccessToken() | ||
if err != nil { | ||
return "", err | ||
} | ||
req := map[string]string{ | ||
"component_appid": ctx.AppID, | ||
} | ||
uri := fmt.Sprintf(getPreCodeURL, cat) | ||
body, err := util.PostJSON(uri, req) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
var ret struct { | ||
PreCode string `json:"pre_auth_code"` | ||
} | ||
if err := json.Unmarshal(body, &ret); err != nil { | ||
return "", err | ||
} | ||
|
||
return ret.PreCode, nil | ||
} | ||
|
||
// ID 微信返回接口中各种类型字段 | ||
type ID struct { | ||
ID int `json:"id"` | ||
} | ||
|
||
// AuthBaseInfo 授权的基本信息 | ||
type AuthBaseInfo struct { | ||
AuthrAccessToken | ||
FuncInfo []AuthFuncInfo `json:"func_info"` | ||
} | ||
|
||
// AuthFuncInfo 授权的接口内容 | ||
type AuthFuncInfo struct { | ||
FuncscopeCategory ID `json:"funcscope_category"` | ||
} | ||
|
||
// AuthrAccessToken 授权方AccessToken | ||
type AuthrAccessToken struct { | ||
Appid string `json:"authorizer_appid"` | ||
AccessToken string `json:"authorizer_access_token"` | ||
ExpiresIn int64 `json:"expires_in"` | ||
RefreshToken string `json:"authorizer_refresh_token"` | ||
} | ||
|
||
// QueryAuthCode 使用授权码换取公众号或小程序的接口调用凭据和授权信息 | ||
func (ctx *Context) QueryAuthCode(authCode string) (*AuthBaseInfo, error) { | ||
cat, err := ctx.GetComponentAccessToken() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
req := map[string]string{ | ||
"component_appid": ctx.AppID, | ||
"authorization_code": authCode, | ||
} | ||
uri := fmt.Sprintf(queryAuthURL, cat) | ||
body, err := util.PostJSON(uri, req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var ret struct { | ||
Info *AuthBaseInfo `json:"authorization_info"` | ||
} | ||
|
||
if err := json.Unmarshal(body, &ret); err != nil { | ||
return nil, err | ||
} | ||
|
||
return ret.Info, nil | ||
} | ||
|
||
// RefreshAuthrToken 获取(刷新)授权公众号或小程序的接口调用凭据(令牌) | ||
func (ctx *Context) RefreshAuthrToken(appid, refreshToken string) (*AuthrAccessToken, error) { | ||
cat, err := ctx.GetComponentAccessToken() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
req := map[string]string{ | ||
"component_appid": ctx.AppID, | ||
"authorizer_appid": appid, | ||
"authorizer_refresh_token": refreshToken, | ||
} | ||
uri := fmt.Sprintf(refreshTokenURL, cat) | ||
body, err := util.PostJSON(uri, req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ret := &AuthrAccessToken{} | ||
if err := json.Unmarshal(body, ret); err != nil { | ||
return nil, err | ||
} | ||
|
||
authrTokenKey := "authorizer_access_token_" + appid | ||
if err := ctx.Cache.Set(authrTokenKey, ret.AccessToken, time.Minute*80); err != nil { | ||
return nil, err | ||
} | ||
return ret, nil | ||
} | ||
|
||
// GetAuthrAccessToken 获取授权方AccessToken | ||
func (ctx *Context) GetAuthrAccessToken(appid string) (string, error) { | ||
authrTokenKey := "authorizer_access_token_" + appid | ||
val := ctx.Cache.Get(authrTokenKey) | ||
if val == nil { | ||
return "", fmt.Errorf("cannot get authorizer %s access token", appid) | ||
} | ||
return val.(string), nil | ||
} | ||
|
||
// AuthorizerInfo 授权方详细信息 | ||
type AuthorizerInfo struct { | ||
NickName string `json:"nick_name"` | ||
HeadImg string `json:"head_img"` | ||
ServiceTypeInfo ID `json:"service_type_info"` | ||
VerifyTypeInfo ID `json:"verify_type_info"` | ||
UserName string `json:"user_name"` | ||
PrincipalName string `json:"principal_name"` | ||
BusinessInfo struct { | ||
OpenStore string `json:"open_store"` | ||
OpenScan string `json:"open_scan"` | ||
OpenPay string `json:"open_pay"` | ||
OpenCard string `json:"open_card"` | ||
OpenShake string `json:"open_shake"` | ||
} | ||
Alias string `json:"alias"` | ||
QrcodeURL string `json:"qrcode_url"` | ||
} | ||
|
||
// GetAuthrInfo 获取授权方的帐号基本信息 | ||
func (ctx *Context) GetAuthrInfo(appid string) (*AuthorizerInfo, *AuthBaseInfo, error) { | ||
cat, err := ctx.GetComponentAccessToken() | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
req := map[string]string{ | ||
"component_appid": ctx.AppID, | ||
"authorizer_appid": appid, | ||
} | ||
|
||
uri := fmt.Sprintf(getComponentInfoURL, cat) | ||
body, err := util.PostJSON(uri, req) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var ret struct { | ||
AuthorizerInfo *AuthorizerInfo `json:"authorizer_info"` | ||
AuthorizationInfo *AuthBaseInfo `json:"authorization_info"` | ||
} | ||
if err := json.Unmarshal(body, &ret); err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
return ret.AuthorizerInfo, ret.AuthorizationInfo, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package context | ||
|
||
import ( | ||
"github.com/silenceper/wechat/v2/openplatform/config" | ||
) | ||
|
||
// Context struct | ||
type Context struct { | ||
*config.Config | ||
} |
Oops, something went wrong.