鱼C论坛

 找回密码
 立即注册
查看: 997|回复: 5

求助!想用钉钉API发送xlsx文件,遇到报错,请大神赐教!

[复制链接]
发表于 2023-8-14 10:47:15 | 显示全部楼层 |阅读模式
20鱼币
求助!想用钉钉API发送xlsx文件,遇到报错,请大神赐教!
本人比较小白,用的代码是网上摘的,遇到了报错,请大神讲解,万分感谢!
代码:
  1. class Client():
  2.     def __init__(self, app_key, app_secret, user_id):
  3.         self.app_key = app_key
  4.         self.app_secret = app_secret
  5.         self.user_id = user_id
  6.         self.domain = "api.dingtalk.com"
  7.         self.token = self.get_access_token()
  8.         self.operator_id = self.get_operator_id(user_id)
  9.         self.unionId = self.operator_id

  10.     def get_access_token(self):
  11.         conn = http.client.HTTPSConnection(self.domain)
  12.         payload = json.dumps({
  13.             "appKey": self.app_key,
  14.             "appSecret": self.app_secret
  15.         })
  16.         headers = {'Content-Type': 'application/json'}
  17.         conn.request("POST", "/v1.0/oauth2/accessToken", payload, headers)
  18.         res = json.load(conn.getresponse())
  19.         token = res.get("accessToken")
  20.         assert token != None, "请检查 appKey appSecret 是否正确"
  21.         return token

  22.     def validate_token(func):
  23.         def inner(self, *args, **kwargs):
  24.             try:
  25.                 res = func(self, *args, **kwargs)
  26.             except Exception as e:
  27.                 self.token = self.get_access_token()
  28.                 res = func(self, *args, **kwargs)
  29.             return res

  30.         return inner

  31.     @validate_token
  32.     def request(self, method, url, payload={}):
  33.         payload = json.dumps(payload)
  34.         headers = {
  35.             'Host': 'api.dingtalk.com',
  36.             'x-acs-dingtalk-access-token': self.token,
  37.             'Content-Type': 'application/json'
  38.         }

  39.         conn = http.client.HTTPSConnection(self.domain)
  40.         conn.request(method, url, payload, headers)
  41.         res = conn.getresponse().read()

  42.         res = json.loads(res)
  43.         print(res)
  44.         return res

  45.     def get_operator_id(self, user_id):
  46.         conn = http.client.HTTPSConnection("oapi.dingtalk.com")
  47.         payload = json.dumps({"language": "zh_CN", "userid": self.user_id})
  48.         headers = {'Content-Type': 'application/json'}
  49.         conn.request("POST", f"/topapi/v2/user/get?access_token={self.token}",
  50.                      payload, headers)
  51.         res = conn.getresponse().read()
  52.         res = json.loads(res)
  53.         print(res)
  54.         assert res.get("errcode") == 0, "请检查 userId"
  55.         return res.get("result").get("unionid")


  56. class Spaces(Client):
  57.     def __init__(self, app_key, app_secret, user_id, space_id) -> Client:
  58.         super().__init__(app_key, app_secret, user_id)
  59.         self.space_id = space_id
  60.         self.url = f"/v1.0/storage/spaces/{space_id}/files"

  61.     def _oss_headers(self, url, headers, filepath):
  62.         result = requests.put(url, data=open(filepath, 'rb'), headers=headers)
  63.         print(result)

  64.     def _get_file_upload_info(self):
  65.         url = f"{self.url}/uploadInfos/query?unionId={self.unionId}"
  66.         payload = {
  67.             "protocol": "HEADER_SIGNATURE",
  68.             "multipart": False,
  69.         }
  70.         res = self.request("POST", url, payload=payload)
  71.         print(res)
  72.         return res["uploadKey"], res["headerSignatureInfo"][
  73.             "resourceUrls"], res["headerSignatureInfo"]["headers"]

  74.     def _commit_file(self, upload_key, filename):
  75.         url = f"{self.url}/commit?unionId={self.unionId}"
  76.         payload = {"uploadKey": upload_key, "name": filename, "parentId": "0"}
  77.         res = self.request("POST", url, payload=payload)
  78.         return res["dentry"]["id"]

  79.     def upload_file(self, filepath):
  80.         """
  81.         上传文件
  82.         """
  83.         try:
  84.             filename = os.path.basename(filepath)
  85.             upload_key, urls, headers = self._get_file_upload_info()
  86.             self._oss_headers(urls[0], headers, filepath)
  87.             file_id = self._commit_file(upload_key, filename)
  88.             return file_id
  89.         except Exception as e:
  90.             print(e)
  91.             # raise Exception("")

  92.     def send_file_to_group(self, dentry_id, open_conversation_id):
  93.         """
  94.         发送文件到群
  95.         :param self:
  96.         :param dentry_id: 文件id
  97.         :param open_conversation_id: 目标会话id
  98.         :return:
  99.         """
  100.         # POST  HTTP/1.1
  101.         # url = f"{self.url}/send?unionId={self.unionId}"
  102.         url = f"/v1.0/convFile/conversations/files/send?unionId={self.unionId}"
  103.         payload = {
  104.             "spaceId": self.space_id,
  105.             "dentryId": dentry_id,
  106.             "openConversationId": open_conversation_id
  107.         }
  108.         self.request("POST", url, payload=payload)

  109.     def add_spaces(self, spaces_name):
  110.         url = "/v1.0/drive/spaces"
  111.         payload = {
  112.             "name": spaces_name,
  113.             "unionId": self.unionId
  114.         }
  115.         res = self.request("POST", url, payload)
  116.         print("空间id", res["spaceId"])
  117.         self.space_id = res["spaceId"]


  118. def dingding_csv(args):
  119.     # 下面是测试
  120.     app_key = args["app_key"]  # dingmxap65f1nswaigt7
  121.     app_secret = args["app_secret"]  # sLwzEHiONPMYVgexjXeG05h4MZlcILUmv3vvWLg-hMj5vCyWexssXOvzMohtIwBa
  122.     user_id = args["user_id"]  # 01065236080226423576
  123.     space_id = args["space_id"]  # 22049120347
  124.     spaces = Spaces(app_key, app_secret, user_id, space_id)
  125.     # spaces.add_spaces("新的空间")
  126.     file_id = spaces.upload_file(args["file_id"])
  127.     open_conversation_id = args['open_conversation_id']  # cidvSKvQIGl8zXnx1DJRlahRw==
  128.     # file_id = "95294040408"
  129.     spaces.send_file_to_group(file_id, open_conversation_id)
