mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-23 13:42:25 +08:00
Compare commits
2 Commits
v2.1.9-rc.
...
24f812d187
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24f812d187 | ||
|
|
dd43b7baa3 |
33
cache/redis.go
vendored
33
cache/redis.go
vendored
@@ -2,6 +2,8 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
@@ -15,25 +17,38 @@ type Redis struct {
|
|||||||
|
|
||||||
// RedisOpts redis 连接属性
|
// RedisOpts redis 连接属性
|
||||||
type RedisOpts struct {
|
type RedisOpts struct {
|
||||||
Host string `yml:"host" json:"host"`
|
Host string `json:"host" yml:"host"`
|
||||||
Username string `yaml:"username" json:"username"`
|
Username string `json:"username" yaml:"username"`
|
||||||
Password string `yml:"password" json:"password"`
|
Password string `json:"password" yml:"password"`
|
||||||
Database int `yml:"database" json:"database"`
|
Database int `json:"database" yml:"database"`
|
||||||
MaxIdle int `yml:"max_idle" json:"max_idle"`
|
MaxIdle int `json:"max_idle" yml:"max_idle"`
|
||||||
MaxActive int `yml:"max_active" json:"max_active"`
|
MaxActive int `json:"max_active" yml:"max_active"`
|
||||||
IdleTimeout int `yml:"idle_timeout" json:"idle_timeout"` // second
|
IdleTimeout int `json:"idle_timeout" yml:"idle_timeout"` // second
|
||||||
|
UseTLS bool `json:"use_tls" yml:"use_tls"` // 是否使用TLS
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRedis 实例化
|
// NewRedis 实例化
|
||||||
func NewRedis(ctx context.Context, opts *RedisOpts) *Redis {
|
func NewRedis(ctx context.Context, opts *RedisOpts) *Redis {
|
||||||
conn := redis.NewUniversalClient(&redis.UniversalOptions{
|
uniOpt := &redis.UniversalOptions{
|
||||||
Addrs: []string{opts.Host},
|
Addrs: []string{opts.Host},
|
||||||
DB: opts.Database,
|
DB: opts.Database,
|
||||||
Username: opts.Username,
|
Username: opts.Username,
|
||||||
Password: opts.Password,
|
Password: opts.Password,
|
||||||
IdleTimeout: time.Second * time.Duration(opts.IdleTimeout),
|
IdleTimeout: time.Second * time.Duration(opts.IdleTimeout),
|
||||||
MinIdleConns: opts.MaxIdle,
|
MinIdleConns: opts.MaxIdle,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if opts.UseTLS {
|
||||||
|
h, _, err := net.SplitHostPort(opts.Host)
|
||||||
|
if err != nil {
|
||||||
|
h = opts.Host
|
||||||
|
}
|
||||||
|
uniOpt.TLSConfig = &tls.Config{
|
||||||
|
ServerName: h,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := redis.NewUniversalClient(uniOpt)
|
||||||
return &Redis{ctx: ctx, conn: conn}
|
return &Redis{ctx: ctx, conn: conn}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ import (
|
|||||||
"github.com/silenceper/wechat/v2/util"
|
"github.com/silenceper/wechat/v2/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const queryURL = "https://api.weixin.qq.com/wxa/query_urllink"
|
const queryURL = "https://api.weixin.qq.com/wxa/query_urllink?access_token=%s"
|
||||||
|
|
||||||
|
// ULQueryRequest 查询加密URLLink请求
|
||||||
|
type ULQueryRequest struct {
|
||||||
|
URLLink string `json:"url_link"`
|
||||||
|
QueryType int `json:"query_type"`
|
||||||
|
}
|
||||||
|
|
||||||
// ULQueryResult 返回的结果
|
// ULQueryResult 返回的结果
|
||||||
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-link/urllink.query.html 返回值
|
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-link/urllink.query.html 返回值
|
||||||
@@ -28,25 +34,35 @@ type ULQueryResult struct {
|
|||||||
ResourceAppid string `json:"resource_appid"`
|
ResourceAppid string `json:"resource_appid"`
|
||||||
} `json:"cloud_base"`
|
} `json:"cloud_base"`
|
||||||
} `json:"url_link_info"`
|
} `json:"url_link_info"`
|
||||||
VisitOpenid string `json:"visit_openid"`
|
VisitOpenid string `json:"visit_openid"`
|
||||||
|
QuotaInfo QuotaInfo `json:"quota_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuotaInfo quota 配置
|
||||||
|
type QuotaInfo struct {
|
||||||
|
RemainVisitQuota int64 `json:"remain_visit_quota"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query 查询小程序 url_link 配置。
|
// Query 查询小程序 url_link 配置。
|
||||||
func (u *URLLink) Query(urlLink string) (*ULQueryResult, error) {
|
func (u *URLLink) Query(urlLink string) (*ULQueryResult, error) {
|
||||||
accessToken, err := u.GetAccessToken()
|
return u.QueryWithType(&ULQueryRequest{URLLink: urlLink})
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
|
||||||
}
|
// QueryWithType 查询加密URLLink
|
||||||
|
// see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-link/queryUrlLink.html
|
||||||
uri := fmt.Sprintf("%s?access_token=%s", queryURL, accessToken)
|
func (u *URLLink) QueryWithType(req *ULQueryRequest) (*ULQueryResult, error) {
|
||||||
response, err := util.PostJSON(uri, map[string]string{"url_link": urlLink})
|
var (
|
||||||
if err != nil {
|
accessToken string
|
||||||
return nil, err
|
err error
|
||||||
}
|
)
|
||||||
var resp ULQueryResult
|
if accessToken, err = u.GetAccessToken(); err != nil {
|
||||||
err = util.DecodeWithError(response, &resp, "URLLink.Query")
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
var response []byte
|
||||||
}
|
if response, err = util.PostJSON(fmt.Sprintf(queryURL, accessToken), req); err != nil {
|
||||||
return &resp, nil
|
return nil, err
|
||||||
|
}
|
||||||
|
result := &ULQueryResult{}
|
||||||
|
err = util.DecodeWithError(response, result, "URLLink.Query")
|
||||||
|
return result, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ const (
|
|||||||
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.query.html#参数
|
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.query.html#参数
|
||||||
type QueryScheme struct {
|
type QueryScheme struct {
|
||||||
// 小程序 scheme 码
|
// 小程序 scheme 码
|
||||||
Scheme string `json:"scheme"`
|
Scheme string `json:"scheme"`
|
||||||
|
QueryType int `json:"query_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SchemeInfo scheme 配置
|
// SchemeInfo scheme 配置
|
||||||
@@ -33,34 +34,47 @@ type SchemeInfo struct {
|
|||||||
EnvVersion EnvVersion `json:"env_version"`
|
EnvVersion EnvVersion `json:"env_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// resQueryScheme 返回结构体
|
// QuotaInfo quota 配置
|
||||||
|
type QuotaInfo struct {
|
||||||
|
RemainVisitQuota int64 `json:"remain_visit_quota"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResQueryScheme 返回结构体
|
||||||
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.query.html#参数
|
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.query.html#参数
|
||||||
type resQueryScheme struct {
|
type ResQueryScheme struct {
|
||||||
// 通用错误
|
// 通用错误
|
||||||
util.CommonError
|
util.CommonError
|
||||||
// scheme 配置
|
// scheme 配置
|
||||||
SchemeInfo SchemeInfo `json:"scheme_info"`
|
SchemeInfo SchemeInfo `json:"scheme_info"`
|
||||||
// 访问该链接的openid,没有用户访问过则为空字符串
|
// 访问该链接的openid,没有用户访问过则为空字符串
|
||||||
VisitOpenid string `json:"visit_openid"`
|
VisitOpenid string `json:"visit_openid"`
|
||||||
|
QuotaInfo QuotaInfo `json:"quota_info"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryScheme 查询小程序 scheme 码
|
// QueryScheme 查询小程序 scheme 码
|
||||||
func (u *URLScheme) QueryScheme(querySchemeParams QueryScheme) (schemeInfo SchemeInfo, visitOpenid string, err error) {
|
func (u *URLScheme) QueryScheme(querySchemeParams QueryScheme) (schemeInfo SchemeInfo, visitOpenid string, err error) {
|
||||||
var accessToken string
|
res, err := u.QuerySchemeWithRes(querySchemeParams)
|
||||||
accessToken, err = u.GetAccessToken()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
urlStr := fmt.Sprintf(querySchemeURL, accessToken)
|
|
||||||
var response []byte
|
|
||||||
response, err = util.PostJSON(urlStr, querySchemeParams)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用通用方法返回错误
|
|
||||||
var res resQueryScheme
|
|
||||||
err = util.DecodeWithError(response, &res, "QueryScheme")
|
|
||||||
return res.SchemeInfo, res.VisitOpenid, err
|
return res.SchemeInfo, res.VisitOpenid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QuerySchemeWithRes 查询scheme码
|
||||||
|
// see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/queryScheme.html
|
||||||
|
func (u *URLScheme) QuerySchemeWithRes(req QueryScheme) (*ResQueryScheme, error) {
|
||||||
|
var (
|
||||||
|
accessToken string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if accessToken, err = u.GetAccessToken(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSON(fmt.Sprintf(querySchemeURL, accessToken), req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := &ResQueryScheme{}
|
||||||
|
err = util.DecodeWithError(response, result, "QueryScheme")
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ func NewURLScheme(ctx *context.Context) *URLScheme {
|
|||||||
return &URLScheme{Context: ctx}
|
return &URLScheme{Context: ctx}
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateURL = "https://api.weixin.qq.com/wxa/generatescheme"
|
const (
|
||||||
|
// generateURL 获取加密scheme码
|
||||||
|
generateURL = "https://api.weixin.qq.com/wxa/generatescheme"
|
||||||
|
// generateNFCURL 获取 NFC 的小程序 scheme
|
||||||
|
generateNFCURL = "https://api.weixin.qq.com/wxa/generatenfcscheme?access_token=%s"
|
||||||
|
)
|
||||||
|
|
||||||
// TExpireType 失效类型 (指定时间戳/指定间隔)
|
// TExpireType 失效类型 (指定时间戳/指定间隔)
|
||||||
type TExpireType int
|
type TExpireType int
|
||||||
@@ -50,11 +55,13 @@ type JumpWxa struct {
|
|||||||
// USParams 请求参数
|
// USParams 请求参数
|
||||||
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html#请求参数
|
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html#请求参数
|
||||||
type USParams struct {
|
type USParams struct {
|
||||||
JumpWxa *JumpWxa `json:"jump_wxa"`
|
JumpWxa *JumpWxa `json:"jump_wxa,omitempty"`
|
||||||
ExpireType TExpireType `json:"expire_type"`
|
ExpireType TExpireType `json:"expire_type,omitempty"`
|
||||||
ExpireTime int64 `json:"expire_time"`
|
ExpireTime int64 `json:"expire_time,omitempty"`
|
||||||
ExpireInterval int `json:"expire_interval"`
|
ExpireInterval int `json:"expire_interval,omitempty"`
|
||||||
IsExpire bool `json:"is_expire,omitempty"`
|
IsExpire bool `json:"is_expire,omitempty"`
|
||||||
|
ModelID string `json:"model_id,omitempty"`
|
||||||
|
Sn string `json:"sn,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// USResult 返回的结果
|
// USResult 返回的结果
|
||||||
@@ -81,3 +88,22 @@ func (u *URLScheme) Generate(params *USParams) (string, error) {
|
|||||||
err = util.DecodeWithError(response, &resp, "URLScheme.Generate")
|
err = util.DecodeWithError(response, &resp, "URLScheme.Generate")
|
||||||
return resp.OpenLink, err
|
return resp.OpenLink, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateNFC 获取 NFC 的小程序 scheme
|
||||||
|
// see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/generateNFCScheme.html
|
||||||
|
func (u *URLScheme) GenerateNFC(params *USParams) (string, error) {
|
||||||
|
var (
|
||||||
|
accessToken string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if accessToken, err = u.GetAccessToken(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSON(fmt.Sprintf(generateNFCURL, accessToken), params); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
result := &USResult{}
|
||||||
|
err = util.DecodeWithError(response, result, "URLScheme.GenerateNFC")
|
||||||
|
return result.OpenLink, err
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user