|
@@ -7,12 +7,34 @@ import okhttp3.OkHttpClient;
|
|
|
import okhttp3.Request;
|
|
import okhttp3.Request;
|
|
|
import okhttp3.RequestBody;
|
|
import okhttp3.RequestBody;
|
|
|
import okhttp3.Response;
|
|
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.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 org.springframework.stereotype.Service;
|
|
|
import shop.alien.entity.store.PrinterDO;
|
|
import shop.alien.entity.store.PrinterDO;
|
|
|
import shop.alien.store.util.Base64Util;
|
|
import shop.alien.store.util.Base64Util;
|
|
|
import shop.alien.store.util.ShaUtil;
|
|
import shop.alien.store.util.ShaUtil;
|
|
|
|
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
+import java.io.BufferedReader;
|
|
|
|
|
+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;
|
|
|
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
@Service
|
|
@Service
|
|
@@ -102,14 +124,72 @@ public class PrintService {
|
|
|
return post("http://api.jhprt.com/api/print", req);
|
|
return post("http://api.jhprt.com/api/print", req);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ==================== 商鹏打印实现 ====================
|
|
|
|
|
|
|
+ // ==================== 商鹏打印实现 (V1) ====================
|
|
|
private boolean printShangPeng(PrinterDO p, String content) {
|
|
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 printUrl = "https://open.spyun.net/v1/printer/print";
|
|
|
|
|
+ String sn = p.getSn();
|
|
|
|
|
+ String apiKey = p.getApiKey();
|
|
|
|
|
+
|
|
|
|
|
+ if (sn == null || apiKey == null || sn.trim().isEmpty() || apiKey.trim().isEmpty()) {
|
|
|
|
|
+ log.error("商鹏打印参数缺失: sn={}, apiKey={}", sn, apiKey);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String base64Content = Base64Util.encode(content);
|
|
|
|
|
+ int times = 1;
|
|
|
|
|
+
|
|
|
|
|
+ HttpURLConnection conn = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ URL url = new URL(printUrl);
|
|
|
|
|
+ conn = (HttpURLConnection) 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");
|
|
|
|
|
+
|
|
|
|
|
+ StringBuilder params = new StringBuilder();
|
|
|
|
|
+ params.append("sn=").append(URLEncoder.encode(sn, StandardCharsets.UTF_8.name()));
|
|
|
|
|
+ // 注意:如果官方文档明确要求参数名为 token,请将 &apikey= 改为 &token=
|
|
|
|
|
+ params.append("&apikey=").append(URLEncoder.encode(apiKey, StandardCharsets.UTF_8.name()));
|
|
|
|
|
+ params.append("&content=").append(URLEncoder.encode(base64Content, StandardCharsets.UTF_8.name()));
|
|
|
|
|
+ params.append("×=").append(times);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("商鹏 V1 打印请求: sn={}, apiKey={}, times={}", sn, mask(apiKey), times);
|
|
|
|
|
+
|
|
|
|
|
+ try (OutputStream os = conn.getOutputStream()) {
|
|
|
|
|
+ os.write(params.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\":200") || 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();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 辅助方法:日志脱敏
|
|
|
|
|
+ private String mask(String key) {
|
|
|
|
|
+ if (key == null || key.length() <= 4) return "***";
|
|
|
|
|
+ return key.substring(0, 4) + "****" + key.substring(key.length() - 2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -131,4 +211,92 @@ public class PrintService {
|
|
|
return false;
|
|
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 print(String sn, String content, int times) throws IOException {
|
|
|
|
|
+ ArrayList<NameValuePair> params = new ArrayList<>();
|
|
|
|
|
+ params.add(new BasicNameValuePair("sn", sn));
|
|
|
|
|
+ params.add(new BasicNameValuePair("content", content));
|
|
|
|
|
+ params.add(new BasicNameValuePair("times", String.valueOf(times)));
|
|
|
|
|
+
|
|
|
|
|
+ return request("POST", "printer/print", params);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 发送请求
|
|
|
|
|
+ private String request(String uri, String s, 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;
|
|
|
|
|
+ HttpPost request = new HttpPost(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);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|