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

Java Spring Boot中RestTemplate提交Google表单遇400错误求助

问题描述

新用户注册时需提交一份Google表单,我用Java Spring Boot的RestTemplate发送请求,将表单数据通过查询参数传递。纯文本参数能正常提交,但下拉选择项会触发400错误。奇怪的是,从RestTemplate调用中复制生成的URL,在浏览器或Postman里提交完全正常,求帮忙排查代码和URL的问题。

相关代码
private static final String GOOGLE_FORM_URL_V2 = "https://docs.google.com/forms/d/e/1FAIpQLSeb_QX8rdKD2WOM5-0rZ10C9rzPsMzqlGL-Aduh7_nM0EEutw/formResponse";


public Boolean submitGoogleFormV2(UserDto userDto) {
        String sampleWhatsappMessage = "Hi David! Your Order is booked and it will be delivered in two days. Thanks for trusting us.";
        String country = new Locale("en", PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(userDto.getCountryCode())).getDisplayCountry();

        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(GOOGLE_FORM_URL_V2)
                .queryParam("submit", "Submit")
                .queryParam("entry.294840288", "Both of the above") // What type of messages will you be sending with WhatsApp?
                .queryParam("entry.305369145", userDto.getPhoneNumber()) // phone number
                .queryParam("entry.365096862", vonageApiProperties.getMasterKey()) // Vonage API Key
                // TODO: Generate new api key for this whatsapp number
                .queryParam("entry.400495561", "tbc") // Vonage API key for WhatsApp Traffic
                .queryParam("entry.631769330", userDto.getRegion().getText()) // Your Region
                .queryParam("entry.901955710", userDto.getFirstName() + " " + userDto.getLastName()) // Your Name
                .queryParam("entry.1208336345", "up to 10,000 Messages / month") // Estimated monthly messages volume
                .queryParam("entry.1259584144", userDto.getEmail()) // Your Email Address
                .queryParam("entry.1489275520", userDto.getBrandName()) // Brand Name
                .queryParam("entry.1510504567", country + " " + userDto.getCountryCode().toString()) // Phone number's country code
                .queryParam("entry.1595895866", userDto.getCompanyName()) // Company Name
                .queryParam("entry.1602423798", userDto.getEmail()) // Email address(s) to be added to the WhatsApp Manager
                .queryParam("entry.1731935104", "No") // Is your chosen WhatsApp phone number a Vonage long virtual number (LVN)?
                .queryParam("entry.1807529240", "Not sure") // Estimated peak messages per second: indicate daily, weekly, or monthly.
                .queryParam("entry.2012164249", "Other/ Don't know") // What is your business vertical?
                .queryParam("entry.292494179", "") // Partner Name
                .queryParam("entry.565847730", "") // Other Email Addresses to be CC'd
                .queryParam("entry.1792374253", "") // Vonage Account Manager's email address
                .queryParam("entry.166684008", userDto.getFbBusinessManagerId()) // Company Facebook Business Manager ID
                .queryParam("entry.1328375169", "") // Company Facebook URL
                .queryParam("entry.1366161341", "") // Company website
                .queryParam("entry.1461623644", sampleWhatsappMessage) // Please provide example message(s) you would be sending over WhatsApp
                .queryParam("entry.309718730", "1000") // What is your expected monthly spend on this project?
                .queryParam("entry.1279938927", ""); // Any Additional Notes

        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", "*/*");
        headers.set("User-Agent", "Mozilla/5.0");
        HttpEntity<?> entity = new HttpEntity<>(headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(builder.toUriString(), entity, String.class);
            log.info("Successfully sent google from to Vonage. Response: {}", response.getBody());
            return true;

        } catch (Exception e) {
            log.error("Unable to send google form to vonage. Error: {}", e.getMessage());
            return false;
        }
    }
生成的请求URL
https://docs.google.com/forms/d/e/1FAIpQLSeb_QX8rdKD2WOM5-0rZ10C9rzPsMzqlGL-Aduh7_nM0EEutw/formResponse?submit=Submit&entry.294840288=Both%20of%20the%20above&entry.305369145=3326252240&entry.365096862=38f794d8&entry.400495561=tbc&entry.631769330=South%20East%20Asia%20(SEA)&entry.901955710=Umaid%20Ashraf&entry.1208336345=up%20to%2010,000%20Messages%20/%20month&entry.1259584144=umaidashraf0@gmail.com&entry.1489275520=Devestem&entry.1510504567=Pakistan%2092&entry.1595895866=Devestem&entry.1602423798=umaidashraf@gmail.com&entry.1731935104=No&entry.1807529240=Not%20sure&entry.2012164249=Other/%20Don't%20know&entry.292494179=&entry.565847730=&entry.1792374253=&entry.166684008=121026849979786&entry.1328375169=&entry.1366161341=&entry.1461623644=Hi%20David!%20Your%20Order%20is%20booked%20and%20it%20will%20be%20delivered%20in%20two%20days.%20Thanks%20for%20trusting%20us.&entry.309718730=1000&entry.1279938927=
排查与解决方案

问题根源在于请求方式和参数传递逻辑不匹配,以及编码细节差异:

  1. 请求方式不符合预期:Google表单默认期望POST请求将数据放在请求体(x-www-form-urlencoded格式),而非URL查询参数。浏览器/Postman能兼容URL参数的提交方式,但RestTemplate发送空请求体+URL参数的POST请求时,服务器对下拉选项这类有固定值限制的字段校验更严格,从而触发400错误。

  2. 编码规则差异:UriComponentsBuilder的字符编码规则和浏览器存在细微差别,比如单引号'、斜杠/的处理,下拉选项文本对编码准确性要求更高,一旦编码不一致就会导致服务器识别失败。

修复步骤:

  • 改用表单提交格式:将参数放在请求体中,以x-www-form-urlencoded格式发送,不再拼在URL里。调整后的代码如下:
public Boolean submitGoogleFormV2(UserDto userDto) {
    String sampleWhatsappMessage = "Hi David! Your Order is booked and it will be delivered in two days. Thanks for trusting us.";
    String country = new Locale("en", PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(userDto.getCountryCode())).getDisplayCountry();

    // 构建表单参数
    MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
    formParams.add("submit", "Submit");
    formParams.add("entry.294840288", "Both of the above");
    formParams.add("entry.305369145", userDto.getPhoneNumber());
    formParams.add("entry.365096862", vonageApiProperties.getMasterKey());
    formParams.add("entry.400495561", "tbc");
    formParams.add("entry.631769330", userDto.getRegion().getText());
    formParams.add("entry.901955710", userDto.getFirstName() + " " + userDto.getLastName());
    formParams.add("entry.1208336345", "up to 10,000 Messages / month");
    formParams.add("entry.1259584144", userDto.getEmail());
    formParams.add("entry.1489275520", userDto.getBrandName());
    formParams.add("entry.1510504567", country + " " + userDto.getCountryCode().toString());
    formParams.add("entry.1595895866", userDto.getCompanyName());
    formParams.add("entry.1602423798", userDto.getEmail());
    formParams.add("entry.1731935104", "No");
    formParams.add("entry.1807529240", "Not sure");
    formParams.add("entry.2012164249", "Other/ Don't know");
    formParams.add("entry.292494179", "");
    formParams.add("entry.565847730", "");
    formParams.add("entry.1792374253", "");
    formParams.add("entry.166684008", userDto.getFbBusinessManagerId());
    formParams.add("entry.1328375169", "");
    formParams.add("entry.1366161341", "");
    formParams.add("entry.1461623644", sampleWhatsappMessage);
    formParams.add("entry.309718730", "1000");
    formParams.add("entry.1279938927", "");

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    headers.set("User-Agent", "Mozilla/5.0");

    HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(formParams, headers);

    try {
        ResponseEntity<String> response = restTemplate.postForEntity(GOOGLE_FORM_URL_V2, entity, String.class);
        log.info("Successfully sent google form to Vonage. Response: {}", response.getBody());
        return true;
    } catch (Exception e) {
        log.error("Unable to send google form to vonage. Error: {}", e.getMessage());
        return false;
    }
}
  • 验证下拉选项文本:确保传递的下拉选项文本和Google表单后台的选项完全一致,包括空格、标点符号,比如"Other/ Don't know"要和表单内的选项完全匹配,避免因文本不一致触发400错误。

内容的提问来源于stack exchange,提问作者umaid ashraf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:37:04