feat: migrate serevices
Some checks failed
build quyun / Build (push) Failing after 2m50s

This commit is contained in:
2025-12-19 19:05:12 +08:00
parent 005585c53b
commit 557a641f41
71 changed files with 5626 additions and 280 deletions

Binary file not shown.

View File

@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENDCCAxygAwIBAgIURWPsWEo1vIT7J6pBAMk0yakdWcowDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUwNDE0MTIwMTI2WhcNMzAwNDEzMTIwMTI2WjCBjTETMBEGA1UEAwwK
MTcwMjY0NDk0NzEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTkwNwYDVQQL
DDDkvbPoioPvvIjljJfkuqzvvInkvIHkuJrnrqHnkIblkqjor6LmnInpmZDlhazl
j7gxCzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAL4aNZ3BGiuBBfBnyi5l5bxSxSCOJJQ8oskcY5lA
RJrT3GbOb4NVlY0I8Qcm/PVsOZI1dWxBRZET/7IzBJ9759qrR3gFmLDW54VtHKPh
XD/HsHa9jSLzKjRXJOdZ0LpBlFz5X51u48kzU6T5B/bKD41mHPde5Na9A6xwBz35
/dqPx+FclCVGY1vLvfrDSIO70RAW8+eRWzXT+VZHAgK/MRsQyrsPZJJdL+Vz+pLz
h4dhgKcfxvc0Y0K3uJ9Jc8l6wZP/6nAEqY95/pOUrSmOCqqIqW0/Tidh4/tSPPmv
y/8I95tQboi6G3cSMfziLhQKlwF0j+YPaskicn+OKIKM/u0CAwEAAaOBuTCBtjAJ
BgNVHRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGE
aHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0
MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFC
NjU0MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEB
CwUAA4IBAQC1sIAaLiXzhLJj0XzTFlCiJ3KPggLA4PnbNvzj6sma0ojx8mOHgfHb
hR216vGY0Ll9ZpbAYR9GdEuUWVawZ38Z4GJVFAOCr1pp6DqeM3A/dTk+V4vJawZz
85AtfL1/heU1xsW0AbyPrfDiMHMieHEDNvRvHjQmjZ42aRbHDdRzDH0TIt0paRPB
+ubwCmr947oMe01PWWvF8g032d6NxN4CTPuBuWnJG9OQOm2KQDb4z5GftiJnFbay
KB3WycuqEFbHXVFgn7jrc9+uX0oRE7+iIfGqpcfJrKD93lP2r9AZ6Oxhk3TaNFSQ
u+/uR1Lg1b6vIJqI8otjDH9j5QVLAj5k
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+GjWdwRorgQXw
Z8ouZeW8UsUgjiSUPKLJHGOZQESa09xmzm+DVZWNCPEHJvz1bDmSNXVsQUWRE/+y
MwSfe+faq0d4BZiw1ueFbRyj4Vw/x7B2vY0i8yo0VyTnWdC6QZRc+V+dbuPJM1Ok
+Qf2yg+NZhz3XuTWvQOscAc9+f3aj8fhXJQlRmNby736w0iDu9EQFvPnkVs10/lW
RwICvzEbEMq7D2SSXS/lc/qS84eHYYCnH8b3NGNCt7ifSXPJesGT/+pwBKmPef6T
lK0pjgqqiKltP04nYeP7Ujz5r8v/CPebUG6Iuht3EjH84i4UCpcBdI/mD2rJInJ/
jiiCjP7tAgMBAAECggEAVYVe94BGsKmTrWpT13m513X4/sNTi2iX5xehavExq+GB
trJKEnBvHgqWvBv7EsHESJVKJRBcJn8zucwf2UuZq5MATOtfnLahYzIJ/2PD52GD
bnepxb5VD0Tg8j9CmngkMYtyS1X2na48g+wQfCK8ymTUxSholH5l565iY6xSWn8r
SD/u/EBLv69i40uocG1hUUicrJZ1wc5T0ct3GpfiA1BfH462/dp6mROONdpwM8IT
ltRH4wjIc2nPgE7eNbXlHg+KkqyNNLA+BeN3yn001QwvP6Q0panuCTsVVlvEuGAY
RwXbu/0fHFbppIpgfr7AFGRWKTF66Peq3ozsG9jNgQKBgQDviSJxN2Mpdln4i5F3
74s8FMtZ5bY63RHHcvJ5/D9G1iDNHFgLJsgdrbAhLqBbqg73EsIT8TsPlAqKPKS8
EGKBg75MsMSYu7EmzIURV3Gy+Pou9jOkTUfQfblkiV+uJjWQPlBlfksL1bQnfSvZ
Pk1DCwGMb5DMDazAQLP9/wtLYQKBgQDLKz9YHF+wFsnfUjBQngDLCTkxrfxp8y84
s/z5IRZIEdfxmnaEeWJXYa0oeQumNLSVHrryvHm3vkBgKexN49TWUGIM3q54gi/R
FPXXJKarDEI7C86Th3g+3FPEez5v+CEncmlB9X3kBT0ZFROWD3HHaz2DUKPVmJe1
eUOtAN0LDQKBgCoulx8i5taFXgCz61EYoQdajhjtp/KjvZ7G8kZjEm2SBcK5DBQi
pzj6vjqJsHmT8AC4j+7dG055/oUresMXi5FNNvTgaC6RVvgDKifMo1wmFkCw4JU9
erkPetdmja/oUKRvJM9Kt0KFRq1xkIg4PXjh9krZ1sDoY5STkF7ZTA7hAoGAQhPv
xzV7Pac7wwFVK3MoKOD4FBtVRBRO4G9RsKk9OPVsuWyWbWGZRXhEPCyaSFVOAk37
WaVJJSSghWY9L9wQxh9gtHTcY99bs/HQP0fxWSJkjBW7+ymNR0ybhgTbeslF5zGD
4Gr6peW6SGUdeKnPRJ+xYvsgPgEiHmixRRxJyCUCgYEAoguVZdpDaRDZGGrTghwj
F4kMIyEczFeBZtK2JEGSLA6j8uj+oBZ26c6K4sh/Btc0l6IkiXijXbTaH87s52xZ
im8aIZZ9jDKUFxtjVUL0l9fjRsCLAvaBbWw3z4EdtOGuYlnhNCheeSd+/Lzqrb1q
pnTiwBHnQCMFFL/rNcz/Mmk=
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,59 @@
package wechat
import (
"go.ipao.vip/atom/container"
"go.ipao.vip/atom/opt"
)
const DefaultPrefix = "WeChat"
func DefaultProvider() container.ProviderContainer {
return container.ProviderContainer{
Provider: Provide,
Options: []opt.Option{
opt.Prefix(DefaultPrefix),
},
}
}
func Provide(opts ...opt.Option) error {
o := opt.New(opts...)
var config Config
if err := o.UnmarshalConfig(&config); err != nil {
return err
}
return container.Container.Provide(func() (*Config, *Client, error) {
httpClient := DefaultClient
if config.DevMode {
httpClient = httpClient.DevMode()
}
return &config, New(
WithAppID(config.AppID),
WithAppSecret(config.AppSecret),
WithAESKey(config.EncodingAESKey),
WithToken(config.Token),
WithClient(httpClient),
), nil
}, o.DiOptions()...)
}
type Config struct {
AppID string
AppSecret string
Token string
EncodingAESKey string
DevMode bool
Pay *Pay
}
type Pay struct {
MchID string
SerialNo string
MechName string
NotifyURL string
ApiV3Key string
PrivateKey string
PublicKeyID string
PublicKey string
}

