如何在Python Flask中使用XML-RPC或JSON-RPC从Odoo 15下载销售订单发票而不需SSH访问?

0 投票
1 回答
53 浏览
提问于 2025-04-14 16:42

我正在开发一个Python Flask应用程序,需要从Odoo 15下载销售订单发票。我可以使用XML-RPC或JSON-RPC来实现这个功能。不过,由于安全原因,我无法通过SSH访问Odoo的源代码。我手头只有Odoo的数据库名称、用户名、密码和我想下载的发票的ID。

有没有办法直接通过API或者使用XML-RPC/JSON-RPC的方法,从Odoo 15下载销售订单发票,而不需要访问源代码?如果能提供一些代码示例或在Python Flask环境中实现的指导,我将非常感激。

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

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

# Core Invoice Fetching Logic
def fetch_and_download_invoice_xmlrpc(invoice_id):
    """Fetches and downloads a sales invoice using 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))

    # Fetch the PDF content 
    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):
    """Fetches and downloads a sales invoice using JSON-RPC"""
    aurl = f"{url}/jsonrpc"
    headers = {'Content-type': 'application/json'}

    # Authentication
    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']

    # Fetch and download invoice
    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 Application
app = Flask(__name__)

@app.route('/download_invoice', methods=['GET'])
def download_invoice():
    invoice_id = request.args.get('invoice_id')
    if not invoice_id:
        return "Please provide an invoice ID", 400

    try:
        # Choose either XML-RPC or JSON-RPC
        fetch_and_download_invoice_xmlrpc(int(invoice_id))  # Convert to integer
        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)

这是我尝试使用XML-RPC和JSON-RPC的方法

编辑 我找到了答案,下面的代码可以正常工作

# Import necessary modules from Flask framework and other libraries
from flask import Flask, request, jsonify, send_file
import xmlrpc.client
import requests

# Set up credentials and URL for Odoo instance
url = 'https://your_odoo_instance_url.com'
db = 'your_odoo_database'
username = 'your_odoo_username'
password = 'your_odoo_password'

# Authenticate and get session ID from Odoo
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']

# Set up XML-RPC connection to Odoo
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))

# Specify the ID of the invoice to retrieve
invoice_id = 21566

# Retrieve information about the specified invoice from Odoo
invoice = models.execute_kw(db, uid, password, 'account.move', 'read', [invoice_id], {'fields': ['name']})

# Trigger the action to send and print the invoice, and retrieve the URL of the generated PDF
pdf_file_url = models.execute_kw(db, uid, password, 'account.move.send', 'action_send_and_print', [4, [invoice_id]])

# Set up headers with the session ID for downloading the PDF
headers = {'Cookie': f'session_id={session_id}'}
download_url = f'{url}{pdf_file_url["url"]}'

# Download the PDF content of the invoice
response = requests.get(download_url, headers=headers)
pdf_content = response.content

# Specify the filename for the downloaded PDF based on the invoice name
filename = '{}.pdf'.format(invoice[0]['name'])

# Save the PDF content to a file
with open(filename, 'wb') as f:
    f.write(pdf_content)

1 个回答

0

请试着使用下面的代码,看看是否对你有帮助:

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

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

# Core Invoice Fetching Logic
def fetch_and_download_invoice(invoice_id, rpc_method):
    """Fetches and downloads a sales invoice using the specified RPC method"""
    if rpc_method not in ['xmlrpc', 'jsonrpc']:
        raise ValueError("Invalid RPC method")

    if rpc_method == 'xmlrpc':
        common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
        uid = common.authenticate(db, username, password, {})
        models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))
    else:  # jsonrpc
        aurl = f"{url}/jsonrpc"
        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']

    # Fetch and download invoice
    data = {"jsonrpc": "2.0" if rpc_method == 'jsonrpc' else None,
            "method": "call",
            "params": {"service": "object", "method": "execute", "args": [db, uid, password, 'ir.actions.report', 'render_qweb_pdf', [invoice_id]]},
            "id": 2 if rpc_method == 'jsonrpc' else None}
    pdf_response = json.loads(urlopen(aurl, json.dumps(data).encode()).read()) if rpc_method == 'jsonrpc' else models.execute_kw(
        db, uid, password, 'ir.actions.report', 'render_qweb_pdf_inherit', [invoice_id]
    )
    pdf_data = base64.b64decode(pdf_response['result'] if rpc_method == 'jsonrpc' else pdf_response)

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

# Flask Application
app = Flask(__name__)

@app.route('/download_invoice', methods=['GET'])
def download_invoice():
    invoice_id = request.args.get('invoice_id')
    rpc_method = request.args.get('rpc_method', 'jsonrpc')  # Default to JSON-RPC if not specified
    if not invoice_id:
        return "Please provide an invoice ID", 400

    try:
        fetch_and_download_invoice(int(invoice_id), rpc_method)
        return send_file(f'invoice_{invoice_id}.pdf', as_attachment=True)

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

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

这段代码把处理XML-RPC和JSON-RPC的逻辑合并到一个叫做 fetch_and_download_invoice 的函数里。这样,你可以根据 rpc_method 这个参数来动态选择使用哪种RPC方法。

撰写回答