mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-13 01:02:27 +08:00
开放平台基本框架
This commit is contained in:
@@ -2,4 +2,7 @@
|
|||||||
|
|
||||||
[官方文档](https://developers.weixin.qq.com/minigame/dev/api-backend/)
|
[官方文档](https://developers.weixin.qq.com/minigame/dev/api-backend/)
|
||||||
|
|
||||||
## 快速入门
|
## 快速入门
|
||||||
|
```go
|
||||||
|
|
||||||
|
```
|
||||||
@@ -2,4 +2,19 @@
|
|||||||
|
|
||||||
[官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/)
|
[官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/)
|
||||||
|
|
||||||
|
|
||||||
|
## 包说明
|
||||||
|
- analysis 数据分析相关API
|
||||||
|
|
||||||
## 快速入门
|
## 快速入门
|
||||||
|
```go
|
||||||
|
wc := wechat.NewWechat()
|
||||||
|
memory := cache.NewMemory()
|
||||||
|
cfg := &miniConfig.Config{
|
||||||
|
AppID: "xxx",
|
||||||
|
AppSecret: "xxx",
|
||||||
|
Cache: memory,
|
||||||
|
}
|
||||||
|
miniprogram := wc.GetMiniProgram(cfg)
|
||||||
|
miniprogram.GetAnalysis().GetAnalysisDailyRetain()
|
||||||
|
```
|
||||||
@@ -72,6 +72,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
//微信开放平台需要用到
|
||||||
// InfoTypeVerifyTicket 返回ticket
|
// InfoTypeVerifyTicket 返回ticket
|
||||||
InfoTypeVerifyTicket InfoType = "component_verify_ticket"
|
InfoTypeVerifyTicket InfoType = "component_verify_ticket"
|
||||||
// InfoTypeAuthorized 授权
|
// InfoTypeAuthorized 授权
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ type OfficialAccount struct {
|
|||||||
|
|
||||||
//NewOfficialAccount 实例化公众号API
|
//NewOfficialAccount 实例化公众号API
|
||||||
func NewOfficialAccount(cfg *config.Config) *OfficialAccount {
|
func NewOfficialAccount(cfg *config.Config) *OfficialAccount {
|
||||||
if cfg.Cache == nil {
|
//if cfg.Cache == nil {
|
||||||
panic("cache未设置")
|
// panic("cache未设置")
|
||||||
}
|
//}
|
||||||
ctx := &context.Context{
|
ctx := &context.Context{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,52 @@
|
|||||||
|
|
||||||
[官方文档](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Third_party_platform_appid.html)
|
[官方文档](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()
|
||||||
|
```
|
||||||
14
openplatform/config/config.go
Normal file
14
openplatform/config/config.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/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
|
||||||
|
}
|
||||||
224
openplatform/context/accessToken.go
Normal file
224
openplatform/context/accessToken.go
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat/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
|
||||||
|
}
|
||||||
10
openplatform/context/context.go
Normal file
10
openplatform/context/context.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/openplatform/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Context struct
|
||||||
|
type Context struct {
|
||||||
|
*config.Config
|
||||||
|
}
|
||||||
32
openplatform/officialaccount/officialaccount.go
Normal file
32
openplatform/officialaccount/officialaccount.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package officialaccount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/officialaccount"
|
||||||
|
offConfig "github.com/silenceper/wechat/officialaccount/config"
|
||||||
|
offContext "github.com/silenceper/wechat/officialaccount/context"
|
||||||
|
opContext "github.com/silenceper/wechat/openplatform/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OfficialAccount struct {
|
||||||
|
//授权的公众号的appID
|
||||||
|
appID string
|
||||||
|
*officialaccount.OfficialAccount
|
||||||
|
opContext *opContext.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewOfficialAccount 实例化
|
||||||
|
//appID :为授权方公众号 APPID,非开放平台第三方平台 APPID
|
||||||
|
func NewOfficialAccount(opCtx *opContext.Context, appID string) *OfficialAccount {
|
||||||
|
officialAccount := officialaccount.NewOfficialAccount(&offConfig.Config{
|
||||||
|
AppID: opCtx.AppID,
|
||||||
|
EncodingAESKey: opCtx.EncodingAESKey,
|
||||||
|
Token: opCtx.Token,
|
||||||
|
Cache: opCtx.Cache,
|
||||||
|
})
|
||||||
|
//设置获取access_token的函数
|
||||||
|
officialAccount.GetContext().SetGetAccessTokenFunc(func(offCtx *offContext.Context) (accessToken string, err error) {
|
||||||
|
// 获取授权方的access_token
|
||||||
|
return opCtx.GetAuthrAccessToken(appID)
|
||||||
|
})
|
||||||
|
return &OfficialAccount{appID: appID, OfficialAccount: officialAccount}
|
||||||
|
}
|
||||||
28
openplatform/openplatform.go
Normal file
28
openplatform/openplatform.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package openplatform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/openplatform/config"
|
||||||
|
"github.com/silenceper/wechat/openplatform/context"
|
||||||
|
"github.com/silenceper/wechat/openplatform/officialaccount"
|
||||||
|
)
|
||||||
|
|
||||||
|
//OpenPlatform 微信开放平台相关api
|
||||||
|
type OpenPlatform struct {
|
||||||
|
*context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewOpenPlatform new openplatform
|
||||||
|
func NewOpenPlatform(cfg *config.Config) *OpenPlatform {
|
||||||
|
if cfg.Cache == nil {
|
||||||
|
panic("cache 未设置")
|
||||||
|
}
|
||||||
|
ctx := &context.Context{
|
||||||
|
Config: cfg,
|
||||||
|
}
|
||||||
|
return &OpenPlatform{ctx}
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetOfficialAccount 公众号代处理
|
||||||
|
func (openPlatform *OpenPlatform) GetOfficialAccount(appID string) *officialaccount.OfficialAccount {
|
||||||
|
return officialaccount.NewOfficialAccount(openPlatform.Context, appID)
|
||||||
|
}
|
||||||
23
wechat.go
23
wechat.go
@@ -1,17 +1,20 @@
|
|||||||
package wechat
|
package wechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/silenceper/wechat/cache"
|
||||||
"github.com/silenceper/wechat/miniprogram"
|
"github.com/silenceper/wechat/miniprogram"
|
||||||
miniConfig "github.com/silenceper/wechat/miniprogram/config"
|
miniConfig "github.com/silenceper/wechat/miniprogram/config"
|
||||||
payConfig "github.com/silenceper/wechat/pay/config"
|
|
||||||
|
|
||||||
"github.com/silenceper/wechat/officialaccount"
|
"github.com/silenceper/wechat/officialaccount"
|
||||||
offConfig "github.com/silenceper/wechat/officialaccount/config"
|
offConfig "github.com/silenceper/wechat/officialaccount/config"
|
||||||
|
"github.com/silenceper/wechat/openplatform"
|
||||||
|
opConfig "github.com/silenceper/wechat/openplatform/config"
|
||||||
"github.com/silenceper/wechat/pay"
|
"github.com/silenceper/wechat/pay"
|
||||||
|
payConfig "github.com/silenceper/wechat/pay/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wechat struct
|
// Wechat struct
|
||||||
type Wechat struct {
|
type Wechat struct {
|
||||||
|
cache cache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config for user
|
// Config for user
|
||||||
@@ -26,13 +29,24 @@ func NewWechat() *Wechat {
|
|||||||
return &Wechat{}
|
return &Wechat{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SetCache 设置cache
|
||||||
|
func (wc *Wechat) SetCache(cahce cache.Cache) {
|
||||||
|
wc.cache = cahce
|
||||||
|
}
|
||||||
|
|
||||||
//GetOfficialAccount 获取微信公众号实例
|
//GetOfficialAccount 获取微信公众号实例
|
||||||
func (wc *Wechat) GetOfficialAccount(cfg *offConfig.Config) *officialaccount.OfficialAccount {
|
func (wc *Wechat) GetOfficialAccount(cfg *offConfig.Config) *officialaccount.OfficialAccount {
|
||||||
|
if cfg.Cache == nil {
|
||||||
|
cfg.Cache = wc.cache
|
||||||
|
}
|
||||||
return officialaccount.NewOfficialAccount(cfg)
|
return officialaccount.NewOfficialAccount(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMiniProgram 获取小程序的实例
|
// GetMiniProgram 获取小程序的实例
|
||||||
func (wc *Wechat) GetMiniProgram(cfg *miniConfig.Config) *miniprogram.MiniProgram {
|
func (wc *Wechat) GetMiniProgram(cfg *miniConfig.Config) *miniprogram.MiniProgram {
|
||||||
|
if cfg.Cache == nil {
|
||||||
|
cfg.Cache = wc.cache
|
||||||
|
}
|
||||||
return miniprogram.NewMiniProgram(cfg)
|
return miniprogram.NewMiniProgram(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,3 +54,8 @@ func (wc *Wechat) GetMiniProgram(cfg *miniConfig.Config) *miniprogram.MiniProgra
|
|||||||
func (wc *Wechat) GetPay(cfg *payConfig.Config) *pay.Pay {
|
func (wc *Wechat) GetPay(cfg *payConfig.Config) *pay.Pay {
|
||||||
return pay.NewPay(cfg)
|
return pay.NewPay(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOpenPlatform 获取微信开放平台的实例
|
||||||
|
func (wc *Wechat) GetOpenPlatform(cfg *opConfig.Config) *openplatform.OpenPlatform {
|
||||||
|
return openplatform.NewOpenPlatform(cfg)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user