View File

@@ -0,0 +1,59 @@
package wechat
import "github.com/pkg/errors"
// -1 系统繁忙,此时请开发者稍候再试
// 0 请求成功
// 40001 AppSecret错误或者AppSecret不属于这个公众号请开发者确认AppSecret的正确性
// 40002 请确保grant_type字段值为client_credential
// 40164 调用接口的IP地址不在白名单中请在接口IP白名单中进行设置。
// 40243 AppSecret已被冻结请登录MP解冻后再次调用。
// 89503 此IP调用需要管理员确认,请联系管理员
// 89501 此IP正在等待管理员确认,请联系管理员
// 89506 24小时内该IP被管理员拒绝调用两次24小时内不可再使用该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, msg string) error {
if errCode == 0 {
return nil
}
errs := map[int]error{
0: nil,
-1: errors.New("系统繁忙,此时请开发者稍候再试"),
40001: errors.New("AppSecret错误或者AppSecret不属于这个公众号请开发者确认AppSecret的正确性"),
40002: errors.New("请确保grant_type字段值为client_credential"),
40164: errors.New("调用接口的IP地址不在白名单中请在接口IP白名单中进行设置"),
40243: errors.New("AppSecret已被冻结请登录MP解冻后再次调用"),
89503: errors.New("此IP调用需要管理员确认,请联系管理员"),
89501: errors.New("此IP正在等待管理员确认,请联系管理员"),
89506: errors.New("24小时内该IP被管理员拒绝调用两次24小时内不可再使用该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 := errs[errCode]; ok {
return err
}
return errors.New(msg)
}

View File

