|
|
@@ -7,12 +7,33 @@ import okhttp3.OkHttpClient;
|
|
|
import okhttp3.Request;
|
|
|
import okhttp3.RequestBody;
|
|
|
import okhttp3.Response;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
+import org.apache.http.HttpEntity;
|
|
|
+import org.apache.http.NameValuePair;
|
|
|
+import org.apache.http.client.ClientProtocolException;
|
|
|
+import org.apache.http.client.config.RequestConfig;
|
|
|
+import org.apache.http.client.entity.UrlEncodedFormEntity;
|
|
|
+import org.apache.http.client.methods.*;
|
|
|
+import org.apache.http.client.utils.URLEncodedUtils;
|
|
|
+import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
+import org.apache.http.impl.client.HttpClients;
|
|
|
+import org.apache.http.message.BasicNameValuePair;
|
|
|
+import org.apache.http.util.EntityUtils;
|
|
|
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;
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.net.URL;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.security.MessageDigest;
|
|
|
+import java.util.*;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -30,7 +51,7 @@ public class PrintService {
|
|
|
public void printAll(List<PrinterDO> list, String content) {
|
|
|
for (PrinterDO p : list) {
|
|
|
// 异步打印:不阻塞,多打印机同时打印
|
|
|
- new Thread(() -> printWithRetry(p, content, 3)).start();
|
|
|
+ new Thread(() -> printWithRetry(p, content, 1)).start();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -102,16 +123,113 @@ public class PrintService {
|
|
|
return post("http://api.jhprt.com/api/print", req);
|
|
|
}
|
|
|
|
|
|
- // ==================== 商鹏打印实现 ====================
|
|
|
+ // ==================== 商鹏打印实现 (V1 官方签名版) ====================
|
|
|
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);
|
|
|
+ String sn = p.getSn();
|
|
|
+ String apiKey = p.getApiKey();
|
|
|
+ String appid = p.getUserId(); // 假设 userId 字段存储的是商鹏 appid
|
|
|
+
|
|
|
+ if (sn == null || apiKey == null || appid == null || sn.trim().isEmpty() || apiKey.trim().isEmpty()) {
|
|
|
+ log.error("商鹏打印参数缺失: sn={}, appid={}, apiKey={}", sn, appid, apiKey);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String base64Content = Base64Util.encode(content);
|
|
|
+ int times = 1; // 强制设置为一次只打印 1 份
|
|
|
+
|
|
|
+ HttpURLConnection conn = null;
|
|
|
+ try {
|
|
|
+ String url = "https://open.spyun.net/v1/printer/print";
|
|
|
+ conn = (HttpURLConnection) new URL(url).openConnection();
|
|
|
+ conn.setRequestMethod("POST");
|
|
|
+ conn.setDoOutput(true);
|
|
|
+ conn.setConnectTimeout(5000);
|
|
|
+ conn.setReadTimeout(10000);
|
|
|
+ conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
|
|
+
|
|
|
+ // 构建请求参数
|
|
|
+ Map<String, String> params = new HashMap<>();
|
|
|
+ params.put("sn", sn);
|
|
|
+// params.put("content", base64Content);
|
|
|
+ params.put("content", content);
|
|
|
+ params.put("times", "1");
|
|
|
+ params.put("appid", appid);
|
|
|
+ params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
|
|
+
|
|
|
+ // 生成签名
|
|
|
+ params.put("sign", makeSign(params, apiKey));
|
|
|
+
|
|
|
+ // 拼接表单参数
|
|
|
+ StringBuilder paramsStr = new StringBuilder();
|
|
|
+ for (Map.Entry<String, String> entry : params.entrySet()) {
|
|
|
+ if (paramsStr.length() > 0) paramsStr.append("&");
|
|
|
+ paramsStr.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()));
|
|
|
+ }
|
|
|
+
|
|
|
+ try (OutputStream os = conn.getOutputStream()) {
|
|
|
+ os.write(paramsStr.toString().getBytes(StandardCharsets.UTF_8));
|
|
|
+ os.flush();
|
|
|
+ }
|
|
|
+
|
|
|
+ int code = conn.getResponseCode();
|
|
|
+ StringBuilder result = new StringBuilder();
|
|
|
+ if (code == 200) {
|
|
|
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
|
|
+ String line;
|
|
|
+ while ((line = reader.readLine()) != null) result.append(line);
|
|
|
+ }
|
|
|
+ log.info("商鹏 V1 打印响应: {}", result);
|
|
|
+ return result.toString().contains("\"code\":0") || result.toString().contains("\"success\":true");
|
|
|
+ } else {
|
|
|
+ log.error("商鹏 V1 打印请求失败,HTTP 状态码: {}", code);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("商鹏 V1 打印异常: sn={}, error={}", sn, e.getMessage(), e);
|
|
|
+ return false;
|
|
|
+ } finally {
|
|
|
+ if (conn != null) conn.disconnect();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 官方签名算法:字典序排序 + MD5 大写
|
|
|
+ private String makeSign(Map<String, String> params, String appsecret) {
|
|
|
+ String[] keys = params.keySet().toArray(new String[0]);
|
|
|
+ Arrays.sort(keys);
|
|
|
+
|
|
|
+ StringBuilder sign = new StringBuilder();
|
|
|
+ for (int i = 0; i < keys.length; i++) {
|
|
|
+ String k = keys[i];
|
|
|
+ String v = params.get(k);
|
|
|
+ if (!k.equals("sign") && !k.equals("appsecret") && v != null && !v.isEmpty()) {
|
|
|
+ if (sign.length() > 0) sign.append("&");
|
|
|
+ sign.append(k).append("=").append(v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sign.append("&appsecret=").append(appsecret);
|
|
|
+
|
|
|
+ try {
|
|
|
+ MessageDigest md = MessageDigest.getInstance("MD5");
|
|
|
+ byte[] digest = md.digest(sign.toString().getBytes(StandardCharsets.UTF_8));
|
|
|
+ StringBuilder hex = new StringBuilder();
|
|
|
+ for (byte b : digest) {
|
|
|
+ String h = Integer.toHexString(0xff & b);
|
|
|
+ if (h.length() == 1) hex.append('0');
|
|
|
+ hex.append(h);
|
|
|
+ }
|
|
|
+ return hex.toString().toUpperCase();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("MD5 签名失败", e);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ // 辅助方法:日志脱敏
|
|
|
+// private String mask(String key) {
|
|
|
+// if (key == null || key.length() <= 4) return "***";
|
|
|
+// return key.substring(0, 4) + "****" + key.substring(key.length() - 2);
|
|
|
+// }
|
|
|
+
|
|
|
/**
|
|
|
* 统一发送POST请求
|
|
|
*/
|
|
|
@@ -131,4 +249,108 @@ public class PrintService {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+// public static final String baseUri = "https://open.spyun.net/v1/";
|
|
|
+// private String appid;
|
|
|
+//
|
|
|
+// private String appsecret;
|
|
|
+//
|
|
|
+// public void Api(String appid, String appsecret) {
|
|
|
+// this.appid = appid;
|
|
|
+// this.appsecret = appsecret;
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+// // 辅助方法:生成签名
|
|
|
+// public String makeSign(ArrayList<NameValuePair> params) {
|
|
|
+// int size = params.size();
|
|
|
+// String[] keys = new String[params.size()];
|
|
|
+// HashMap<String, String> values = new HashMap<>();
|
|
|
+// for (int i = 0; i < size; i++) {
|
|
|
+// NameValuePair p = params.get(i);
|
|
|
+// keys[i] = p.getName();
|
|
|
+// values.put(p.getName(), p.getValue());
|
|
|
+// }
|
|
|
+// Arrays.sort(keys);
|
|
|
+//
|
|
|
+// String sign = "";
|
|
|
+// for (int i = 0; i < keys.length; i++) {
|
|
|
+// String v = values.get(keys[i]);
|
|
|
+// if (!keys[i].equals("sign") && !keys[i].equals("appsecret") && !v.equals("")) {
|
|
|
+// if (i > 0) {
|
|
|
+// sign += "&";
|
|
|
+// }
|
|
|
+// sign += keys[i] + "=" + v;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// sign += "&appsecret=" + appsecret;
|
|
|
+//
|
|
|
+// return DigestUtils.md5Hex(sign).toUpperCase();
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// public String getPrintsOrders(String sn, String date) throws IOException {
|
|
|
+// ArrayList<NameValuePair> params = new ArrayList<>();
|
|
|
+// params.add(new BasicNameValuePair("sn", sn));
|
|
|
+// params.add(new BasicNameValuePair("date", date));
|
|
|
+//
|
|
|
+// return request("POST", "printer/order/number", params);
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 发送请求
|
|
|
+// private String request(String method, String uri, ArrayList<NameValuePair> params) throws IOException {
|
|
|
+// RequestConfig requestConfig = RequestConfig.custom()
|
|
|
+// .setSocketTimeout(4000) //读取超时
|
|
|
+// .setConnectTimeout(1000) //连接超时
|
|
|
+// .build();
|
|
|
+//
|
|
|
+// CloseableHttpClient httpClient = HttpClients.custom()
|
|
|
+// .setDefaultRequestConfig(requestConfig)
|
|
|
+// .build();
|
|
|
+//
|
|
|
+// // 公共请求参数
|
|
|
+// params.add(new BasicNameValuePair("appid", appid));
|
|
|
+// params.add(new BasicNameValuePair("timestamp", String.valueOf(System.currentTimeMillis() / 1000)));
|
|
|
+// params.add(new BasicNameValuePair("sign", makeSign(params)));
|
|
|
+//
|
|
|
+// CloseableHttpResponse response = null;
|
|
|
+// String url = baseUri + uri;
|
|
|
+// if (method.equals("GET")) {
|
|
|
+// HttpGet request = new HttpGet(url + "?" + URLEncodedUtils.format(params, "utf-8"));
|
|
|
+// response = httpClient.execute(request);
|
|
|
+// } else if (method.equals("DELETE")) {
|
|
|
+// HttpDelete request = new HttpDelete(url + "?" + URLEncodedUtils.format(params, "utf-8"));
|
|
|
+// response = httpClient.execute(request);
|
|
|
+// } else if (method.equals("POST")) {
|
|
|
+// HttpPost request = new HttpPost(url);
|
|
|
+// request.setEntity(new UrlEncodedFormEntity(params,"utf-8"));
|
|
|
+// response = httpClient.execute(request);
|
|
|
+// } else if (method.equals("PATCH")) {
|
|
|
+// HttpPatch request = new HttpPatch(url);
|
|
|
+// request.setEntity(new UrlEncodedFormEntity(params,"utf-8"));
|
|
|
+// response = httpClient.execute(request);
|
|
|
+// } else if (method.equals("PUT")) {
|
|
|
+// HttpPut request = new HttpPut(url);
|
|
|
+// request.setEntity(new UrlEncodedFormEntity(params,"utf-8"));
|
|
|
+// response = httpClient.execute(request);
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (response == null) {
|
|
|
+// throw new ClientProtocolException();
|
|
|
+// }
|
|
|
+//
|
|
|
+// HttpEntity httpEntity = response.getEntity();
|
|
|
+// if (httpEntity == null) {
|
|
|
+// throw new ClientProtocolException();
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (response.getStatusLine().getStatusCode() != 200) {
|
|
|
+// throw new ClientProtocolException(EntityUtils.toString(httpEntity));
|
|
|
+// }
|
|
|
+//
|
|
|
+// return EntityUtils.toString(httpEntity);
|
|
|
+// }
|
|
|
+
|
|
|
}
|