快递鸟电子面单打印功能基于java

陈灬大灬海      2022-04-17     445

关键词:

之前的后天管理系统的电子面单打印使用的是灵通打单。

使用相对比较麻烦,需要到处Excel之后再导入,麻烦。

快递鸟有电子面单api,后台系统直接对接很是方便,不过也遇到了好些问题。

不难是不难,但是遇到的坑着实是不少,特此记录一下。

快递鸟电子面单API地址:http://www.kdniao.com/api-eorder

都是在正式环境下,申请对应的商户id等一系列东西。

在对应的快递鸟后台,可以进行如下的批量打印。

想把这个打印功能集成到自己内部系统,可以下载官方的demo

跑起来挺容易的,直接放入tomcat运行就可以了

不过demo需要tomcat8.5,需要修改的话找到项目的.settings文件夹下有一个

org.eclipse.wst.common.project.facet.core.xml 将tomcat8.5修改为对应的版本就可以了。

官方demo代码

 

package cc.kdniao.api;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.xml.internal.messaging.saaj.util.Base64;

/**
 * Servlet implementation class printOrder
 */
@WebServlet("/printOrder")
public class printOrder extends HttpServlet {
    private static final long serialVersionUID = 1L;

    final String EBussinessID = "";//kdniao.com EBusinessID
    final String AppKey = ""; //kdniao.com AppKey
    final Integer IsPreview = 0; //是否预览 0-不预览 1-预览

    /**
     * @see HttpServlet#HttpServlet()
     */
    public printOrder() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //response.getWriter().append("Served at: ").append(request.getContextPath());
        PrintWriter print = response.getWriter();
        String jsonResult = "";
        try {
            String ip = getIpAddress(request);
            jsonResult = getPrintParam(ip);
        } catch (Exception e) {
            //write log
        }
        print.println(jsonResult);
        print.flush();
        print.close();
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, UnsupportedEncodingException {
        // TODO Auto-generated method stub
        response.setContentType("");
        PrintWriter print = response.getWriter();
        String jsonResult = "";
        try {
            String ip = getIpAddress(request);
            jsonResult = getPrintParam(ip);
        } catch (Exception e) {
            //wirte log
        }
        print.println(jsonResult);
        print.flush();
        print.close();
    }

    /**
     * get print order param to json string
     * @return
     * 
     * @throws Exception 
     */
    private String getPrintParam(String ip) throws Exception {
        String data = "[{\"OrderCode\":\"234351215333113311353\",\"PortName\":\"SF\"},{\"OrderCode\":\"234351215333113311354\",\"PortName\":\"打印机名称二\"}]";
        String result = "{\"RequestData\": \"" + URLEncoder.encode(data, "UTF-8") + "\", \"EBusinessID\":\"" + EBussinessID + "\", \"DataSign\":\"" + encrpy(ip + data, AppKey) + "\", \"IsPreview\":\""
                        + IsPreview + "\"}";
        return result;
    }

    private String md5(String str, String charset) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str.getBytes(charset));
        byte[] result = md.digest();
        StringBuffer sb = new StringBuffer(32);
        for (int i = 0; i < result.length; i++) {
            int val = result[i] & 0xff;
            if (val <= 0xf) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString().toLowerCase();
    }

    private String encrpy(String content, String key) throws UnsupportedEncodingException, Exception {
        String charset = "UTF-8";
        return new String(Base64.encode(md5(content + key, charset).getBytes(charset)));
    }

    /** 
     * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址; 
     *  
     * @param request 
     * @return 
     * @throws IOException 
     */
    public final static String getIpAddress(HttpServletRequest request) throws IOException {
        // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址  

        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

}

 

 

 

但是,需要注意的是,API有一个ip参数,获取这个ip快递鸟提供的方法是如下

 

