1
0
mirror of https://github.com/silenceper/wechat.git synced 2026-02-06 13:42:26 +08:00

feat:新增JS-SDK使用权限签名

This commit is contained in:
wind
2024-09-27 16:05:25 +08:00
parent 2e0708845b
commit 61bcd6b0e4
3 changed files with 184 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
package credential
import (
"encoding/json"
"fmt"
"sync"
"time"
"github.com/silenceper/wechat/v2/cache"
"github.com/silenceper/wechat/v2/util"
)
// 获取ticket的url https://developer.work.weixin.qq.com/document/path/90506
const getQyWxTicketURL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=%s"
const getQyAppTicketURL = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=%s&type=agent_config"
// WorkJsTicket 默认获取js ticket方法
type WorkJsTicket struct {
appID string
agentID string
cacheKeyPrefix string
cache cache.Cache
//jsAPITicket 读写锁 同一个AppID一个
jsAPITicketLock *sync.Mutex
}
// NewWorkJsTicket new
func NewWorkJsTicket(appID string, agentID string, cacheKeyPrefix string, cache cache.Cache) JsTicketHandle {
return &WorkJsTicket{
appID: appID,
agentID: agentID,
cache: cache,
cacheKeyPrefix: cacheKeyPrefix,
jsAPITicketLock: new(sync.Mutex),
}
}
// GetTicket 获取企业微信jsapi_ticket
func (js *WorkJsTicket) GetTicket(accessToken string) (ticketStr string, err error) {
//先从cache中取
jsAPITicketCacheKey := fmt.Sprintf("%s_jsapi_ticket_%s", js.cacheKeyPrefix, js.appID)
if val := js.cache.Get(jsAPITicketCacheKey); val != nil {
return val.(string), nil
}
js.jsAPITicketLock.Lock()
defer js.jsAPITicketLock.Unlock()
// 双检,防止重复从微信服务器获取
if val := js.cache.Get(jsAPITicketCacheKey); val != nil {
return val.(string), nil
}
var ticket ResTicket
ticket, err = GetQyWxTicketFromServer(accessToken, js.agentID != "")
if err != nil {
return
}
expires := ticket.ExpiresIn - 1500
err = js.cache.Set(jsAPITicketCacheKey, ticket.Ticket, time.Duration(expires)*time.Second)
ticketStr = ticket.Ticket
return
}
// GetQyWxTicketFromServer 从企业微信服务器中获取ticket
func GetQyWxTicketFromServer(accessToken string, isApp bool) (ticket ResTicket, err error) {
var response []byte
url := fmt.Sprintf(getQyWxTicketURL, accessToken)
if isApp {
url = fmt.Sprintf(getQyAppTicketURL, accessToken)
}
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
}

93
work/js/js.go Normal file
View File

@@ -0,0 +1,93 @@
package js
import (
"fmt"
"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
credential.JsTicketHandle
}
// Config 返回给用户jssdk配置信息
type Config struct {
CorpID string `json:"corp_id"`
Agentid string `json:"agentid"`
Timestamp int64 `json:"timestamp"`
NonceStr string `json:"nonce_str"`
Signature string `json:"signature"`
}
// NewJs init
func NewJs(context *context.Context) *Js {
js := new(Js)
js.Context = context
jsTicketHandle := credential.NewWorkJsTicket(context.CorpID, context.AgentID, credential.CacheKeyWorkPrefix, context.Cache)
js.SetJsTicketHandle(jsTicketHandle)
return js
}
// SetJsTicketHandle 自定义js ticket取值方式
func (js *Js) SetJsTicketHandle(ticketHandle credential.JsTicketHandle) {
js.JsTicketHandle = ticketHandle
}
// GetConfig 获取jssdk需要的配置参数
// uri 为当前网页地址
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.GetTicket(accessToken)
if err != nil {
return
}
nonceStr := util.RandomStr(16)
timestamp := util.GetCurrTS()
str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", ticketStr, nonceStr, timestamp, uri)
sigStr := util.Signature(str)
config.CorpID = js.CorpID
config.Agentid = js.AgentID
config.NonceStr = nonceStr
config.Timestamp = timestamp
config.Signature = sigStr
return
}
// GetAgentConfig 获取jssdk需要的配置参数
// uri 为当前网页地址
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.GetTicket(accessToken)
if err != nil {
return
}
nonceStr := util.RandomStr(16)
timestamp := util.GetCurrTS()
str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", ticketStr, nonceStr, timestamp, uri)
sigStr := util.Signature(str)
config.CorpID = js.CorpID
config.NonceStr = nonceStr
config.Timestamp = timestamp
config.Signature = sigStr
return
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/silenceper/wechat/v2/work/context"
"github.com/silenceper/wechat/v2/work/externalcontact"
"github.com/silenceper/wechat/v2/work/invoice"
"github.com/silenceper/wechat/v2/work/js"
"github.com/silenceper/wechat/v2/work/kf"
"github.com/silenceper/wechat/v2/work/material"
"github.com/silenceper/wechat/v2/work/message"
@@ -91,3 +92,8 @@ func (wk *Work) GetInvoice() *invoice.Client {
func (wk *Work) GetCheckin() *checkin.Client {
return checkin.NewClient(wk.ctx)
}
// GetJs js-sdk配置
func (wk *Work) GetJs() *js.Js {
return js.NewJs(wk.ctx)
}