# -*- coding: utf-8 -*- import json,requests,time,os,sys,logging,datetime from util import Config,APIError from cache import Cache _logger = logging.getLogger(__name__) ''' http call ''' def _http_call(url, params, method='GET'): _logger.info('+++++++++++++++++++++++++++++') _logger.info('request : ' + url) _logger.info(params) if method == 'GET': res = requests.get(url, params=params) else: res = requests.post(url,data=params) if res.status_code == 200: data = res.json() _logger.info('response : ') _logger.info(data) if data['errcode'] == 0 and data['errmsg'] == 'ok': return data else: raise APIError(data['errcode'],data['errmsg'],url) else: raise APIError(res.status_code,'api error',url) def _http_get(url, params): return _http_call(url,params) def _http_post(url, access_token, params): uri = '%s?access_token=%s'%(url,access_token) return _http_call(uri,json.dumps(params),'POST') class DingTalkClient: def __init__(self, corpid=None, corpsecret=None): self.corp_params = { 'corpid': corpid, 'corpsecret': corpsecret } cf = Config() self.api = cf.get('api') self.method = cf.get('method') self.cache = Cache.factory(cf.get('cache').adapter) self.access_token = self.cache.get('access_token') def get_access_token(self): token = self.cache.get('access_token') if token: self.access_token = token else: resp = _http_call(self.api.url_access_token, self.corp_params) self.access_token = resp['access_token'] self.cache.add('access_token',self.access_token,7000) return self.access_token ''' 通过CODE换取微应用管理员的身份信息 ''' def get_sso_userinfo(self, code): token = self.cache.get('sso_token'); if not token: resp = _http_call(self.api.url_sso_token, self.corp_params) token = resp['access_token'] self.cache.add('sso_token', token, 7000) params = {'access_token': token, 'code': code} return _http_call(self.api.url_sso_user_info, params) def get_user_info(self, code): params = {'access_token': self.access_token, 'code':code} return _http_call(self.api.url_user_info, params) def get_jsapi_ticket(self): ticket = self.cache.get('jsapi_ticket'); if not ticket: params = {'access_token': self.access_token} resp = _http_call(self.api.url_jsapi_ticket, params) ticket = resp['ticket'] return ticket def sign(self, ticket, nonce_str, time_stamp, url): import hashlib plain = 'jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}'.format(ticket, nonce_str, time_stamp, url) return hashlib.sha1(plain).hexdigest() def get_user_simple_list(self, department_id, params={}): params.update({'access_token': self.access_token, 'department_id': department_id}) return _http_call(self.api.url_user_list_simple, params) def get_user_list(self, department_id, params={}): params.update({'access_token': self.access_token, 'department_id': department_id}) return _http_call(self.api.url_user_list, params) def create_user(self, params): return _http_post(self.api.url_user_create, self.access_token, params) def update_user(self, params): return _http_post(self.api.url_user_update, self.access_token, params) def get_department_detail(self, department_id): params = {'access_token': self.access_token, 'id': department_id} return _http_call(self.api.url_department_detail, params) def get_department_list(self, id=None): params={'access_token': self.access_token} if id: params.update({'id': id}) data = _http_call(self.api.url_department_list, params ) return data['department'] def update_department(self, params): return _http_post(self.api.url_department_update, self.access_token, params) def create_department(self, params): return _http_post(self.api.url_department_create,self.access_token, params) def list_label_groups(self, size=20, offset=0): return self.request_list('dingtalk.corp.ext.listlabelgroups',size, offset) def get_corp_ext_list(self, size=20, offset=0): """ 获取外部联系人 """ return self.request_list('dingtalk.corp.ext.list', size, offset) def get_all_ext_list(self): """ 获取全部的外部联系人 """ size = 100 offset = 0 dd_customer_list = [] while True: dd_customers = self.get_corp_ext_list(size=size, offset=offset) if len(dd_customers) <= 0: break else: dd_customer_list.extend(dd_customers) offset += size return dd_customer_list def add_corp_ext(self, contact): """ 添加外部联系人 """ url = self.get_request_url('dingtalk.corp.ext.add', self.access_token) contact = json.dumps(contact) resp = _http_call(url, {'contact': contact.encode('utf-8')},'POST') return resp def create_bpms_instance(self, process_code, originator_user_id, dept_id, approvers, form_component_values, agent_id=None): """ 发起审批实例 """ agent_id = agent_id or self.agent_id url = get_request_url('dingtalk.smartwork.bpms.processinstance.create', self.access_token) params = {} args = locals() for key in ('process_code', 'originator_user_id', 'dept_id', 'approvers', 'form_component_values', 'agent_id', 'cc_list', 'cc_position'): if args.get(key, no_value) is not None: params.update({key: args[key]}) return _http_call(url,params,'POST'); def get_bpms_instance_list(self, process_code, start_time, end_time=None, size=10, cursor=0): """ 企业可以根据审批流的唯一标识,分页获取该审批流对应的审批实例。只能取到权限范围内的相关部门的审批实例 """ start_time = datetime.timestamp(start_time) start_time = int(round(start_time * 1000)) if end_time: end_time = datetime.timestamp(end_time) end_time = int(round(end_time * 1000)) args = locals() url = get_request_url('dingtalk.smartwork.bpms.processinstance.list', self.access_token) params = {} for key in ('process_code', 'start_time', 'end_time', 'size', 'cursor'): if args.get(key, no_value) is not None: params.update({key: args[key]}) return _http_call(url,params) def request_list(self, method, size=20, offset=0): ''' 根据method获取列表 ''' url = self.get_request_url(method) params = {'size': size, 'offset': offset} resp = _http_call(url, params) data = json.loads(resp[self.method[method]]['result']) return data def get_request_url(self, method, format_='json', v='2.0', simplify='false', partner_id=None): """ 根据code获取请求地址 """ timestamp = self.get_timestamp() url = '{0}?method={1}&session={2}×tamp={3}&format={4}&v={5}'.format( _config['URL_METHODS_URL'], method, self.access_token, timestamp, format_, v) if format_ == 'json': url = '{0}&simplify={1}'.format(url, simplify) if partner_id: url = '{0}&partner_id={1}'.format(url, partner_id) return url def get_timestamp(self): """ 生成时间戳 """ return datetime.now().strftime('yyyy-MM-dd HH:mm:ss')