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

Spring集成Zoho Invoice创建联系人API返回400错误求助

解决Zoho Invoice创建联系人API返回400错误的问题

从你的代码和请求信息来看,问题主要出在请求头的Content-Type设置和请求体的格式处理上,下面是具体的分析和修复方案:

核心问题分析

  • Content-Type不匹配:你设置了multipart/form-data,但Zoho Invoice的Create Contact API要求请求体是JSON格式,对应的Content-Type应该是application/json。
  • 请求体格式错误:你当前用ParameterStringBuilder.getParamsString(params)把Map转成了表单编码的字符串(比如key1=value1&key2=value2),但API需要的是完整的JSON结构体,嵌套的billing_address和shipping_address没法通过普通的键值对Map正确传递。

修复步骤及代码修改

1. 调整请求头的Content-Type

把con.setRequestProperty("Content-Type", "multipart/form-data");改成con.setRequestProperty("Content-Type", "application/json");。

2. 直接发送JSON字符串作为请求体

不需要再用Map来传递参数,直接把你准备好的JSON字符串写入输出流,而不是转成表单格式。

修改后的完整代码示例

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public String processZohoRequest(String apiUrl, String jsonBody, String method, String auth) throws UnsupportedEncodingException, IOException {
    URL url = new URL(apiUrl);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setRequestMethod(method);
    
    if (!AppUtility.isEmpty(auth)) {
        con.setRequestProperty("Authorization", auth);
        con.setRequestProperty("Content-Type", "application/json"); // 修正Content-Type
        con.setRequestProperty("X-com-zoho-invoice-organizationid", testZohoOrgId);
    }
    
    if (!AppUtility.isEmpty(jsonBody)) {
        con.setDoOutput(true);
        // 直接写入JSON字符串,用UTF-8编码保证兼容性
        try (OutputStream os = con.getOutputStream()) {
            byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }
    }
    
    // 新增错误流处理:400等错误码时,读取错误流获取具体报错信息
    int responseCode = con.getResponseCode();
    BufferedReader in;
    if (responseCode >= 200 && responseCode < 300) {
        in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    } else {
        in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
    }
    
    String inputLine;
    StringBuffer content = new StringBuffer();
    while ((inputLine = in.readLine()) != null) {
        content.append(inputLine);
    }
    in.close();
    con.disconnect();
    
    return content.toString();
}

3. 调用方式调整

调用这个方法时,直接传入你准备好的JSON字符串(注意替换${address}为实际地址值),而不是Map:

String apiUrl = "https://invoice.zoho.com/api/v3/contacts";
String jsonBody = "{\"contact_name\":\"Jay Panjwanai\",\"company_name\":\"Ozone\",\"billing_address\":{\"attention\":\"Jay \",\"address\":\"实际地址内容\",\"city\":\"INDORE\",\"country\":\"India\",\"phone\":9xxxxxxxxx},\"shipping_address\":{\"attention\":\"Jay\",\"address\":\"实际地址内容\",\"city\":\"INDORE\",\"country\":\"India\",\"phone\":9xxxxxxxxx}}";
String auth = "Bearer 你的AuthToken"; // 注意格式是「Bearer + 空格 + Token」
String result = processZohoRequest(apiUrl, jsonBody, "POST", auth);

额外验证要点

  • 确认X-com-zoho-invoice-organizationid的值是正确的组织ID,这个ID可以在Zoho Invoice的后台设置中找到。
  • 确认AuthToken的格式正确,必须包含Bearer前缀和后续的空格,不要直接传入纯Token字符串。
  • 检查JSON字符串是否有语法错误,比如引号是否配对、嵌套结构是否正确,可以用在线JSON校验工具提前验证。

内容的提问来源于stack exchange,提问作者Jayesh Choudhary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:59:37