// 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址  
    public final static String getIpAddress(HttpServletRequest request) throws IOException {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

 

注意这个方法是没有问题的,但是你如果直接输入快递单号OrderCode进行打印,这个时候提交总是说数据验证不通过,并不是签名问题,而是ip问题。

因为上一个方法只要是在局域网下面,即使能访问外网,也没用,获取到的ip永远都是内网ip

有一种方式可以在本地验证通过,那就是直接百度ip,只有会有自己的ip地址

OK,在后台将ip写死,就可以进行打印预览操作了。

打印需要安装lodop打印插件,安装完成之后访问 http://localhost:8000/CLodopfuncs.js 会有相应的控件js

需要对应的打印插件,必须要有设备(热敏打印机),要不我也不至于出差了。

之后根据打印机型号,进入对应的官网下载打印驱动。之后perfect,就可以进行打印了。

官方demo给的是servlet

我使用的是SpringMVC,将代码贴出。

final String EBussinessID = "12677**";//kdniao.com EBusinessID
    final String AppKey = "8e9dcb4b-f0a1-42f6-9d80-372a67f851**"; //kdniao.com AppKey
    final Integer IsPreview = 1; //是否预览 0-不预览 1-预览

    @RequestMapping("/getCloudPrintData.do")
    @ResponseBody
    public Map<String, Object> getCloudPrintData(HttpServletRequest request,String OrderCode,String ip) throws Exception{
        System.out.println("ok:"+OrderCode+"---"+ip);
        Map<String,Object> map = new HashMap<String, Object>();
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        Map<String,Object> dataMap = new HashMap<String, Object>();
        dataMap.put("OrderCode", OrderCode);
        dataMap.put("PortName", "Xprinter XP-DT108A LABEL");
        list.add(dataMap);
        String jsonString = JSONArray.fromObject(dataMap).toString();        
        map.put("RequestData", URLEncoder.encode(jsonString, "UTF-8"));
        if(StringUtils.isEmpty(ip)) {
            ip = getIpAddress(request);
        }
        map.put("DataSign",encrpy(ip + jsonString, AppKey));
        System.out.println("map:"+map);
        return map;
    }
    
    @RequestMapping("/getIpAddressByJava.do")
    @ResponseBody
    public String getIpAddressByJava(HttpServletRequest request) throws IOException {
        return getIpAddress(request);
    }
    
    private String encrpy(String content, String key) throws UnsupportedEncodingException, Exception {
        String charset = "UTF-8";
        return new String(Base64.encode(md5(content + key, charset).getBytes(charset)));
    }
    
    private String md5(String str, String charset) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str.getBytes(charset));
        byte[] result = md.digest();
        StringBuffer sb = new StringBuffer(32);
        for (int i = 0; i < result.length; i++) {
            int val = result[i] & 0xff;
            if (val <= 0xf) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString().toLowerCase();
    }
    
    // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址  
    public final static String getIpAddress(HttpServletRequest request) throws IOException {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

 

 对应的html

<body>
<script type="text/javascript">
    function fasong(){
        var orderNo = $("#orderNo").val();
        var ipAddress = $("#ipAddress").val();
        $.ajax({
            url:'/jeeadmin/jeecms/getCloudPrintData.do',
            data:{OrderCode:orderNo,ip:ipAddress},
            success:function(data){
                $("#RequestData").val(data.RequestData)
                $("#DataSign").val(data.DataSign)
            }
        })
    }
    function getIp(){
        $.ajax({
            url:'/jeeadmin/jeecms/getIpAddressByJava.do',
            success:function(data){
                alert(data);
            }
        })
    }
</script>
<h1>测试打印页面</h1>
    <div id="head"></div>
    <div>
        <input type="text" id="orderNo">
        <input type="text" id="ipAddress">
        <input type="button" onclick="fasong()" value="发送" />
    </div>
    <div>
        <input type="button" onclick="getIp()" value="获取ip地址通过java"/>
    </div>
    <form id="form1" action="http://www.kdniao.com/External/PrintOrder.aspx" method="post" target="_self">
        <div style="">
            <div><input type="text" id="RequestData" name="RequestData" readonly="readonly"/>请求数据</div>
            <div><input type="text" id="DataSign" name="DataSign" readonly="readonly"/>签名</div>
            <div><input type="text" id="EBusinessID" name="EBusinessID" value="1267739"/>商户id</div>
            <div><input type="text" id="IsPreview" name="IsPreview" value="1"/><span style="color: red;">是否预览 0-不预览 1-预览</span></div>
            <div><input type="submit" id="tijiao" value="打印" /></div>
        </div>
    </form>
</body>

 lodop有云打印机,目前并不清楚,需要的话可以再研究下。

 年轻人,fighting!!!

 

 

 

 

电子面单api接口_java调用示例

...操作打印电子面单。  目前电子面单接口类型有:快递公司自行提供接口、菜鸟电子面单接口、快递鸟电子面单接口。菜鸟电子面单接口、快递鸟电子面单接口接入方式类似,都支持15家快递查询,其 查看详情

顺丰电子面单api接口怎么接入?

...技术A目前我国电子面单的接口主要有三种方式,分别是快递公司电子面单接口、快递鸟电子面单接口、菜鸟电子面单接口1、快递公司接口由各个快递公司单独开发的接口,面向商家。商家需先注册账号申请对接,快递鸟与快递... 查看详情

关于快递鸟的顺丰电子面单打印(代码片段)

1.form表单传递数据,到控制器,之后的复制操作1顺丰信息2//快递信息3$eorder=[];4$eorder["ShipperCode"]=$express_number[$number];//快递公司编码5$eorder["OrderCode"]=$ship_order_data[‘ship_order_number‘];//发货单编号()67$eorder["PayType"]=3;// 查看详情

电商适用电子面单接口对接案例

电子面单接口现在有快递公司、菜鸟和快递鸟提供快递公司是一家家合作,要接口文档,逐一对接菜鸟和快递鸟是电子面单接口集成方,能打印多家快递电子面单,菜鸟目前支持15家,快递鸟支持20家,基本上都是常用的快递,... 查看详情

免费圆通电子面单接口对接

  电子面单接口是快递鸟提供给独立电商、仓储管理系统、物流供应链等物流系统平台使用的下单接口,满足客户在线发货需求并提供打印面单的服务,客户通过网络选择物流公司发送请求通知贵公司有快递要发货,把数... 查看详情

圆通电子面单接口对接及调试

  电子面单接口是快递鸟提供给独立电商、仓储管理系统、物流供应链等物流系统平台使用的下单接口,满足客户在线发货需求并提供打印面单的服务,客户通过网络选择物流公司发送请求通知贵公司有快递要发货,把数... 查看详情

各种电子面单-api接口(顺丰快递鸟菜鸟)(代码片段)

...子面单的意思可能并不是很了解;说白了,就是快递员给你打印的快递单的电子版。专业解释:电子面单是一种通过热敏纸打印输出纸质物流面单的物流服务。通过热感应显示文字&#x 查看详情

快递鸟打印电子面单数据验证不通过,非法参数

下载官方的批量打印面单Demo,修改成自己ID和Key后运行一直报错,提示“数据验证不通过,非法参数”等,   弄了半天没弄出个所以然,想了下应该是加密的问题,调试了下发现GetIp()获取到的ip地址既不是本机... 查看详情

快递---快递鸟的电子面单取消操作-----------

近期在对接快递接口,公司使用了第三方快递接口获取快递数据,这边由于业务需求,有可能会对已取号的快递电子面单做出处理为此自己东拉西扯总算完善了接口当然详细的明细还得各位有使用的朋友,自己去查看所提供的api... 查看详情

电子面单打印模板规格汇总以及使用指南

1.完成前期准备工作1.1,去快递鸟免费注册一个对接账号1.2,免费获得一个apiKey(接口权限验证需要)1.3,完成实名认证流程1.4,订购一个免费套餐1.5,准备打印机、打印纸打印机:???电子面单模板对打印机品牌、型号等没有要求,只要是... 查看详情

常用电子面单接口对接技术文档

 一.电子面单接口类型及定义1.快递电子面单接口:快递公司自己开发的电子面单服务,商家使用必须快递公司上门做系统对接,使用一家快递则需要对接一次。2.菜鸟电子面单接口:可一次对接15家快递公司,无需和每一家... 查看详情

各种电子面单_api接口

...作打印电子面单。 一.电子面单接口类型及定义 1.快递电子面单接口:快递公司自己开发的电子面单服务,商家使用必须快递公司上门做系统对接,使用一家快递则需要对接一次。 2 查看详情

电子面单打印机如何使用

参考技术A  电子面单,亦可称为热敏纸快递标签、经济型面单,二维码面单等,指的是根据物流公司的规定要求,在不干胶热敏纸上打印客户收发件信息的面单。  电子面单在国外已经成功应用多年,如联邦快递(FedEx)和国... 查看详情

电子面单打印模板规格汇总以及使用指南

1.完成前期准备工作1.1,去快递鸟免费注册一个对接账号1.2,免费获得一个apiKey(接口权限验证需要)1.3,完成实名认证流程1.4,订购一个免费套餐1.5,准备打印机、打印纸打印机:???电子面单模板对打印机品牌、型号等没有要求,只要是... 查看详情

查快递,对接哪个接口比较好?

快递查询接口可以直接找物流公司对接,也可以找第三方接口服务商一次性对接所有快递公司的查询接口,做的比较好的就是菜鸟、快递鸟,目前淘宝和天猫等阿里的都用菜鸟,其他的大部分电商平台比如美团、云集、凯叔讲故... 查看详情

电脑上怎么下载,安装阿里巴巴?

...市场,在搜索框输入《智能打印》进行搜索,找到:智能快递单打印_热敏打印订购后并且进入软件。2进入软件后首先进行菜鸟电子面单授权3电子面单授权完成后,开始打印发货即可。注意事项必须先开通菜鸟电子面单需要使用... 查看详情

求快递查询api,想接入一个到自己网站上?

我们公司网站刚对接了快递鸟的物流查询接口,综合对比多家选择了快递鸟。在快递查询接口领域比较知名的了,有在途监控、在途监控地图版、快递查询、在途监控国际版等接口,支持1600+国内外主流物流快递公司,一次性对... 查看详情

小程序商城后台如何连接快递服务?

了解一下快递鸟,还有快递100不知道怎么去连接一件发物流,求大神知道,大神有知道的留个V交流下公司叫别开发了个小程序,但是开发公司没有帮忙对接上快递接上,不懂操作求解一般小程序系统都内置快递发货接口,根据需求和预... 查看详情