1. 程式人生 > >快遞鳥電子面單列印功能基於java

快遞鳥電子面單列印功能基於java

之前的後天管理系統的電子面單列印使用的是靈通打單。

使用相對比較麻煩,需要到處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!!!