init
This commit is contained in:
commit
829259f72f
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.sum
|
||||||
|
*.yaml
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
@ -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×tamp=%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
|
||||||
|
}
|
||||||
|
|
@ -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"`
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue