|
@@ -0,0 +1,134 @@
|
|
|
|
|
+package shop.alien.store.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import okhttp3.MediaType;
|
|
|
|
|
+import okhttp3.OkHttpClient;
|
|
|
|
|
+import okhttp3.Request;
|
|
|
|
|
+import okhttp3.RequestBody;
|
|
|
|
|
+import okhttp3.Response;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import shop.alien.entity.store.PrinterDO;
|
|
|
|
|
+import shop.alien.store.util.Base64Util;
|
|
|
|
|
+import shop.alien.store.util.ShaUtil;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Service
|
|
|
|
|
+public class PrintService {
|
|
|
|
|
+ // HTTP请求工具
|
|
|
|
|
+ private final OkHttpClient client = new OkHttpClient();
|
|
|
|
|
+ // JSON请求头
|
|
|
|
|
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 批量打印:给所有打印机发打印指令
|
|
|
|
|
+ * @param list 打印机列表
|
|
|
|
|
+ * @param content 打印内容
|
|
|
|
|
+ */
|
|
|
|
|
+ public void printAll(List<PrinterDO> list, String content) {
|
|
|
|
|
+ for (PrinterDO p : list) {
|
|
|
|
|
+ // 异步打印:不阻塞,多打印机同时打印
|
|
|
|
|
+ new Thread(() -> printWithRetry(p, content, 3)).start();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 打印重试机制
|
|
|
|
|
+ * @param printer 打印机
|
|
|
|
|
+ * @param content 内容
|
|
|
|
|
+ * @param retry 重试次数
|
|
|
|
|
+ * @return 是否成功
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean printWithRetry(PrinterDO printer, String content, int retry) {
|
|
|
|
|
+ while (retry-- > 0) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ boolean ok = printSingle(printer, content);
|
|
|
|
|
+ if (ok) return true;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.err.println("打印失败,剩余重试:" + retry);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 单台打印机打印
|
|
|
|
|
+ * 根据品牌自动分发
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean printSingle(PrinterDO printer, String content) {
|
|
|
|
|
+ String brand = printer.getBrand();
|
|
|
|
|
+ if ("XINYE".equalsIgnoreCase(brand)) {
|
|
|
|
|
+ return printXinYe(printer, content);
|
|
|
|
|
+ } else if ("JIAHANG".equalsIgnoreCase(brand)) {
|
|
|
|
|
+ return printJiaHang(printer, content);
|
|
|
|
|
+ } else if ("SHANGPENG".equalsIgnoreCase(brand)) {
|
|
|
|
|
+ return printShangPeng(printer, content);
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 芯烨打印实现 ====================
|
|
|
|
|
+ private boolean printXinYe(PrinterDO p, String content) {
|
|
|
|
|
+ // 时间戳(秒)
|
|
|
|
|
+ long ts = System.currentTimeMillis() / 1000;
|
|
|
|
|
+ // SHA1签名:user + userKey + timestamp
|
|
|
|
|
+ String sign = ShaUtil.sha1(p.getUserId() + p.getApiKey() + ts);
|
|
|
|
|
+
|
|
|
|
|
+ // 构造API参数
|
|
|
|
|
+ JSONObject req = new JSONObject();
|
|
|
|
|
+ req.put("user", p.getUserId());
|
|
|
|
|
+ req.put("sn", p.getSn());
|
|
|
|
|
+// req.put("content", Base64Util.encode(content));
|
|
|
|
|
+ req.put("content", content);
|
|
|
|
|
+ req.put("copies", 1);
|
|
|
|
|
+ req.put("timestamp", ts);
|
|
|
|
|
+ req.put("sign", sign);
|
|
|
|
|
+ req.put("mode", 1);
|
|
|
|
|
+
|
|
|
|
|
+ // 发送请求
|
|
|
|
|
+ return post("https://open.xpyun.net/api/openapi/xprinter/print", req);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 佳航打印实现 ====================
|
|
|
|
|
+ private boolean printJiaHang(PrinterDO p, String content) {
|
|
|
|
|
+ JSONObject req = new JSONObject();
|
|
|
|
|
+ req.put("merchantId", p.getUserId());
|
|
|
|
|
+ req.put("deviceNo", p.getSn());
|
|
|
|
|
+ req.put("key", p.getApiKey());
|
|
|
|
|
+ req.put("printContent", Base64Util.encode(content));
|
|
|
|
|
+ req.put("copy", 1);
|
|
|
|
|
+ return post("http://api.jhprt.com/api/print", req);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 商鹏打印实现 ====================
|
|
|
|
|
+ private boolean printShangPeng(PrinterDO p, String content) {
|
|
|
|
|
+ JSONObject req = new JSONObject();
|
|
|
|
|
+ req.put("sn", p.getSn());
|
|
|
|
|
+ req.put("token", p.getApiKey());
|
|
|
|
|
+ req.put("content", Base64Util.encode(content));
|
|
|
|
|
+ req.put("times", 1);
|
|
|
|
|
+ return post("https://api.spyun.net/api/print", req);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 统一发送POST请求
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean post(String url, JSONObject req) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ RequestBody body = RequestBody.create(JSON, req.toJSONString());
|
|
|
|
|
+ Request request = new Request.Builder().url(url).post(body).build();
|
|
|
|
|
+ try (Response res = client.newCall(request).execute()) {
|
|
|
|
|
+ String str = res.body().string();
|
|
|
|
|
+ System.out.println("打印响应:" + str);
|
|
|
|
|
+ JSONObject json = JSONObject.parseObject(str);
|
|
|
|
|
+ // 通用成功判断:code=0 或 success=true
|
|
|
|
|
+ return json.getIntValue("code") == 0 || json.getBooleanValue("success");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|