用友T+ OpenAPI 企业自建应用对接指南

发布时间 2023-09-07 15:59:19作者: Mike Von

首先,官方文档地址: https://open.chanjet.com/docs/file/guide/commonContent/jcwd-ruzz/zn-zjyyjrzn

官方出的视频教程:https://c4960-openplatform-train-oss.oss-cn-beijing.aliyuncs.com/open/app/selfuse01 

这里面会用到公网域名地址,如果企业本身有的话就还好,没有的话,建议用一些工具比如贝锐的花生壳,金万维的快解析等。

提前备好记事本类工具,把appkey  appsecret token certificate appTicket 记下来。

在控制台里配置消息接收地址的时候,请确保已经在开发管理中给当前用户做了授权,不然消息地址就设不成功。

在配置消息接收地址的时候,需要有一个程序运行在服务器上,以下是一个Python的服务端程序:

该Python文件名为getTPtoken.py, 很重要,下记代码里有用到。

from fastapi import FastAPI
from fastapi.responses import FileResponse
import uvicorn
import os.path
import base64
from Crypto.Cipher import AES  
from pydantic import BaseModel
from datetime import datetime

class Item(BaseModel):
    encryptMsg: str

#https://open.chanjet.com/console/selfApp/14281/message
#该值来源于消息配置里的消息密钥
SECRET_KEY='1234567890123456'

#该class来自于 cnblogs.com/gqv2009/p/14365911.html
class AES_ENCRYPT(object):
    def __init__(self):
        self.key = SECRET_KEY
        self.mode = AES.MODE_ECB

    def pading(self, text):
        """对加密字符的处理"""
        return text + (len(self.key) - len(text) % len(self.key)) * chr(len(self.key) - len(text) % len(self.key))

    def unpading(self, text):
        """对解密字符的处理"""
        return text[0:-ord(text[-1:])]

    def getKey(self, key):
        """对key的处理,key 的长度 16,24,32"""
        key_len = len(key)
        if key_len <= 16:
            key += "0" * (16 - key_len)
        elif 16 < key_len <= 24:
            key += "0" * (24 - key_len)
        elif key_len <= 32:
            key += "0" * (32 - key_len)
        else:
            key = key[:32]
        return key

    # 加密函数
    def encrypt(self, text):
        cryptor = AES.new(self.key.encode("utf-8"), self.mode)  # ECB 模式
        self.ciphertext = cryptor.encrypt(bytes(self.pading(text), encoding="utf-8"))
        encrypt_string = str(base64.b64encode(self.ciphertext)).lstrip("b")
        return encrypt_string[1:len(encrypt_string)-1] #去掉头尾的引号

    # 解密函数
    def decrypt(self, text):
        decode = base64.b64decode(text)
        cryptor = AES.new(self.key.encode("utf-8"), self.mode)  # ECB 模式
        plain_text = cryptor.decrypt(decode)
        decrypt_string = str(self.unpading(plain_text)).lstrip("b")
        return decrypt_string[1:len(decrypt_string)-1] #去掉头尾的引号

app = FastAPI()


@app.get("/")
def read_root_get():
    return {"welcome":"T+"}

@app.post("/")
def read_root(item: Item):
    encryptMsg = item.encryptMsg
    aes_encrypt = AES_ENCRYPT()
    msg = aes_encrypt.decrypt(encryptMsg)
    print(f"{datetime.now()} {msg}")

    return {"result":"success"}
            

@app.get("/CHANJET_CHECK.txt")
def get_CHANJET_CHECK():
    file_object = open("CHANJET_CHECK.txt", 'w')
    #https://open.chanjet.com/console/domainManage/domainManage
    #该值来自于可信域名管理页面上CHANJET_CHECK.txt的内容
    file_object.write('NTRiYTI0OTZlMTIwNDkzYTllNmMzODA2YTJkNDNlYzI=')
    file_object.close()
    
    f = os.path.join('./', "CHANJET_CHECK.txt")
    print(f)
    return FileResponse(path=f,
        filename="CHANJET_CHECK.txt",)

@app.post("/api/retn")
def read_tokenPost(code: str= '', state: str=''):
    print(f'code:{code}, state:{state}')
    file_object = open("token.txt", 'a+')
    file_object.write(f'code:{code}, state:{state} \n')
    return {'code':code, 'state':state}

@app.get("/api/retn")
def read_tokenGet(code: str= '', state: str=''):
    print(f'code:{code}, state:{state}')
    file_object = open("token.txt", 'a+')
    file_object.write(f'code:{code}, state:{state} \n')
    return {'code':code, 'state':state}

if __name__ == '__main__':
    uvicorn.run(app='getTPtoken:app', host="0.0.0.0", port=8080, reload=True)
    

 

老的 T+API 测试工具:

https://www.chanjetvip.com/product/tool/detail?id=5b96318ce58795001a44598b

工具里的有个按钮“其他功能”默认是关闭的,正常打开是看不到的,可以自己代码里默认打开。