集成通联支付

This commit is contained in:
liuchengqian 2025-03-27 14:49:57 +08:00
parent 238b854ec3
commit 63bccbe4ef
42 changed files with 3383 additions and 1 deletions

BIN
lib/bcpkix-jdk15on-1.59.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/bcprov-jdk15on-1.59.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/commons-codec-1.11.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/commons-lang-2.6.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/ezmorph-1.0.6.jar Normal file

Binary file not shown.

BIN
lib/json-lib-2.4-jdk15.jar Normal file

Binary file not shown.

14
pom.xml
View File

@ -9,7 +9,7 @@
<relativePath/>
</parent>
<groupId>com.xkrs</groupId>
<artifactId>fire_point</artifactId>
<artifactId>fire_point_allinpay</artifactId>
<version>0.0.1</version>
<name>fire_point</name>
<description>火点项目</description>
@ -253,6 +253,18 @@
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,375 @@
package com.xkrs.allinpay;
import cn.hutool.core.util.StrUtil;
import com.xkrs.allinpay.model.*;
import com.xkrs.allinpay.utils.QRCodeUtils;
import com.xkrs.allinpay.utils.SybConstants;
import com.xkrs.allinpay.utils.SybUtil;
import com.xkrs.common.encapsulation.PromptMessageEnum;
import com.xkrs.common.tool.TokenUtil;
import com.xkrs.dao.SysUserDao;
import com.xkrs.dao.TranNotifyDao;
import com.xkrs.dao.TranQueryDao;
import com.xkrs.dao.UnitOrderPayDao;
import com.xkrs.model.entity.SysUserEntity;
import com.xkrs.websocket.pay.PayWebSocketUsers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject;
@RestController
@RequestMapping(value = "/pay")
public class SybPayController {
public static Logger log = LoggerFactory.getLogger(SybPayController.class);
private final Locale locale = LocaleContextHolder.getLocale();
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Value("${qrCode.saveDirPath}")
public String qrCodeSaveDirPath;
@Value("${qrCode.accessDirPath}")
public String qrCodeAccessDirPath;
@Value("${pay.notifyUrl}")
public String payNotifyUrl;
@Resource
private SysUserDao sysUserDao;
@Resource
private UnitOrderPayDao unitOrderPayDao;
@Resource
private TranNotifyDao tranNotifyDao;
@Resource
private TranQueryDao tranQueryDao;
@GetMapping("/notify1")
public String getNotify(HttpServletRequest request) {
return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "get method,no deal", locale);
}
@PostMapping("/notify")
public String postNotify(HttpServletRequest request) throws ServletException, IOException {
System.out.println("收到用户支付通知");
request.setCharacterEncoding("UTF-8");//通知传输的编码为GBK
TreeMap<String, String> notifyMap = new TreeMap<String, String>();
Map params = request.getParameterMap();
for (Object key : params.keySet()) {
String value = ((String[]) params.get(key))[0];
System.out.println(key + ";" + value);
notifyMap.put(key.toString(), value);
}
try {
String appkey = "";
if ("RSA".equals(notifyMap.get("signtype"))) appkey = SybConstants.SYB_RSATLPUBKEY;
else if ("SM2".equals(notifyMap.get("signtype"))) appkey = SybConstants.SYB_SM2TLPUBKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
boolean isSign = SybUtil.validSign(notifyMap, appkey, notifyMap.get("signtype"));// 接受到推送通知,首先验签
System.out.println("验签结果:" + isSign);
//验签完毕进行业务处理
//收到的支付通知
TranNotifyEntity tranNotifyEntity = TranNotifyUtils.getEntityByMap(notifyMap);
//保存或更新交易通知
saveAndUpdateTranNotify(tranNotifyEntity);
//再查一下订单
final String trxid = tranNotifyEntity.getTrxid();
SybPayService service = new SybPayService();
Map<String, String> queryMap = service.query("", trxid);
TranQueryEntity tranQueryEntity = TranQueryUtils.getEntityByMap(queryMap);
UnitOrderPayEntity unitOrderPay = getUnitOrderPayByTranQuery(tranQueryEntity);
if (unitOrderPay != null) {
tranQueryEntity.setOrderid(unitOrderPay.getId());
}
//保存或更新交易查询
saveAndUpdateTranQuery(tranQueryEntity);
//判断用户支付成功
if ("0000".equals(tranNotifyEntity.getTrxstatus())) {
if (unitOrderPay != null) {
unitOrderPay.setPayResult("支付成功");
unitOrderPayDao.saveAndFlush(unitOrderPay);
}
//通知前端支付成功
log.info("支付成功");
String retMsg = outputEncapsulationObject(PromptMessageEnum.SUCCESS, "支付成功", locale);
PayWebSocketUsers.sendMessageToUsersByText(retMsg);
return "success";
}
if (unitOrderPay != null) {
unitOrderPay.setPayResult("支付失败");
unitOrderPayDao.saveAndFlush(unitOrderPay);
}
//通知前端支付失败
log.info("支付失败");
String retMsg = outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, "支付失败", locale);
PayWebSocketUsers.sendMessageToUsersByText(retMsg);
return "fail";
} catch (Exception e) {//处理异常
e.printStackTrace();
log.info(e.getMessage());
return "fail";
}
}
private void saveAndUpdateTranNotify(TranNotifyEntity newTranNotify) throws Exception {
final String cusid = newTranNotify.getCusid();
final String appid = newTranNotify.getAppid();
final String trxid = newTranNotify.getTrxid();
final String cusorderid = newTranNotify.getCusorderid();
Specification<TranNotifyEntity> notifySpecification = (root, criteriaQuery, criteriaBuilder) -> {
//查询条件集合
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(criteriaBuilder.equal(root.get("cusid").as(String.class), cusid));
predicateList.add(criteriaBuilder.equal(root.get("appid").as(String.class), appid));
predicateList.add(criteriaBuilder.equal(root.get("trxid").as(String.class), trxid));
predicateList.add(criteriaBuilder.equal(root.get("cusorderid").as(String.class), cusorderid));
Predicate[] predicateArray = new Predicate[predicateList.size()];
return criteriaBuilder.and(predicateList.toArray(predicateArray));
};
List<TranNotifyEntity> oldTranNotifyList = tranNotifyDao.findAll(notifySpecification);
if (oldTranNotifyList.isEmpty()) {
System.out.println("用户支付通知成功");
tranNotifyDao.saveAndFlush(newTranNotify);
} else if (oldTranNotifyList.size() == 1) {
//TODO 用户支付重复通知一次
System.out.println("用户支付重复通知一次");
TranNotifyEntity oldTranNotify = oldTranNotifyList.get(0);
TranNotifyUtils.updateEntity(newTranNotify, oldTranNotify);
tranNotifyDao.saveAndFlush(oldTranNotify);
} else {
//TODO 用户支付重复通知多次
System.out.println("用户支付重复通知多次");
for (TranNotifyEntity oldTranNotify : oldTranNotifyList) {
TranNotifyUtils.updateEntity(newTranNotify, oldTranNotify);
tranNotifyDao.saveAndFlush(oldTranNotify);
}
}
}
private void saveAndUpdateTranQuery(TranQueryEntity newTranQuery) throws Exception {
String cusid = newTranQuery.getCusid();
String appid = newTranQuery.getAppid();
String trxid = newTranQuery.getTrxid();
String reqsn = newTranQuery.getReqsn();
Specification<TranQueryEntity> querySpecification = (root, criteriaQuery, criteriaBuilder) -> {
//查询条件集合
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(criteriaBuilder.equal(root.get("cusid").as(String.class), cusid));
predicateList.add(criteriaBuilder.equal(root.get("appid").as(String.class), appid));
predicateList.add(criteriaBuilder.equal(root.get("trxid").as(String.class), trxid));
predicateList.add(criteriaBuilder.equal(root.get("reqsn").as(String.class), reqsn));
Predicate[] predicateArray = new Predicate[predicateList.size()];
return criteriaBuilder.and(predicateList.toArray(predicateArray));
};
List<TranQueryEntity> oldTranQueryList = tranQueryDao.findAll(querySpecification);
if (oldTranQueryList.isEmpty()) {
System.out.println("用户支付查询成功");
tranQueryDao.saveAndFlush(newTranQuery);
} else if (oldTranQueryList.size() == 1) {
//TODO 用户支付重复查询一次
System.out.println("用户支付重复查询一次");
TranQueryEntity oldTranQuery = oldTranQueryList.get(0);
TranQueryUtils.updateEntity(newTranQuery, oldTranQuery);
tranQueryDao.saveAndFlush(oldTranQuery);
} else {
//TODO 用户支付重复查询多次
System.out.println("用户支付重复查询多次");
for (TranQueryEntity oldTranQuery : oldTranQueryList) {
TranQueryUtils.updateEntity(newTranQuery, oldTranQuery);
tranQueryDao.saveAndFlush(oldTranQuery);
}
}
}
/**
* 通过查询记录找到订单记录
*/
private UnitOrderPayEntity getUnitOrderPayByTranQuery(TranQueryEntity tranQueryEntity) {
String cusid = tranQueryEntity.getCusid();
String appid = tranQueryEntity.getAppid();
String trxid = tranQueryEntity.getTrxid();
String reqsn = tranQueryEntity.getReqsn();
Specification<UnitOrderPayEntity> orderSpecification = (root, criteriaQuery, criteriaBuilder) -> {
//查询条件集合
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(criteriaBuilder.equal(root.get("cusid").as(String.class), cusid));
predicateList.add(criteriaBuilder.equal(root.get("appid").as(String.class), appid));
predicateList.add(criteriaBuilder.equal(root.get("trxid").as(String.class), trxid));
predicateList.add(criteriaBuilder.equal(root.get("reqsn").as(String.class), reqsn));
Predicate[] predicateArray = new Predicate[predicateList.size()];
return criteriaBuilder.and(predicateList.toArray(predicateArray));
};
List<UnitOrderPayEntity> orderList = unitOrderPayDao.findAll(orderSpecification);
if (orderList.isEmpty()) {
System.out.println("用户更新订单不存在");
return null;
}
if (orderList.size() == 1) {
System.out.println("用户更新订单成功");
return orderList.get(0);
}
System.out.println("用户支付重复查询多次");
return orderList.get(0);
}
/**
* 统一下单支付
*/
@PostMapping("/unitorderpay")
public String unitOrderPay(@RequestHeader(value = "Authorization") String token, @RequestBody UnitOrderPayQo unitOrderPayQo) {
try {
// 验证token
String tokenUserName = TokenUtil.getTokenUserName(token);
SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
if (sysUserEntity == null) {
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, "您还没有注册登录,请先注册登录", locale);
}
String trxAmtYuan = unitOrderPayQo.getTrxAmtYuan();
String payType = unitOrderPayQo.getPayType();
String body = unitOrderPayQo.getBody();
long trxAmt = (long) (Double.parseDouble(trxAmtYuan) * 100);
if ((!"W01".equals(payType)) && (!"A01".equals(payType))) {
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
}
SybPayService service = new SybPayService();
long currentTimeMillis = System.currentTimeMillis();
String reqsn = String.valueOf(currentTimeMillis);
Map<String, String> resultMap = service.pay(trxAmt, reqsn, payType, body, "备注", "", "120", payNotifyUrl, "", "", "", "", "", "", "", "", "", "", "", "");
if ("SUCCESS".equals(resultMap.get("retcode")) && "0000".equals(resultMap.get("trxstatus"))) {
UnitOrderPayEntity entity = UnitOrderPayUtils.getEntityByMap(resultMap);
String path = QRCodeUtils.generateQRCodeImage(entity.getPayinfo(), 350, 350, qrCodeSaveDirPath, qrCodeAccessDirPath, reqsn + "_" + trxAmt + ".png");
if (StrUtil.isEmpty(path)) {
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
}
entity.setUserId(sysUserEntity.getId());
entity.setCreateTime(dateFormat.format(new Date(currentTimeMillis)));
entity.setBody(body);
entity.setQrCodePath(path);
unitOrderPayDao.saveAndFlush(entity);
return outputEncapsulationObject(PromptMessageEnum.SUCCESS, entity, locale);
}
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
} catch (Exception e) {
e.printStackTrace();
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
}
}
/**
* 查询用户订单
*/
@GetMapping("/queryorder")
public String queryOrder(@RequestHeader(value = "Authorization") String token,//token
@RequestParam(value = "userName", required = false) String userName,//要查询的用户名
@RequestParam(value = "pageNum", required = false) String pageNum,//分页第几页可以不填
@RequestParam(value = "pageSize", required = false) String pageSize,//分页每页有多少条可以不填
@RequestParam(value = "startTime", required = false) String startTime,//开始时间可以不填
@RequestParam(value = "endTime", required = false) String endTime//结束时间可以不填
) {
// 验证token
String tokenUserName = TokenUtil.getTokenUserName(token);
SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
if (sysUserEntity == null) {
return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR, "您还没有注册登录,请先注册登录", locale);
}
//分页查询
int pageNumInt = 1;
int pageSizeInt = 10;
if (StrUtil.isNotEmpty(pageNum) && StrUtil.isNotEmpty(pageSize)) {
pageNumInt = Integer.parseInt(pageNum);
pageSizeInt = Integer.parseInt(pageSize);
}
//查询交易记录
List<Map<String, String>> queryTranVoList = new LinkedList<>();
if ("管理员".equals(sysUserEntity.getAccountType())) {
System.out.println("管理员查" + (StrUtil.isEmpty(userName) ? "全部" : userName));
List<Map<String, String>> list = tranQueryDao.queryTranByAdmin(StrUtil.isEmpty(userName) ? "" : userName, pageNumInt, pageSizeInt);
queryTranVoList.addAll(list);
} else {
System.out.println(sysUserEntity.getUserName() + "查自己");
List<Map<String, String>> list = tranQueryDao.queryTran(sysUserEntity.getId(), pageNumInt, pageSizeInt);
queryTranVoList.addAll(list);
}
List<QueryTran> collect = queryTranVoList.stream().map(TranQueryUtils::transform).collect(Collectors.toList());
return outputEncapsulationObject(PromptMessageEnum.SUCCESS, collect, locale);
}
/**
* 统一下单退款
*/
@PostMapping("/unitorderrefund")
public String unitOrderRefund(@RequestBody UnitOrderRefundQo unitOrderRefundQo) {
try {
String trxAmtYuan = unitOrderRefundQo.getTrxAmtYuan();
String oldReqSn = unitOrderRefundQo.getOldReqSn();
long trxAmt = (long) (Double.parseDouble(trxAmtYuan) * 100);
SybPayService service = new SybPayService();
String reqsn = String.valueOf(System.currentTimeMillis());
Map<String, String> map = service.refund(trxAmt, reqsn, "", oldReqSn);
return outputEncapsulationObject(PromptMessageEnum.SUCCESS, map, locale);
} catch (Exception e) {
e.printStackTrace();
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
}
}
/**
* 统一下单查询
*/
@GetMapping("/unitorderquery")
public String unitOrderQuery(@RequestParam(value = "trxId") String trxId) {
try {
SybPayService service = new SybPayService();
Map<String, String> map = service.query("", trxId);
return outputEncapsulationObject(PromptMessageEnum.SUCCESS, map, locale);
} catch (Exception e) {
e.printStackTrace();
return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL, null, locale);
}
}
}