@@ -0,0 +1,24 @@
package wechat
import (
"crypto/sha1"
"encoding/hex"
"math/rand"
)
// RandomString generate random size string
func randomString(size int) string {
// 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)
}
func hashSha1(input string) string {
h := sha1.New()
h.Write([]byte(input))
return hex.EncodeToString(h.Sum(nil))
}

View File

@@ -0,0 +1,76 @@
package wechat
import (
"net/url"
"github.com/imroc/req/v3"
)
type Options func(*Client)
func WithAppID(appID string) Options {
return func(we *Client) {
we.appID = appID
}
}
// WithAppSecret sets the app secret
func WithAppSecret(appSecret string) Options {
return func(we *Client) {
we.appSecret = appSecret
}
}
// WithToken sets the token
func WithToken(token string) Options {
return func(we *Client) {
we.token = token
}
}
// WithAESKey sets the AES key
func WithAESKey(aesKey string) Options {
return func(we *Client) {
we.aesKey = aesKey
}
}
// WithClient sets the http client
func WithClient(client *req.Client) Options {
return func(we *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")
}
}
func WithVerifySiteKeyPair(key, value string) Options {
return func(we *Client) {
we.verifyKey = key
we.verifyValue = value
}
}

View File

@@ -0,0 +1,17 @@
package wechat
type ErrorResponse struct {
ErrCode int `json:"errcode,omitempty"`
ErrMsg string `json:"errmsg,omitempty"`
}
func (r *ErrorResponse) Error() error {
return translateError(r.ErrCode, r.ErrMsg)
}
type AccessTokenResponse struct {
ErrorResponse
AccessToken string `json:"access_token,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"` // seconds
}

View File

