python連線釘釘自動化提交OA審批

Abraverman發表於2024-08-13

一、準備工作

1、安裝阿里雲支援包,點選跳轉:https://open.dingtalk.com/document/resourcedownload/download-server-sdk
2、註冊釘釘開發者賬號,點選連結:https://open.dingtalk.com/
3、獲取AK,SK
4、USERID透過企業管理後臺可以檢視每個使用者的ID或者透過介面獲取
5、PROCESS_CODE 在流程編輯頁面的URL上面(是一個奇葩的設定,無語了家人們)

二、開發流程

1、獲取企業token
2、提交審批
3、獲取審批返回

import os
import sys

from typing import List

from alibabacloud_dingtalk.workflow_1_0.client import Client as dingtalkworkflow_1_0Client
from alibabacloud_dingtalk.oauth2_1_0.client import Client as dingtalkoauth2_1_0Client
from alibabacloud_dingtalk.oauth2_1_0 import models as dingtalkoauth_2__1__0_models
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dingtalk.workflow_1_0 import models as dingtalkworkflow__1__0_models
from alibabacloud_tea_util import models as util_models


USER_ID = "1405122143xxxxxx"
PROCESS_CODE = "PROC-B897CFC7-CA66-449C-8C70-xxxxxx"

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client() -> dingtalkoauth2_1_0Client:
        """
        使用 Token 初始化賬號Client
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config()
        config.protocol = 'https'
        config.region_id = 'central'
        return dingtalkoauth2_1_0Client(config)

    @staticmethod
    def create_client_1_0() -> dingtalkworkflow_1_0Client:
        """
        使用 Token 初始化賬號Client
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config()
        config.protocol = 'https'
        config.region_id = 'central'
        return dingtalkworkflow_1_0Client(config)

    @staticmethod
    def get_token() -> str:
        """
        獲取例項TOKEN
        """
        client = Sample.create_client()
        get_access_token_request = dingtalkoauth_2__1__0_models.GetAccessTokenRequest(
            app_key='xxxxx',
            app_secret='yyyyyyyyyyyyyyyyy'
        )
        res = client.get_access_token(get_access_token_request)
        accessToken = res.body.access_token
        print("accessToken", accessToken)
        return accessToken

    @staticmethod
    def get_user_info(_token, _code):
        """
        沒用,測試中
        """
        client = Sample.create_client()
        get_sso_user_info_headers = dingtalkoauth_2__1__0_models.GetSsoUserInfoHeaders()
        get_sso_user_info_headers.x_acs_dingtalk_access_token = _token
        get_sso_user_info_request = dingtalkoauth_2__1__0_models.GetSsoUserInfoRequest(
            code=_code
        )
        print(_token, _code)
        res = client.get_sso_user_info_with_options(get_sso_user_info_request, get_sso_user_info_headers,
                                              util_models.RuntimeOptions())
        print("res", res)

    @staticmethod
    def get_process_schema_info(token, process_code):
        """
        獲取審批結構,例如審批中有哪些欄位需要填寫,可獲取如下結構
        https://open-dev.dingtalk.com/apiExplorer?spm=ding_open_doc.document.0.0.61e032c7Lzbckc#/?devType=org&api=workflow_1.0%23QuerySchemaByProcessCode
        _formList = [
            {'id': 'TextField_1B9X1OGLRIDC0', 'name': '部門', 'value': "平臺"},
            {'id': 'MoneyField_265MJ5CX7OLC', 'name': '金額(元)', 'value': "100"},
            {'id': 'TextareaField_1JQHWE0CZJ6O0', 'name': '分潤明細', 'value': "https://www.baidu.com"},
            {'id': 'TextField_12VLX2OCTGNK0', 'name': '對公-公司全稱', 'value': "途強"},
            {'id': 'TextField_23VZA2Q6HHLS0', 'name': '開戶行', 'value': "途強"},
            {'id': 'NumberField_5DTYPD4WMP40', 'name': '對公賬號', 'value': "123123123"},
            {'id': 'TextField_15B01GLYJL280', 'name': '聯絡人', 'value': "途強"},
            {'id': 'TextField_UTT9HNYLMV40', 'name': '聯絡電話', 'value': "途強"},
            {'id': 'TextareaField_BIO57GH5LFC0', 'name': '備註', 'value': "https://www.baidu.com"}
        ]
        """
        client = Sample.create_client_1_0()
        query_schema_by_process_code_headers = dingtalkworkflow__1__0_models.QuerySchemaByProcessCodeHeaders()
        query_schema_by_process_code_headers.x_acs_dingtalk_access_token = token
        query_schema_by_process_code_request = dingtalkworkflow__1__0_models.QuerySchemaByProcessCodeRequest(
            process_code=process_code
        )

        res = client.query_schema_by_process_code_with_options(query_schema_by_process_code_request, query_schema_by_process_code_headers, util_models.RuntimeOptions())
        # print("res", res.body.result.schema_content.items)
        items = res.body.result.schema_content.items
        formComponentObj = {
            "name":"",
            "value":""
        }
        formComponentValues = []
        for item in items:
            Obj = {
                "id": item.props.id,
                "name": item.props.label,
                "value": 123
            }
            formComponentValues.append(Obj)
        return formComponentValues

    @staticmethod
    def post_process_instance(token, user_id, process_code, form_list):
        """
        建立一個新的審批, 每一個欄位的name value 是必填欄位
        https://open-dev.dingtalk.com/apiExplorer?spm=ding_open_doc.document.0.0.61e032c7Lzbckc#/?devType=org&api=workflow_1.0%23StartProcessInstance
        _formList = [
            {'id': 'TextField_1B9X1OGLRIDC0', 'name': '部門', 'value': "平臺"},
            {'id': 'MoneyField_265MJ5CX7OLC', 'name': '金額(元)', 'value': "100"},
            ...
        ]
        """
        client = Sample.create_client_1_0()
        start_process_instance_headers = dingtalkworkflow__1__0_models.StartProcessInstanceHeaders()
        start_process_instance_headers.x_acs_dingtalk_access_token = token
        form_component_values = []
        for item in form_list:
            values_obj = dingtalkworkflow__1__0_models.StartProcessInstanceRequestFormComponentValues(
                id=item['id'],
                name=item['name'],
                value=item['value']
            )
            form_component_values.append(values_obj)
            # break
        start_process_instance_request = dingtalkworkflow__1__0_models.StartProcessInstanceRequest(
            dept_id=890417386,
            originator_user_id=user_id,
            process_code=process_code,
            form_component_values=form_component_values
        )

        res = client.start_process_instance_with_options(start_process_instance_request, start_process_instance_headers,
                                                   util_models.RuntimeOptions())
        print("res====", res)
        return res.body.instance_id

    @staticmethod
    def get_instance_info(token, instance_id):
        """
        查詢例項審批狀態
        https://open-dev.dingtalk.com/apiExplorer?spm=ding_open_doc.document.0.0.61e032c7Lzbckc#/?devType=org&api=workflow_1.0%23GetProcessInstance
        {
            "business_id": res.body.result.business_id,  # 審批例項業務編號。 可透過釘釘查詢
            "status": res.body.result.status,  # 狀態 RUNNING:審批中  TERMINATED:已撤銷  COMPLETED:審批完成
            "result": res.body.result.result # agree:同意  refuse:拒絕 status為COMPLETED且result為agree時,表示審批單完結並審批透過。
        }
        """
        client = Sample.create_client_1_0()
        get_process_instance_headers = dingtalkworkflow__1__0_models.GetProcessInstanceHeaders()
        get_process_instance_headers.x_acs_dingtalk_access_token = token
        get_process_instance_request = dingtalkworkflow__1__0_models.GetProcessInstanceRequest(
            process_instance_id=instance_id
        )
        res = client.get_process_instance_with_options(get_process_instance_request, get_process_instance_headers,
                                                 util_models.RuntimeOptions())
        if res.body.success:
            return {
                "business_id": res.body.result.business_id,  # 審批例項業務編號。 可透過釘釘查詢
                "status": res.body.result.status,  # 狀態 RUNNING:審批中  TERMINATED:已撤銷  COMPLETED:審批完成
                "result": res.body.result.result # agree:同意  refuse:拒絕 status為COMPLETED且result為agree時,表示審批單完結並審批透過。
            }
        else:
            return {}


