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

使用相对比较麻烦,需要到处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!!!

快递鸟电子面单打印功能基于java的更多相关文章

  1. 快递鸟电子面单API对接方法?

    之前说了一下快递公司.菜鸟和快递鸟的电子面单接口,很多人不知道快递鸟要怎么对接,现在为大家讲解一下.快递鸟是全球物流接口服务商,为电商 ERP.电商平台.仓储.清关公司提供物流跟踪.电子面单.智选物流 ...

  2. 电商平台如何接入快递鸟电子面单API?

    快递鸟是全球物流接口服务商,为电商 ERP.电商平台.仓储.清关公司提供物流跟踪.电子面单.智选物流.物流金融.在线下单等服务,解决电商的物流管理模块和金融模块.现就对快递鸟电子面单API做基本描述, ...

  3. 快递鸟顺丰电子面单接口API-JAVA

    一.电子面单对接案例 1.接口描述 接口支持的消息接收方式:HTTP POST 请求方法的编码格式(utf-8):"application/x-www-form-urlencoded;cha ...

  4. 快递鸟API接口调用代码示例(免费不限量)

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  5. springmvc基于java配置的实现

    该案例的github地址:https://github.com/zhouyanger/demo/tree/master/springmvc-noxml-demo 1.介绍 之前搭建SpringMvc项 ...

  6. [2015.08.13]万峰快递单打印软件 v2.2

    <万峰快递单打印软件>是一款简单易用,且支持所有快递单的打印软件.1.支持文字打印位置的坐标精确定位和微调的打印工具.2.操作灵活,只需录入收件人和发件人信息即可打印:3.快递单打印尺寸和 ...

  7. 快递鸟顺丰物流api接口对接多种方法整理

    目前很多自营电商平台.ERP系统.仓储系统.快递柜企业,对物流模块数据需求还是比较旺盛的.之前有介绍过简单的接口对接方法,这次给大家整理介绍两种快递数据的获取方法. 接口秘钥可以向顺丰公司申请,或者一 ...

  8. 解决在TP5中无法使用快递鸟的即时查询API

    快递鸟的接口对接其实很简单,先去官网注册账号,登陆把基本信息填好,然后在产品管理中订购一下“物流查询”,免费,不过其他产品是收费,免费的有对接口调用频率限制,结合自己的应用流量够用就可以. 使用前复制 ...

  9. 物流跟踪 调用快递鸟API

    概要:关于调用快递鸟API,我有几句话想说,有几行代码想写 业务需求:就是做做商城,卖卖东西.然后需要做个物流跟踪的功能 需要获取的信息大概就是这个样子 现在看这个快递怎么这么慢 如何实现? 直接调用 ...

随机推荐

  1. 连接mysql提示Establishing SSL connection without server's identity verification is not recommended错误

    Establishing SSL connection without server's identity verification is not recommended. According to ...

  2. 并发编程(三) IO模型

    五 IO模型 常用的IO模型有4种: 阻塞IO 非阻塞IO IO多路复用 异步IO 不常用的有: 驱动信号 5.1 阻塞IO.非阻塞IO 阻塞IO:进程不能做其他的事情 非阻塞IO:等待数据无阻塞 阻 ...

  3. (CoreText框架)NSAttributedString 2

    CHENYILONG Blog (CoreText框架)NSAttributedString 2 Fullscreen © chenyilong. Powered by Postach.io Blog

  4. 微服务深入浅出(9)-- Nginx

    Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,处理请求是异步非阻塞的,多个连接(万级别)可以对应一个进程.而Apache是同步多进程模型,一个连接对 ...

  5. c++刷题(9/100):链表

    题目一:https://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tqId=11156&tP ...

  6. canvas画布,写字板

    <!doctype html><html><head> <meta charset="utf-8"> <meta http-e ...

  7. mysql zip 解压安装

    系统:win10 专业版 mysql 5.7.21 解压安装. 对于Windows,mysql官网推荐使用可执行文件进行安装,这里我还是暂时用noinstall 解压zip文件来安装 zip 文件解压 ...

  8. Shell脚本-自动化部署反向代理、WEB、nfs

    部署nginx反向代理三个web服务,调度算法使用加权轮询(由于物理原因只开启两台服务器) AutoNginxNfsService.sh #/bin/bash systemctl status ngi ...

  9. Bresenham直线算法与画圆算法

    在我们内部开发使用的一个工具中,我们需要几乎从 0 开始实现一个高效的二维图像渲染引擎.比较幸运的是,我们只需要画直线.圆以及矩形,其中比较复杂的是画直线和圆.画直线和圆已经有非常多的成熟的算法了,我 ...

  10. 【Java基础】JAVA不可变类(immutable)机制与String的不可变性

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...