This commit is contained in:
wyh 2021-11-17 11:17:31 +08:00
commit 829259f72f
6 changed files with 315 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.sum
*.yaml

15
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "E://dingd"
}
]
}

View File

@ -0,0 +1,27 @@
package dingtalk
import (
"github.com/hugozhu/godingtalk"
"github.com/spf13/viper"
)
var _client *godingtalk.DingTalkClient
var _appkey = viper.GetString("app.AppKey")
var _appsecret = viper.GetString("app.AppSecret")
var _agentid = viper.GetString("app.AgentId")
//getDingtalkClient 获取钉钉client
func getDingtalkClient(appkey *string, appsecret *string, agentid *string) *godingtalk.DingTalkClient {
if _client != nil {
_client.RefreshAccessToken()
return _client
}
_client = godingtalk.NewDingTalkClient(*appkey, *appsecret)
_client.AgentID = *agentid
_client.RefreshAccessToken()
return _client
}
func GET() *godingtalk.DingTalkClient {
return getDingtalkClient(&_appkey, &_appsecret, &_agentid)
}

26
go.mod Normal file
View File

@ -0,0 +1,26 @@
module myschools.me/wyh/dingd.git
go 1.17
require (
github.com/hugozhu/godingtalk v1.0.6
github.com/sirupsen/logrus v1.8.1
github.com/spf13/viper v1.9.0
)
require (
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
golang.org/x/text v0.3.6 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

176
main.go Normal file
View File

@ -0,0 +1,176 @@
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"myschools.me/wyh/dingd.git/model"
)
const (
AuthCode = "bdbc74ebecaf30259895b145d3c48d35"
Appkey = "dinguipztmzpv8sog933"
AppSecret = "kUYbKHxNixdMhTmW6IrdTE-yVnWfQLs1C7RQIAsrlwz8BYlVmceFs-3JRBmU32rQ"
)
func main() {
cf := flag.String("config", "config.yaml", "file of config")
flag.Parse()
viper.SetConfigFile(*cf)
if err := viper.ReadInConfig(); err != nil {
logrus.WithFields(logrus.Fields{
"func": "main",
}).Errorf("%s", err.Error())
return
}
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10) // 毫秒时间戳
signature := EncodeSHA256(timestamp, AppSecret) // 加密签名 加密算法见我另一个函数
url := fmt.Sprintf("https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey=%s&timestamp=%s&signature=%s",
Appkey, timestamp, signature)
p := struct {
Tmp_auth_code string `json:"tmp_auth_code"`
}{AuthCode} // post数据
p1, _ := json.Marshal(p)
p2 := string(p1)
p3 := strings.NewReader(p2) //构建post数据
resp, err := http.Post(url, "application/json;charset=UTF-8", p3)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
i := make(map[string]interface{})
_ = json.Unmarshal(body, &i)
fmt.Println(i)
errcode := i["errcode"].(float64)
if errcode != 0 {
log.Fatal("errcode ==0")
}
unionid := i["user_info"].(map[string]interface{})["unionid"].(string)
accesstoken, err := GetAccesstoken()
if err != nil {
log.Fatal(err)
}
userid, err := GetUseridByUnionid(accesstoken, unionid)
if err != nil {
log.Fatal(err)
}
userinfo, err := GETUserInfo(accesstoken, userid)
if err != nil {
log.Fatal(err)
}
fmt.Println(userinfo)
}
func EncodeSHA256(message, secret string) string {
// 钉钉签名算法实现
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(message))
sum := h.Sum(nil) // 二进制流
message1 := base64.StdEncoding.EncodeToString(sum)
uv := url.Values{}
uv.Add("0", message1)
message2 := uv.Encode()[2:]
return message2
}
func GetAccesstoken() (accesstoken string, err error) {
var resp *http.Response
//var AppKey, AppSecret string
//获取access_token
url := fmt.Sprintf("https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s", Appkey, AppSecret)
resp, err = http.Get(url)
if err != nil {
return "", err
}
//fmt.Println(resp)
//fmt.Println(err)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var i map[string]interface{}
_ = json.Unmarshal(body, &i)
//fmt.Println(1, string(body), i["errmsg"])
if i["errcode"].(float64) == 0 {
return i["access_token"].(string), nil
}
return "", errors.New("accesstoken获取错误" + i["errmsg"].(string))
}
func GetUseridByUnionid(accesstoken, unionid string) (userid string, err error) {
//根据unionid获取userid
var resp *http.Response
url := fmt.Sprintf("https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token=%s", accesstoken)
p := struct {
Unionid string `json:"unionid"`
}{unionid} // post数据
p1, _ := json.Marshal(p)
p2 := string(p1)
p3 := strings.NewReader(p2) //构建post数据
resp, err = http.Post(url, "application/json;charset=UTF-8", p3)
if err != nil {
return "", nil
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", nil
}
//fmt.Println(1, string(body), err)
var i map[string]interface{}
_ = json.Unmarshal(body, &i)
errcode := i["errcode"].(float64)
if errcode != 0 {
return "", fmt.Errorf("userid获取错误: %f, %s", errcode, i["errmsg"].(string))
}
return i["result"].(map[string]interface{})["userid"].(string), nil
}
func GETUserInfo(accesstoken, userid string) (*model.DingtalkUserInfoResponse, error) {
var resp *http.Response
url := fmt.Sprintf("https://oapi.dingtalk.com/topapi/v2/user/get?access_token=%s", accesstoken)
p := struct {
UserID string `json:"userid"`
Language string `json:"language"`
}{
UserID: userid,
Language: "zh_CN",
}
p1, _ := json.Marshal(p)
p2 := string(p1)
p3 := strings.NewReader(p2) //构建post数据
resp, err := http.Post(url, "application/json;charset=UTF-8", p3)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
userinfo := &model.DingtalkUserInfoResponse{}
_ = json.Unmarshal(body, userinfo)
errcode := userinfo.ErrCode
if errcode != 0 {
log.Fatal("errcode!=0")
}
return userinfo, nil
}