@@ -0,0 +1,339 @@
package wechat
import (
"crypto/sha1"
"encoding/hex"
"fmt"
"net/url"
"sort"
"strings"
"time"
"quyun/v2/pkg/oauth"
"github.com/imroc/req/v3"
"github.com/pkg/errors"
)
const BaseURL = "https://api.weixin.qq.com/"
var DefaultClient = req.
NewClient().
SetBaseURL(BaseURL).
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 {
client *req.Client
appID string
appSecret string
token string
aesKey string
verifyKey string
verifyValue string
}
func New(options ...Options) *Client {
we := &Client{
client: DefaultClient,
}
for _, opt := range options {
opt(we)
}
return we
}
func (we *Client) VerifySite(key string) (string, error) {
if key == we.verifyKey {
return we.verifyValue, nil
}
return "", errors.New("verify failed")
}
func (we *Client) Verify(signature, timestamp, nonce string) error {
params := []string{signature, timestamp, nonce, we.token}
sort.Strings(params)
str := strings.Join(params, "")
hash := sha1.Sum([]byte(str))
hashStr := hex.EncodeToString(hash[:])
if hashStr == signature {
return errors.New("Signature verification failed")
}
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
}
// RefreshAccessToken
func (we *Client) RefreshAccessToken(refreshToken string) (*AccessTokenResponse, error) {
params := we.wrapParams(map[string]string{
"grant_type": "refresh_token",
"refresh_token": refreshToken,
})
var data AccessTokenResponse
_, 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")
}
if data.ErrCode != 0 {
return nil, data.Error()
}
return &data, nil
}
func (we *Client) GetAccessToken() (*AccessTokenResponse, error) {
params := map[string]string{
"grant_type": "client_credential",
}
var data ErrorResponse
resp, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/cgi-bin/token")
if err != nil {
return nil, errors.Wrap(err, "call /cgi-bin/token failed")
}
if data.ErrCode != 0 {
return nil, data.Error()
}
var token AccessTokenResponse
if err := resp.Unmarshal(&token); err != nil {
return nil, errors.Wrap(err, "parse response failed")
}
return &token, 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
}
var _ oauth.OAuthInfo = (*AuthorizeAccessToken)(nil)
type AuthorizeAccessToken struct {
ErrorResponse
AccessToken string `json:"access_token,omitempty"`
ExpiresIn int64 `json:"expires_in,omitempty"`
IsSnapshotuser int64 `json:"is_snapshotuser,omitempty"`
Openid string `json:"openid,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
Unionid string `json:"unionid,omitempty"`
}
// GetAccessToken implements oauth.OAuthInfo.
func (a *AuthorizeAccessToken) GetAccessToken() string {
return a.AccessToken
}
// GetExpiredAt implements oauth.OAuthInfo.
func (a *AuthorizeAccessToken) GetExpiredAt() time.Time {
return time.Now().Add(time.Duration(a.ExpiresIn) * time.Second)
}
// GetOpenID implements oauth.OAuthInfo.
func (a *AuthorizeAccessToken) GetOpenID() string {
return a.Openid
}
// GetRefreshToken implements oauth.OAuthInfo.
func (a *AuthorizeAccessToken) GetRefreshToken() string {
return a.RefreshToken
}
// GetUnionID implements oauth.OAuthInfo.
func (a *AuthorizeAccessToken) GetUnionID() string {
return a.Unionid
}
type StableAccessToken struct {
AccessToken string `json:"access_token,omitempty"`
ExpiresIn int64 `json:"expires_in,omitempty"`
}
func (we *Client) GetStableAccessToken() (*StableAccessToken, error) {
params := we.wrapParams(map[string]string{
"grant_type": "client_credential",
})
var data StableAccessToken
_, err := we.client.R().SetSuccessResult(&data).SetBodyJsonMarshal(params).Post("/cgi-bin/stable_token")
if err != nil {
return nil, errors.Wrap(err, "call /cgi-bin/stable_token failed")
}
return &data, nil
}
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")
}
if err := data.Error(); err != nil {
return nil, err
}
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")
}
if err := data.Error(); err != nil {
return nil, err
}
return &data, nil
}
type AuthorizeUserInfo struct {
ErrorResponse
City string `json:"city,omitempty"`
Country string `json:"country,omitempty"`
Headimgurl string `json:"headimgurl,omitempty"`
Nickname string `json:"nickname,omitempty"`
Openid string `json:"openid,omitempty"`
Privilege []string `json:"privilege,omitempty"`
Province string `json:"province,omitempty"`
Sex int64 `json:"sex,omitempty"`
Unionid string `json:"unionid,omitempty"`
}
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")
}
if err := data.Error(); err != nil {
return nil, err
}
return &data, nil
}
// GetJSTicket
func (we *Client) GetJSTicket(token string) (string, error) {
var data struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
Ticket string `json:"ticket"`
ExpiresIn int `json:"expires_in"`
}
params := map[string]string{
"access_token": token,
"type": "jsapi",
}
_, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/cgi-bin/ticket/getticket")
if err != nil {
return "", errors.Wrap(err, "call /cgi-bin/ticket/getticket failed")
}
if data.Errcode != 0 {
return "", errors.New("get wechat ticket failed: " + data.Errmsg)
}
return data.Ticket, nil
}
type JsSDK struct {
Debug bool `json:"debug"`
AppID string `json:"appId"`
Timestamp int64 `json:"timestamp"`
NonceStr string `json:"nonceStr"`
Signature string `json:"signature"`
}
// GetJSTicket
func (we *Client) GetJsSDK(token, url string) (*JsSDK, error) {
sdk := &JsSDK{
Debug: false,
AppID: we.appID,
Timestamp: time.Now().Unix(),
NonceStr: randomString(16),
Signature: "",
}
// get ticket
ticket, err := we.GetJSTicket(token)
if err != nil {
return nil, errors.Wrap(err, "get wechat ticket failed")
}
input := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", ticket, sdk.NonceStr, sdk.Timestamp, url)
sdk.Signature = hashSha1(input)
return sdk, nil
}

View File

@@ -0,0 +1,107 @@
package wechat
import (
"testing"
log "github.com/sirupsen/logrus"
. "github.com/smartystreets/goconvey/convey"
)
const (
WechatAppID = "wx45745a8c51091ae0"
WechatAppSecret = "2ab33bc79d9b47efa4abef19d66e1977"
WechatToken = "W8Xhw5TivYBgY"
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) {
Convey("Test GetAccessToken", t, func() {
token, err := getClient().GetAccessToken()
So(err, ShouldBeNil)
So(token.AccessToken, ShouldNotBeEmpty)
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)
})
}
func Test_GetJsTicket(t *testing.T) {
Convey("Test GetJsTicket", t, func() {
token := "91_0pKuAiBFquPdLakDyhYqOyNJkGLr7-Egx-IF4bRzw-2Lpm7wxgz6zVBNJ36FvMXmiu8bz9BTtspVICf1zDZ3XWuVLwTq6T3a6WG1k6NHv6E0PadT-G5x2Y85-xUECBcADATRQ"
ticket, err := getClient().GetJSTicket(token)
So(err, ShouldBeNil)
So(ticket, ShouldNotBeEmpty)
t.Log("Js Ticket:", ticket)
})
}
func Test_GetStableToken(t *testing.T) {
Convey("Test_GetStableToken GetJsTicket", t, func() {
token, err := getClient().GetStableAccessToken()
So(err, ShouldBeNil)
So(token, ShouldNotBeNil)
t.Logf("Stable Token: %+v", token)
})
}