复制代码

遇到的问题:
  1. {'errcode': 0, 'errmsg': 'ok', 'result': {'active': True, 'admin': False, 'avatar': '', 'boss': False, 'dept_id_list': [1], 'dept_order_list': [{'dept_id': 1, 'order': 176227112446945512}], 'email': '', 'exclusive_account': False, 'hide_mobile': False, 'job_number': '', 'leader_in_dept': [{'dept_id': 1, 'leader': False}], 'mobile': '13691255250', 'name': '梁圣垚', 'real_authed': False, 'remark': '', 'senior': False, 'state_code': '86', 'telephone': '', 'title': '', 'unionid': '3aOSoG0L1elLDOusbHagCQiEiE', 'userid': '01065236080226423576', 'work_place': ''}, 'request_id': '15rddatxj82xa'}
  2. {'protocol': 'HEADER_SIGNATURE', 'uploadKey': 'hgHPAAAABSI64FsCzwAAABpNzmwGAwEEoTcF2gA4I2lBRUhBcVJtYVd4bEE2aDVkVzVrYVhOck1BVE9JUWQ1RUFYTkNva0dhZ2ZPWk5tUzFRak5EbWcGqERJTkdUQUxL', 'storageDriver': 'DINGTALK', 'headerSignatureInfo': {'headers': {'Authorization': 'OSS LTAIjmWpzHta71rc:NLzJtL8II+jixf+DyZqE5akQDL8=', 'x-oss-date': 'Mon, 14 Aug 2023 02:35:01 GMT'}, 'resourceUrls': ['https://zjk-dualstack.trans.dingtalk.com/yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file'], 'expirationSeconds': 900, 'internalResourceUrls': ['lippi-space-zjk.oss-cn-zhangjiakou-internal.aliyuncs.com/yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file'], 'region': 'ZHANGJIAKOU'}}
  3. {'protocol': 'HEADER_SIGNATURE', 'uploadKey': 'hgHPAAAABSI64FsCzwAAABpNzmwGAwEEoTcF2gA4I2lBRUhBcVJtYVd4bEE2aDVkVzVrYVhOck1BVE9JUWQ1RUFYTkNva0dhZ2ZPWk5tUzFRak5EbWcGqERJTkdUQUxL', 'storageDriver': 'DINGTALK', 'headerSignatureInfo': {'headers': {'Authorization': 'OSS LTAIjmWpzHta71rc:NLzJtL8II+jixf+DyZqE5akQDL8=', 'x-oss-date': 'Mon, 14 Aug 2023 02:35:01 GMT'}, 'resourceUrls': ['https://zjk-dualstack.trans.dingtalk.com/yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file'], 'expirationSeconds': 900, 'internalResourceUrls': ['lippi-space-zjk.oss-cn-zhangjiakou-internal.aliyuncs.com/yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file'], 'region': 'ZHANGJIAKOU'}}
  4. HTTPSConnectionPool(host='zjk-dualstack.trans.dingtalk.com', port=443): Max retries exceeded with url: /yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1129)')))
  5. {'code': 'MissingdentryId', 'requestid': '9F71FA7C-DD36-76EF-80EB-65FA7B525C51', 'message': 'dentryId is mandatory for this action.'}
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-14 10:47:49 | 显示全部楼层
问题分析:
根据代码和报错信息,可以看出问题出现在发送文件到群的过程中。具体报错信息为: HTTPSConnectionPool(host='zjk-dualstack.trans.dingtalk.com', port=443): Max retries exceeded with url: /yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1129)'))) 和 {'code': 'MissingdentryId', 'requestid': '9F71FA7C-DD36-76EF-80EB-65FA7B525C51', 'message': 'dentryId is mandatory for this action.'} 。

