钉钉python实现审批(通过软件和钉钉审批流的结合)

news/2024/7/3 20:35:18

为了实现工单系统,又不想自己去结合钉钉的组织架构实现一套审批流,所以采用钉钉的审批结合自己的系统去实现工单。

由钉钉实现审批流,软件实现查询,记录工单等。

一、具体流程

 

 

二、具体的实现方式

获取token的函数

def getToken(self):
    '''
    获取钉钉的token
    :return: 钉钉token
    '''
    url = 'https://oapi.dingtalk.com/gettoken?appkey=XXXXXXXXXXXXXXXXX&appsecret=XXXXXXXXXXXXXXXXXXXXXXXXXX'
    req = requests.get(url)
    req = json.loads(req.text)
    return req['access_token']

1. 注册回调函数

def createCallbackDd(self, request):
    '''
    注册钉钉回调函数
    :return:
    '''
    url = 'https://oapi.dingtalk.com/call_back/register_call_back?access_token=' + self.getToken()
    data = {
        "call_back_tag": ["bpms_task_change", "bpms_instance_change"],  #这两个回调种类是审批的
        "token": TOKEN,  #自定义的字符串
        "aes_key": AES_KEY, #自定义的43位字符串,密钥
        "url": URL  #回调地址
    }
    requests.post(url, data=json.dumps(data))
    return HttpResponse('OK')

 

2. 创建钉钉审批

注意:不使用python的dingtalk-sdk,这个版本必须要传approvers(审批人)这个参数,导致不能使用后台配置的工单流,直接使用接口或者找到最新版的sdk

def create(self, request):
    '''
    创建钉钉审批
    :param request:
    :return:
    '''
    url = 'https://oapi.dingtalk.com/topapi/processinstance/create?access_token=' + self.getToken()
    form_component_value_vo = [{'name': '姓名', 'value': '测试2'}, {'name': '部门', 'value': '测试2'}, {'name': '["开始时间","结束时间"]', 'value': '["2019-06-10 10:32","2019-06-10 10:36"]'}, {'name': '加班事由', 'value': '测试2'}] #钉钉后台配置的需要填写的字段(这一段由点到传过来实现,这里只是测试使用)
    data = {
        'agent_id': None,
        'process_code': 'XXXXXXXXXXXXXXXX',  #工单id
        'originator_user_id': 'manager2606', #创建人的钉钉userid
        'dept_id': -1,  #创建人的钉钉部门id
        'form_component_values': str(form_component_value_vo), #钉钉后台配置的需要填写的字段
    }
    response = requests.post(url, data=data)
    print(response.text)
    return HttpResponse('成功')

 

3. 回调函数

在您注册事件回调接口的时候,钉钉服务器会向您“注册回调接口”时候上传的url(接收回调的url)推送一条消息,用来测试url的合法性。收到消息后,需要返回经过加密后的字符串“success”的json数据,否则钉钉服务器将认为url不合法。

class Crypto(object):
    def __init__(self):
        # 随便填的字符串
        self.token = TOKEN
        # 自己生成的43位随机字符串
        self.aes_key = AES_KEY
        # 钉钉企业ID
        self.corpid = CORPID
        self.crypto = DingTalkCrypto(
            token=self.token,
            encoding_aes_key=self.aes_key,
            corpid_or_suitekey=self.corpid
        )
def callbackDd(self, request):
    encrypt = request.data.get('encrypt')

    msgSignature = request.GET.get("signature")
    timeStamp = request.GET.get("timestamp")
    nonce = request.GET.get("nonce")

    callback = json.loads(Crypto().crypto.decrypt_encrypt_str(
        encrypt_str=encrypt,
        nonce=nonce,
        timestamp=timeStamp,
        signature=msgSignature
    ))
    print(callback)
    #第一次调用回调函数的验证,关键字是check_url
    if callback['EventType'] == 'check_url':
        result = Crypto().crypto.encrypt_message(
            msg="success",
            nonce="123456",
            timestamp=int(time.time() * 1000)
        )

        return Response(result)
    # bpms_task_change :  审批任务开始,结束,转交
    # bpms_instance_change:审批实例开始,结束
    elif callback['EventType'] == 'bpms_task_change':
        pass  #实现入库
    elif callback['EventType'] == 'bpms_instance_change':
        pass  #实现入库

 

三、钉钉的后台配置

参考钉钉的文档:https://open-doc.dingtalk.com/microapp/serverapi2/tvu5f4

上面的代码实现,我的配置方式是:

 

结尾:后续的数据库设计会在后面的内容中展示。


http://www.niftyadmin.cn/n/2813904.html

相关文章

跨组件传参 react

const Context React.createContext();// console.log(Context.Provider);// 提供者// console.log(Context.Consumer);//使用者//孙子class Son extends React.Component{render(){return <div className"son"><Context.Consumer>{(data)>{return &…

k8s之pod基础(下)

1.2 镜像拉取的策略 IfNotPresent 只有当镜像在本地不存在时才会拉取。&#xff08;先对本地进行排查&#xff0c;本地有该镜像直接使用&#xff0c;本地没有该镜像则选择在仓库中拉取&#xff09; Always 总是从仓库拉取镜像&#xff0c;无论本地是否存在镜像&#xff08…

钉钉python实现审批数据库设计

为了实现工单系统&#xff0c;又不想自己去结合钉钉的组织架构实现一套审批流&#xff0c;所以采用钉钉的审批结合自己的系统去实现工单。 由钉钉实现审批流&#xff0c;软件实现查询&#xff0c;记录工单等。 在上一篇中已经实现了审批流程以及回调函数的实现和整个工单的逻…

高阶组件 基础模板 react

function Dialog(Component){return class extends React.Component{render(){return <Component />}}}class DialogComponent extends React.Component{render(){return <div classNamebox>凌晨两点半</div>}}let DialogDom Dialog(DialogComponent )…

高阶组件

高阶组件 高阶组件是什么他能给我们带来什么他的优点是什么

react 路由基础配置解释 模板 精简

路由的基本用法 // 下载第三方包 react-router-domimport {BrowserRouter,Route,Redirect,Link,NavLink} from react-router-dom;//在组件当中class Index extends Component{render(){return <BrowserRouter><Route path{} component{} exact/></BrowserRoute…

js监听浏览器变化的函数,大于500px时,打印console.log('hello'),且只打印一次

let str ;window.onresize function(){if(document.body.clientWidth> 500){if(str ){strhello;console.log(str);}else{return;}}}

redux 解析

下载第三方包 && 并且引入 const { createStore } require(redux);console.log( createStore ); // [Function: createStore] 是一个函数可以进行调用const { createStore } require(redux);let reducer (state,action)>{// action默认是{ type: redux/INITb.2…