如何将MOT历史API的CURL转为Android Java代码解决403认证错误
问题:Android调用MOT历史API返回403未授权错误
我尝试实现MOT历史API,其提供的CURL示例通过在线工具测试时,使用给定的API密钥可成功运行。但在Android中用HttpPost实现时,请求返回403状态码,提示“未授权——请求头中的x-api-key缺失或无效”,但密钥本身是有效的。
我的代码如下:
//Tried with full URL and by adding the registration as a header. //HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + reg_selected); HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests"); httpPost.addHeader("Content-Type", "application/json"); httpPost.addHeader("Accept", "application/json+v6"); httpPost.addHeader("x-api-key", "abcdefgh123456"); httpPost.addHeader("registration", reg_selected); StringEntity entity = new StringEntity(jsonObj.toString(), HTTP.UTF_8); httpPost.setEntity(entity); HttpClient client = new DefaultHttpClient(); try { HttpResponse response = client.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) { InputStream inputStream = response.getEntity().getContent(); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String readLine = bufferedReader.readLine(); String jsonStr = readLine; JSONObject myJsonObj = new JSONObject(jsonStr); }else if (response.getStatusLine().getStatusCode() == 400){ //Bad Request Invalid data in the request. Check your URL and parameters error_text = "Bad Request"; }else if (response.getStatusLine().getStatusCode() == 403){ //Unauthorised – The x-api-key is missing or invalid in the header error_text = "Authentication error"; //<<<< FAILS HERE 403 } } catch (Exception e) { // 异常处理 }
请问如何正确将该CURL转换为Android Java代码,避免服务器返回403错误?
解决方案
核心问题分析
- 请求方式错误:该MOT历史API的车辆查询接口实际为GET请求,而非你使用的POST请求,服务器会拒绝不符合要求的请求方式,导致403。
- 参数传递错误:
registration(车牌)应作为URL查询参数传递,而非放在请求头中。 - 使用废弃API:
DefaultHttpClient在Android 6.0(API 23)后已被废弃,存在兼容性和安全问题,建议改用HttpURLConnection或OkHttp。
修正后的代码示例(使用OkHttp,推荐)
首先在build.gradle中添加OkHttp依赖:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
然后编写请求代码:
String apiKey = "abcdefgh123456"; String registration = reg_selected; // 对车牌参数进行URL编码,避免特殊字符导致请求异常 String encodedReg = URLEncoder.encode(registration, "UTF-8"); String url = "https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + encodedReg; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(url) .addHeader("Accept", "application/json+v6") .addHeader("x-api-key", apiKey) .get() // 明确指定GET请求 .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { // 请求失败处理 e.printStackTrace(); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { // 解析响应 String jsonStr = response.body().string(); try { JSONObject myJsonObj = new JSONObject(jsonStr); // 处理返回数据 } catch (JSONException e) { e.printStackTrace(); } } else { switch (response.code()) { case 400: error_text = "Bad Request"; break; case 403: error_text = "Authentication error"; break; default: error_text = "Request failed with code: " + response.code(); } } } });
使用HttpURLConnection的替代方案
如果你不想引入第三方库,也可以用原生的HttpURLConnection:
String apiKey = "abcdefgh123456"; String registration = reg_selected; String encodedReg = URLEncoder.encode(registration, "UTF-8"); String urlStr = "https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + encodedReg; // 网络请求必须在子线程执行 new Thread(() -> { HttpURLConnection connection = null; BufferedReader reader = null; try { URL url = new URL(urlStr); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "application/json+v6"); connection.setRequestProperty("x-api-key", apiKey); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } String jsonStr = sb.toString(); JSONObject myJsonObj = new JSONObject(jsonStr); // 处理返回数据 } else { switch (responseCode) { case HttpURLConnection.HTTP_BAD_REQUEST: error_text = "Bad Request"; break; case HttpURLConnection.HTTP_FORBIDDEN: error_text = "Authentication error"; break; default: error_text = "Request failed with code: " + responseCode; } } } catch (Exception e) { e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start();
注意事项
- 所有网络请求必须在子线程中执行,避免触发Android主线程网络操作限制。
- 务必对
registration参数进行URL编码,防止特殊字符(如空格、符号)导致请求格式错误。 - 确认API密钥与CURL测试时完全一致,无额外空格或特殊字符。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