69
model/dingtalk-model.go Normal file
View File

@ -0,0 +1,69 @@
package model
type DingtalkUserInfoResponse struct {
RequestID string `json:"request_id"`
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
Result DingtalkUserGetResponse
}
type DingtalkUserGetResponse struct {
UserID string `json:"userid"`
Unionid string `json:"unionid"`
Name string `json:"name"`
Avatar string `json:"avatar"`
StateCode string `json:"state_code"`
ManagerUserID string `json:"manager_userid"`
Mobile string `json:"mobile"`
HideMobile bool `json:"hide_mobile"`
Telephone string `json:"telephone"`
JobNumber string `json:"job_number"`
Title string `json:"title"`
Email string `json:"email"`
WorkPlace string `json:"work_place"`
Remark string `json:"remark"`
LoginID string `json:"login_id"`
ExclusiveAccountType string `json:"exclusive_account_type"`
ExclusiveAccount bool `json:"exclusive_account"`
DeptIDList []int `json:"dept_id_list"`
DeptOrderList []DingtalkDeptOrder
Extension string `json:"extension"`
HiredDate int `json:"hired_date"`
Active bool `json:"active"`
RealAuthed bool `json:"real_authed"`
OrgEmail string `json:"org_email"`
OrgEmailType string `json:"org_email_type"`
Senior bool `json:"senior"`
Admin bool `json:"admin"`
Boss bool `json:"boss"`
LeaderInDept []DingtalkDeptLeader
RoleList []DingtalkUserRole
UnionEmpExt UnionEmpExt
}
type DingtalkDeptOrder struct {
DeptID int `json:"dept_id"`
Order int `json:"order"`
}
type DingtalkDeptLeader struct {
DeptID int `json:"dept_id"`
Leader bool `json:"leader"`
}
type DingtalkUserRole struct {
ID int
Name string
GroupName string
}
type UnionEmpExt struct {
UserID string `json:"userid"`
UnionEmpMapList []DingtalkUnionEmpMapVo
CorpId string `json:"corp_id"`
}
type DingtalkUnionEmpMapVo struct {
UserID string `json:"userid"`
CorpID string `json:"corpid"`
}