Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 32 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7e24cb9
完善企业微信API
Oct 28, 2021
829356e
fork github.com/hb1707/wechat/v2
Oct 28, 2021
af5115f
fork github.com/silenceper/wechat/v2
Oct 28, 2021
73adb7d
删除冗余代码
Oct 28, 2021
7ae8e08
企业微信内部开发API:消息推送与接收,以及回调处理
Nov 24, 2021
5704abb
企业微信内部开发API:新增获取客户列表,客户详情,并群发消息
Nov 29, 2021
1f80c26
企业微信内部开发API:新增jssdk支持和Oauth用户身份验证
Jan 26, 2022
88f07bc
企业微信内部开发API:新增jssdk支持
Jan 26, 2022
6313e3d
企业微信内部开发API:完善企业内部消息推送
Mar 2, 2022
96e7945
企业微信内部开发API:消息推送》接收消息与事件》事件格式》模板卡片事件推送
Mar 17, 2022
586a3b0
企业微信内部开发API:消息推送》接收消息与事件》事件格式》模板卡片事件推送
Mar 24, 2022
502a781
企业微信内部开发API:客户联系》编辑客户企业标签
Jan 9, 2023
da20182
企业微信内部开发API:忽略掉一些可能不需要的字段
Jan 9, 2023
cec8177
企业微信内部开发API:增加README.md
Jan 9, 2023
b440267
Merge branch 'release-2.0' of github.com:hb1707/wechat into release-2.0
Jan 9, 2023
1cd6133
与origin代码同步
Jan 9, 2023
589de19
与origin代码同步
Jan 9, 2023
e351d0b
与origin代码同步
Jan 9, 2023
158fbca
新增模板卡片消息
Feb 15, 2023
1c23607
Merge remote-tracking branch 'origin/release-2.0' into release-2.0
Apr 12, 2024
06c225c
Merge remote-tracking branch '官方/v2' into release-2.0
May 13, 2024
4a4339f
补丁
Sep 27, 2024
61bcd6b
feat:新增JS-SDK使用权限签名
Sep 27, 2024
bcdb2fa
feat:新增企业微信消息推送接收和发送
Sep 27, 2024
a7347f9
Merge pull request #1 from hb1707/v2-hb
hb1707 Nov 15, 2024
8a044dc
自用分支
Nov 15, 2024
06e92dd
Merge remote-tracking branch 'origin/release-2.0-hb' into release-2.0-hb
Nov 15, 2024
0f3c9cd
还原
Nov 15, 2024
961d560
Merge pull request #2 from hb1707/release-2.0-hb
hb1707 Nov 15, 2024
d28c61a
Merge branch 'silenceper:v2' into v2
hb1707 Nov 15, 2024
d08b189
Merge pull request #3 from hb1707/v2
hb1707 Nov 15, 2024
0e7907e
Merge pull request #4 from hb1707/v2-hb
hb1707 Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions credential/work_js_ticket.go
Original file line number Diff line number Diff line change
@@ -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)
houseme marked this conversation as resolved.
Show resolved Hide resolved
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 changes: 93 additions & 0 deletions work/js/js.go
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议 Config 对象在使用时在创建,如在88行之前创建。GetConfig 方法也是同样建议

var accessToken string
accessToken, err = js.GetAccessToken()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

73,74合并处理,下面的78,79也是一样,以及83-86 是不是可以合并定义呢?

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
}
Loading
Loading