feat: complete auth
This commit is contained in:
11
consts.go
11
consts.go
@@ -1,8 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// WechatAppID = "wxf5bf0adeb99c2afd"
|
||||||
|
// WechatAppSecret = "3cf8fad4aa414f2b861399f111b22bb5"
|
||||||
|
// WechatToken = "W8Xhw5TivYBgY"
|
||||||
|
// WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
|
||||||
|
// )
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WechatAppID = "wxf5bf0adeb99c2afd"
|
WechatAppID = "wx45745a8c51091ae0"
|
||||||
WechatAppSecret = "3cf8fad4aa414f2b861399f111b22bb5"
|
WechatAppSecret = "2ab33bc79d9b47efa4abef19d66e1977"
|
||||||
WechatToken = "W8Xhw5TivYBgY"
|
WechatToken = "W8Xhw5TivYBgY"
|
||||||
WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
|
WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
|
||||||
)
|
)
|
||||||
|
|||||||
19
main.go
19
main.go
@@ -1,11 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.ipao.vip/rogeecn/mp-qvyun/pkg/middlewares/fiberv3"
|
||||||
"git.ipao.vip/rogeecn/mp-qvyun/pkg/wechat"
|
"git.ipao.vip/rogeecn/mp-qvyun/pkg/wechat"
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
wechatClient := wechat.New(
|
wechatClient := wechat.New(
|
||||||
wechat.WithAppID(WechatAppID),
|
wechat.WithAppID(WechatAppID),
|
||||||
@@ -14,15 +19,17 @@ func main() {
|
|||||||
wechat.WithToken(WechatToken),
|
wechat.WithToken(WechatToken),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
wechatMiddlewares := fiberv3.Init(wechatClient)
|
||||||
|
|
||||||
// create a new fiber server
|
// create a new fiber server
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
app.Use(LogAll)
|
||||||
|
app.Use(wechatMiddlewares.Verify)
|
||||||
|
app.Use(wechatMiddlewares.AuthUserInfo)
|
||||||
|
app.Use(wechatMiddlewares.SilentAuth)
|
||||||
|
|
||||||
app.Use(VerifyWechatServer(wechatClient))
|
app.Get("/", func(c fiber.Ctx) error {
|
||||||
|
return c.SendString("Hello World")
|
||||||
app.Get("/videos", func(c fiber.Ctx) error {
|
|
||||||
log.Infof("GET: %+v", c.Queries())
|
|
||||||
log.Infof("POST: %s", c.Body())
|
|
||||||
return c.SendString(c.Query("echostr", "Error"))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// listen on port 3000
|
// listen on port 3000
|
||||||
|
|||||||
@@ -1,36 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.ipao.vip/rogeecn/mp-qvyun/pkg/wechat"
|
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
"github.com/gofiber/fiber/v3/log"
|
"github.com/gofiber/fiber/v3/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func VerifyWechatServer(wechatClient *wechat.Client) fiber.Handler {
|
func LogAll(c fiber.Ctx) error {
|
||||||
return func(c fiber.Ctx) error {
|
log.Info("------------------------------------------")
|
||||||
// get the query parameters
|
log.Infof("Request Method: %s", c.Method())
|
||||||
signature := c.Query("signature")
|
log.Infof("Request Headers: %s", &c.Request().Header)
|
||||||
timestamp := c.Query("timestamp")
|
log.Infof("Request URL: %s", c.OriginalURL())
|
||||||
nonce := c.Query("nonce")
|
log.Infof("Request Query: %+v", c.Queries())
|
||||||
echostr := c.Query("echostr")
|
log.Infof("Request Body: %s", c.BodyRaw())
|
||||||
|
log.Info("------------------------------------------")
|
||||||
if signature == "" || timestamp == "" || nonce == "" || echostr == "" {
|
return c.Next()
|
||||||
return c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof(
|
|
||||||
"begin verify signature, signature: %s, timestamp: %s, nonce: %s, echostr: %s",
|
|
||||||
signature,
|
|
||||||
timestamp,
|
|
||||||
nonce,
|
|
||||||
echostr,
|
|
||||||
)
|
|
||||||
|
|
||||||
// verify the signature
|
|
||||||
if err := wechatClient.VerifyServer(signature, timestamp, nonce); err != nil {
|
|
||||||
return c.SendString(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.SendString(echostr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
100
pkg/middlewares/fiberv3/middlewares.go
Normal file
100
pkg/middlewares/fiberv3/middlewares.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package fiberv3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ipao.vip/rogeecn/mp-qvyun/pkg/wechat"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fiberMiddlewares struct {
|
||||||
|
client *wechat.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(client *wechat.Client) *fiberMiddlewares {
|
||||||
|
return &fiberMiddlewares{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fiberMiddlewares) Verify(c fiber.Ctx) error {
|
||||||
|
// get the query parameters
|
||||||
|
signature := c.Query("signature")
|
||||||
|
timestamp := c.Query("timestamp")
|
||||||
|
nonce := c.Query("nonce")
|
||||||
|
echostr := c.Query("echostr")
|
||||||
|
|
||||||
|
if signature == "" || timestamp == "" || nonce == "" || echostr == "" {
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(
|
||||||
|
"begin verify signature, signature: %s, timestamp: %s, nonce: %s, echostr: %s",
|
||||||
|
signature,
|
||||||
|
timestamp,
|
||||||
|
nonce,
|
||||||
|
echostr,
|
||||||
|
)
|
||||||
|
|
||||||
|
// verify the signature
|
||||||
|
if err := f.client.Verify(signature, timestamp, nonce); err != nil {
|
||||||
|
return c.SendString(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendString(echostr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fiberMiddlewares) SilentAuth(c fiber.Ctx) error {
|
||||||
|
// if cookie not exists key "openid", then redirect to the wechat auth page
|
||||||
|
sid := c.Cookies("sid", "")
|
||||||
|
if sid != "" {
|
||||||
|
// TODO: verify sid
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current full url
|
||||||
|
url := c.BaseURL()
|
||||||
|
url = "https://qvyun.mp.jdwan.com"
|
||||||
|
log.WithField("module", "middleware.SilentAuth").Debug("url:", url)
|
||||||
|
|
||||||
|
to, err := f.client.ScopeAuthorizeURL(
|
||||||
|
wechat.ScopeAuthorizeURLWithRedirectURI(url),
|
||||||
|
wechat.ScopeAuthorizeURLWithState("sns_basic_auth"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to get wechat auth url")
|
||||||
|
}
|
||||||
|
log.WithField("module", "middleware.SilentAuth").Debug("redirectTo: ", to.String())
|
||||||
|
|
||||||
|
return c.Redirect().To(to.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fiberMiddlewares) AuthUserInfo(c fiber.Ctx) error {
|
||||||
|
state := c.Query("state")
|
||||||
|
code := c.Query("code")
|
||||||
|
|
||||||
|
if state == "" && code == "" {
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if state != "sns_basic_auth" {
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
log.WithField("module", "middleware.AuthUserInfo").Debug("code", code)
|
||||||
|
|
||||||
|
// get the openid
|
||||||
|
token, err := f.client.AuthorizeCode2Token(code)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to get openid")
|
||||||
|
}
|
||||||
|
// TODO: store the openid to the session
|
||||||
|
|
||||||
|
// set the openid to the cookie
|
||||||
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "sid",
|
||||||
|
Value: token.Openid,
|
||||||
|
HTTPOnly: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
return c.Redirect().To("/")
|
||||||
|
}
|
||||||
@@ -12,6 +12,17 @@ import "github.com/pkg/errors"
|
|||||||
// 89501 此IP正在等待管理员确认,请联系管理员
|
// 89501 此IP正在等待管理员确认,请联系管理员
|
||||||
// 89506 24小时内该IP被管理员拒绝调用两次,24小时内不可再使用该IP调用
|
// 89506 24小时内该IP被管理员拒绝调用两次,24小时内不可再使用该IP调用
|
||||||
// 89507 1小时内该IP被管理员拒绝调用一次,1小时内不可再使用该IP调用
|
// 89507 1小时内该IP被管理员拒绝调用一次,1小时内不可再使用该IP调用
|
||||||
|
// 10003 redirect_uri域名与后台配置不一致
|
||||||
|
// 10004 此公众号被封禁
|
||||||
|
// 10005 此公众号并没有这些scope的权限
|
||||||
|
// 10006 必须关注此测试号
|
||||||
|
// 10009 操作太频繁了,请稍后重试
|
||||||
|
// 10010 scope不能为空
|
||||||
|
// 10011 redirect_uri不能为空
|
||||||
|
// 10012 appid不能为空
|
||||||
|
// 10013 state不能为空
|
||||||
|
// 10015 公众号未授权第三方平台,请检查授权状态
|
||||||
|
// 10016 不支持微信开放平台的Appid,请使用公众号Appid
|
||||||
func translateError(errCode int) error {
|
func translateError(errCode int) error {
|
||||||
errors := map[int]error{
|
errors := map[int]error{
|
||||||
0: nil,
|
0: nil,
|
||||||
@@ -24,6 +35,17 @@ func translateError(errCode int) error {
|
|||||||
89501: errors.New("此IP正在等待管理员确认,请联系管理员"),
|
89501: errors.New("此IP正在等待管理员确认,请联系管理员"),
|
||||||
89506: errors.New("24小时内该IP被管理员拒绝调用两次,24小时内不可再使用该IP调用"),
|
89506: errors.New("24小时内该IP被管理员拒绝调用两次,24小时内不可再使用该IP调用"),
|
||||||
89507: errors.New("1小时内该IP被管理员拒绝调用一次,1小时内不可再使用该IP调用"),
|
89507: errors.New("1小时内该IP被管理员拒绝调用一次,1小时内不可再使用该IP调用"),
|
||||||
|
10003: errors.New("redirect_uri域名与后台配置不一致"),
|
||||||
|
10004: errors.New("此公众号被封禁"),
|
||||||
|
10005: errors.New("此公众号并没有这些scope的权限"),
|
||||||
|
10006: errors.New("必须关注此测试号"),
|
||||||
|
10009: errors.New("操作太频繁了,请稍后重试"),
|
||||||
|
10010: errors.New("scope不能为空"),
|
||||||
|
10011: errors.New("redirect_uri不能为空"),
|
||||||
|
10012: errors.New("appid不能为空"),
|
||||||
|
10013: errors.New("state不能为空"),
|
||||||
|
10015: errors.New("公众号未授权第三方平台,请检查授权状态"),
|
||||||
|
10016: errors.New("不支持微信开放平台的Appid,请使用公众号Appid"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := errors[errCode]; ok {
|
if err, ok := errors[errCode]; ok {
|
||||||
|
|||||||
14
pkg/wechat/funcs.go
Normal file
14
pkg/wechat/funcs.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package wechat
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
|
||||||
|
// RandomString generate random size string
|
||||||
|
func randomString(size int) (string, error) {
|
||||||
|
// generate size string [0-9a-zA-Z]
|
||||||
|
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
b := make([]byte, size)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = chars[rand.Intn(len(chars))]
|
||||||
|
}
|
||||||
|
return string(b), nil
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package wechat
|
package wechat
|
||||||
|
|
||||||
import "github.com/imroc/req/v3"
|
import (
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/imroc/req/v3"
|
||||||
|
)
|
||||||
|
|
||||||
type Options func(*Client)
|
type Options func(*Client)
|
||||||
|
|
||||||
@@ -37,3 +41,29 @@ func WithClient(client *req.Client) Options {
|
|||||||
we.client = client
|
we.client = client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ScopeAuthorizeURLOptions func(url.Values)
|
||||||
|
|
||||||
|
func ScopeAuthorizeURLWithScope(scope AuthScope) ScopeAuthorizeURLOptions {
|
||||||
|
return func(v url.Values) {
|
||||||
|
v.Set("scope", scope.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeAuthorizeURLWithRedirectURI(uri string) ScopeAuthorizeURLOptions {
|
||||||
|
return func(v url.Values) {
|
||||||
|
v.Set("redirect_uri", uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeAuthorizeURLWithState(state string) ScopeAuthorizeURLOptions {
|
||||||
|
return func(v url.Values) {
|
||||||
|
v.Set("state", state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeAuthorizeURLWithForcePopup() ScopeAuthorizeURLOptions {
|
||||||
|
return func(v url.Values) {
|
||||||
|
v.Set("forcePopup", "true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ func (r *Response) Error() error {
|
|||||||
|
|
||||||
type AccessTokenResponse struct {
|
type AccessTokenResponse struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
ExpiresIn int `json:"expires_in"`
|
ExpiresIn int `json:"expires_in"` // seconds
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package wechat
|
|||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -17,6 +18,17 @@ var DefaultClient = req.
|
|||||||
SetBaseURL(BaseURL).
|
SetBaseURL(BaseURL).
|
||||||
SetCommonHeader("Content-Type", "application/json")
|
SetCommonHeader("Content-Type", "application/json")
|
||||||
|
|
||||||
|
const (
|
||||||
|
ScopeBase = "snsapi_base"
|
||||||
|
ScopeUserInfo = "snsapi_userinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthScope string
|
||||||
|
|
||||||
|
func (s AuthScope) String() string {
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
client *req.Client
|
client *req.Client
|
||||||
|
|
||||||
@@ -38,7 +50,7 @@ func New(options ...Options) *Client {
|
|||||||
return we
|
return we
|
||||||
}
|
}
|
||||||
|
|
||||||
func (we *Client) VerifyServer(signature, timestamp, nonce string) error {
|
func (we *Client) Verify(signature, timestamp, nonce string) error {
|
||||||
params := []string{signature, timestamp, nonce, we.token}
|
params := []string{signature, timestamp, nonce, we.token}
|
||||||
sort.Strings(params)
|
sort.Strings(params)
|
||||||
str := strings.Join(params, "")
|
str := strings.Join(params, "")
|
||||||
@@ -52,11 +64,20 @@ func (we *Client) VerifyServer(signature, timestamp, nonce string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (we *Client) wrapParams(params map[string]string) map[string]string {
|
||||||
|
if params == nil {
|
||||||
|
params = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
params["appid"] = we.appID
|
||||||
|
params["secret"] = we.appSecret
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
func (we *Client) GetAccessToken() (*AccessTokenResponse, error) {
|
func (we *Client) GetAccessToken() (*AccessTokenResponse, error) {
|
||||||
params := map[string]string{
|
params := map[string]string{
|
||||||
"grant_type": "client_credential",
|
"grant_type": "client_credential",
|
||||||
"appid": we.appID,
|
|
||||||
"secret": we.appSecret,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var data AccessTokenResponse
|
var data AccessTokenResponse
|
||||||
@@ -67,3 +88,95 @@ func (we *Client) GetAccessToken() (*AccessTokenResponse, error) {
|
|||||||
|
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScopeAuthorizeURL
|
||||||
|
func (we *Client) ScopeAuthorizeURL(opts ...ScopeAuthorizeURLOptions) (*url.URL, error) {
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("appid", we.appID)
|
||||||
|
params.Add("response_type", "code")
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.Get("scope") == "" {
|
||||||
|
params.Add("scope", ScopeBase)
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse("https://open.weixin.qq.com/connect/oauth2/authorize")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "parse url failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
u.Fragment = "wechat_redirect"
|
||||||
|
u.RawQuery = url.Values(params).Encode()
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthorizeAccessToken struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int64 `json:"expires_in"`
|
||||||
|
IsSnapshotuser int64 `json:"is_snapshotuser"`
|
||||||
|
Openid string `json:"openid"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Unionid string `json:"unionid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (we *Client) AuthorizeCode2Token(code string) (*AuthorizeAccessToken, error) {
|
||||||
|
params := we.wrapParams(map[string]string{
|
||||||
|
"code": code,
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
})
|
||||||
|
|
||||||
|
var data AuthorizeAccessToken
|
||||||
|
_, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/sns/oauth2/access_token")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "call /sns/oauth2/access_token failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (we *Client) AuthorizeRefreshAccessToken(accessToken string) (*AuthorizeAccessToken, error) {
|
||||||
|
params := we.wrapParams(map[string]string{
|
||||||
|
"refresh_token": accessToken,
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
})
|
||||||
|
|
||||||
|
var data AuthorizeAccessToken
|
||||||
|
_, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/sns/oauth2/refresh_token")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "call /sns/oauth2/refresh_token failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthorizeUserInfo struct {
|
||||||
|
City string `json:"city"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
Headimgurl string `json:"headimgurl"`
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
Openid string `json:"openid"`
|
||||||
|
Privilege []string `json:"privilege"`
|
||||||
|
Province string `json:"province"`
|
||||||
|
Sex int64 `json:"sex"`
|
||||||
|
Unionid string `json:"unionid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (we *Client) AuthorizeUserInfo(accessToken, openID string) (*AuthorizeUserInfo, error) {
|
||||||
|
params := (map[string]string{
|
||||||
|
"access_token": accessToken,
|
||||||
|
"openid": openID,
|
||||||
|
})
|
||||||
|
|
||||||
|
var data AuthorizeUserInfo
|
||||||
|
_, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/sns/userinfo")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "call /sns/userinfo failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,27 +8,79 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WechatAppID = "wxf5bf0adeb99c2afd"
|
WechatAppID = "wx45745a8c51091ae0"
|
||||||
WechatAppSecret = "3cf8fad4aa414f2b861399f111b22bb5"
|
WechatAppSecret = "2ab33bc79d9b47efa4abef19d66e1977"
|
||||||
WechatToken = "W8Xhw5TivYBgY"
|
WechatToken = "W8Xhw5TivYBgY"
|
||||||
WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
|
WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClient() *Client {
|
||||||
|
return New(
|
||||||
|
WithAppID(WechatAppID),
|
||||||
|
WithAppSecret(WechatAppSecret),
|
||||||
|
WithAESKey(WechatAesKey),
|
||||||
|
WithToken(WechatToken),
|
||||||
|
WithClient(DefaultClient.DevMode()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWechatClient_GetAccessToken(t *testing.T) {
|
func TestWechatClient_GetAccessToken(t *testing.T) {
|
||||||
Convey("Test GetAccessToken", t, func() {
|
Convey("Test GetAccessToken", t, func() {
|
||||||
log.SetLevel(log.DebugLevel)
|
token, err := getClient().GetAccessToken()
|
||||||
|
|
||||||
wechatClient := New(
|
|
||||||
WithAppID(WechatAppID),
|
|
||||||
WithAppSecret(WechatAppSecret),
|
|
||||||
WithAESKey(WechatAesKey),
|
|
||||||
WithToken(WechatToken),
|
|
||||||
WithClient(DefaultClient.DevMode()),
|
|
||||||
)
|
|
||||||
|
|
||||||
token, err := wechatClient.GetAccessToken()
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(token.AccessToken, ShouldNotBeEmpty)
|
So(token.AccessToken, ShouldNotBeEmpty)
|
||||||
So(token.ExpiresIn, ShouldBeGreaterThan, 0)
|
So(token.ExpiresIn, ShouldBeGreaterThan, 0)
|
||||||
|
|
||||||
|
t.Log("Access Token:", token.AccessToken)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_ScopeAuthorizeURL(t *testing.T) {
|
||||||
|
Convey("Test ScopeAuthorizeURL", t, func() {
|
||||||
|
url, err := getClient().ScopeAuthorizeURL(
|
||||||
|
ScopeAuthorizeURLWithScope(ScopeBase),
|
||||||
|
ScopeAuthorizeURLWithRedirectURI("https://qvyun.mp.jdwan.com/"),
|
||||||
|
)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(url, ShouldNotBeEmpty)
|
||||||
|
t.Log("URL:", url)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AuthorizeCode2Token(t *testing.T) {
|
||||||
|
code := "011W1sll2Xv4Ae4OjUnl2I7jvd2W1slX"
|
||||||
|
|
||||||
|
Convey("Test AuthorizeCode2Token", t, func() {
|
||||||
|
token, err := getClient().AuthorizeCode2Token(code)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
t.Logf("token: %+v", token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AuthorizeRefreshAccessToken(t *testing.T) {
|
||||||
|
token := "86_m_EAHq0RKlo6RzzGAsY8gVmiCqHqIiAJufxhm8mK8imyIW6yoE4NTcIr2vaukp7dexPWId0JWP1iZWYaLpXT_MJv1N7YQW8Qt3zOZDpJY90"
|
||||||
|
|
||||||
|
Convey("Test AuthorizeCode2Token", t, func() {
|
||||||
|
token, err := getClient().AuthorizeRefreshAccessToken(token)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
t.Logf("token: %+v", token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AuthorizeUserInfo(t *testing.T) {
|
||||||
|
token := "86_ZxJa8mIwbml5mDlHHbIUle_UKW8LA75nOuB0wqiome8AX5LlMWU8JwRKMZykdLEjDnKX8EJavz5GeQn3T1ot7TwpULp8imQvNIgFIjC4er8"
|
||||||
|
openID := "oMLa5tyJ2vRHa-HI4CMEkHztq3eU"
|
||||||
|
|
||||||
|
Convey("Test AuthorizeUserInfo", t, func() {
|
||||||
|
user, err := getClient().AuthorizeUserInfo(token, openID)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
t.Logf("user: %+v", user)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user