View File

@ -0,0 +1,182 @@
package com.xkrs.allinpay;
import com.xkrs.allinpay.utils.HttpConnectionUtil;
import com.xkrs.allinpay.utils.SybConstants;
import com.xkrs.allinpay.utils.SybUtil;
import java.util.Map;
import java.util.TreeMap;
public class SybPayService {
public Map<String, String> pay(long trxamt, String reqsn, String paytype, String body, String remark, String acct, String validtime, String notify_url, String limit_pay, String idno, String truename, String asinfo, String sub_appid, String goods_tag, String benefitdetail, String chnlstoreid, String subbranch, String extendparams, String cusip, String fqnum) throws Exception {
HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/pay");
http.init();
TreeMap<String, String> params = new TreeMap<String, String>();
if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) params.put("orgid", SybConstants.SYB_ORGID);
params.put("cusid", SybConstants.SYB_CUSID);
params.put("appid", SybConstants.SYB_APPID);
params.put("version", "11");
params.put("trxamt", String.valueOf(trxamt));
params.put("reqsn", reqsn);
params.put("paytype", paytype);
params.put("randomstr", SybUtil.getValidatecode(8));
params.put("body", body);
params.put("remark", remark);
params.put("validtime", validtime);
params.put("acct", acct);
params.put("notify_url", notify_url);
params.put("limit_pay", limit_pay);
params.put("sub_appid", sub_appid);
params.put("goods_tag", goods_tag);
params.put("benefitdetail", benefitdetail);
params.put("chnlstoreid", chnlstoreid);
params.put("subbranch", subbranch);
params.put("extendparams", extendparams);
params.put("cusip", cusip);
params.put("fqnum", fqnum);
params.put("idno", idno);
params.put("truename", truename);
params.put("asinfo", asinfo);
params.put("signtype", SybConstants.SIGN_TYPE);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSACUSPRIKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2PPRIVATEKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
byte[] bys = http.postParams(params, true);
String result = new String(bys, "UTF-8");
Map<String, String> resultMap = handleResult(result);
return resultMap;
}
public Map<String, String> cancel(long trxamt, String reqsn, String oldtrxid, String oldreqsn) throws Exception {
HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/cancel");
http.init();
TreeMap<String, String> params = new TreeMap<String, String>();
if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) params.put("orgid", SybConstants.SYB_ORGID);
params.put("cusid", SybConstants.SYB_CUSID);
params.put("appid", SybConstants.SYB_APPID);
params.put("version", "11");
params.put("trxamt", String.valueOf(trxamt));
params.put("reqsn", reqsn);
params.put("oldtrxid", oldtrxid);
params.put("oldreqsn", oldreqsn);
params.put("randomstr", SybUtil.getValidatecode(8));
params.put("signtype", SybConstants.SIGN_TYPE);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSACUSPRIKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2PPRIVATEKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
byte[] bys = http.postParams(params, true);
String result = new String(bys, "UTF-8");
Map<String, String> map = handleResult(result);
return map;
}
public Map<String, String> refund(long trxamt, String reqsn, String oldtrxid, String oldreqsn) throws Exception {
HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/refund");
http.init();
TreeMap<String, String> params = new TreeMap<String, String>();
if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) params.put("orgid", SybConstants.SYB_ORGID);
params.put("cusid", SybConstants.SYB_CUSID);
params.put("appid", SybConstants.SYB_APPID);
params.put("version", "11");
params.put("trxamt", String.valueOf(trxamt));
params.put("reqsn", reqsn);
params.put("oldreqsn", oldreqsn);
params.put("oldtrxid", oldtrxid);
params.put("randomstr", SybUtil.getValidatecode(8));
params.put("signtype", SybConstants.SIGN_TYPE);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSACUSPRIKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2PPRIVATEKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
byte[] bys = http.postParams(params, true);
String result = new String(bys, "UTF-8");
Map<String, String> map = handleResult(result);
return map;
}
public Map<String, String> query(String reqsn, String trxid) throws Exception {
HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/query");
http.init();
TreeMap<String, String> params = new TreeMap<String, String>();
if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) params.put("orgid", SybConstants.SYB_ORGID);
params.put("cusid", SybConstants.SYB_CUSID);
params.put("appid", SybConstants.SYB_APPID);
params.put("version", "11");
params.put("reqsn", reqsn);
params.put("trxid", trxid);
params.put("randomstr", SybUtil.getValidatecode(8));
params.put("signtype", SybConstants.SIGN_TYPE);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSACUSPRIKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2PPRIVATEKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
byte[] bys = http.postParams(params, true);
String result = new String(bys, "UTF-8");
Map<String, String> map = handleResult(result);
return map;
}
@SuppressWarnings({"rawtypes", "unchecked"})
public static Map<String, String> handleResult(String result) throws Exception {
System.out.println("ret:" + result);
Map map = SybUtil.json2Obj(result, Map.class);
if (map == null) {
throw new Exception("返回数据错误");
}
if ("SUCCESS".equals(map.get("retcode"))) {
TreeMap tmap = new TreeMap();
tmap.putAll(map);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSATLPUBKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2TLPUBKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
if (SybUtil.validSign(tmap, appkey, SybConstants.SIGN_TYPE)) {
System.out.println("签名成功");
return map;
} else {
throw new Exception("验证签名失败");
}
} else {
throw new Exception(map.get("retmsg").toString());
}
}
public Map<String, String> scanPay(long trxamt, String reqsn, String body, String remark, String authcode, String limit_pay, String idno, String truename, String asinfo) throws Exception {
// TODO Auto-generated method stub
HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/scanqrpay");
http.init();
TreeMap<String, String> params = new TreeMap<String, String>();
if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) params.put("orgid", SybConstants.SYB_ORGID);
params.put("cusid", SybConstants.SYB_CUSID);
params.put("appid", SybConstants.SYB_APPID);
params.put("version", "11");
params.put("trxamt", String.valueOf(trxamt));
params.put("reqsn", reqsn);
params.put("randomstr", SybUtil.getValidatecode(8));
params.put("body", body);
params.put("remark", remark);
params.put("authcode", authcode);
params.put("limit_pay", limit_pay);
params.put("asinfo", asinfo);
params.put("signtype", SybConstants.SIGN_TYPE);
String appkey = "";
if (SybConstants.SIGN_TYPE.equals("RSA")) appkey = SybConstants.SYB_RSACUSPRIKEY;
else if (SybConstants.SIGN_TYPE.equals("SM2")) appkey = SybConstants.SYB_SM2PPRIVATEKEY;
else appkey = SybConstants.SYB_MD5_APPKEY;
params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
byte[] bys = http.postParams(params, true);
String result = new String(bys, "UTF-8");
Map<String, String> map = handleResult(result);
return map;
}
}

View File

@ -0,0 +1,80 @@
package com.xkrs.allinpay.model;
public class QueryTran {
private String trxid;
private String reqsn;
private String username;
private String reallyname;
private String body;
private String trxamt;
private String fintime;
private String trxstatus;
public QueryTran() {
}
public String getTrxid() {
return trxid;
}
public void setTrxid(String trxid) {
this.trxid = trxid;
}
public String getReqsn() {
return reqsn;
}
public void setReqsn(String reqsn) {
this.reqsn = reqsn;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getReallyname() {
return reallyname;
}
public void setReallyname(String reallyname) {
this.reallyname = reallyname;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getTrxamt() {
return trxamt;
}
public void setTrxamt(String trxamt) {
this.trxamt = trxamt;
}
public String getFintime() {
return fintime;
}
public void setFintime(String fintime) {
this.fintime = fintime;
}
public String getTrxstatus() {
return trxstatus;
}
public void setTrxstatus(String trxstatus) {
this.trxstatus = trxstatus;
}
}

View File

@ -0,0 +1,415 @@
package com.xkrs.allinpay.model;
import javax.persistence.*;
import java.io.Serializable;
/**
* 支付通知实体类
*/
@Entity
@Table(name = "tran_notify")
public class TranNotifyEntity implements Serializable {
/**
* 指定主键建立自增序列主键值取自序列
*/
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tran_notify_seq_gen")
@SequenceGenerator(name = "tran_notify_seq_gen", sequenceName = "tran_notify_id_seq", allocationSize = 1)
private Long id;
/**
* 收银宝APPID
*/
private String appid;
/**
* 第三方交易号
*/
private String outtrxid;
/**
* 交易类型
*/
private String trxcode;
/**
* 收银宝交易单号
*/
private String trxid;
/**
* 原始下单金额
*/
private String initamt;
/**
* 交易金额
*/
private String trxamt;
/**
* 交易请求日期
*/
private String trxdate;
/**
* 交易完成时间
*/
private String paytime;
/**
* 渠道流水号
*/
private String chnltrxid;
/**
* 交易结果码
*/
private String trxstatus;
/**
* 商户编号
*/
private String cusid;
/**
* 终端编号
*/
private String termno;
/**
* 终端批次号
*/
private String termbatchid;
/**
* 终端流水号
*/
private String termtraceno;
/**
* 终端授权码
*/
private String termauthno;
/**
* 终端参考号
*/
private String termrefnum;
/**
* 业务关联内容
*/
private String trxreserved;
/**
* 原交易流水
*/
private String srctrxid;
/**
* 业务流水
*/
private String cusorderid;
/**
* 交易账号
*/
private String acct;
/**
* 手续费
*/
private String fee;
/**
* 签名类型
*/
private String signtype;
/**
* 渠道子商户号
*/
private String cmid;
/**
* 渠道号
*/
private String chnlid;
/**
* 渠道信息
*/
private String chnldata;
/**
* 借贷标识
*/
private String accttype;
/**
* 发卡行
*/
private String bankcode;
/**
* 用户账号
*/
private String logonid;
/**
* 分期数
*/
private String fqnum;
/**
* 结算周期
*/
private String feecycle;
/**
* 通联渠道侧OPENID
*/
private String tlopenid;
/**
* 基础营销权益抵扣明细
*/
private String mktresult;
public TranNotifyEntity() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getOuttrxid() {
return outtrxid;
}
public void setOuttrxid(String outtrxid) {
this.outtrxid = outtrxid;
}
public String getTrxcode() {
return trxcode;
}
public void setTrxcode(String trxcode) {
this.trxcode = trxcode;
}
public String getTrxid() {
return trxid;
}
public void setTrxid(String trxid) {
this.trxid = trxid;
}
public String getInitamt() {
return initamt;
}
public void setInitamt(String initamt) {
this.initamt = initamt;
}
public String getTrxamt() {
return trxamt;
}
public void setTrxamt(String trxamt) {
this.trxamt = trxamt;
}
public String getTrxdate() {
return trxdate;
}
public void setTrxdate(String trxdate) {
this.trxdate = trxdate;
}
public String getPaytime() {
return paytime;
}
public void setPaytime(String paytime) {
this.paytime = paytime;
}
public String getChnltrxid() {
return chnltrxid;
}
public void setChnltrxid(String chnltrxid) {
this.chnltrxid = chnltrxid;
}
public String getTrxstatus() {
return trxstatus;
}
public void setTrxstatus(String trxstatus) {
this.trxstatus = trxstatus;
}
public String getCusid() {
return cusid;
}
public void setCusid(String cusid) {
this.cusid = cusid;
}
public String getTermno() {
return termno;
}
public void setTermno(String termno) {
this.termno = termno;
}
public String getTermbatchid() {
return termbatchid;
}
public void setTermbatchid(String termbatchid) {
this.termbatchid = termbatchid;
}
public String getTermtraceno() {
return termtraceno;
}
public void setTermtraceno(String termtraceno) {
this.termtraceno = termtraceno;
}
public String getTermauthno() {
return termauthno;
}
public void setTermauthno(String termauthno) {
this.termauthno = termauthno;
}
public String getTermrefnum() {
return termrefnum;
}
public void setTermrefnum(String termrefnum) {
this.termrefnum = termrefnum;
}
public String getTrxreserved() {
return trxreserved;
}
public void setTrxreserved(String trxreserved) {
this.trxreserved = trxreserved;
}
public String getSrctrxid() {
return srctrxid;
}
public void setSrctrxid(String srctrxid) {
this.srctrxid = srctrxid;
}
public String getCusorderid() {
return cusorderid;
}
public void setCusorderid(String cusorderid) {
this.cusorderid = cusorderid;
}
public String getAcct() {
return acct;
}
public void setAcct(String acct) {
this.acct = acct;
}
public String getFee() {
return fee;
}
public void setFee(String fee) {
this.fee = fee;
}
public String getSigntype() {
return signtype;
}
public void setSigntype(String signtype) {
this.signtype = signtype;
}
public String getCmid() {
return cmid;
}
public void setCmid(String cmid) {
this.cmid = cmid;
}
public String getChnlid() {
return chnlid;
}
public void setChnlid(String chnlid) {
this.chnlid = chnlid;
}
public String getChnldata() {
return chnldata;
}
public void setChnldata(String chnldata) {
this.chnldata = chnldata;
}
public String getAccttype() {
return accttype;
}
public void setAccttype(String accttype) {
this.accttype = accttype;
}
public String getBankcode() {
return bankcode;
}
public void setBankcode(String bankcode) {
this.bankcode = bankcode;
}
public String getLogonid() {
return logonid;
}
public void setLogonid(String logonid) {
this.logonid = logonid;
}
public String getFqnum() {
return fqnum;
}
public void setFqnum(String fqnum) {
this.fqnum = fqnum;
}
public String getFeecycle() {
return feecycle;
}
public void setFeecycle(String feecycle) {
this.feecycle = feecycle;
}
public String getTlopenid() {
return tlopenid;
}
public void setTlopenid(String tlopenid) {
this.tlopenid = tlopenid;
}
public String getMktresult() {
return mktresult;
}
public void setMktresult(String mktresult) {
this.mktresult = mktresult;
}
}

View File

@ -0,0 +1,83 @@
package com.xkrs.allinpay.model;
import java.util.Map;
public class TranNotifyUtils {
public static TranNotifyEntity getEntityByMap(Map<String, String> map) {
TranNotifyEntity entity = new TranNotifyEntity();
entity.setAppid(map.get("appid"));
entity.setOuttrxid(map.get("outtrxid"));
entity.setTrxcode(map.get("trxcode"));
entity.setTrxid(map.get("trxid"));
entity.setInitamt(map.get("initamt"));
entity.setTrxamt(map.get("trxamt"));
entity.setTrxdate(map.get("trxdate"));
entity.setPaytime(map.get("paytime"));
entity.setChnltrxid(map.get("chnltrxid"));
entity.setTrxstatus(map.get("trxstatus"));
entity.setCusid(map.get("cusid"));
entity.setTermno(map.get("termno"));
entity.setTermbatchid(map.get("termbatchid"));
entity.setTermtraceno(map.get("termtraceno"));
entity.setTermauthno(map.get("termauthno"));
entity.setTermrefnum(map.get("termrefnum"));
entity.setTrxreserved(map.get("trxreserved"));
entity.setSrctrxid(map.get("srctrxid"));
entity.setCusorderid(map.get("cusorderid"));
entity.setAcct(map.get("acct"));
entity.setFee(map.get("fee"));
entity.setSigntype(map.get("signtype"));
entity.setCmid(map.get("cmid"));
entity.setChnlid(map.get("chnlid"));
entity.setChnldata(map.get("chnldata"));
entity.setAccttype(map.get("accttype"));
entity.setBankcode(map.get("bankcode"));
entity.setLogonid(map.get("logonid"));
entity.setFqnum(map.get("fqnum"));
entity.setFeecycle(map.get("feecycle"));
entity.setTlopenid(map.get("tlopenid"));
entity.setMktresult(map.get("mktresult"));
return entity;
}
public static void updateEntity(TranNotifyEntity newTranNotify, TranNotifyEntity oldTranNotify) {
oldTranNotify.setAppid(newTranNotify.getAppid());
oldTranNotify.setOuttrxid(newTranNotify.getOuttrxid());
oldTranNotify.setTrxcode(newTranNotify.getTrxcode());
oldTranNotify.setTrxid(newTranNotify.getTrxid());
oldTranNotify.setInitamt(newTranNotify.getInitamt());
oldTranNotify.setTrxamt(newTranNotify.getTrxamt());
oldTranNotify.setTrxdate(newTranNotify.getTrxdate());
oldTranNotify.setPaytime(newTranNotify.getPaytime());
oldTranNotify.setChnltrxid(newTranNotify.getChnltrxid());
oldTranNotify.setTrxstatus(newTranNotify.getTrxstatus());
oldTranNotify.setCusid(newTranNotify.getCusid());
oldTranNotify.setTermno(newTranNotify.getTermno());
oldTranNotify.setTermbatchid(newTranNotify.getTermbatchid());
oldTranNotify.setTermtraceno(newTranNotify.getTermtraceno());
oldTranNotify.setTermauthno(newTranNotify.getTermauthno());
oldTranNotify.setTermrefnum(newTranNotify.getTermrefnum());
oldTranNotify.setTrxreserved(newTranNotify.getTrxreserved());
oldTranNotify.setSrctrxid(newTranNotify.getSrctrxid());
oldTranNotify.setCusorderid(newTranNotify.getCusorderid());
oldTranNotify.setAcct(newTranNotify.getAcct());
oldTranNotify.setFee(newTranNotify.getFee());
oldTranNotify.setSigntype(newTranNotify.getSigntype());
oldTranNotify.setCmid(newTranNotify.getCmid());
oldTranNotify.setChnlid(newTranNotify.getChnlid());
oldTranNotify.setChnldata(newTranNotify.getChnldata());
oldTranNotify.setAccttype(newTranNotify.getAccttype());
oldTranNotify.setBankcode(newTranNotify.getBankcode());
oldTranNotify.setLogonid(newTranNotify.getLogonid());
oldTranNotify.setFqnum(newTranNotify.getFqnum());
oldTranNotify.setFeecycle(newTranNotify.getFeecycle());
oldTranNotify.setTlopenid(newTranNotify.getTlopenid());
oldTranNotify.setMktresult(newTranNotify.getMktresult());
}
}

View File

@ -0,0 +1,331 @@
package com.xkrs.allinpay.model;
import javax.persistence.*;
import java.io.Serializable;
/**
* 统一查询实体类
*/
@Entity
@Table(name = "tran_query")
public class TranQueryEntity implements Serializable {
/**
* 指定主键建立自增序列主键值取自序列
*/
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tran_query_seq_gen")
@SequenceGenerator(name = "tran_query_seq_gen", sequenceName = "tran_query_id_seq", allocationSize = 1)
private Long id;
/**
* 订单ID
*/
private Long orderid;
/**
* 商户号
*/
private String cusid;
/**
* 应用ID
*/
private String appid;
/**
* 交易单号
*/
private String trxid;
/**
* 支付渠道交易单号
*/
private String chnltrxid;
/**
* 商户订单号
*/
private String reqsn;
/**
* 交易类型
*/
private String trxcode;
/**
* 交易金额
*/
private String trxamt;
/**
* 交易状态
*/
private String trxstatus;
/**
* 支付平台用户标识
*/
private String acct;
/**
* 交易完成时间
*/
private String fintime;
/**
* 随机字符串
*/
private String randomstr;
/**
* 错误原因
*/
private String errmsg;
/**
* 渠道子商户号
*/
private String cmid;
/**
* 渠道号
*/
private String chnlid;
/**
* 原交易金额
*/
private String initamt;
/**
* 手续费
*/
private String fee;
/**
* 渠道信息
*/
private String chnldata;
/**
* 借贷标识
*/
private String accttype;
/**
* 所属银行
*/
private String bankcode;
/**
* 买家账号
*/
private String logonid;
/**
* 分期数
*/
private String fqnum;
/**
* 结算周期
*/
private String feecycle;
/**
* 交易备注
*/
private String trxreserve;
/**
* 通联渠道侧OPENID
*/
private String tlopenid;
public TranQueryEntity() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getOrderid() {
return orderid;
}
public void setOrderid(Long orderid) {
this.orderid = orderid;
}
public String getCusid() {
return cusid;
}
public void setCusid(String cusid) {
this.cusid = cusid;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getTrxid() {
return trxid;
}
public void setTrxid(String trxid) {
this.trxid = trxid;
}
public String getChnltrxid() {
return chnltrxid;
}
public void setChnltrxid(String chnltrxid) {
this.chnltrxid = chnltrxid;
}
public String getReqsn() {
return reqsn;
}
public void setReqsn(String reqsn) {
this.reqsn = reqsn;
}
public String getTrxcode() {
return trxcode;
}
public void setTrxcode(String trxcode) {
this.trxcode = trxcode;
}
public String getTrxamt() {
return trxamt;
}
public void setTrxamt(String trxamt) {
this.trxamt = trxamt;
}
public String getTrxstatus() {
return trxstatus;
}
public void setTrxstatus(String trxstatus) {
this.trxstatus = trxstatus;
}
public String getAcct() {
return acct;
}
public void setAcct(String acct) {
this.acct = acct;
}
public String getFintime() {
return fintime;
}
public void setFintime(String fintime) {
this.fintime = fintime;
}
public String getRandomstr() {
return randomstr;
}
public void setRandomstr(String randomstr) {
this.randomstr = randomstr;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getCmid() {
return cmid;
}
public void setCmid(String cmid) {
this.cmid = cmid;
}
public String getChnlid() {
return chnlid;
}
public void setChnlid(String chnlid) {
this.chnlid = chnlid;
}
public String getInitamt() {
return initamt;
}
public void setInitamt(String initamt) {
this.initamt = initamt;
}
public String getFee() {
return fee;
}
public void setFee(String fee) {
this.fee = fee;
}
public String getChnldata() {
return chnldata;
}
public void setChnldata(String chnldata) {
this.chnldata = chnldata;
}
public String getAccttype() {
return accttype;
}
public void setAccttype(String accttype) {
this.accttype = accttype;
}
public String getBankcode() {
return bankcode;
}
public void setBankcode(String bankcode) {
this.bankcode = bankcode;
}
public String getLogonid() {
return logonid;
}
public void setLogonid(String logonid) {
this.logonid = logonid;
}
public String getFqnum() {
return fqnum;
}
public void setFqnum(String fqnum) {
this.fqnum = fqnum;
}
public String getFeecycle() {
return feecycle;
}
public void setFeecycle(String feecycle) {
this.feecycle = feecycle;
}
public String getTrxreserve() {
return trxreserve;
}
public void setTrxreserve(String trxreserve) {
this.trxreserve = trxreserve;
}
public String getTlopenid() {
return tlopenid;
}
public void setTlopenid(String tlopenid) {
this.tlopenid = tlopenid;
}
}

View File

@ -0,0 +1,106 @@
package com.xkrs.allinpay.model;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
public class TranQueryUtils {
public static TranQueryEntity getEntityByMap(Map<String, String> map) {
TranQueryEntity entity = new TranQueryEntity();
entity.setCusid(map.get("cusid"));
entity.setAppid(map.get("appid"));
entity.setTrxid(map.get("trxid"));
entity.setChnltrxid(map.get("chnltrxid"));
entity.setReqsn(map.get("reqsn"));
entity.setTrxcode(map.get("trxcode"));
entity.setTrxamt(map.get("trxamt"));
entity.setTrxstatus(map.get("trxstatus"));
entity.setAcct(map.get("acct"));
entity.setFintime(map.get("fintime"));
entity.setRandomstr(map.get("randomstr"));
entity.setErrmsg(map.get("errmsg"));
entity.setCmid(map.get("cmid"));
entity.setChnlid(map.get("chnlid"));
entity.setInitamt(map.get("initamt"));
entity.setFee(map.get("fee"));
entity.setChnldata(map.get("chnldata"));
entity.setAccttype(map.get("accttype"));
entity.setBankcode(map.get("bankcode"));
entity.setLogonid(map.get("logonid"));
entity.setFqnum(map.get("fqnum"));
entity.setFeecycle(map.get("feecycle"));
entity.setTrxreserve(map.get("trxreserve"));
entity.setTlopenid(map.get("tlopenid"));
return entity;
}
public static void updateEntity(TranQueryEntity newTranQuery, TranQueryEntity oldTranQuery) {
oldTranQuery.setCusid(newTranQuery.getCusid());
oldTranQuery.setAppid(newTranQuery.getAppid());
oldTranQuery.setTrxid(newTranQuery.getTrxid());
oldTranQuery.setChnltrxid(newTranQuery.getChnltrxid());
oldTranQuery.setReqsn(newTranQuery.getReqsn());
oldTranQuery.setTrxcode(newTranQuery.getTrxcode());
oldTranQuery.setTrxamt(newTranQuery.getTrxamt());
oldTranQuery.setTrxstatus(newTranQuery.getTrxstatus());
oldTranQuery.setAcct(newTranQuery.getAcct());
oldTranQuery.setFintime(newTranQuery.getFintime());
oldTranQuery.setRandomstr(newTranQuery.getRandomstr());
oldTranQuery.setErrmsg(newTranQuery.getErrmsg());
oldTranQuery.setCmid(newTranQuery.getCmid());
oldTranQuery.setChnlid(newTranQuery.getChnlid());
oldTranQuery.setInitamt(newTranQuery.getInitamt());
oldTranQuery.setFee(newTranQuery.getFee());
oldTranQuery.setChnldata(newTranQuery.getChnldata());
oldTranQuery.setAccttype(newTranQuery.getAccttype());
oldTranQuery.setBankcode(newTranQuery.getBankcode());
oldTranQuery.setLogonid(newTranQuery.getLogonid());
oldTranQuery.setFqnum(newTranQuery.getFqnum());
oldTranQuery.setFeecycle(newTranQuery.getFeecycle());
oldTranQuery.setTrxreserve(newTranQuery.getTrxreserve());
oldTranQuery.setTlopenid(newTranQuery.getTlopenid());
}
private static final SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyyMMddHHmmss");
private static final SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final DecimalFormat decimalFormat = new DecimalFormat("0.00");
public static QueryTran transform(Map<String, String> queryTranVo) {
String trxid = queryTranVo.get("trxid");
String reqsn = queryTranVo.get("reqsn");
String username = queryTranVo.get("username");
String reallyname = queryTranVo.get("reallyname");
String body = queryTranVo.get("body");
String trxamt = queryTranVo.get("trxamt");
String fintime = queryTranVo.get("fintime");
String trxstatus = queryTranVo.get("trxstatus");
String finishTime = "";
try {
finishTime = dateFormat2.format(dateFormat1.parse(fintime));
} catch (ParseException e) {
throw new RuntimeException(e);
}
QueryTran queryTran = new QueryTran();
queryTran.setTrxid(trxid);
queryTran.setReqsn(reqsn);
queryTran.setUsername(username);
queryTran.setReallyname(reallyname);
queryTran.setBody(body);
queryTran.setTrxamt("" + decimalFormat.format(Long.parseLong(trxamt) / 100.0D));
queryTran.setFintime(finishTime);
queryTran.setTrxstatus("0000".equals(trxstatus) ? "支付成功" : "支付失败");
return queryTran;
}
}

View File

@ -0,0 +1,196 @@
package com.xkrs.allinpay.model;
import javax.persistence.*;
import java.io.Serializable;
/**
* 订单实体类
*/
@Entity
@Table(name = "unit_order_pay")
public class UnitOrderPayEntity implements Serializable {
/**
* 指定主键建立自增序列主键值取自序列
*/
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "unit_order_pay_seq_gen")
@SequenceGenerator(name = "unit_order_pay_seq_gen", sequenceName = "unit_order_pay_id_seq", allocationSize = 1)
private Long id;
/**
* 用户ID
*/
private Integer userId;
/**
* 订单创建时间
*/
private String createTime;
/**
* 订单标题
*/
private String body;
/**
* 支付结果
*/
private String payResult;
/**
* 二维码路径
*/
private String qrCodePath;
private String cusid;
private String appid;
private String trxid;
private String chnltrxid;
private String reqsn;
private String randomstr;
private String trxstatus;
private String fintime;
private String errmsg;
private String payinfo;
private String trxcode;
public UnitOrderPayEntity() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getPayResult() {
return payResult;
}
public void setPayResult(String payResult) {
this.payResult = payResult;
}
public String getQrCodePath() {
return qrCodePath;
}
public void setQrCodePath(String qrCodePath) {
this.qrCodePath = qrCodePath;
}
public String getCusid() {
return cusid;
}
public void setCusid(String cusid) {
this.cusid = cusid;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getTrxid() {
return trxid;
}
public void setTrxid(String trxid) {
this.trxid = trxid;
}
public String getChnltrxid() {
return chnltrxid;
}
public void setChnltrxid(String chnltrxid) {
this.chnltrxid = chnltrxid;
}
public String getReqsn() {
return reqsn;
}
public void setReqsn(String reqsn) {
this.reqsn = reqsn;
}
public String getRandomstr() {
return randomstr;
}
public void setRandomstr(String randomstr) {
this.randomstr = randomstr;
}
public String getTrxstatus() {
return trxstatus;
}
public void setTrxstatus(String trxstatus) {
this.trxstatus = trxstatus;
}
public String getFintime() {
return fintime;
}
public void setFintime(String fintime) {
this.fintime = fintime;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getPayinfo() {
return payinfo;
}
public void setPayinfo(String payinfo) {
this.payinfo = payinfo;
}
public String getTrxcode() {
return trxcode;
}
public void setTrxcode(String trxcode) {
this.trxcode = trxcode;
}
}

View File

@ -0,0 +1,52 @@
package com.xkrs.allinpay.model;
/**
* 订单参数
*/
public class UnitOrderPayQo {
/**
* 交易金额
*/
private String trxAmtYuan;
/**
* 支付方式
* W01 微信扫码支付
* A01 支付宝扫码支付
*/
private String payType;
/**
* 订单标题
* 订单商品名称空则以商户名作为商品名称
*/
private String body;
public UnitOrderPayQo() {
}
public String getTrxAmtYuan() {
return trxAmtYuan;
}
public void setTrxAmtYuan(String trxAmtYuan) {
this.trxAmtYuan = trxAmtYuan;
}
public String getPayType() {
return payType;
}
public void setPayType(String payType) {
this.payType = payType;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

View File

@ -0,0 +1,106 @@
package com.xkrs.allinpay.model;
import java.util.Map;
public class UnitOrderPayUtils {
public static UnitOrderPayEntity getEntityByMap(Map<String, String> map) {
UnitOrderPayEntity entity = new UnitOrderPayEntity();
entity.setCusid(map.get("cusid"));
entity.setAppid(map.get("appid"));
entity.setTrxid(map.get("trxid"));
entity.setChnltrxid(map.get("chnltrxid"));
entity.setReqsn(map.get("reqsn"));
entity.setRandomstr(map.get("randomstr"));
entity.setTrxstatus(map.get("trxstatus"));
entity.setFintime(map.get("fintime"));
entity.setErrmsg(map.get("errmsg"));
entity.setPayinfo(map.get("payinfo"));
entity.setTrxcode(map.get("trxcode"));
return entity;
}
private static String getTrxStatusDesc(String trxStatus) {
return null;
}
private static String getTrxCodeDesc(String trxCode) {
if ("VSP501".equals(trxCode)) {
return "微信支付";
}
if ("VSP502".equals(trxCode)) {
return "微信支付撤销";
}
if ("VSP503".equals(trxCode)) {
return "微信支付退款";
}
if ("VSP511".equals(trxCode)) {
return "支付宝支付";
}
if ("VSP512".equals(trxCode)) {
return "支付宝支付撤销";
}
if ("VSP513".equals(trxCode)) {
return "支付宝支付退款";
}
if ("VSP541".equals(trxCode)) {
return "扫码支付";
}
if ("VSP542".equals(trxCode)) {
return "扫码撤销";
}
if ("VSP543".equals(trxCode)) {
return "扫码退货";
}
if ("VSP551".equals(trxCode)) {
return "银联扫码支付";
}
if ("VSP552".equals(trxCode)) {
return "银联扫码撤销";
}
if ("VSP553".equals(trxCode)) {
return "银联扫码退货";
}
if ("VSP907".equals(trxCode)) {
return "差错借记调整";
}
if ("VSP908".equals(trxCode)) {
return "差错贷记调整";
}
if ("VSP611".equals(trxCode)) {
return "数字货币支付";
}
if ("VSP612".equals(trxCode)) {
return "数字货币撤销";
}
if ("VSP613".equals(trxCode)) {
return "数字货币退货";
}
if ("VSP621".equals(trxCode)) {
return "分期支付";
}
if ("VSP622".equals(trxCode)) {
return "分期撤销";
}
if ("VSP623".equals(trxCode)) {
return "分期退货";
}
if ("300002".equals(trxCode)) {
return "充值";
}
if ("VSP681".equals(trxCode)) {
return "微信订单预消费";
}
if ("VSP682".equals(trxCode)) {
return "微信订单退款";
}
if ("VSP683".equals(trxCode)) {
return "微信订单完成";
}
if ("VSP684".equals(trxCode)) {
return "微信订单完成退款";
}
return null;
}
}

View File

@ -0,0 +1,34 @@
package com.xkrs.allinpay.model;
public class UnitOrderRefundQo {
/**
* 交易金额
*/
private String trxAmtYuan;
/**
* 原交易订单号
*/
private String oldReqSn;
public UnitOrderRefundQo() {
}
public String getTrxAmtYuan() {
return trxAmtYuan;
}
public void setTrxAmtYuan(String trxAmtYuan) {
this.trxAmtYuan = trxAmtYuan;
}
public String getOldReqSn() {
return oldReqSn;
}
public void setOldReqSn(String oldReqSn) {
this.oldReqSn = oldReqSn;
}
}

View File

@ -0,0 +1,112 @@
package com.xkrs.allinpay.test;
import com.xkrs.allinpay.SybPayService;
import java.util.Map;
public class ApiTestV2 {
public static void main(String[] args) throws Exception {
// testPay();//统一下单异步类交易
// testScanPay();//统一扫码被扫交易
// testCancel();//撤销
testRefund();//退款
// testQuery();//查询
}
/**
* chnlid;205299480
* randomstr;281692226001
* trxcode;VSP501
* sign;S3+78r3sPP/F1EV9ICo+fBu4UKC8nY47QAcTyVJSrzGX4/advm7B2lqrzjzGiMmrNpFiRy8zrNmBjPV94q484Q==
* errmsg;缺少必要字段 terminal_info(UP01A5100)
* cmid;625141525
* trxid;250310119743017937
* trxstatus;3045
* accttype;99
* reqsn;1741585763289
* fintime;20250310134920
* cusid;990440148166000
* appid;00000003
* initamt;1
* acct;000000
* bankcode;0000
* trxamt;1
* retcode;SUCCESS
*/
public static void testScanPay() throws Exception {
SybPayService service = new SybPayService();
String reqsn = String.valueOf(System.currentTimeMillis());
Map<String, String> map = service.scanPay(1, reqsn, "标题", "备注", "134775931316089668", "", "", "", "");
print(map);
}
/**
* chnlid;205299480
* randomstr;134591333810
* trxcode;VSP501
* sign;UZwP/m6ZbZhSkjgpa27a0VdKElbzR1OgTH+BwPtUcLRy9v34DaQKb1C55Sd06+f6kkQ+VsrgEN8ocFtEiRd7TA==
* errmsg;缺少必要字段 terminal_info(UP01A5100)
* cmid;625141525
* trxid;250310119743017937
* trxstatus;3045
* accttype;99
* reqsn;1741585763289
* fintime;20250310134920
* cusid;990440148166000
* appid;00000003
* initamt;1
* acct;000000
* bankcode;0000
* trxamt;1
* retcode;SUCCESS
*/
public static void testQuery() throws Exception {
SybPayService service = new SybPayService();
Map<String, String> map = service.query("", "250310119743017937");
print(map);
}
public static void testRefund() throws Exception {
SybPayService service = new SybPayService();
String reqsn = String.valueOf(System.currentTimeMillis());
// Map<String, String> map = service.refund(1, reqsn, "", "1742278978287");
Map<String, String> map = service.refund(1, reqsn, "250326129022241524", "");
print(map);
}
public static void testCancel() throws Exception {
SybPayService service = new SybPayService();
String reqsn = String.valueOf(System.currentTimeMillis());
Map<String, String> map = service.cancel(1, reqsn, "1741655699800", "");
print(map);
}
/**
* randomstr;319561317577
* trxcode;VSP501
* cusid;990440148166000
* appid;00000003
* sign;twRKyHVn5prsyy469n+/XfZ/SGsPwfJwQGu0MbWZHV83sxOuFBIJ78QYyRIWg/QdBIkxRuuCSlnhg7rZk6TFEw==
* payinfo;https://syb.allinpay.com/apiweb/h5unionpay/native?key=GCnOxovaUMsSEXeDw8RhG%2Fcy
* trxid;250310112843002292
* trxstatus;0000
* reqsn;1741585650888
* retcode;SUCCESS
*/
public static void testPay() throws Exception {
SybPayService service = new SybPayService();
String reqsn = String.valueOf(System.currentTimeMillis());
Map<String, String> map = service.pay(1, reqsn, "W01", "标题", "备注", "", "123", "http://8.142.26.238:6801/pay/notify", "", "", "", "", "", "", "", "", "", "", "", "");
print(map);
}
public static void print(Map<String, String> map) {
System.out.println("返回数据如下:");
if (map != null) {
for (String key : map.keySet()) {
System.out.println(key + ";" + map.get(key));
}
}
}
}

View File

@ -0,0 +1,33 @@
package com.xkrs.allinpay.utils;
public class FileUploadPath {
/**
* 上传路径
*/
private String uploadPath;
/**
* 访问路径
*/
private String accessPath;
public FileUploadPath() {
}
public String getUploadPath() {
return uploadPath;
}
public void setUploadPath(String uploadPath) {
this.uploadPath = uploadPath;
}
public String getAccessPath() {
return accessPath;
}
public void setAccessPath(String accessPath) {
this.accessPath = accessPath;
}
}

View File

@ -0,0 +1,58 @@
package com.xkrs.allinpay.utils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
public class FileUploadUtils {
/**
* 上传文件
*
* @param file 文件
* @param baseDirPath Base文件夹
* @param dirPath 自定义配置文件夹会在Base文件夹的下层
* @param fileName 自定义文件名
* @return 映射后的文件路径
*/
public static String uploadFile(MultipartFile file, FileUploadPath baseDirPath, String dirPath, String fileName) throws IOException {
//确定新的文件名
String newFileName = fileName;
if (StrUtil.isEmpty(fileName)) {
newFileName = UUID.randomUUID().toString() + "." + FileUtil.extName(file.getOriginalFilename());
}
//确定上传到哪个目录
File uploadDir;
if (StrUtil.isEmpty(dirPath)) {
uploadDir = new File(baseDirPath.getUploadPath());
} else {
uploadDir = new File(baseDirPath.getUploadPath(), dirPath);
}
if ((!uploadDir.exists()) || (!uploadDir.isDirectory())) {
boolean mkdirs = uploadDir.mkdirs();
System.out.println("新建文件夹" + (mkdirs ? "成功" : "失败") + "" + uploadDir.getAbsolutePath());
}
//删除重复文件
File uploadFile = new File(uploadDir, newFileName);
if (uploadFile.exists() && uploadFile.isFile()) {
boolean delete = uploadFile.delete();
System.out.println("删除旧文件" + (delete ? "成功" : "失败") + "" + uploadFile.getAbsolutePath());
}
//上传
file.transferTo(uploadFile);
//生成映射文件路径
File accessDir;
if (StrUtil.isEmpty(dirPath)) {
accessDir = new File(baseDirPath.getAccessPath());
} else {
accessDir = new File(baseDirPath.getAccessPath(), dirPath);
}
return new File(accessDir, newFileName).getPath();
}
}

View File

@ -0,0 +1,115 @@
package com.xkrs.allinpay.utils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
public class HttpConnectionUtil {
private HttpURLConnection conn;
private String connectUrl;
public HttpConnectionUtil(String connectUrl) {
this.connectUrl = connectUrl;
}
public void init() throws Exception {
URL url = new URL(connectUrl);
System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return urlHostName.equals(session.getPeerHost());
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
URLConnection conn = url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setReadTimeout(60000);
conn.setConnectTimeout(30000);
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
httpsConn.setSSLSocketFactory(SSLUtil.getInstance().getSSLSocketFactory());
} else if (conn instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) conn;
} else {
throw new Exception("不是http/https协议的url");
}
this.conn = (HttpURLConnection) conn;
initDefaultPost();
}
public void destory() {
try {
if (this.conn != null) {
this.conn.disconnect();
}
} catch (Exception e) {
}
}
private void initDefaultPost() throws Exception {
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
public byte[] postParams(Map<String, String> params, boolean readreturn) throws IOException {
StringBuilder outBuf = new StringBuilder();
boolean isNotFirst = false;
for (Map.Entry<String, String> entry : params.entrySet()) {
if (isNotFirst) outBuf.append('&');
isNotFirst = true;
outBuf.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
System.out.println("参数:" + outBuf.toString());
return postParams(outBuf.toString(), readreturn);
}
public byte[] postParams(String message, boolean readreturn) throws IOException {
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(message.getBytes("UTF-8"));
out.close();
if (readreturn) {
return readBytesFromStream(conn.getInputStream());
} else {
return null;
}
}
public byte[] postParams(byte[] message, boolean readreturn) throws IOException {
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(message);
out.close();
if (readreturn) {
return readBytesFromStream(conn.getInputStream());
} else {
return null;
}
}
private byte[] readBytesFromStream(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int readLen;
byte[] tmpBuf = new byte[4096];
while ((readLen = is.read(tmpBuf)) > 0) baos.write(tmpBuf, 0, readLen);
is.close();
return baos.toByteArray();
}
public HttpURLConnection getConn() {
return conn;
}
}

View File

@ -0,0 +1,64 @@
package com.xkrs.allinpay.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class QRCodeUtils {
/**
* 生成二维码
*
* @param content 二维码内容
* @param width 宽度
* @param height 高度
* @param saveDirPath 保存目录
* @param accessDirPath 访问目录
* @param fileName 文件名
* @return 访问路径
*/
public static String generateQRCodeImage(String content, int width, int height, String saveDirPath, String accessDirPath, String fileName) {
try {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符编码
hints.put(EncodeHintType.MARGIN, 1); // 设置二维码边缘与内容的间隙
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
bufferedImage.createGraphics();
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
graphics.setColor(java.awt.Color.WHITE);
graphics.fillRect(0, 0, width, height);
graphics.setColor(java.awt.Color.BLACK);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
if (bitMatrix.get(i, j)) {
graphics.fillRect(i, j, 1, 1);
}
}
}
File saveDir = new File(saveDirPath);
if ((!saveDir.exists()) || (!saveDir.isDirectory())) {
boolean mkdirs = saveDir.mkdirs();
}
ImageIO.write(bufferedImage, "png", new File(saveDir, fileName));
return new File(accessDirPath, fileName).getPath();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,56 @@
package com.xkrs.allinpay.utils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* SSL管理助手类
*
* @author Administrator
*/
public class SSLUtil implements X509TrustManager {
private SSLSocketFactory sslFactory = null;
private SSLUtil() {
}
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
/**
* 获取SSL Socket工厂
*/
public SSLSocketFactory getSSLSocketFactory() {
return sslFactory;
}
private static SSLUtil _instance = null;
/**
* 获取SSL管理助手类实例
*/
synchronized public static SSLUtil getInstance() throws NoSuchAlgorithmException, KeyManagementException {
if (_instance == null) {
_instance = new SSLUtil();
// SSLContext sc = SSLContext.getInstance("SSLv3");
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, new TrustManager[]{new SSLUtil()}, null);
_instance.sslFactory = sc.getSocketFactory();
}
return _instance;
}
}

View File

@ -0,0 +1,146 @@
package com.xkrs.allinpay.utils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
public class SmUtil {
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* 算法常量:SM3withSM2
*/
public static final String ALGORITHM_SM3SM2_BCPROV = "SM3withSM2";
private final static int SM3withSM2_RS_LEN = 32;
public static void main(String[] args) throws Exception {
/**商户平台分配的appid,也是签名的certid**/
String appid = "00000156";
/**商户sm2私钥,用于向通联发起请求前进行签名**/
String cusPrivateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgjj4Rk+b0YjwO+UwXofnHf4bK+kaaY5Btkd8nMP2VimmgCgYIKoEcz1UBgi2hRANCAAQqlALW4qGC3bP1x3wo5QsKxaCMEZJ2ODTTwOQ+d8UGU7GoK/y/WMBQWf5upMnFU06p5FxGooXYYoBtldgm03hq";
/**商户sm2公钥需要配置到通联商户平台**/
String cusPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEKpQC1uKhgt2z9cd8KOULCsWgjBGSdjg008DkPnfFBlOxqCv8v1jAUFn+bqTJxVNOqeRcRqKF2GKAbZXYJtN4ag==";
/**通联平台sm2公钥用于请求返回或者通联通知的验签**/
String tlPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE/BnA8BawehBtH0ksPyayo4pmzL/u1FQ2sZcqwOp6bjVqQX4tjo930QAvHZPJ2eez8sCz/RYghcqv4LvMq+kloQ==";
String blankStr = "请求待签名数据";
PrivateKey privkey = privKeySM2FromBase64Str(cusPrivateKey);
String sign = signSM3SM2RetBase64(privkey, appid, blankStr.getBytes("UTF-8"));//签名
System.out.println(sign);
String rspBlankStr = "返回待验签数据";//通联返回的明文
String rspSign = "AovBKQGUe0xuJ0ox7FgIIX+yB3DzbudgUsnNvJmDV0IdHZtU2Y8vdeUY1pd2vmPUf08hNgdkoz+4WP/D/ktOcA==";//通联返回的签名
PublicKey publicKey = pubKeySM2FromBase64Str(tlPubKey);
boolean isOk = verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(rspSign), rspBlankStr.getBytes("UTF-8"));
System.out.println("验签结果:" + isOk);
}
/**
* 签名并BASE64编码-SM3WithSM2
*/
public static String signSM3SM2RetBase64(final PrivateKey privateKey, String certid, final byte[] data) throws Exception {
return Base64.encodeBase64String(signSM3SM2(privateKey, certid, data));
}
/**
* 签名-SM3WithSM2
*/
public static byte[] signSM3SM2(final PrivateKey privateKey, String certid, final byte[] data) throws Exception {
SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes());
Signature signer = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
signer.setParameter(parameterSpec);
signer.initSign(privateKey, new SecureRandom());
signer.update(data);
return byteAsn12BytePlain(signer.sign());
}
/**
* 验证签名-SM3WithSM2
*/
public static boolean verifySM3SM2(final PublicKey publicKey, String certid, final byte[] signData, final byte[] srcData) throws Exception {
SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes());
Signature verifier = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
verifier.setParameter(parameterSpec);
verifier.initVerify(publicKey);
verifier.update(srcData);
return verifier.verify(bytePlain2ByteAsn1(signData));
}
/**
* 从字符串读取私钥-目前支持PKCS8(keystr为BASE64格式)
*/
public static PrivateKey privKeySM2FromBase64Str(String keystr) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(keystr)));
}
/**
* 从字符串读取RSA公钥(keystr为BASE64格式)
*/
public static PublicKey pubKeySM2FromBase64Str(String keystr) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(keystr)));
}
/**
* 将普通字节数组转换为ASN1字节数组 适用于SM3withSM2验签时验签明文转换
*/
private static byte[] bytePlain2ByteAsn1(byte[] data) {
if (data.length != SM3withSM2_RS_LEN * 2) throw new RuntimeException("err data. ");
BigInteger r = new BigInteger(1, Arrays.copyOfRange(data, 0, SM3withSM2_RS_LEN));
BigInteger s = new BigInteger(1, Arrays.copyOfRange(data, SM3withSM2_RS_LEN, SM3withSM2_RS_LEN * 2));
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
try {
return new DERSequence(v).getEncoded("DER");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 将ASN1字节数组转换为普通字节数组 适用于SM3withSM2签名时签名结果转换
*/
private static byte[] byteAsn12BytePlain(byte[] dataAsn1) {
ASN1Sequence seq = ASN1Sequence.getInstance(dataAsn1);
byte[] r = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
byte[] s = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue());
byte[] result = new byte[SM3withSM2_RS_LEN * 2];
System.arraycopy(r, 0, result, 0, r.length);
System.arraycopy(s, 0, result, SM3withSM2_RS_LEN, s.length);
return result;
}
private static byte[] bigIntToFixexLengthBytes(BigInteger rOrS) {
byte[] rs = rOrS.toByteArray();
if (rs.length == SM3withSM2_RS_LEN) return rs;
else if (rs.length == SM3withSM2_RS_LEN + 1 && rs[0] == 0) return Arrays.copyOfRange(rs, 1, SM3withSM2_RS_LEN + 1);
else if (rs.length < SM3withSM2_RS_LEN) {
byte[] result = new byte[SM3withSM2_RS_LEN];
Arrays.fill(result, (byte) 0);
System.arraycopy(rs, 0, result, SM3withSM2_RS_LEN - rs.length, rs.length);
return result;
} else {
throw new RuntimeException("err rs: " + Hex.toHexString(rs));
}
}
}

View File

@ -0,0 +1,16 @@
package com.xkrs.allinpay.utils;
public class SybConstants {
public static final String SYB_ORGID = "";//集团/机构模式下该参数不为空且appid与key是与次参数对应
public static final String SYB_CUSID = "660452048163877";
public static final String SYB_APPID = "00343859";
public static final String SYB_MD5_APPKEY = "a0ea3fa20dbd3bb4d5abf1d56d63bae8";
public static final String SYB_APIURL = "https://vsp.allinpay.com/apiweb/unitorder";//生产环境
public static final String SIGN_TYPE = "RSA";
public static final String SYB_RSACUSPRIKEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz8RM/Rmvc5XJSGHV1t9HMfnN8nroYY6tUgvJdH1gamPiEX/lm2QYYoQ5nsZRUaHC4GDUOQhsrhaKmyqo2aIJqYoKEzbmt1/pLi0P9j24jEcKOfYMPoBHKxVldxigF8c6H45GRGM/P/gutdZuDo7C7EpHtExEeoZSgTHPFdQgMQC/3gYaHmQtiYcSBeBHoVokFnZqQI9Bn8LQkTn2lYR4coILEv3wtdlIHrsPpMc5V5ue+T0ooj1WzY9I+vZEHU+2wMaE2jPTr8r09xvtWprqungy2aYU91FNUVpEKF0xdWQFQAhqthGEYRMi1jMe916Hwm0e4V0Ts3x41XrjeAqaNAgMBAAECggEAE6SgQ4LKQRO6Glypq+dca3ytWkAQlBuDR0dBMmm6yjKDRJ4egXv1BqjERA0WYm2BSpN37T3JrgNZWWhb0vMvM3JcCafUmnXukKMcEbi/3uuwJ7JrZYAFmTNYeVxpn5aBQ4PT7vk8rFmxCCdDygfLQey5yd3QO14LtcEKzVYkggOrcpsJ5HF/czQtl55vlbUNYrR1UFGT+dHixAAXKRahc+B572my1P57AP6w7gPeJLpF6MjUWvggm2p2e4HuZychnT0HcnIWBfMxfI4DKsSuB/j8C6yR6gKmB9NEf1Yik6w/N83RrWnRJOG906rYRXp80fU7rlBFegm+jcqbJQsLsQKBgQD3g/Qota5IM3cwo7tyvXUHurms0n8nOjJ+XbF0Ooz/BCAJPIytqwm8RiOQBBx6OH5TuBDocJroXg5+soMGwH63AXgRxZpEoGYW0TStT5wN9D+mXLSHYraJR8uFXPAOTUUDRxwmhcZwGpBHL01r1dJN/C1oxDWFxAjEBjUAemrp0QKBgQC6HCKQP2quZ3CXiopdxOK8eiyTh/RtqE3yb7qLAfllmMSvCA4VqnaIX8TVdNJWVsWCscdKh4zQnIw63hgaLwSiYoUdIjBH9/0QfmQ1XO9lvPitX7SYSIClplYhBq+2cYV0dyl6DjqbZm2Mxb9CIYzs9KIOKuPuJjnn8ipN1MIj/QKBgQDSIiWsViojRAZBtg/S5sOvjzhJX9/xlrf9jl+0dGz1qDPmg5BPdLDsNYPFpafjn4ioXNGF9OuesROPPtB8b/pkNgwQ0nkZIC/r2SrmpHqxYhaTj4r4kba0r846Z9+p1LHtiXZ9wf7pd7Pbq24ISdyktp56nnFuIjLq8PYYdNXFsQKBgFfEyvwSHEKRn8Sn3mcoYfGXAIy28iwA0nnB/UxvKumh6SfOea34DRx1ZcNw630yQMVJB/56/IqpOWzNrroycFIQekxqAjD+n8b2hFWyNWhafUBuQSIMFzeHwVij6Zv134U0aUgZi8QbwxA/ddo/LlHVcNOToJiASJC9YPwBmWkVAoGALcumHYi4rr7CfE52PJblMlI/oKJ+I54SszSBMVRa25ltxZXLFHV65Us3bO3c4Nm2o8jqaMkvwiLAsTIB+Wu9CG47crhC9iJ9/CDF4ALP2cR0TnMyYpA89oIXtVxs18NvyS8RxAIFLB2JMPuNSD4y+tHFqrUqZin6S+if2Neaklo=";
public static final String SYB_RSATLPUBKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm9OV6zH5DYH/ZnAVYHscEELdCNfNTHGuBv1nYYEY9FrOzE0/4kLl9f7Y9dkWHlc2ocDwbrFSm0Vqz0q2rJPxXUYBCQl5yW3jzuKSXif7q1yOwkFVtJXvuhf5WRy+1X5FOFoMvS7538No0RpnLzmNi3ktmiqmhpcY/1pmt20FHQQIDAQAB";
public static final String SYB_SM2PPRIVATEKEY = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg28au4QWNMGLD4qwMTDb2rFIHPoC4+ZFudX/qsC8DirygCgYIKoEcz1UBgi2hRANCAATmdMFOdBiAYlipVwxtQMFwAdK97hMjdaoFZ53bA0SdwJ2oYMLncUpYXe+e/DI/qTwW8lyo3li/+BAwcOSvzT7g";
public static final String SYB_SM2TLPUBKEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEBQicgWm0KAMqhO3bdqMUEDrKQvYg8cCXHhdGwq7CGE6oJDzJ1P/94HpuVdBf1KidmPxr7HOH+0DAnpeCcx9TcQ==";
}

View File

@ -0,0 +1,206 @@
package com.xkrs.allinpay.utils;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
public class SybUtil {
/**
* js转化为实体
*
* @param <T>
* @param jsonstr
* @param cls
* @return
*/
public static <T> T json2Obj(String jsonstr, Class<T> cls) {
JSONObject jo = JSONObject.fromObject(jsonstr);
T obj = (T) JSONObject.toBean(jo, cls);
return obj;
}
/**
* md5
*
* @param b
* @return
*/
public static String md5(byte[] b) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(b);
byte[] hash = md.digest();
StringBuffer outStrBuf = new StringBuffer(32);
for (int i = 0; i < hash.length; i++) {
int v = hash[i] & 0xFF;
if (v < 16) {
outStrBuf.append('0');
}
outStrBuf.append(Integer.toString(v, 16).toLowerCase());
}
return outStrBuf.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return new String(b);
}
}
/**
* 判断字符串是否为空
*
* @param s
* @return
*/
public static boolean isEmpty(String s) {
if (s == null || "".equals(s.trim())) return true;
return false;
}
/**
* 生成随机码
*
* @param n
* @return
*/
public static String getValidatecode(int n) {
Random random = new Random();
String sRand = "";
n = n == 0 ? 4 : n;// default 4
for (int i = 0; i < n; i++) {
String rand = String.valueOf(random.nextInt(10));
sRand += rand;
}
return sRand;
}
public static boolean validSign(TreeMap<String, String> param, String appkey, String signType) throws Exception {
if (param != null && !param.isEmpty()) {
if (!param.containsKey("sign")) return false;
String sign = param.remove("sign");
if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
param.put("key", appkey);
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : param.entrySet()) {
if (entry.getValue() != null && entry.getValue().length() > 0) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
if ("MD5".equals(signType)) {
return sign.toLowerCase().equals(md5(sb.toString().getBytes("UTF-8")).toLowerCase());
} else if ("SM2".equals(signType)) {
PublicKey publicKey = SmUtil.pubKeySM2FromBase64Str(appkey);
return SmUtil.verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(sign), sb.toString().getBytes("UTF-8"));
} else {
return rsaVerifyPublickey(sb.toString(), sign, appkey, "UTF-8");
}
}
return false;
}
public static boolean rsaVerifyPublickey(String content, String sign, String publicKey, String charset) throws Exception {
try {
PublicKey pubKey = getPublicKeyFromX509("RSA", Base64.decodeBase64(publicKey.getBytes()));
return rsaVerifyPublickey(content, sign, pubKey, charset);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
}
}
public static boolean rsaVerifyPublickey(String content, String sign, PublicKey pubKey, String charset) throws Exception {
try {
java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");
signature.initVerify(pubKey);
if (charset == null || "".equals(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
return signature.verify(Base64.decodeBase64(sign.getBytes()));
} catch (Exception e) {
throw e;
}
}
public static String unionSign(TreeMap<String, String> params, String appkey, String signType) throws Exception {
// TODO Auto-generated method stub
params.remove("sign");
if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
params.put("key", appkey);
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (entry.getValue() != null && entry.getValue().length() > 0) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
String sign = "";
if ("MD5".equals(signType)) {
System.out.println(sb.toString());
sign = md5(sb.toString().getBytes("UTF-8"));// 记得是md5编码的加签
params.remove("key");
} else if ("SM2".equals(signType)) {
System.out.println(sb.toString());
PrivateKey privkey = SmUtil.privKeySM2FromBase64Str(appkey);
sign = SmUtil.signSM3SM2RetBase64(privkey, params.get("appid"), sb.toString().getBytes("UTF-8"));//签名
} else {
System.out.println(sb.toString());
sign = rsaSign(sb.toString(), appkey, "UTF-8");
}
return sign;
}
public static String rsaSign(String content, String privateKey, String charset) throws Exception {
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", Base64.decodeBase64(privateKey.getBytes()));
return rsaSign(content, priKey, charset);
}
public static String rsaSign(String content, byte[] privateKey, String charset) throws Exception {
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", privateKey);
return rsaSign(content, priKey, charset);
}
public static String rsaSign(String content, PrivateKey priKey, String charset) throws Exception {
java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");
signature.initSign(priKey);
if (charset == null || "".equals(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
}
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, byte[] encodedKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
public static PublicKey getPublicKeyFromX509(String algorithm, byte[] encodedKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
}

View File

@ -34,6 +34,7 @@ class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 所有OPTIONS请求都放行
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/global/configuration/**").permitAll()
.antMatchers("/websocket/**").permitAll()//支付结果通知前端
.antMatchers("/push/**").permitAll()
.antMatchers("/debug").permitAll()
.antMatchers("/queryFirePoint").permitAll()

View File

@ -0,0 +1,10 @@
package com.xkrs.dao;
import com.xkrs.allinpay.model.TranNotifyEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Component;
@Component
public interface TranNotifyDao extends JpaRepository<TranNotifyEntity, Long>, JpaSpecificationExecutor<TranNotifyEntity> {
}

View File

@ -0,0 +1,37 @@
package com.xkrs.dao;
import com.xkrs.allinpay.model.TranQueryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public interface TranQueryDao extends JpaRepository<TranQueryEntity, Long>, JpaSpecificationExecutor<TranQueryEntity> {
/**
* 普通用户查询订单
*
* @param userId
* @param pageNum
* @param pageSize
* @return
*/
@Query(value = "SELECT q.trxid, q.reqsn, u.user_name AS username, u.really_name AS reallyname, o.body, q.trxamt, q.fintime, q.trxstatus FROM tran_query AS q LEFT JOIN unit_order_pay AS o ON q.orderid = o.id LEFT JOIN sys_user AS u ON o.user_id = u.id WHERE u.id = ?1 ORDER BY q.fintime DESC LIMIT ?3 OFFSET (?2 - 1) * ?3", nativeQuery = true)
List<Map<String, String>> queryTran(int userId, int pageNum, int pageSize);
/**
* 管理员查询订单
*
* @param userName
* @param pageNum
* @param pageSize
* @return
*/
@Query(value = "SELECT q.trxid, q.reqsn, u.user_name AS username, u.really_name AS reallyname, o.body, q.trxamt, q.fintime, q.trxstatus FROM tran_query AS q LEFT JOIN unit_order_pay AS o ON q.orderid = o.id LEFT JOIN sys_user AS u ON o.user_id = u.id WHERE u.user_name LIKE %?1% ORDER BY q.fintime DESC LIMIT ?3 OFFSET (?2 - 1) * ?3", nativeQuery = true)
List<Map<String, String>> queryTranByAdmin(String userName, int pageNum, int pageSize);
}

View File

@ -0,0 +1,10 @@
package com.xkrs.dao;
import com.xkrs.allinpay.model.UnitOrderPayEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Component;
@Component
public interface UnitOrderPayDao extends JpaRepository<UnitOrderPayEntity, Long>, JpaSpecificationExecutor<UnitOrderPayEntity> {
}

View File

@ -0,0 +1,49 @@
package com.xkrs.websocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Semaphore;
/**
* 信号量相关处理
*
* @author ruoyi
*/
public class SemaphoreUtils {
/**
* SemaphoreUtils 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
/**
* 获取信号量
*
* @param semaphore
* @return
*/
public static boolean tryAcquire(Semaphore semaphore) {
boolean flag = false;
try {
flag = semaphore.tryAcquire();
} catch (Exception e) {
LOGGER.error("获取信号量异常", e);
}
return flag;
}
/**
* 释放信号量
*
* @param semaphore
*/
public static void release(Semaphore semaphore) {
try {
semaphore.release();
} catch (Exception e) {
LOGGER.error("释放信号量异常", e);
}
}
}

View File

@ -0,0 +1,20 @@
package com.xkrs.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* websocket 配置
*
* @author ruoyi
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@ -0,0 +1,93 @@
package com.xkrs.websocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.Semaphore;
/**
* websocket 消息处理
*
* @author ruoyi
*/
@Component
@ServerEndpoint("/websocket/message")
public class WebSocketServer {
/**
* WebSocketServer 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
/**
* 默认最多允许同时在线人数100
*/
public static int socketMaxOnlineCount = 100;
private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) throws Exception {
boolean semaphoreFlag = false;
// 尝试获取信号量
semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
if (!semaphoreFlag) {
// 未获取到信号量
LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
session.close();
} else {
// 添加用户
WebSocketUsers.put(session.getId(), session);
LOGGER.info("\n 建立连接 - {}", session);
LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
WebSocketUsers.sendMessageToUserByText(session, "连接成功");
}
}
/**
* 连接关闭时处理
*/
@OnClose
public void onClose(Session session) {
LOGGER.info("\n 关闭连接 - {}", session);
// 移除用户
WebSocketUsers.remove(session.getId());
// 获取到信号量则需释放
SemaphoreUtils.release(socketSemaphore);
}
/**
* 抛出异常时处理
*/
@OnError
public void onError(Session session, Throwable exception) throws Exception {
if (session.isOpen()) {
// 关闭连接
session.close();
}
String sessionId = session.getId();
LOGGER.info("\n 连接异常 - {}", sessionId);
LOGGER.info("\n 异常信息 - {}", exception);
// 移出用户
WebSocketUsers.remove(sessionId);
// 获取到信号量则需释放
SemaphoreUtils.release(socketSemaphore);
}
/**
* 服务器接收到客户端消息时调用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
String msg = message.replace("", "").replace("", "");
WebSocketUsers.sendMessageToUserByText(session, msg);
}
}

View File

@ -0,0 +1,120 @@
package com.xkrs.websocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* websocket 客户端用户集
*
* @author ruoyi
*/
public class WebSocketUsers {
/**
* WebSocketUsers 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
/**
* 用户集
*/
private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
/**
* 存储用户
*
* @param key 唯一键
* @param session 用户信息
*/
public static void put(String key, Session session) {
USERS.put(key, session);
}
/**
* 移除用户
*
* @param session 用户信息
* @return 移除结果
*/
public static boolean remove(Session session) {
String key = null;
boolean flag = USERS.containsValue(session);
if (flag) {
Set<Map.Entry<String, Session>> entries = USERS.entrySet();
for (Map.Entry<String, Session> entry : entries) {
Session value = entry.getValue();
if (value.equals(session)) {
key = entry.getKey();
break;
}
}
} else {
return true;
}
return remove(key);
}
/**
* 移出用户
*
* @param key
*/
public static boolean remove(String key) {
LOGGER.info("\n 正在移出用户 - {}", key);
Session remove = USERS.remove(key);
if (remove != null) {
boolean containsValue = USERS.containsValue(remove);
LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
return containsValue;
} else {
return true;
}
}
/**
* 获取在线用户列表
*
* @return 返回用户集合
*/
public static Map<String, Session> getUsers() {
return USERS;
}
/**
* 群发消息文本消息
*
* @param message 消息内容
*/
public static void sendMessageToUsersByText(String message) {
Collection<Session> values = USERS.values();
for (Session value : values) {
sendMessageToUserByText(value, message);
}
}
/**
* 发送文本消息
*
* @param session 自己的用户
* @param message 消息内容
*/
public static void sendMessageToUserByText(Session session, String message) {
if (session != null) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
LOGGER.error("\n[发送消息异常]", e);
}
} else {
LOGGER.info("\n[你已离线]");
}
}
}

View File

@ -0,0 +1,49 @@
package com.xkrs.websocket.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Semaphore;
/**
* 信号量相关处理
*
* @author ruoyi
*/
public class PaySemaphoreUtils {
/**
* SemaphoreUtils 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PaySemaphoreUtils.class);
/**
* 获取信号量
*
* @param semaphore
* @return
*/
public static boolean tryAcquire(Semaphore semaphore) {
boolean flag = false;
try {
flag = semaphore.tryAcquire();
} catch (Exception e) {
LOGGER.error("获取信号量异常", e);
}
return flag;
}
/**
* 释放信号量
*
* @param semaphore
*/
public static void release(Semaphore semaphore) {
try {
semaphore.release();
} catch (Exception e) {
LOGGER.error("释放信号量异常", e);
}
}
}

View File

@ -0,0 +1,95 @@
package com.xkrs.websocket.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.Semaphore;
/**
* websocket 消息处理
*
* @author ruoyi
* <p>
* ws://8.142.26.238:7801/websocket/pay
*/
@Component
@ServerEndpoint("/websocket/pay")
public class PayWebSocketServer {
/**
* WebSocketServer 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PayWebSocketServer.class);
/**
* 默认最多允许同时在线人数100
*/
public static int socketMaxOnlineCount = 100;
private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) throws Exception {
boolean semaphoreFlag = false;
// 尝试获取信号量
semaphoreFlag = PaySemaphoreUtils.tryAcquire(socketSemaphore);
if (!semaphoreFlag) {
// 未获取到信号量
LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
PayWebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
session.close();
} else {
// 添加用户
PayWebSocketUsers.put(session.getId(), session);
LOGGER.info("\n 建立连接 - {}", session);
LOGGER.info("\n 当前人数 - {}", PayWebSocketUsers.getUsers().size());
PayWebSocketUsers.sendMessageToUserByText(session, "连接成功");
}
}
/**
* 连接关闭时处理
*/
@OnClose
public void onClose(Session session) {
LOGGER.info("\n 关闭连接 - {}", session);
// 移除用户
PayWebSocketUsers.remove(session.getId());
// 获取到信号量则需释放
PaySemaphoreUtils.release(socketSemaphore);
}
/**
* 抛出异常时处理
*/
@OnError
public void onError(Session session, Throwable exception) throws Exception {
if (session.isOpen()) {
// 关闭连接
session.close();
}
String sessionId = session.getId();
LOGGER.info("\n 连接异常 - {}", sessionId);
LOGGER.info("\n 异常信息 - {}", exception);
// 移出用户
PayWebSocketUsers.remove(sessionId);
// 获取到信号量则需释放
PaySemaphoreUtils.release(socketSemaphore);
}
/**
* 服务器接收到客户端消息时调用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
String msg = message.replace("", "").replace("", "");
PayWebSocketUsers.sendMessageToUserByText(session, msg);
}
}

View File

@ -0,0 +1,120 @@
package com.xkrs.websocket.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* websocket 客户端用户集
*
* @author ruoyi
*/
public class PayWebSocketUsers {
/**
* WebSocketUsers 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PayWebSocketUsers.class);
/**
* 用户集
*/
private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
/**
* 存储用户
*
* @param key 唯一键
* @param session 用户信息
*/
public static void put(String key, Session session) {
USERS.put(key, session);
}
/**
* 移除用户
*
* @param session 用户信息
* @return 移除结果
*/
public static boolean remove(Session session) {
String key = null;
boolean flag = USERS.containsValue(session);
if (flag) {
Set<Map.Entry<String, Session>> entries = USERS.entrySet();
for (Map.Entry<String, Session> entry : entries) {
Session value = entry.getValue();
if (value.equals(session)) {
key = entry.getKey();
break;
}
}
} else {
return true;
}
return remove(key);
}
/**
* 移出用户
*
* @param key
*/
public static boolean remove(String key) {
LOGGER.info("\n 正在移出用户 - {}", key);
Session remove = USERS.remove(key);
if (remove != null) {
boolean containsValue = USERS.containsValue(remove);
LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
return containsValue;
} else {
return true;
}
}
/**
* 获取在线用户列表
*
* @return 返回用户集合
*/
public static Map<String, Session> getUsers() {
return USERS;
}
/**
* 群发消息文本消息
*
* @param message 消息内容
*/
public static void sendMessageToUsersByText(String message) {
Collection<Session> values = USERS.values();
for (Session value : values) {
sendMessageToUserByText(value, message);
}
}
/**
* 发送文本消息
*
* @param session 自己的用户
* @param message 消息内容
*/
public static void sendMessageToUserByText(Session session, String message) {
if (session != null) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
LOGGER.error("\n[发送消息异常]", e);
}
} else {
LOGGER.info("\n[你已离线]");
}
}
}