原文轉載自「劉悅的技術博客」https://v3u.cn/a_id_147
新冠疫情期間,大多數(shù)公司為了避免交叉感染都或多或少的采用了遠程辦公的方式,這顯然是一個明智的選擇,基本上釘釘(dingding)作為一個遠程辦公平臺來用的話,雖然差強人意,但是奈何市面上沒有啥更好的選擇,矬子里拔將軍,也還是可以湊合用的,不過遠程辦公有個問題,就是每天需要檢查員工的考勤,居家辦公雖然靈活,但是大家究竟有沒有辦公,則是另外一回事,釘釘提供的解決方案就是考勤在線打卡功能,但是檢查出勤釘釘在移動端就有點費勁,需要在釘釘app里點擊至少5次,還不能實時刷新,pc端的釘釘oa系統(tǒng)做的更爛,還不如移動端來得方便,另外如果你在一家上千人的企業(yè)里,這家企業(yè)有大大小小幾十個部門,你又非常倒霉的擔任這家公司的人事主管,每天按部門來出員工考勤報表就不是一件容易事了,所以利用釘釘開放的接口,使用Django自己打造一套實時監(jiān)控員工考勤的web平臺是我們本次的目的。
項目背景是一家普通科技公司,大概有五個部門,每個部門100人左右

首先進入釘釘開放平臺 :open-dev.dingtalk.com
在企業(yè)內(nèi)部開發(fā)中,選擇小程序,新建一個小程序應用,這里其實也還有別的選擇,比如h5微應用,主要是小程序兼容性更好一點。
填寫應用的名稱、簡介、Logo等基本信息這些按下不表,按照要求填寫即可,也不必非得填寫真實信息,這里有個坑就是一定不要忘了配置安全域名或者ip,安全域名是當我們的檢測平臺上線的時候部署的域名,應用可以跟指定的域名進行網(wǎng)絡通信,如果不配置的話,請求釘釘接口會報403錯誤。

另外還有一個坑,也就是釘釘默認開放的接口僅限于基礎權限接口

如果需要考勤或者簽到接口的話,還得單獨點擊申請,這就有點讓人看不懂了,那么多接口,全都得靠用鼠標點擊開通,不開通就用不了,這個用戶體驗真是讓人非常酸爽,產(chǎn)品設計成這樣,釘釘?shù)膒m難辭其咎。

OK,前置準備工作就已經(jīng)就緒了,現(xiàn)在我們只要根據(jù)官方文檔來寫接口就可以了,選擇服務端api文檔:https://ding-doc.dingtalk.com/doc#/serverapi2/gh60vz
釘釘考勤打卡的接口說明是這樣的:
該接口用于返回企業(yè)內(nèi)員工的實際打卡記錄。比如,企業(yè)給一個員工設定的排班是上午9點和下午6點各打一次卡,但是員工在這期間打了多次,該接口會把所有的打卡記錄都返回。
如果只要獲取打卡結果數(shù)據(jù),不需要詳情數(shù)據(jù),可使用獲取打卡結果接口。
請求方式:POST(HTTPS)
請求地址:https://oapi.dingtalk.com/attendance/listRecord?access_token=ACCESS_TOKEN
請求包結構體:
{
"userIds": ["001","002"],
"checkDateFrom": "yyyy-MM-dd hh:mm:ss",
"checkDateTo": "yyyy-MM-dd hh:mm:ss",
"isI18n":"false"
}
這里每個接口都需要一個access_token用來鑒權,這個token是用id和秘鑰通過接口交換回來的,具體在應用詳情里可以獲取

這里我們封裝成方法
import requests
appkey = '你的key'
appsecret = '你的秘鑰'
api_url = "https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s"%(appkey,appsecret)
def get_token():
res = requests.get(api_url)
if res.status_code == 200:
str_res = res.text
token = (json.loads(str_res)).get('access_token')
return token
搞定了token,還需要獲取您的部門下所有員工的員工id,因為考勤接口參數(shù)只能接受員工id,而非部門id
#獲取用戶id
token = get_token()
#獲取用戶id
res = requests.get('https://oapi.dingtalk.com/user/simplelist?access_token=%s&department_id=235636048' % token)
str_res = res.text
res = json.loads(str_res)
ids = []
id_name = {}
for val in res['userlist']:
ids.append(val['userid'])
id_name[val['userid']] = val['name']
n = 50 #大列表中幾個數(shù)據(jù)組成一個小列表
l = ids
biglist = [l[i:i + n] for i in range(0, len(l), n)]
最后請求考勤接口即可
result_all = []
#請求打卡接口
for x in biglist:
res = requests.post('https://oapi.dingtalk.com/attendance/list?access_token=%s' % token,json ={'access_token':token,'workDateFrom':'%s 00:00:00' % mydate,'workDateTo':'%s 10:00:00' % mydate,'userIdList':str(x),'offset':0,'limit':50})
str_res = res.text
#print(str_res)
res = json.loads(str_res)
for xy in res['recordresult']:
result_all.append(xy)
slist = []
for val in result_all:
if val['timeResult'] == 'NotSigned':
print(val['timeResult'])
mydic = {}
mydic[id_name[val['userId']]] = '未打卡'
slist.append(mydic)
完整的后臺Django后臺接口
import requests
from rest_framework.response import Response
from rest_framework.views import APIView
import time
appkey = '你的key'
appsecret = '你的秘鑰'
api_url = "https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s"%(appkey,appsecret)
def get_token():
res = requests.get(api_url)
if res.status_code == 200:
str_res = res.text
token = (json.loads(str_res)).get('access_token')
return token
class GetQianHandler(APIView):
def get(self,request):
mydate = request.GET.get('date',None)
if mydate == None:
return Response({'message':'需要傳遞日期'})
dt_start = '%s 00:00:00' % mydate
dt_end = '%s 23:59:59' % mydate
ts_start = int(time.mktime(time.strptime(dt_start, "%Y-%m-%d %H:%M:%S"))) * 1000
ts_end = int(time.mktime(time.strptime(dt_end, "%Y-%m-%d %H:%M:%S"))) * 1000
token = get_token()
#獲取用戶id
res = requests.get('https://oapi.dingtalk.com/user/simplelist?access_token=%s&department_id=235636048' % token)
str_res = res.text
res = json.loads(str_res)
ids = []
id_name = {}
for val in res['userlist']:
ids.append(val['userid'])
id_name[val['userid']] = val['name']
n = 50 #大列表中幾個數(shù)據(jù)組成一個小列表
l = ids
biglist = [l[i:i + n] for i in range(0, len(l), n)]
result_all = []
print('workDateFrom %s 00:00:00' % mydate)
#請求打卡接口
for x in biglist:
res = requests.post('https://oapi.dingtalk.com/attendance/list?access_token=%s' % token,json ={'access_token':token,'workDateFrom':'%s 00:00:00' % mydate,'workDateTo':'%s 10:00:00' % mydate,'userIdList':str(x),'offset':0,'limit':50})
str_res = res.text
#print(str_res)
res = json.loads(str_res)
for xy in res['recordresult']:
result_all.append(xy)
slist = []
for val in result_all:
if val['timeResult'] == 'NotSigned':
print(val['timeResult'])
mydic = {}
mydic[id_name[val['userId']]] = '未打卡'
slist.append(mydic)
return Response(slist)
這樣,就可以愉快的通過線上平臺來實時監(jiān)測部門員工考勤了,效果是這樣的:

原文轉載自「劉悅的技術博客」 https://v3u.cn/a_id_147