| | |
| | | |
| | | |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.security.MessageDigest; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Base64; |
| | | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang.StringUtils; |
| | | import org.apache.http.HttpResponse; |
| | | import org.apache.http.client.ClientProtocolException; |
| | | import org.apache.http.client.config.RequestConfig; |
| | | import org.apache.http.client.methods.HttpPost; |
| | | import org.apache.http.entity.ContentType; |
| | |
| | | import org.apache.http.impl.client.CloseableHttpClient; |
| | | import org.apache.http.impl.client.HttpClientBuilder; |
| | | import org.apache.http.util.EntityUtils; |
| | | import org.springframework.core.io.ClassPathResource; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | |
| | |
| | | |
| | | private final String url = "https://wycapi.jtj.gz.gov.cn/api/app/common/binapi"; |
| | | |
| | | private final String filePath = "src/main/resources/files/"; |
| | | private static final String PTJB_SYMBOL = "XPQCB67N_S0612018007357G"; |
| | | |
| | | private static final String PROTOCOL_VERSION = "V2.0"; |
| | | |
| | | private static final DateTimeFormatter FILE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); |
| | | |
| | | private static final DateTimeFormatter DATA_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public String getToken(){ |
| | | try { |
| | | String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")); |
| | | String format = LocalDateTime.now().format(FILE_TIME_FORMATTER); |
| | | String filename = platform + "_TOKEN_ACCESS_REQ_" + format + ".json"; |
| | | HttpPost post = new HttpPost(url); |
| | | JSONObject body = new JSONObject(); |
| | | body.put("platform", platform); |
| | | body.put("key", key); |
| | | InputStream in = new ByteArrayInputStream(body.toJSONString().getBytes("UTF-8")); |
| | | String md5 = hash(in); |
| | | in.reset(); |
| | | return uploadJsonFile(filename, body.toJSONString(), platform); |
| | | }catch (Exception e){ |
| | | log.error("获取交通部token失败", e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 报送网约车平台公司基本信息(PTJB) |
| | | * |
| | | * @return 监管平台原始响应 |
| | | */ |
| | | public String pushPlatformBaseInfo() { |
| | | String token = parseToken(getToken()); |
| | | JSONObject item = buildPlatformBaseInfo(); |
| | | JSONObject body = new JSONObject(); |
| | | JSONArray items = new JSONArray(); |
| | | items.add(item); |
| | | body.put("items", items); |
| | | |
| | | String format = LocalDateTime.now().format(FILE_TIME_FORMATTER); |
| | | String filename = platform + "_BASIC_PTJB_REQ_" + format + ".json"; |
| | | return uploadJsonFile(filename, body.toJSONString(), token); |
| | | } |
| | | |
| | | private JSONObject buildPlatformBaseInfo() { |
| | | JSONObject item = new JSONObject(); |
| | | item.put("symbol", PTJB_SYMBOL); |
| | | item.put("companyId", companyId); |
| | | item.put("companyName", "广州易点智慧出行科技有限公司"); |
| | | item.put("identifier", "91440101MA5AWEB67N"); |
| | | item.put("contactPhone", "18306304567"); |
| | | item.put("address", "440000"); |
| | | item.put("businessScope", "网络预约出租汽车客运"); |
| | | item.put("contactAddress", "广州市天河区岑村丰庄大街10号T2"); |
| | | item.put("economicType", "159"); |
| | | item.put("regCapital", "壹仟万元(人民币)"); |
| | | item.put("legalName", "陈志远"); |
| | | item.put("legalId", "445221199101121937"); |
| | | item.put("legalPhone", "15915905487"); |
| | | item.put("legalPhoto", encodePdf("陈志远新复印件.pdf")); |
| | | item.put("legalPhotoId", ""); |
| | | item.put("identifierPhoto", encodePdf("易点智慧出行-营副-20250716.pdf")); |
| | | item.put("state", "0"); |
| | | item.put("flag", "1"); |
| | | item.put("updateTime", LocalDateTime.now().format(DATA_TIME_FORMATTER)); |
| | | item.put("serviceItem", "网络预约出租汽车服务"); |
| | | item.put("servicePromise", "严格遵守国家及地方有关网络预约出租汽车经营的法律法规及行业规范,依法取得相关许可,证照齐全、亮证经营"); |
| | | item.put("protocolVersion", PROTOCOL_VERSION); |
| | | return item; |
| | | } |
| | | |
| | | private String encodePdf(String filename) { |
| | | if (StringUtils.isBlank(filename)) { |
| | | return ""; |
| | | } |
| | | String resourcePath = "files/" + filename.trim(); |
| | | ClassPathResource resource = new ClassPathResource(resourcePath); |
| | | try { |
| | | long contentLength = resource.contentLength(); |
| | | if (contentLength > 10 * 1024 * 1024) { |
| | | throw new RuntimeException("文件超过10M: " + filename); |
| | | } |
| | | try (InputStream inputStream = resource.getInputStream()) { |
| | | byte[] bytes = new byte[(int) contentLength]; |
| | | int offset = 0; |
| | | int read; |
| | | while (offset < bytes.length && (read = inputStream.read(bytes, offset, bytes.length - offset)) != -1) { |
| | | offset += read; |
| | | } |
| | | if (offset != bytes.length) { |
| | | throw new RuntimeException("文件读取不完整: " + filename); |
| | | } |
| | | return Base64.getEncoder().encodeToString(bytes); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("读取PDF文件失败: " + filename, e); |
| | | } |
| | | } |
| | | |
| | | private String uploadJsonFile(String filename, String jsonBody, String auth) { |
| | | try { |
| | | byte[] bytes = jsonBody.getBytes("UTF-8"); |
| | | String md5 = hash(new ByteArrayInputStream(bytes)); |
| | | HttpPost post = new HttpPost(url); |
| | | MultipartEntityBuilder builder = MultipartEntityBuilder.create(); |
| | | post.addHeader("binfile-md5", md5); |
| | | post.addHeader("binfile-auth", platform); |
| | | post.addHeader("binfile-auth", auth); |
| | | post.addHeader("binfile-gzip", "false"); |
| | | post.addHeader("binfile-reqlen", String.valueOf(in.available())); |
| | | builder.addBinaryBody("binFile", in, ContentType.DEFAULT_BINARY, filename);// 文件 |
| | | post.addHeader("binfile-reqlen", String.valueOf(bytes.length)); |
| | | builder.addBinaryBody("binFile", new ByteArrayInputStream(bytes), ContentType.DEFAULT_BINARY, filename); |
| | | builder.addTextBody("filename", filename, ContentType.create(ContentType.DEFAULT_TEXT.getMimeType(), "UTF-8")); |
| | | post.setEntity(builder.build()); |
| | | |
| | | int connTimeout = 10000; |
| | | int soTimeout = -1; |
| | | |
| | | HttpClientBuilder clientBuilder = HttpClientBuilder.create(); |
| | | RequestConfig.Builder configBuilder = RequestConfig.custom(); |
| | | if (connTimeout > 0) configBuilder.build(); |
| | | if (soTimeout > 0) configBuilder.setSocketTimeout(soTimeout); |
| | | clientBuilder.setDefaultRequestConfig(configBuilder.build()); |
| | | if (!false) clientBuilder.disableContentCompression(); |
| | | CloseableHttpClient client = clientBuilder.build(); |
| | | HttpResponse response = client.execute(post); |
| | | |
| | | log.info("response.toString() = \n"+response.toString()); |
| | | log.info("response.getStatusLine().getStatusCode() = \n"+response.getStatusLine().getStatusCode()); |
| | | InputStream ins = response.getEntity().getContent(); |
| | | byte[] s = new byte[1024]; |
| | | while(ins.read(s,0,1024) != -1){ |
| | | String str = new String(s,"UTF-8"); |
| | | System.out.println(str); |
| | | RequestConfig requestConfig = RequestConfig.custom() |
| | | .setConnectTimeout(10000) |
| | | .build(); |
| | | clientBuilder.setDefaultRequestConfig(requestConfig); |
| | | clientBuilder.disableContentCompression(); |
| | | try (CloseableHttpClient client = clientBuilder.build()) { |
| | | HttpResponse response = client.execute(post); |
| | | String responseBody = response.getEntity() == null ? "" : EntityUtils.toString(response.getEntity(), "UTF-8"); |
| | | log.info("交通部接口响应 status={}, filename={}, responseLength={}", |
| | | response.getStatusLine().getStatusCode(), filename, responseBody.length()); |
| | | return responseBody; |
| | | } |
| | | log.info("内容:"+ EntityUtils.toString(response.getEntity())); |
| | | return EntityUtils.toString(response.getEntity()); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("上传交通部接口文件失败: " + filename, e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private String parseToken(String tokenResponse) { |
| | | if (StringUtils.isBlank(tokenResponse)) { |
| | | throw new RuntimeException("交通部token响应为空"); |
| | | } |
| | | try { |
| | | JSONObject response = JSON.parseObject(tokenResponse); |
| | | String token = response.getString("token"); |
| | | if (StringUtils.isNotBlank(token)) { |
| | | return token; |
| | | } |
| | | JSONArray items = response.getJSONArray("items"); |
| | | if (items != null && !items.isEmpty()) { |
| | | token = items.getJSONObject(0).getString("token"); |
| | | if (StringUtils.isNotBlank(token)) { |
| | | return token; |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("解析交通部token失败: " + tokenResponse, e); |
| | | } |
| | | throw new RuntimeException("交通部token响应中未找到token: " + tokenResponse); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | private static char[] commonDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
| | | |
| | | public static void main(String[] args) throws ClientProtocolException, IOException |
| | | { |
| | | |
| | | } |
| | | |
| | | public static String hash(InputStream in) |
| | | { |