You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无SSH权限下,用Python Flask通过XML-RPC/JSON-RPC下载Odoo15销售订单发票

问题

我正在开发一个Python Flask应用,需要通过XML-RPC或JSON-RPC从Odoo 15下载销售订单发票。但受安全限制,我无法通过SSH访问Odoo源码,仅拥有Odoo数据库名称、用户名、密码以及需要下载的发票ID。

请问是否可以通过调用API或使用XML-RPC/JSON-RPC方法,在不访问源码的情况下直接从Odoo 15下载销售订单发票?希望能提供在Python Flask环境下实现的代码片段或指导。


最初的尝试(XML-RPC & JSON-RPC)

我分别用XML-RPC和JSON-RPC做了以下尝试:

import xmlrpc.client
import json
import base64
from urllib.request import urlopen
from flask import Flask, request, send_file

# Odoo 配置
url = 'https://your_odoo_instance_url.com'
db = 'your_odoo_database'
username = 'your_odoo_username'
password = 'your_odoo_password'

# 核心发票获取逻辑
def fetch_and_download_invoice_xmlrpc(invoice_id):
    """使用XML-RPC获取并下载销售发票"""
    common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
    uid = common.authenticate(db, username, password, {})
    models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))

    # 获取PDF内容
    pdf_content_encoded = models.execute_kw(
        db, uid, password, 'ir.actions.report', 'render_qweb_pdf_inherit', [invoice_id]
    )
    pdf_data = base64.b64decode(pdf_content_encoded)

    with open('invoice_{}.pdf'.format(invoice_id), 'wb') as f:
        f.write(pdf_data)

def fetch_and_download_invoice_jsonrpc(invoice_id):
    """使用JSON-RPC获取并下载销售发票"""
    aurl = f"{url}/jsonrpc"
    headers = {'Content-type': 'application/json'}

    # 认证
    auth_data = {
        "jsonrpc": "2.0",
        "method": "call",
        "params": {"db": db, "login": username, "password": password},
        "id": 1
    }
    auth_response = json.loads(urlopen(aurl, json.dumps(auth_data).encode()).read())
    if auth_response.get('error'):
        raise Exception(auth_response['error'])
    uid = auth_response['result']

    # 获取并下载发票
    data = {
        "jsonrpc": "2.0",
        "method": "call",
        "params": {
            "service": "object",
            "method": "execute",
            "args": [db, uid, password, 'ir.actions.report', 'render_qweb_pdf', [invoice_id]]
        },
        "id": 2
    }
    pdf_response = json.loads(urlopen(aurl, json.dumps(data).encode()).read())
    pdf_data = base64.b64decode(pdf_response['result'])

    with open('invoice_{}.pdf'.format(invoice_id), 'wb') as f:
        f.write(pdf_data)

# Flask 应用
app = Flask(__name__)

@app.route('/download_invoice', methods=['GET'])
def download_invoice():
    invoice_id = request.args.get('invoice_id')
    if not invoice_id:
        return "请提供发票ID", 400

    try:
        # 选择XML-RPC或JSON-RPC其中一种即可
        fetch_and_download_invoice_xmlrpc(int(invoice_id))  # 转换为整数
        # fetch_and_download_invoice_jsonrpc(int(invoice_id))

        return send_file('invoice_{}.pdf'.format(invoice_id), as_attachment=True)

    except Exception as e:
        return str(e), 500

if __name__ == '__main__':
    app.run(debug=True)

可行解决方案

我已经找到可以正常运行的方案,代码如下:

# 导入Flask框架及其他必要库
from flask import Flask, request, jsonify, send_file
import xmlrpc.client
import requests

# 配置Odoo实例的凭证和URL
url = 'https://your_odoo_instance_url.com'
db = 'your_odoo_database'
username = 'your_odoo_username'
password = 'your_odoo_password'

# 向Odoo认证并获取会话ID
session_url = f'{url}web/session/authenticate'
data = {
    'jsonrpc': '2.0',
    'method': 'call',
    'params': {
        "service": "common",
        "method": "login",
        'db': db,
        'login': username,
        'password': password,
    }
}
session_response = requests.post(session_url, json=data)
session_data = session_response.json()
session_id = session_response.cookies['session_id']

# 建立与Odoo的XML-RPC连接
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))

# 指定要获取的发票ID
invoice_id = 21566

# 从Odoo获取指定发票的信息
invoice = models.execute_kw(db, uid, password, 'account.move', 'read', [invoice_id], {'fields': ['name']})

# 触发发票发送并打印的动作,获取生成的PDF链接
pdf_file_url = models.execute_kw(db, uid, password, 'account.move.send', 'action_send_and_print', [4, [invoice_id]])

# 设置包含会话ID的请求头用于下载PDF
headers = {'Cookie': f'session_id={session_id}'}
download_url = f'{url}{pdf_file_url["url"]}'

# 下载发票的PDF内容
response = requests.get(download_url, headers=headers)
pdf_content = response.content

# 根据发票名称指定下载后的PDF文件名
filename = '{}.pdf'.format(invoice[0]['name'])

# 将PDF内容保存到文件
with open(filename, 'wb') as f:
    f.write(pdf_content)

内容的提问来源于stack exchange,提问作者Aditya Irri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:44:56