if __name__ == '__main__':
    token = Sample.get_token()
    formList = Sample.get_process_schema_info(token, PROCESS_CODE)
    # 如果已知審批結構可以直接寫死,不用去獲取結構
    _formList = [
        {'id': 'TextField_1B9X1OGLRIDC0', 'name': '部門', 'value': "平臺"},
        {'id': 'MoneyField_265MJ5CX7OLC', 'name': '金額(元)', 'value': "100"},
        {'id': 'TextareaField_1JQHWE0CZJ6O0', 'name': '分潤明細', 'value': "https://www.baidu.com"},
        {'id': 'TextField_12VLX2OCTGNK0', 'name': '對公-公司全稱', 'value': "途強"},
        {'id': 'TextField_23VZA2Q6HHLS0', 'name': '開戶行', 'value': "途強"},
        {'id': 'NumberField_5DTYPD4WMP40', 'name': '對公賬號', 'value': "123123123"},
        {'id': 'TextField_15B01GLYJL280', 'name': '聯絡人', 'value': "途強"},
        {'id': 'TextField_UTT9HNYLMV40', 'name': '聯絡電話', 'value': "途強"},
        {'id': 'TextareaField_BIO57GH5LFC0', 'name': '備註', 'value': "https://www.baidu.com"}
    ]
	# 提交審批,並返回審批ID
    instanceId = Sample.post_process_instance("beab04e9490a3700a577a4c1c15d9698", USER_ID, PROCESS_CODE, _formList)
	# 獲取審批其他詳細資訊
    result = Sample.get_instance_info("beab04e9490a3700a577a4c1c15d9698", "tlB2uVSURhOhp9SzVPbi3g08441723284181")
    # print("result", result)

相關文章