-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat:企业微信客户端API JS-SDK wx.config 和 wx.agentConfig 方法权限签名 (#817)
* feat: enhance WorkAccessToken to include AgentID for improved token management - Added AgentID field to WorkAccessToken struct. - Updated NewWorkAccessToken function to accept AgentID as a parameter. - Modified access token cache key to incorporate AgentID, ensuring unique cache entries per agent. This change improves the handling of access tokens in a multi-agent environment. * refactor: enhance WorkAccessToken to improve cache key handling - Updated the AgentID field in WorkAccessToken struct to clarify its optional nature for distinguishing applications. - Modified the access token cache key construction to support both new and legacy formats based on the presence of AgentID. - Added comments for better understanding of the cache key logic and its compatibility with historical versions. This change improves the flexibility and clarity of access token management in multi-agent scenarios. * feat(work): add JsSdk method for JavaScript SDK integration - Introduced a new JsSdk method in the Work struct to facilitate the creation of a Js instance. - This addition enhances the functionality of the Work module by enabling JavaScript SDK support. This change improves the integration capabilities for developers working with the WeChat Work API. * fix gofmt
- Loading branch information
Showing
4 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package credential | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/silenceper/wechat/v2/cache" | ||
"github.com/silenceper/wechat/v2/util" | ||
) | ||
|
||
// TicketType ticket类型 | ||
type TicketType int | ||
|
||
const ( | ||
// TicketTypeCorpJs 企业jsapi ticket | ||
TicketTypeCorpJs TicketType = iota | ||
// TicketTypeAgentJs 应用jsapi ticket | ||
TicketTypeAgentJs | ||
) | ||
|
||
// 企业微信相关的 ticket URL | ||
const ( | ||
// 企业微信 jsapi ticket | ||
getWorkJsTicketURL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=%s" | ||
// 企业微信应用 jsapi ticket | ||
getWorkAgentJsTicketURL = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=%s&type=agent_config" | ||
) | ||
|
||
// WorkJsTicket 企业微信js ticket获取 | ||
type WorkJsTicket struct { | ||
corpID string | ||
agentID string | ||
cacheKeyPrefix string | ||
cache cache.Cache | ||
jsAPITicketLock *sync.Mutex | ||
} | ||
|
||
// NewWorkJsTicket new WorkJsTicket | ||
func NewWorkJsTicket(corpID, agentID, cacheKeyPrefix string, cache cache.Cache) *WorkJsTicket { | ||
return &WorkJsTicket{ | ||
corpID: corpID, | ||
agentID: agentID, | ||
cache: cache, | ||
cacheKeyPrefix: cacheKeyPrefix, | ||
jsAPITicketLock: new(sync.Mutex), | ||
} | ||
} | ||
|
||
// GetTicket 根据类型获取相应的jsapi_ticket | ||
func (js *WorkJsTicket) GetTicket(accessToken string, ticketType TicketType) (ticketStr string, err error) { | ||
var cacheKey string | ||
switch ticketType { | ||
case TicketTypeCorpJs: | ||
cacheKey = fmt.Sprintf("%s_corp_jsapi_ticket_%s", js.cacheKeyPrefix, js.corpID) | ||
case TicketTypeAgentJs: | ||
if js.agentID == "" { | ||
err = fmt.Errorf("agentID is empty") | ||
return | ||
} | ||
cacheKey = fmt.Sprintf("%s_agent_jsapi_ticket_%s_%s", js.cacheKeyPrefix, js.corpID, js.agentID) | ||
default: | ||
err = fmt.Errorf("unsupported ticket type: %v", ticketType) | ||
return | ||
} | ||
|
||
if val := js.cache.Get(cacheKey); val != nil { | ||
return val.(string), nil | ||
} | ||
|
||
js.jsAPITicketLock.Lock() | ||
defer js.jsAPITicketLock.Unlock() | ||
|
||
// 双检,防止重复从微信服务器获取 | ||
if val := js.cache.Get(cacheKey); val != nil { | ||
return val.(string), nil | ||
} | ||
|
||
var ticket ResTicket | ||
ticket, err = js.getTicketFromServer(accessToken, ticketType) | ||
if err != nil { | ||
return | ||
} | ||
expires := ticket.ExpiresIn - 1500 | ||
err = js.cache.Set(cacheKey, ticket.Ticket, time.Duration(expires)*time.Second) | ||
ticketStr = ticket.Ticket | ||
return | ||
} | ||
|
||
// getTicketFromServer 从服务器中获取ticket | ||
func (js *WorkJsTicket) getTicketFromServer(accessToken string, ticketType TicketType) (ticket ResTicket, err error) { | ||
var url string | ||
switch ticketType { | ||
case TicketTypeCorpJs: | ||
url = fmt.Sprintf(getWorkJsTicketURL, accessToken) | ||
case TicketTypeAgentJs: | ||
url = fmt.Sprintf(getWorkAgentJsTicketURL, accessToken) | ||
default: | ||
err = fmt.Errorf("unsupported ticket type: %v", ticketType) | ||
return | ||
} | ||
|
||
var response []byte | ||
response, err = util.HTTPGet(url) | ||
if err != nil { | ||
return | ||
} | ||
err = json.Unmarshal(response, &ticket) | ||
if err != nil { | ||
return | ||
} | ||
if ticket.ErrCode != 0 { | ||
err = fmt.Errorf("getTicket Error : errcode=%d , errmsg=%s", ticket.ErrCode, ticket.ErrMsg) | ||
return | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package jsapi | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/silenceper/wechat/v2/credential" | ||
"github.com/silenceper/wechat/v2/util" | ||
"github.com/silenceper/wechat/v2/work/context" | ||
) | ||
|
||
// Js struct | ||
type Js struct { | ||
*context.Context | ||
jsTicket *credential.WorkJsTicket | ||
} | ||
|
||
// NewJs init | ||
func NewJs(context *context.Context) *Js { | ||
js := new(Js) | ||
js.Context = context | ||
js.jsTicket = credential.NewWorkJsTicket( | ||
context.Config.CorpID, | ||
context.Config.AgentID, | ||
credential.CacheKeyWorkPrefix, | ||
context.Cache, | ||
) | ||
return js | ||
} | ||
|
||
// Config 返回给用户使用的配置 | ||
type Config struct { | ||
Timestamp int64 `json:"timestamp"` | ||
NonceStr string `json:"nonce_str"` | ||
Signature string `json:"signature"` | ||
} | ||
|
||
// GetConfig 获取企业微信JS配置 https://developer.work.weixin.qq.com/document/path/90514 | ||
func (js *Js) GetConfig(uri string) (config *Config, err error) { | ||
config = new(Config) | ||
var accessToken string | ||
accessToken, err = js.GetAccessToken() | ||
if err != nil { | ||
return | ||
} | ||
var ticketStr string | ||
ticketStr, err = js.jsTicket.GetTicket(accessToken, credential.TicketTypeCorpJs) | ||
if err != nil { | ||
return | ||
} | ||
config.NonceStr = util.RandomStr(16) | ||
config.Timestamp = util.GetCurrTS() | ||
config.Signature = util.Signature(ticketStr, config.NonceStr, strconv.FormatInt(config.Timestamp, 10), uri) | ||
return | ||
} | ||
|
||
// GetAgentConfig 获取企业微信应用JS配置 https://developer.work.weixin.qq.com/document/path/94313 | ||
func (js *Js) GetAgentConfig(uri string) (config *Config, err error) { | ||
config = new(Config) | ||
var accessToken string | ||
accessToken, err = js.GetAccessToken() | ||
if err != nil { | ||
return | ||
} | ||
var ticketStr string | ||
ticketStr, err = js.jsTicket.GetTicket(accessToken, credential.TicketTypeAgentJs) | ||
if err != nil { | ||
return | ||
} | ||
config.NonceStr = util.RandomStr(16) | ||
config.Timestamp = util.GetCurrTS() | ||
config.Signature = util.Signature(ticketStr, config.NonceStr, strconv.FormatInt(config.Timestamp, 10), uri) | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters