diff --git a/pom.xml b/pom.xml
index 9b26a15..7d728d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -207,6 +207,13 @@
${ruoyi.version}
+
+
+ com.ruoyi
+ ruoyi-pay
+ ${ruoyi.version}
+
+
jakarta.servlet
jakarta.servlet-api
@@ -231,6 +238,7 @@
ruoyi-generator
ruoyi-common
ruoyi-oauth
+ ruoyi-pay
pom
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
index c1c58db..43d770b 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
@@ -1,7 +1,10 @@
package com.ruoyi.common.utils.sign;
+import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
+
+import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,41 +13,32 @@ import org.slf4j.LoggerFactory;
*
* @author ruoyi
*/
-public class Md5Utils
-{
+public class Md5Utils {
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
- private static byte[] md5(String s)
- {
+ private static byte[] md5(String s) {
MessageDigest algorithm;
- try
- {
+ try {
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
log.error("MD5 Error...", e);
}
return null;
}
- private static final String toHex(byte hash[])
- {
- if (hash == null)
- {
+ private static final String toHex(byte hash[]) {
+ if (hash == null) {
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
- for (i = 0; i < hash.length; i++)
- {
- if ((hash[i] & 0xff) < 0x10)
- {
+ for (i = 0; i < hash.length; i++) {
+ if ((hash[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
@@ -52,16 +46,20 @@ public class Md5Utils
return buf.toString();
}
- public static String hash(String s)
- {
- try
- {
+ public static String hash(String s) {
+ try {
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
log.error("not supported charset...{}", e);
return s;
}
}
+
+ public static String encryptMd5(String string) throws UnsupportedEncodingException {
+ return encryptMd5(string, "UTF-8");
+ }
+
+ public static String encryptMd5(String string, String charSet) throws UnsupportedEncodingException {
+ return DigestUtils.md5Hex(string.getBytes(charSet));
+ }
}
diff --git a/ruoyi-pay/pom.xml b/ruoyi-pay/pom.xml
index 2442c17..108a5f1 100644
--- a/ruoyi-pay/pom.xml
+++ b/ruoyi-pay/pom.xml
@@ -26,6 +26,13 @@
ruoyi-common
${ruoyi.version}
+
+
+
+ com.ruoyi
+ ruoyi-pay-sqb
+ ${ruoyi.version}
+
diff --git a/ruoyi-pay/ruoyi-pay-sqb/pom.xml b/ruoyi-pay/ruoyi-pay-sqb/pom.xml
index 0e57d0f..0d20665 100644
--- a/ruoyi-pay/ruoyi-pay-sqb/pom.xml
+++ b/ruoyi-pay/ruoyi-pay-sqb/pom.xml
@@ -3,13 +3,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- ruoyi
+ ruoyi-pay
com.ruoyi
3.8.7.3.1
4.0.0
- ruoyi-oauth
+ ruoyi-pay-sqb
system系统模块
@@ -23,6 +23,13 @@
ruoyi-common
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.2
+
+
\ No newline at end of file
diff --git a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/constant/SqbConstant.java b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/constant/SqbConstant.java
new file mode 100644
index 0000000..e417d4a
--- /dev/null
+++ b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/constant/SqbConstant.java
@@ -0,0 +1,71 @@
+package com.ruoyi.pay.sqb.constant;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+@Component
+public class SqbConstant {
+ @Value("${pay.sqb.apiDomain}")
+ private String apiDomain;
+
+ @Value("${pay.sqb.terminalSn}")
+ private String terminalSn;
+
+ @Value("${pay.sqb.terminalKey}")
+ private String terminalKey;
+
+ @Value("${pay.sqb.appId}")
+ private String appId;
+
+ public String getApiDomain() {
+ return apiDomain;
+ }
+
+ public void setApiDomain(String apiDomain) {
+ this.apiDomain = apiDomain;
+ }
+
+ public String getTerminalSn() {
+ return terminalSn;
+ }
+
+ public void setTerminalSn(String terminalSn) {
+ this.terminalSn = terminalSn;
+ }
+
+ public String getTerminalKey() {
+ return terminalKey;
+ }
+
+ public void setTerminalKey(String terminalKey) {
+ this.terminalKey = terminalKey;
+ }
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public void setAppId(String appId) {
+ this.appId = appId;
+ }
+
+ public String getVendorSn() {
+ return vendorSn;
+ }
+
+ public void setVendorSn(String vendorSn) {
+ this.vendorSn = vendorSn;
+ }
+
+ public String getVendorKey() {
+ return vendorKey;
+ }
+
+ public void setVendorKey(String vendorKey) {
+ this.vendorKey = vendorKey;
+ }
+
+ @Value("${pay.sqb.vendorSn}")
+ private String vendorSn;
+
+ @Value("${pay.sqb.vendorKey}")
+ private String vendorKey;
+}
diff --git a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/third/service/Impl/SQBServiceImpl.java b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java
similarity index 55%
rename from ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/third/service/Impl/SQBServiceImpl.java
rename to ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java
index 9838f9f..e75217e 100644
--- a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/third/service/Impl/SQBServiceImpl.java
+++ b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java
@@ -1,28 +1,21 @@
-package org.jeecg.modules.sqb.service.impl;
-
-
-import org.json.JSONObject;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.stereotype.Service;
-import java.net.URLEncoder;
-import java.net.URLDecoder;
+package com.ruoyi.pay.sqb.service.Impl;
import java.io.UnsupportedEncodingException;
-import java.util.Random;
+import java.net.URLEncoder;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.sign.Md5Utils;
+import com.ruoyi.pay.sqb.constant.SqbConstant;
+import com.ruoyi.pay.sqb.utils.HttpUtil;
@Service
-@PropertySource("classpath:sqbpay.properties")
-@ConfigurationProperties(prefix = "sqbpay")
-@Data
public class SQBServiceImpl {
- private String apiDomain;
- private String terminalSn;
- private String terminalKey;
- private String appId;
- private String vendorSn;
- private String vendorKey;
- private final static String CHARSET_UTF8 = "utf8";
+ @Autowired
+ SqbConstant sqbConstant;
/**
* 计算字符串的MD5值
@@ -30,9 +23,9 @@ public class SQBServiceImpl {
* @param signStr:签名字符串
* @return
*/
- public String getSign(String signStr) {
+ private String getSign(String signStr) {
try {
- String md5 = MD5Util.encryptMd5(signStr);
+ String md5 = Md5Utils.encryptMd5(signStr);
return md5;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
@@ -47,24 +40,23 @@ public class SQBServiceImpl {
* @return {terminal_sn:"$终端号",terminal_key:"$终端密钥"}
*/
public JSONObject activate(String code, String deviceId, String clientSn, String name) {
- String url = apiDomain + "/terminal/activate";
+ String url = sqbConstant.getApiDomain() + "/terminal/activate";
JSONObject params = new JSONObject();
try {
- params.put("app_id", appId); // app_id,必填
+ params.put("app_id", sqbConstant.getAppId()); // app_id,必填
params.put("code", code); // 激活码,必填
params.put("device_id", deviceId); // 客户方收银终端序列号,需保证同一app_id下唯一,必填。为方便识别,建议格式为“品牌名+门店编号+‘POS’+POS编号“
params.put("client_sn", clientSn); // 客户方终端编号,一般客户方或系统给收银终端的编号,必填
params.put("name", name); // 客户方终端名称,必填
- String sign = getSign(params.toString() + vendorKey);
- System.out.println(params.toString() + vendorKey);
- String result = HttpUtil.httpPost(url, params.toString(), sign, vendorSn);
- JSONObject retObj = new JSONObject(result);
+ String sign = getSign(params.toString() + sqbConstant.getVendorKey());
+ String result = HttpUtil.httpPost(url, params.toString(), sign, sqbConstant.getVendorSn());
+ JSONObject retObj = JSON.parseObject(result);
String resCode = retObj.get("result_code").toString();
if (!resCode.equals("200"))
return null;
String responseStr = retObj.get("biz_response").toString();
- JSONObject terminal = new JSONObject(responseStr);
+ JSONObject terminal = JSON.parseObject(responseStr);
if (terminal.get("terminal_sn") == null || terminal.get("terminal_key") == null)
return null;
return terminal;
@@ -79,21 +71,21 @@ public class SQBServiceImpl {
* @return {terminal_sn:"$终端号",terminal_key:"$终端密钥"}
*/
public JSONObject checkin() {
- String url = apiDomain + "/terminal/checkin";
+ String url = sqbConstant.getApiDomain() + "/terminal/checkin";
JSONObject params = new JSONObject();
try {
- params.put("terminal_sn", terminalSn);
+ params.put("terminal_sn", sqbConstant.getTerminalSn());
params.put("device_id", "HUISUAN001POS01");
params.put("os_info", "Mac OS");
params.put("sdk_version", "Java SDK v1.0");
- String sign = getSign(params.toString() + terminalKey);
- String result = HttpUtil.httpPost(url, params.toString(), sign, terminalSn);
- JSONObject retObj = new JSONObject(result);
+ String sign = getSign(params.toString() + sqbConstant.getTerminalKey());
+ String result = HttpUtil.httpPost(url, params.toString(), sign, sqbConstant.getTerminalSn());
+ JSONObject retObj = JSON.parseObject(result);
String resCode = retObj.get("result_code").toString();
if (!resCode.equals("200"))
return null;
String responseStr = retObj.get("biz_response").toString();
- JSONObject terminal = new JSONObject(responseStr);
+ JSONObject terminal = JSON.parseObject(responseStr);
if (terminal.get("terminal_sn") == null || terminal.get("terminal_key") == null)
return null;
return terminal;
@@ -107,18 +99,19 @@ public class SQBServiceImpl {
*
* @return
*/
- public String refund(SageOrder orderPay) {
- String url = apiDomain + "/upay/v2/refund";
+ public String refund(String clientSn, String total, String payway, String subject, String operator,
+ String terminalSn) {
+ String url = sqbConstant.getApiDomain() + "/upay/v2/refund";
JSONObject params = new JSONObject();
try {
- params.put("terminal_sn", terminalSn); // 收钱吧终端ID
- params.put("client_sn", orderPay.getSn()); // 商户系统订单号,必须在商户系统内唯一;且长度不超过64字节
- params.put("refund_amount", orderPay.getTotalAmount()); // 退款金额
+ params.put("terminal_sn", sqbConstant.getTerminalSn()); // 收钱吧终端ID
+ params.put("client_sn", clientSn); // 商户系统订单号,必须在商户系统内唯一;且长度不超过64字节
+ params.put("refund_amount", total); // 退款金额
params.put("refund_request_no", "2"); // 商户退款所需序列号,表明是第几次退款
params.put("operator", "kay"); // 门店操作员
- String sign = getSign(params.toString() + terminalKey);
- String result = HttpUtil.httpPost(url, params.toString(), sign, terminalSn);
+ String sign = getSign(params.toString() + sqbConstant.getTerminalKey());
+ String result = HttpUtil.httpPost(url, params.toString(), sign, sqbConstant.getTerminalSn());
return result;
} catch (Exception e) {
@@ -131,16 +124,18 @@ public class SQBServiceImpl {
*
* @return
*/
- public String query(SageOrder orderPay) {
- String url = apiDomain + "/upay/v2/query";
+
+ public String query(String clientSn, String total, String payway, String subject, String operator,
+ String terminalSn) {
+ String url = sqbConstant.getApiDomain() + "/upay/v2/query";
JSONObject params = new JSONObject();
try {
- params.put("terminal_sn", terminalSn); // 终端号
- params.put("client_sn", orderPay.getSn()); // 商户系统订单号,必须在商户系统内唯一;且长度不超过64字节
- System.out.println(params.toString() + terminalKey);
- String sign = getSign(params.toString() + terminalKey);
- String result = HttpUtil.httpPost(url, params.toString(), sign, terminalSn);
- JSONObject retObj = new JSONObject(result);
+ params.put("terminal_sn", sqbConstant.getTerminalSn()); // 终端号
+ params.put("client_sn", clientSn); // 商户系统订单号,必须在商户系统内唯一;且长度不超过64字节
+ System.out.println(params.toString() + sqbConstant.getTerminalKey());
+ String sign = getSign(params.toString() + sqbConstant.getTerminalKey());
+ String result = HttpUtil.httpPost(url, params.toString(), sign, sqbConstant.getTerminalSn());
+ JSONObject retObj = JSON.parseObject(result);
String resCode = retObj.get("result_code").toString();
if (!resCode.equals("200"))
return null;
@@ -151,22 +146,23 @@ public class SQBServiceImpl {
}
}
- public String payUrl(SageOrder orderPay) throws UnsupportedEncodingException {
+ public String payUrl(String clientSn, String total, String payway, String subject, String operator,
+ String terminalSn) throws UnsupportedEncodingException {
String param = "" +
- "client_sn=" + orderPay.getSn() +
- "&operator=" + orderPay.getOperator() +
+ "client_sn=" + clientSn +
+ "&operator=" + operator +
"&return_url=" + "https://www.shouqianba.com/" +
- "&subject=" + orderPay.getSubject() +
+ "&subject=" + subject +
"&terminal_sn=" + terminalSn +
- "&total_amount=" + orderPay.getTotalAmount();
+ "&total_amount=" + total;
String urlParam = "" +
- "client_sn=" + orderPay.getSn() +
- "&operator=" + URLEncoder.encode(orderPay.getOperator(), "UTF-8") +
+ "client_sn=" + clientSn +
+ "&operator=" + URLEncoder.encode(operator, "UTF-8") +
"&return_url=" + "https://www.shouqianba.com/" +
- "&subject=" + URLEncoder.encode(orderPay.getSubject(), "UTF-8") +
+ "&subject=" + URLEncoder.encode(subject, "UTF-8") +
"&terminal_sn=" + terminalSn +
- "&total_amount=" + orderPay.getTotalAmount();
- String sign = getSign(param + "&key=" + terminalKey);
+ "&total_amount=" + total;
+ String sign = getSign(param + "&key=" + sqbConstant.getTerminalKey());
return "https://qr.shouqianba.com/gateway?" + urlParam + "&sign=" + sign.toUpperCase();
}
@@ -175,19 +171,19 @@ public class SQBServiceImpl {
*
* @return
*/
- public String precreate(SageOrder orderPay) {
- String url = apiDomain + "/upay/v2/precreate";
+ public String precreate(String sn, String total, String payway, String subject, String operator) {
+ String url = sqbConstant.getApiDomain() + "/upay/v2/precreate";
JSONObject params = new JSONObject();
try {
- params.put("terminal_sn", terminalSn); // 收钱吧终端ID
- params.put("client_sn", orderPay.getSn()); // 商户系统订单号,必须在商户系统内唯一;且长度不超过32字节
- params.put("total_amount", orderPay.getTotalAmount()); // 交易总金额
- params.put("payway", orderPay.getPayway()); // 支付方式
- params.put("subject", orderPay.getSubject()); // 交易简介
- params.put("operator", orderPay.getOperator()); // 门店操作员
+ params.put("terminal_sn", sqbConstant.getTerminalSn()); // 收钱吧终端ID
+ params.put("client_sn", sn); // 商户系统订单号,必须在商户系统内唯一;且长度不超过32字节
+ params.put("total_amou nt", total); // 交易总金额
+ params.put("payway", payway); // 支付方式
+ params.put("subject", subject); // 交易简介
+ params.put("operator", operator); // 门店操作员
- String sign = getSign(params.toString() + terminalKey);
- String result = HttpUtil.httpPost(url, params.toString(), sign, terminalSn);
+ String sign = getSign(params.toString() + sqbConstant.getTerminalKey());
+ String result = HttpUtil.httpPost(url, params.toString(), sign, sqbConstant.getTerminalSn());
return result;
} catch (Exception e) {
return null;
@@ -202,7 +198,7 @@ public class SQBServiceImpl {
* @return
*/
public String cancel(String terminal_sn, String terminal_key) {
- String url = apiDomain + "/upay/v2/cancel";
+ String url = sqbConstant.getApiDomain() + "/upay/v2/cancel";
JSONObject params = new JSONObject();
try {
params.put("terminal_sn", terminal_sn); // 终端号
diff --git a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/utils/HttpUtil.java b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/utils/HttpUtil.java
new file mode 100644
index 0000000..6085178
--- /dev/null
+++ b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/utils/HttpUtil.java
@@ -0,0 +1,132 @@
+package com.ruoyi.pay.sqb.utils;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.util.EntityUtils;
+
+public class HttpUtil {
+ public static String httpPostWithoutException(String url, String string,String sign,String sn) {
+ String xmlRes = "{}";
+ try {
+ xmlRes = httpPost(url, string,sign,sn);
+ } catch (UnrecoverableKeyException e) {
+
+ } catch (NoSuchAlgorithmException e) {
+
+ } catch (KeyStoreException e) {
+
+ } catch (KeyManagementException e) {
+
+ }
+ return xmlRes;
+ }
+ /**
+ * http POST 请求
+ * @param url:请求地址
+ * @param body: body实体字符串
+ * @param sign:签名
+ * @param sn: 序列号
+ * @return
+ */
+ public static String httpPost(String url, String body,String sign,String sn) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+ String xmlRes = "{}";
+ HttpClient client = createSSLClientDefault();
+ HttpPost httpost = new HttpPost(url);
+ try {
+ System.out.println("Request string: " + body);
+ //所有请求的body都需采用UTF-8编码
+ StringEntity entity = new StringEntity(body,"UTF-8");//
+ entity.setContentType("application/json");
+ httpost.setEntity(entity);
+
+ //支付平台所有的API仅支持JSON格式的请求调用,HTTP请求头Content-Type设为application/json
+ httpost.addHeader("Content-Type","application/json");
+
+ //支付平台所有的API调用都需要签名验证,签名首部: Authorization: sn + " " + sign
+ httpost.addHeader("Authorization",sn + " " + sign);
+ System.out.println("Authorization" + sn + " " + sign);
+ HttpResponse response = client.execute(httpost);
+
+ //所有响应也采用UTF-8编码
+ xmlRes = EntityUtils.toString(response.getEntity(), "UTF-8");
+ System.out.println("Response string: " + xmlRes);
+ } catch (ClientProtocolException e) {
+
+ } catch (IOException e) {
+
+ }
+ return xmlRes;
+ }
+
+ public static CloseableHttpClient createSSLClientDefault() {
+ try {
+ SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
+ //信任所有
+ public boolean isTrusted(X509Certificate[] chain,
+ String authType) throws CertificateException {
+ return true;
+ }
+ }).build();
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
+ return HttpClients.custom().setSSLSocketFactory(sslsf).build();
+ } catch (KeyManagementException e) {
+
+ } catch (NoSuchAlgorithmException e) {
+
+ } catch (KeyStoreException e) {
+
+ }
+ return HttpClients.createDefault();
+ }
+
+ public static String doGet(String url,String parameter)
+ {
+ String uriAPI =url+"?"+parameter ; //"http://XXXXX?str=I+am+get+String";
+ String result= "";
+ HttpClient client = createSSLClientDefault();
+ HttpGet httpRequst = new HttpGet(uriAPI);
+ try {
+
+ HttpResponse httpResponse = client.execute(httpRequst);//其中HttpGet是HttpUriRequst的子类
+ if(httpResponse.getStatusLine().getStatusCode() == 200)
+ {
+ HttpEntity httpEntity = httpResponse.getEntity();
+ result = EntityUtils.toString(httpEntity);//取出应答字符串
+ // 一般来说都要删除多余的字符
+ result.replaceAll("\r", "");//去掉返回结果中的"\r"字符,否则会在结果字符串后面显示一个小方格
+ }
+ else
+ httpRequst.abort();
+ } catch (ClientProtocolException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ result = e.getMessage().toString();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ result = e.getMessage().toString();
+ }
+ return result;
+ }
+
+}