Просмотр исходного кода

Merge branch 'f-openplatform' into release-2.0

silenceper 6 лет назад
Родитель
Сommit
5557975960

+ 3 - 0
go.mod

@@ -4,6 +4,9 @@ go 1.14
 
 
 require (
 require (
 	github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
 	github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/gomodule/redigo v1.8.1
 	github.com/gomodule/redigo v1.8.1
+	github.com/kr/pretty v0.1.0 // indirect
 	golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
 	golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
+	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
 )
 )

+ 7 - 0
go.sum

@@ -2,8 +2,13 @@ github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pO
 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
 github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
 github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
 github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -18,5 +23,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 4 - 1
minigame/README.md

@@ -2,4 +2,7 @@
 
 
 [官方文档](https://developers.weixin.qq.com/minigame/dev/api-backend/)
 [官方文档](https://developers.weixin.qq.com/minigame/dev/api-backend/)
 
 
-## 快速入门
+## 快速入门
+```go
+
+```

+ 15 - 0
miniprogram/README.md

@@ -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()
+```

+ 2 - 0
officialaccount/message/message.go

@@ -72,6 +72,8 @@ const (
 )
 )
 
 
 const (
 const (
+	//微信开放平台需要用到
+
 	// InfoTypeVerifyTicket 返回ticket
 	// InfoTypeVerifyTicket 返回ticket
 	InfoTypeVerifyTicket InfoType = "component_verify_ticket"
 	InfoTypeVerifyTicket InfoType = "component_verify_ticket"
 	// InfoTypeAuthorized 授权
 	// InfoTypeAuthorized 授权

+ 3 - 3
officialaccount/officialaccount.go

@@ -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 {
-		panic("cache未设置")
-	}
+	//if cfg.Cache == nil {
+	//	panic("cache未设置")
+	//}
 	ctx := &context.Context{
 	ctx := &context.Context{
 		Config: cfg,
 		Config: cfg,
 	}
 	}

+ 51 - 1
openplatform/README.md

@@ -1,5 +1,55 @@
 # 微信开放平台
 # 微信开放平台
 
 
+状态:开发中
+
 [官方文档](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 - 0
openplatform/config/config.go

@@ -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
+}

+ 224 - 0
openplatform/context/accessToken.go

@@ -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
+}

+ 10 - 0
openplatform/context/context.go

@@ -0,0 +1,10 @@
+package context
+
+import (
+	"github.com/silenceper/wechat/v2/openplatform/config"
+)
+
+// Context struct
+type Context struct {
+	*config.Config
+}

+ 52 - 0
openplatform/miniprogram/basic/basic.go

@@ -0,0 +1,52 @@
+package basic
+
+import (
+	"fmt"
+
+	openContext "github.com/silenceper/wechat/v2/openplatform/context"
+	"github.com/silenceper/wechat/v2/util"
+)
+
+const (
+	getAccountBasicInfoURL = "https://api.weixin.qq.com/cgi-bin/account/getaccountbasicinfo"
+)
+
+//Basic 基础信息设置
+type Basic struct {
+	*openContext.Context
+	appID string
+}
+
+//NewBasic new
+func NewBasic(opContext *openContext.Context, appID string) *Basic {
+	return &Basic{Context: opContext, appID: appID}
+}
+
+//AccountBasicInfo 基础信息
+type AccountBasicInfo struct {
+	util.CommonError
+}
+
+//GetAccountBasicInfo 获取小程序基础信息
+//reference:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/Mini_Program_Information_Settings.html
+func (basic *Basic) GetAccountBasicInfo() (*AccountBasicInfo, error) {
+	ak, err := basic.GetAuthrAccessToken(basic.AppID)
+	if err != nil {
+		return nil, err
+	}
+	url := fmt.Sprintf("%s?access_token=%s", getAccountBasicInfoURL, ak)
+	data, err := util.HTTPGet(url)
+	if err != nil {
+		return nil, err
+	}
+	result := &AccountBasicInfo{}
+	if err := util.DecodeWithError(data, result, "account/getaccountbasicinfo"); err != nil {
+		return nil, err
+	}
+	return result, nil
+}
+
+//modify_domain设置服务器域名
+//TODO
+//func (basic *Basic) modifyDomain() {
+//}

+ 69 - 0
openplatform/miniprogram/component/component.go

@@ -0,0 +1,69 @@
+package component
+
+import (
+	"fmt"
+
+	openContext "github.com/silenceper/wechat/v2/openplatform/context"
+	"github.com/silenceper/wechat/v2/util"
+)
+
+const (
+	fastregisterweappURL = "https://api.weixin.qq.com/cgi-bin/component/fastregisterweapp"
+)
+
+//Component 快速创建小程序
+type Component struct {
+	*openContext.Context
+}
+
+//NewComponent new
+func NewComponent(opContext *openContext.Context) *Component {
+	return &Component{opContext}
+}
+
+//RegisterMiniProgramParam 快速注册小程序参数
+type RegisterMiniProgramParam struct {
+	Name               string `json:"name"`                 //企业名
+	Code               string `json:"code"`                 //企业代码
+	CodeType           string `json:"code_type"`            //企业代码类型 1:统一社会信用代码(18 位) 2:组织机构代码(9 位 xxxxxxxx-x) 3:营业执照注册号(15 位)
+	LegalPersonaWechat string `json:"legal_persona_wechat"` //法人微信号
+	LegalPersonaName   string `json:"legal_persona_name"`   //法人姓名(绑定银行卡)
+	ComponentPhone     string `json:"component_phone"`      //第三方联系电话(方便法人与第三方联系)
+}
+
+//RegisterMiniProgram 快速创建小程
+//reference: https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/Fast_Registration_Interface_document.html
+func (component *Component) RegisterMiniProgram(param *RegisterMiniProgramParam) error {
+	componentAK, err := component.GetComponentAccessToken()
+	if err != nil {
+		return nil
+	}
+	url := fmt.Sprintf(fastregisterweappURL+"?action=create&component_access_token=%s", componentAK)
+	data, err := util.PostJSON(url, param)
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(data, "component/fastregisterweapp?action=create")
+}
+
+//GetRegistrationStatusParam 查询任务创建状态
+type GetRegistrationStatusParam struct {
+	Name               string `json:"name"`                 //企业名
+	LegalPersonaWechat string `json:"legal_persona_wechat"` //法人微信号
+	LegalPersonaName   string `json:"legal_persona_name"`   //法人姓名(绑定银行卡)
+
+}
+
+//GetRegistrationStatus 查询创建任务状态.
+func (component *Component) GetRegistrationStatus(param *GetRegistrationStatusParam) error {
+	componentAK, err := component.GetComponentAccessToken()
+	if err != nil {
+		return nil
+	}
+	url := fmt.Sprintf(fastregisterweappURL+"?action=search&component_access_token=%s", componentAK)
+	data, err := util.PostJSON(url, param)
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(data, "component/fastregisterweapp?action=search")
+}

+ 32 - 0
openplatform/miniprogram/miniprogram.go

@@ -0,0 +1,32 @@
+package miniprogram
+
+import (
+	openContext "github.com/silenceper/wechat/v2/openplatform/context"
+	"github.com/silenceper/wechat/v2/openplatform/miniprogram/basic"
+	"github.com/silenceper/wechat/v2/openplatform/miniprogram/component"
+)
+
+//MiniProgram 代小程序实现业务
+type MiniProgram struct {
+	AppID       string
+	openContext *openContext.Context
+}
+
+//NewMiniProgram 实例化
+func NewMiniProgram(opCtx *openContext.Context, appID string) *MiniProgram {
+	return &MiniProgram{
+		openContext: opCtx,
+		AppID:       appID,
+	}
+}
+
+//GetComponent get component
+//快速注册小程序相关
+func (miniProgram *MiniProgram) GetComponent() *component.Component {
+	return component.NewComponent(miniProgram.openContext)
+}
+
+//GetBasic 基础信息设置
+func (miniProgram *MiniProgram) GetBasic() *basic.Basic {
+	return basic.NewBasic(miniProgram.openContext, miniProgram.AppID)
+}

+ 33 - 0
openplatform/officialaccount/officialaccount.go

@@ -0,0 +1,33 @@
+package officialaccount
+
+import (
+	"github.com/silenceper/wechat/v2/officialaccount"
+	offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
+	offContext "github.com/silenceper/wechat/v2/officialaccount/context"
+	opContext "github.com/silenceper/wechat/v2/openplatform/context"
+)
+
+//OfficialAccount 代公众号实现业务
+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}
+}

+ 34 - 0
openplatform/openplatform.go

@@ -0,0 +1,34 @@
+package openplatform
+
+import (
+	"github.com/silenceper/wechat/v2/openplatform/config"
+	"github.com/silenceper/wechat/v2/openplatform/context"
+	"github.com/silenceper/wechat/v2/openplatform/miniprogram"
+	"github.com/silenceper/wechat/v2/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)
+}
+
+//GetMiniProgram 小程序代理
+func (openPlatform *OpenPlatform) GetMiniProgram(opCtx *context.Context, appID string) *miniprogram.MiniProgram {
+	return miniprogram.NewMiniProgram(opCtx, appID)
+}

+ 21 - 9
wechat.go

@@ -1,24 +1,20 @@
 package wechat
 package wechat
 
 
 import (
 import (
+	"github.com/silenceper/wechat/v2/cache"
 	"github.com/silenceper/wechat/v2/miniprogram"
 	"github.com/silenceper/wechat/v2/miniprogram"
 	miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
 	miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
-	payConfig "github.com/silenceper/wechat/v2/pay/config"
-
 	"github.com/silenceper/wechat/v2/officialaccount"
 	"github.com/silenceper/wechat/v2/officialaccount"
 	offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
 	offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
+	"github.com/silenceper/wechat/v2/openplatform"
+	openConfig "github.com/silenceper/wechat/v2/openplatform/config"
 	"github.com/silenceper/wechat/v2/pay"
 	"github.com/silenceper/wechat/v2/pay"
+	payConfig "github.com/silenceper/wechat/v2/pay/config"
 )
 )
 
 
 // Wechat struct
 // Wechat struct
 type Wechat struct {
 type Wechat struct {
-}
-
-// Config for user
-type Config struct {
-	PayMchID     string //支付 - 商户 ID
-	PayNotifyURL string //支付 - 接受微信支付结果通知的接口地址
-	PayKey       string //支付 - 商户后台设置的支付 key
+	cache cache.Cache
 }
 }
 
 
 // NewWechat init
 // NewWechat init
@@ -26,13 +22,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 +47,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 *openConfig.Config) *openplatform.OpenPlatform {
+	return openplatform.NewOpenPlatform(cfg)
+}