问题解答:
第一个报错是由于 SSL 协议错误导致的连接异常。这可能是由于网络问题或 SSL 证书配置错误导致的。可以尝试检查网络连接是否正常,或者尝试更新 SSL 证书。

第二个报错是由于缺少  dentryId  参数导致的。根据代码可以看出,在发送文件到群的函数  send_file_to_group  中,需要传入文件的  dentryId  参数。可以检查代码中是否正确获取了文件的  dentryId ,并确保在调用函数时传入了正确的参数。

综上所述,解决这个问题的步骤如下:
1. 检查网络连接是否正常。
2. 检查 SSL 证书配置是否正确。
3. 检查代码中是否正确获取了文件的  dentryId 。
4. 确保在调用  send_file_to_group  函数时传入了正确的参数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-14 10:48:16 | 显示全部楼层
根据您提供的代码和报错信息,有几个问题可能导致报错:

1. 错误信息:HTTPSConnectionPool(host='zjk-dualstack.trans.dingtalk.com', port=443): Max retries exceeded with url: /yundisk0/iAEHAqRmaWxlA6h5dW5kaXNrMATOIQd5EAXNCokGagfOZNmS1QjNDmg.file (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1129)')))

这个错误可能是由于SSL连接问题导致的。请确保您的代码中使用的钉钉API请求的URL、域名以及端口号都是正确的,并且确保网络连接正常。

2. 错误信息:{'code': 'MissingdentryId', 'requestid': '9F71FA7C-DD36-76EF-80EB-65FA7B525C51', 'message': 'dentryId is mandatory for this action.'}

这个错误信息显示缺少dentryId参数,对于该操作是必需的。请确认您在调用spaces.send_file_to_group方法时是否正确传递了dentry_id参数,确保参数值不为空。

针对以上问题,请检查以下几点:

1. 确保您的API请求URL、域名和端口号都是正确的,可以在钉钉开发者文档中查找正确的API地址和端口号。

2. 确保在调用spaces.send_file_to_group方法时正确传递了dentry_id参数,并且确保参数值不为空。

3. 如果您的网络连接正常,但仍然遇到SSL连接问题,请检查您的代码中是否有关于SSL证书的配置或验证,确保配置正确。

希望以上信息对您有帮助,如果问题仍然存在,请提供更多的代码和错误信息,以便我能够更好地帮助您解决问题。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-8-14 10:51:56 | 显示全部楼层
debug发现是在upload_file时以下代码请求失败
  1.     def _get_file_upload_info(self):
  2.         url = f"{self.url}/uploadInfos/query?unionId={self.unionId}"
  3.         payload = {
  4.             "protocol": "HEADER_SIGNATURE",
  5.             "multipart": False,
  6.         }
  7.         res = self.request("POST", url, payload=payload)
  8.         print(res)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-8-14 15:49:52 | 显示全部楼层
已经解决了!是dingding权限问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-15 08:52:11 | 显示全部楼层
本帖最后由 wuliangtdi 于 2023-8-15 08:55 编辑
13691255250 发表于 2023-8-14 15:49
已经解决了!是dingding权限问题


那能把最佳给我嘛?(口气模仿来自【学习编程中的Ben】不用真给我,开个玩笑)

如图


                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-29 02:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表