代码借鉴海关179对接API.(如有侵权马上删除)

步骤

  • 拿到ukey(运营或产品哪里应该会有)
  • 获取开发文档179号开发文档
  • 开发接收海关请求接口(按文档要求不能有端口号)
  • 组装数据进行加签
  • 拼接加签数据上报
  • 完成

以上文档等不多介绍主要是开发(身为CV工程师直接上代码)

接收海关请求
接收海关请求并存储请求(因为加签需要在本地而接收请求要在开放服务器所以使用mq传输数据)

@PostMapping(value = "/platDataOpen")@ResponseBodypublic JSONObject platDataOpen(@RequestParam String openReq){//解析获取数据openReq = StringUtils.replace(openReq, """, "\"");JSONObject jsonObject = JSONObject.parseObject(openReq);String orderNo = jsonObject.getString("orderNo");String sessionID = jsonObject.getString("sessionID");Long serviceTime = jsonObject.getLong("serviceTime");System.out.println(orderNo+sessionID+serviceTime);//查询是否有订单String source = customsService.insertCustoms(orderNo,sessionID,serviceTime);JSONObject result = new JSONObject();if (source.equals("10000")){result.put("code", "10000");result.put("message", "");}else{result.put("code", "205");result.put("message", "没有此订单");}result.put("serviceTime", System.currentTimeMillis());return result;}
@ResourceRabbitTemplate rabbitTemplate;/*** 添加请求数据* @param orderNo* @param sessionID* @param serviceTime* @return*/@Overridepublic String insertCustoms(String orderNo, String sessionID, Long serviceTime) {logger.info("海关抽查订单"+orderNo);OmsOrderExample omsOrderExample = new OmsOrderExample();omsOrderExample.createCriteria().andOrderSnEqualTo(orderNo);List<OmsOrder> omsOrders = omsOrderMapper.selectByExample(omsOrderExample);//判断是否有指定订单if(omsOrders.size()>0){//查询是否存在订单号PaycheckExample example = new PaycheckExample();example.createCriteria().andOrderNoEqualTo(orderNo);List<Paycheck> paychecks = paycheckMapper.selectByExample(example);if(paychecks.size()>0){paychecks.get(0).setSessionId(sessionID);int num = paycheckMapper.updateByPrimaryKey(paychecks.get(0));if(num>0){System.out.println("修改成功");}}else{Paycheck paycheck = new Paycheck();paycheck.setOrderNo(orderNo);paycheck.setSessionId(sessionID);paycheck.setAddTime(new Date());paycheck.setStatus((byte) 0);paycheck.setBackTime(new Date());int num = paycheckMapper.insert(paycheck);if (num>0){System.out.println("添加成功");}}logger.info("发送消息到CUSTOMS_EXPORT_QUEUE");rabbitTemplate.convertAndSend(DirectRabbitConfig.CUSTOMS_EXPORT_EXCHANGE,DirectRabbitConfig.CUSTOMS_EXPORT_ROUTING,orderId);//webscoketTest(orderNo);return "10000";}return "205";}

创建实体类存放数据

import lombok.Data;import java.util.List;/*** @author qjy* @Explanation* @create 2021-11-07 18:30*/
@Data
@JSONType(orders={"sessionID","payExchangeInfoHead","payExchangeInfoLists","serviceTime","certNo","signValue"})
public class HaiguanVO {//@JSONType很重要作用就是JSON化的时候数据的排序//@JSONType(orders={"sessionID","payExchangeInfoHead","payExchangeInfoLists","serviceTime","certNo","signValue"})/** 海关发起请求时,平台接收的会话ID  */public String sessionID;public PayExchangeInfoHead payExchangeInfoHead;public List<PayExchangeInfoLists> payExchangeInfoLists;/** 返回时的系统时间 时间戳的字符串 */public String serviceTime;/** 证书编号  */public String certNo;/** 签名结果值  */public String signValue;}
package com.example.customsspotcheck.vo;import com.alibaba.fastjson.annotation.JSONType;
import lombok.Data;/*** @author qjy* @Explanation* @create 2021-11-07 18:31*/
@Data
@JSONType(orders={"guid","initalRequest","initalResponse","ebpCode","payCode","payTransactionId","totalAmount","currency","verDept","tradingTime"})
public class PayExchangeInfoHead {/** 系统唯一序号  */public String guid;/** 支付原始请求  */public String initalRequest;/** 支付原始响应  */public String initalResponse;/** 电商平台代码  */public String ebpCode;/** 支付企业代码  */public String payCode;/** 交易流水号  */public String payTransactionId;/** 交易金额 单位:元 */public Double totalAmount;/** 币制  人民币:142 */public String currency;/** 验核机构  */public String verDept;/** 支付类型(非必填所以不填)  *///public String payType;/** 交易成功时间 */public String tradingTime;/** 备注 (非必填所以不填) *///public String note;
}
package com.example.customsspotcheck.vo;import com.alibaba.fastjson.annotation.JSONType;
import lombok.Data;import java.util.List;/*** @author qjy* @Explanation* @create 2021-11-07 18:32*/
@Data
@JSONType(orders={"orderNo","goodsInfo","recpAccount","recpCode","recpName"})
public class PayExchangeInfoLists {/** 订单编号  */public String orderNo;/** 商品信息  */public List<goodsInfo> goodsInfo;/** 收款账号  */public String recpAccount;/** 收款企业代码  */public String recpCode;/** 收款企业名称  */public String recpName;}
package com.example.customsspotcheck.vo;import com.alibaba.fastjson.annotation.JSONType;
import lombok.Data;/*** @author qjy* @Explanation* @create 2021-11-07 18:39*/
@Data
@JSONType(orders={"gname","itemLink"})
public class goodsInfo {/** 商品名称  */public String gname;/** 商品展示链接地址  */public String itemLink;}

以上是全部的实体类(通过自己的情况查询数据添加即可)

接下来是加签
加签是获取signValue海关会验签
加签有js加签 websocket加签 (本人纯后端前端不太会所以使用websocket加签)
websocket加签要有一个操作员的卡(一个U盘)
插入后启动


就会在本地开放两个个websocket服务
请求地址:
ws://127.0.0.1:61232
wss://wss.singlewindow.cn:61231

编写websocket加签代码

首先组装数据

package com.example.customsspotcheck.service.impl;import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;import com.alibaba.fastjson.JSONObject;
import com.example.customsspotcheck.mapper.PaycheckDao;
import com.example.customsspotcheck.service.HaiguanService;
import com.example.customsspotcheck.util.HaiguanSign;
import com.example.customsspotcheck.vo.HgCheckVO;
import org.apache.http.Consts;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;/*** @author qjy* @Explanation* @create 2021-11-08 9:39*/
@Service
public class HaiguanServiceImpl implements HaiguanService {@ResourceHaiguanSign haiguanSign;@Value(value = "${spring.customs.haiguan.certNo}")private String certNo;@Value(value = "${spring.customs.haiguan.password}")private String password;@Value(value = "${spring.customs.haiguan.uploadUrl}")private String uploadUrl;@ResourcePaycheckDao paycheckDao;/*** 组装数据进行加签* @param entity*/@Overridepublic void repDataApply(HgCheckVO entity) {/*加签成海关指定数据格式(4项:不能多不能少)*/StringBuffer sb = new StringBuffer();sb.append("\"sessionID\":\"").append(entity.getSessionID()).append("\"").append("||");String headerString = JSON.toJSONString(entity.getPayExchangeInfoHead(), SerializerFeature.SortField);sb.append("\"payExchangeInfoHead\":\"").append(headerString).append("\"").append("||");String listString = JSON.toJSONString(entity.getPayExchangeInfoLists(), SerializerFeature.SortField);sb.append("\"payExchangeInfoLists\":\"").append(listString).append("\"").append("||");sb.append("\"serviceTime\":\"").append(entity.getServiceTime()).append("\"");String signValue = sb.toString();//组装加签数据Map<String,String> args = new java.util.HashMap<>();args.put("inData", signValue);args.put("passwd", password);JSONObject epdata = new JSONObject(true);epdata.put("_method", "cus-sec_SpcSignDataAsPEM");epdata.put("_id", 1);epdata.put("args", args);//加签(使用websocket加签)haiguanSign.sign(epdata,entity);}/*** 上报海关* @param entity*/@Overridepublic void shangbao(HgCheckVO entity) {//吧获取到的全部数据转JSON然后上报给海关System.out.println("---海关179数据上报数据:payExInfoStr=" + JSON.toJSONString(entity));try {List<NameValuePair> param = new ArrayList<NameValuePair>();//组装数据param.add(new BasicNameValuePair("payExInfoStr", JSON.toJSONString(entity)));CloseableHttpClient client = getHttpsClient();HttpPost post = new HttpPost(uploadUrl);post.setEntity(new UrlEncodedFormEntity(param,Consts.UTF_8));try {CloseableHttpResponse xx = client.execute(post);if(HttpStatus.SC_OK == xx.getStatusLine().getStatusCode()) {String result = EntityUtils.toString(xx.getEntity(), Consts.UTF_8);System.out.println("---海关179数据上报结果:" + result);//解析返回数据表Map mapType = JSON.parseObject(result,Map.class);//获取订单idString OederSn = entity.getPayExchangeInfoLists().get(0).getOrderNo();System.out.println(mapType.get("code"));if(mapType.get("code").equals("10000")){System.out.println("上传成功:"+OederSn);//修改上报状态paycheckDao.updatePaycheck(OederSn,1);}else{System.out.println("上传失败:"+OederSn);//修改上报状态paycheckDao.updatePaycheck(OederSn,2);}}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}catch (Exception e){}}private static CloseableHttpClient getHttpsClient(){SSLConnectionSocketFactory sslsf = null;try {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}}).build();sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {return true;}@Overridepublic void verify(String host, SSLSocket ssl) throws IOException {}@Overridepublic void verify(String host, X509Certificate cert) throws SSLException {}@Overridepublic void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {}});} catch (GeneralSecurityException e) {e.printStackTrace();}return HttpClients.custom().setSSLSocketFactory(sslsf).build();}
}
package com.example.customsspotcheck.util;import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;import com.example.customsspotcheck.service.HaiguanService;
import com.example.customsspotcheck.vo.HgCheckVO;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import javax.annotation.Resource;/*** @author qjy* @Explanation* @create 2021-11-08 9:43*/@Service
public class HaiguanSign {private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(HaiguanSign.class);/*** 超时时间*/public static final Integer TIME_OUT = 3 * 60 * 1000;/*** 时间步长*/public static final Integer TIME_STEP = 10;@Value(value = "${spring.customs.haiguan.sign.wsUrl}")private String wsUrl;@Value(value = "${spring.customs.haiguan.certNo}")private String certNo;@ResourceHaiguanService haiguanService;/*** 保存WebSocket链接*/private Map<String, WebSocketClient> clientPool = new HashMap<>();/*** 海关数据加签。<br>** @param value*            待加签后的值.<br>* @return signValue加签后的值.<br>*/public String sign(JSONObject value, HgCheckVO entity) {System.out.println("请求加签报文->" + value);WebSocketClient client = clientPool.get(wsUrl);if (client != null && client.isConnecting() && client.isOpen()) {client.send(String.valueOf(value));} else {try {client = new WebSocketClient(new URI(wsUrl)) {@Overridepublic void onOpen(ServerHandshake shake) {// TODO Auto-generated method stubSystem.out.println("握手...");for (Iterator<String> it = shake.iterateHttpFields(); it.hasNext();) {String key = it.next();System.out.println(key + "->" + shake.getFieldValue(key));}}@Overridepublic void onMessage(String message) {// TODO Auto-generated method stubif (!StringUtils.isEmpty(message)) {System.out.println("接收到消息:" + message);JSONObject jsonObject = JSON.parseObject(String.valueOf(message));Integer id = jsonObject.getInteger("_id");if (id != null && id == 0) {System.out.println("根据海关ws报文,第一次回复为握手通知,并非'加签'信息!");//第一次(id=0)} else if (id != null && id == 1) {JSONArray data = jsonObject.getJSONObject("_args").getJSONArray("Data");String signValue = data.getString(0);/** 证书编号  */entity.setCertNo(certNo);/** 签名结果值  */entity.setSignValue(signValue);//上报数据haiguanService.shangbao(entity);}}}@Overridepublic void onClose(int code, String reason, boolean remote) {// TODO Auto-generated method stubSystem.out.println("-----------close()");}@Overridepublic void onError(Exception ex) {// TODO Auto-generated method stubSystem.out.println("-----------onError:"+ex.getMessage());}};} catch (URISyntaxException e) {e.printStackTrace();System.out.println("--------->websocket client exception.");}client.connect();Integer count = 0;// 阻塞等待OPENwhile (!client.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {try {count += TIME_STEP;Thread.sleep(TIME_STEP);if (count >= TIME_OUT) {LOGGER.info("error-{}", new Exception("WS服务器连接超时!或服务器已经关闭"));break;}} catch (InterruptedException e) {LOGGER.error("发送信息异常-{}", e);}}client.send(String.valueOf(value));// 放入缓存clientPool.put(wsUrl, client);}return "";}
}

以上就是海关179对接如有疑问可以留言(海关179对接过最坑的没有之一)

JAVA版海关179号对接流程相关推荐

  1. 项目总结24:海关179号(实时获取电商平台企业支付相关原始数据)开发流程和相关资料...

    项目总结24:海关179号(实时获取跨境电子商务平台企业支付相关原始数据接入)开发流程和相关资料 欢迎大家留言探讨 1.致谢 感谢:https://blog.csdn.net/ccbox_net/ar ...

  2. 我的世界电脑java版服务器,《我的世界》中国版PC Java版不限号 Hypixel闪电饥饿游戏...

    随着<我的世界>中国版PC Java版不限号测试正式开启,喜欢探索与创造的冒险家们,终于能够零门槛地回归这片无比自由的方块世界. 除了基础的生存和创造模式,遍布全球的游戏玩家,基于< ...

  3. 海关179号公告对接联调

    从2019年4月1日开始,所有跨境电商平台必须对接支付源,也就是179号公告:经过这么久的完善,终于有一位大神将这个对接联调全部完善了. 链接: 完善文档.

  4. 海关179号公文接入

    179号公文对接 上海公服示例 package net.shop.controller.admin.warehouse;import cn.hutool.core.codec.Base64; impo ...

  5. java版微信公众号支付

    前言 今天是2020-4-1愚人节,好久没写博客了,今天准备写一篇微信公众号支付,刚好公司给了我账户,让我有参数测试,由于以前对于支付是小白,所以把这个功能打通花了2天,一天8小时,首先看官网文档,其 ...

  6. 山东单一窗口-跨境进口报文上报方案(海关179/报关对接)

    >>上报报文类型,2种 CEB311Message.xml, 电子订单 CEB621Message.xml,电子清单 只能上报这两种 海关的所有对接都是, 电商企业推送到二级节点, 由二级 ...

  7. 记录海关165号、179号个人流程整理-JAVA版

    首先,非常感谢前人的努力,开发是依照此文档进行,在此主要给出个人的流程图及JAVA版本注意的地方. 转载学习文档:https://blog.csdn.net/ccbox_net/article/det ...

  8. 微信服务号对接流程记录

    项目背景 以web为主,以微信服务号为媒介,进行用户绑定.并通过菜单进入相应页面进行操作 技术栈 React进行微信对接,页面展示 Java负责数据获取 开始 RTFM,不过看微信的文档确实头疼,感觉 ...

  9. 海关179号出口运单报文CEB505Message描述规范

    海关出口报文规范 CEB505Message运单报文描述 名称 英文名称 类型 必填 说明 报文编号 guid an36 是 报文的36位系统唯一序号(英文字母大写). 版本号 version an. ...

最新文章

  1. 服务器中加速BIOS启动的方法
  2. spring中事务控制的一组API
  3. php dump utfp,php pchart乱码-使用REST接口获取GeoServer中的...-结合 thinkPHP 分页写成自己分页类_169IT.COM...
  4. 【渝粤题库】陕西师范大学163202 管理学原理 作业(高起本 专升本)
  5. meta http-equiv=X-UA-Compatible content=IE=edge / 的说明
  6. word 2007如何插入参考文献引用
  7. php取到的时间总是差8小时的解决方法
  8. 图书管理系统 C语言
  9. C语言练习——判断位数
  10. layui 表格前端分页
  11. 迅捷在线PDF转换成Word转换器简介
  12. day01 pathon基础
  13. 2022新版域名防红系统源码
  14. java+ssm的班级同学录聚会报名网站
  15. Windows与USB的通信
  16. 玩安卓从 0 到 1 之架构思考
  17. iOS 自动订阅开发
  18. 第二章 Binary Search
  19. 【转】嵌入式开发正在日薄西山_有道理哦
  20. 云管理平台是个什么东西

热门文章

  1. 优波尔:QQ几个跳转的API接口
  2. 布局管理--grid
  3. QUIC协议设计(一)-QUIC的特点
  4. vb.net video设备数量_给新手写的便宜好用录音设备推荐(四)sE V7 X动圈话筒+guitaRF吉他音箱声学隔板...
  5. 科普| USB接口,你真的懂吗?
  6. 51中ret和reti的区别
  7. 爱丁堡大学的PMR(PMR in the University of Edinburgh)【1】
  8. 网络和计算机加密驱动,Win7电脑驱动器怎么加密?Win7系统给驱动器加密的方法和详细步骤...
  9. 阿里巴巴项目P8技术咖总结的Java心得,完整版PDF可下载
  10. C++分数加法(公式推导)