增加支付宝支付
This commit is contained in:
parent
92f431caa8
commit
079bfb5509
@ -7,7 +7,10 @@ import cn.com.tenlion.operator.pojo.dtos.customorg.CustomOrgDTO;
|
||||
import cn.com.tenlion.operator.service.accountbank.IAccountBankService;
|
||||
import cn.com.tenlion.operator.service.accountrecharge.IAccountRechargeService;
|
||||
import cn.com.tenlion.operator.util.UserUtil;
|
||||
import cn.com.tenlion.operator.util.pay.ALiPay;
|
||||
import cn.com.tenlion.operator.util.pay.PayResultDTO;
|
||||
import cn.com.tenlion.operator.util.pay.PayUtil;
|
||||
import cn.com.tenlion.operator.util.pay.WXPay;
|
||||
import cn.com.tenlion.operator.util.socket.MessageWebSocketServer;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import ink.wgink.annotation.CheckRequestBodyAnnotation;
|
||||
@ -58,23 +61,30 @@ public class AccountController extends DefaultBaseController {
|
||||
|
||||
@ApiOperation(value = "支付宝支付成功后回调", notes = "支付宝支付成功后回调")
|
||||
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||
@PostMapping("pay-zfb")
|
||||
public synchronized Object payZfb() {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", "SUCCESS");
|
||||
json.put("message", null);
|
||||
return json;
|
||||
@PostMapping("pay-zfb/{rechargeId}")
|
||||
public synchronized String payZfb(@PathVariable("rechargeId") String rechargeId) {
|
||||
AccountRechargeDTO dto = iAccountRechargeService.get(rechargeId);
|
||||
// 成功
|
||||
if (dto.getThirdParty().equals("支付宝") && !dto.getReconciliationStatus().equals("1") && !dto.getRechargeCheck().equals("-1") && !dto.getRechargeCheck().equals("2")) {
|
||||
PayResultDTO payResultDTO = ALiPay.queryPay(rechargeId);
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
// 发送socket
|
||||
MessageWebSocketServer.sendAll(rechargeId, "success");
|
||||
}
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
@ApiOperation(value = "微信支付成功后回调", notes = "支付成功后回调接口")
|
||||
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||
@PostMapping("pay/{rechargeId}")
|
||||
public synchronized Object pay(@PathVariable("rechargeId") String rechargeId) {
|
||||
@PostMapping("pay-wx/{rechargeId}")
|
||||
public synchronized String pay(@PathVariable("rechargeId") String rechargeId) {
|
||||
AccountRechargeDTO dto = iAccountRechargeService.get(rechargeId);
|
||||
// 成功
|
||||
if (dto.getThirdParty().equals("微信") && !dto.getReconciliationStatus().equals("1") && !dto.getRechargeCheck().equals("-1") && !dto.getRechargeCheck().equals("2")) {
|
||||
AccountRechargePayResultDTO payResultDTO = PayUtil.queryOrder(rechargeId);
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(dto.getRechargeMoney())) {
|
||||
PayResultDTO payResultDTO = WXPay.queryPay(rechargeId);
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
// 发送socket
|
||||
MessageWebSocketServer.sendAll(rechargeId, "success");
|
||||
@ -82,9 +92,8 @@ public class AccountController extends DefaultBaseController {
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", "SUCCESS");
|
||||
json.put("message", null);
|
||||
System.out.println(rechargeId);
|
||||
return json;
|
||||
json.put("message", "成功");
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
@ -10,8 +10,12 @@ import cn.com.tenlion.operator.service.accountbank.IAccountBankService;
|
||||
import cn.com.tenlion.operator.service.accountitem.IAccountItemService;
|
||||
import cn.com.tenlion.operator.service.remote.IRemoteWangGengInvoiceService;
|
||||
import cn.com.tenlion.operator.util.UserUtil;
|
||||
import cn.com.tenlion.operator.util.pay.ALiPay;
|
||||
import cn.com.tenlion.operator.util.pay.PayResultDTO;
|
||||
import cn.com.tenlion.operator.util.pay.PayUtil;
|
||||
import cn.com.tenlion.operator.util.pay.WXPay;
|
||||
import cn.com.tenlion.projectconfig.util.ProjectConfigUtil;
|
||||
import com.alipay.api.internal.util.AlipayUtils;
|
||||
import ink.wgink.common.base.DefaultBaseService;
|
||||
import ink.wgink.exceptions.SaveException;
|
||||
import ink.wgink.exceptions.SearchException;
|
||||
@ -284,9 +288,9 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
|
||||
accountRechargeVO.setRechargeCheck("0");
|
||||
accountRechargeVO.setReconciliationStatus("0");
|
||||
Integer totalMoney = PayUtil.buiderMoney(accountRechargeVO.getRechargeMoney());
|
||||
if (totalMoney < 10 || totalMoney > 200000) { // 最大2000块,最小1毛
|
||||
/* if (totalMoney < 10 || totalMoney > 200000) { // 最大2000块,最小1毛
|
||||
throw new SaveException("金额输入错误");
|
||||
}
|
||||
}*/
|
||||
AccountRechargePayDTO payDTO = new AccountRechargePayDTO();
|
||||
Map<String, Object> params = HashMapUtil.beanToMap(accountRechargeVO);
|
||||
if ("微信".equals(thirdParty)) {
|
||||
@ -296,12 +300,27 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
|
||||
params.put("accountRechargeId", accountRechargeId);
|
||||
params.put("rechargeFinalTime", DateUtil.getTime());
|
||||
|
||||
String brcode = PayUtil.nativePay(ProjectConfigUtil.getText("RechargePayTitle"), accountRechargeId, totalMoney);
|
||||
String brcode = WXPay.createPay(accountRechargeId, totalMoney, ProjectConfigUtil.getText("RechargePayTitle"));
|
||||
|
||||
payDTO.setAccountRechargeId(accountRechargeId);
|
||||
payDTO.setThirdParty(thirdParty);
|
||||
payDTO.setThirdPartyPayUrl(brcode);
|
||||
}
|
||||
|
||||
if ("支付宝".equals(thirdParty)) {
|
||||
|
||||
String accountRechargeId = getUUID("zfb");
|
||||
params.put("rechargeType", "2");
|
||||
params.put("accountRechargeId", accountRechargeId);
|
||||
params.put("rechargeFinalTime", DateUtil.getTime());
|
||||
|
||||
String brcode = ALiPay.createPay(accountRechargeId, totalMoney, ProjectConfigUtil.getText("RechargePayTitle"));
|
||||
|
||||
payDTO.setAccountRechargeId(accountRechargeId);
|
||||
payDTO.setThirdParty(thirdParty);
|
||||
payDTO.setThirdPartyPayUrl(brcode);
|
||||
}
|
||||
|
||||
if ("对公转账".equals(thirdParty)) {
|
||||
String accountRechargeId = getUUID("oto");
|
||||
params.put("rechargeType", "1");
|
||||
@ -393,7 +412,18 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
|
||||
return rechargePayResultDTO;
|
||||
}
|
||||
if (dto.getThirdParty().equals("微信")) {
|
||||
AccountRechargePayResultDTO payResultDTO = PayUtil.queryOrder(accountRechargeId);
|
||||
PayResultDTO payResultDTO = WXPay.queryPay(accountRechargeId);
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1")) {
|
||||
saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
rechargePayResultDTO.setOrderMessage("付款金额已到账");
|
||||
}else{
|
||||
rechargePayResultDTO.setOrderMessage("到账情况稍后在账户明细查看");
|
||||
}
|
||||
return rechargePayResultDTO;
|
||||
}
|
||||
if (dto.getThirdParty().equals("支付宝")) {
|
||||
PayResultDTO payResultDTO = ALiPay.queryPay(accountRechargeId);
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1")) {
|
||||
saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
|
146
src/main/java/cn/com/tenlion/operator/util/pay/ALiPay.java
Normal file
146
src/main/java/cn/com/tenlion/operator/util/pay/ALiPay.java
Normal file
@ -0,0 +1,146 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.AlipayConfig;
|
||||
import com.alipay.api.domain.AlipayTradeCloseModel;
|
||||
import com.alipay.api.domain.AlipayTradePrecreateModel;
|
||||
import com.alipay.api.domain.AlipayTradeQueryModel;
|
||||
import com.alipay.api.request.AlipayTradeCloseRequest;
|
||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||
import com.alipay.api.response.AlipayTradeCloseResponse;
|
||||
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||
import com.alipay.api.request.AlipayTradePrecreateRequest;
|
||||
import com.alipay.api.response.AlipayTradeQueryResponse;
|
||||
import ink.wgink.exceptions.SaveException;
|
||||
import ink.wgink.exceptions.SearchException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* 支付宝支付
|
||||
* 2024年3月19日15:47:30
|
||||
* 崔宝铖
|
||||
*/
|
||||
@Component
|
||||
public class ALiPay {
|
||||
|
||||
@Autowired
|
||||
private AliPayProperties aliPayProperties;
|
||||
|
||||
private static AliPayProperties aliPayStaticProperties;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
aliPayStaticProperties = this.aliPayProperties;
|
||||
}
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static void closePay(String orderNo) {
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
alipayConfig.setServerUrl(aliPayStaticProperties.getUrl());// 支付地址
|
||||
alipayConfig.setAppId(aliPayStaticProperties.getAppId());// 应用ID
|
||||
alipayConfig.setPrivateKey(aliPayStaticProperties.getPrivateKey());// 应用私钥
|
||||
alipayConfig.setFormat("json");
|
||||
alipayConfig.setAlipayPublicKey(aliPayStaticProperties.getAliPublicKey());// 支付宝公钥
|
||||
alipayConfig.setCharset("UTF-8");
|
||||
alipayConfig.setSignType("RSA2");// 编码
|
||||
try{
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
|
||||
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
|
||||
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
|
||||
model.setOutTradeNo(orderNo);
|
||||
request.setBizModel(model);
|
||||
AlipayTradeCloseResponse response = alipayClient.execute(request);
|
||||
if (!response.isSuccess() && !response.getSubMsg().equals("交易不存在")) {
|
||||
throw new SearchException(response.getSubMsg());
|
||||
}
|
||||
}catch(Exception e) {
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static PayResultDTO queryPay(String orderNo) {
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
alipayConfig.setServerUrl(aliPayStaticProperties.getUrl());// 支付地址
|
||||
alipayConfig.setAppId(aliPayStaticProperties.getAppId());// 应用ID
|
||||
alipayConfig.setPrivateKey(aliPayStaticProperties.getPrivateKey());// 应用私钥
|
||||
alipayConfig.setFormat("json");
|
||||
alipayConfig.setAlipayPublicKey(aliPayStaticProperties.getAliPublicKey());// 支付宝公钥
|
||||
alipayConfig.setCharset("UTF-8");
|
||||
alipayConfig.setSignType("RSA2");// 编码
|
||||
try{
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
|
||||
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
||||
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
||||
model.setOutTradeNo(orderNo);
|
||||
request.setBizModel(model);
|
||||
AlipayTradeQueryResponse response = alipayClient.execute(request);
|
||||
PayResultDTO dto = new PayResultDTO();
|
||||
dto.setOrderStatus("0");
|
||||
dto.setOrderNo(response.getOutTradeNo());
|
||||
if (response.isSuccess()) {
|
||||
dto.setOrderId(response.getTradeNo());
|
||||
dto.setOrderStatus(response.getTradeStatus().equals("TRADE_SUCCESS") || response.getTradeStatus().equals("TRADE_FINISHED") ? "1" : "0");
|
||||
dto.setOrderSuccessTime(sdf.format(response.getSendPayDate()));
|
||||
dto.setMoney(PayUtil.buiderMoney(Double.parseDouble(response.getTotalAmount())));
|
||||
}
|
||||
if (response == null || (!response.isSuccess() && !response.getSubMsg().equals("交易不存在"))) {
|
||||
throw new SearchException(response.getSubMsg());
|
||||
}
|
||||
return dto;
|
||||
}catch(Exception e) {
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付的二维码
|
||||
* @param orderNo 本地订单编号(唯一)
|
||||
* @param money 支付金额, 1元为100
|
||||
* @param orderDescription 订单详细说明
|
||||
* @return
|
||||
*/
|
||||
public static String createPay(String orderNo, Integer money, String orderDescription) {
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
alipayConfig.setServerUrl(aliPayStaticProperties.getUrl());// 支付地址
|
||||
alipayConfig.setAppId(aliPayStaticProperties.getAppId());// 应用ID
|
||||
alipayConfig.setPrivateKey(aliPayStaticProperties.getPrivateKey());// 应用私钥
|
||||
alipayConfig.setFormat("json");
|
||||
alipayConfig.setAlipayPublicKey(aliPayStaticProperties.getAliPublicKey());// 支付宝公钥
|
||||
alipayConfig.setCharset("UTF-8");
|
||||
alipayConfig.setSignType("RSA2");// 编码
|
||||
try{
|
||||
if (PayUtil.buiderMoney(money) > aliPayStaticProperties.getMaxMoney() || PayUtil.buiderMoney(money) < aliPayStaticProperties.getMinMoney()) {
|
||||
throw new SaveException("支付金额超出范围");
|
||||
}
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
|
||||
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
|
||||
String notifyUrl = aliPayStaticProperties.getNotifyUrl().replaceAll("\\{orderNo}", orderNo);
|
||||
request.setNotifyUrl(notifyUrl);
|
||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||
model.setOutTradeNo(orderNo);// 本地订单号
|
||||
model.setTotalAmount(PayUtil.buiderMoney(money) + ""); // 本次付款金额
|
||||
model.setTimeoutExpress(aliPayStaticProperties.getTimeOut() + "m");//交易超时时间
|
||||
model.setQrCodeTimeoutExpress(aliPayStaticProperties.getTimeOut() + "m");//二维码失效时间
|
||||
model.setSubject(orderDescription); // 本次订单说明
|
||||
request.setBizModel(model);
|
||||
AlipayTradePrecreateResponse response = alipayClient.execute(request);
|
||||
if (response.isSuccess()) {
|
||||
String qrCode = response.getQrCode();
|
||||
if (qrCode.startsWith("http")) {
|
||||
BufferedImage bufferedImage = QRUtils.createQrCodeImage(QRUtils.createQrCode(qrCode, 330, 330), "");
|
||||
return QRUtils.imageToBase64(bufferedImage);
|
||||
}
|
||||
}
|
||||
throw new SaveException(response.getSubMsg());
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SaveException("生成支付二维码失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 从配置文件读取阿里支付的配置文件
|
||||
* 2024年3月21日10:20:50
|
||||
* 崔宝铖
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "pay.ali-pay")
|
||||
public class AliPayProperties {
|
||||
|
||||
// 应用ID
|
||||
private String appId;
|
||||
|
||||
// 支付宝服务器地址
|
||||
private String url;
|
||||
|
||||
// 应用私钥
|
||||
private String privateKey;
|
||||
|
||||
// 支付宝公钥
|
||||
private String aliPublicKey;
|
||||
|
||||
// 超时时间
|
||||
private String timeOut;
|
||||
|
||||
// 接收结果通知地址
|
||||
private String notifyUrl;
|
||||
|
||||
// 单笔最大金额
|
||||
private Double maxMoney;
|
||||
|
||||
// 单笔最小金额
|
||||
private Double minMoney;
|
||||
|
||||
public String getAppId() {
|
||||
return appId == null ? "" : appId.trim();
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url == null ? "" : url.trim();
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey == null ? "" : privateKey.trim();
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getAliPublicKey() {
|
||||
return aliPublicKey == null ? "" : aliPublicKey.trim();
|
||||
}
|
||||
|
||||
public void setAliPublicKey(String aliPublicKey) {
|
||||
this.aliPublicKey = aliPublicKey;
|
||||
}
|
||||
|
||||
public String getTimeOut() {
|
||||
return timeOut == null ? "5" : timeOut.trim();
|
||||
}
|
||||
|
||||
public void setTimeOut(String timeOut) {
|
||||
this.timeOut = timeOut;
|
||||
}
|
||||
|
||||
public String getNotifyUrl() {
|
||||
return notifyUrl == null ? "" : notifyUrl.trim();
|
||||
}
|
||||
|
||||
public void setNotifyUrl(String notifyUrl) {
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
|
||||
public Double getMaxMoney() {
|
||||
return maxMoney == null ? 2000 : maxMoney;
|
||||
}
|
||||
|
||||
public void setMaxMoney(Double maxMoney) {
|
||||
this.maxMoney = maxMoney;
|
||||
}
|
||||
|
||||
public Double getMinMoney() {
|
||||
return minMoney == null ? 0.1 : minMoney;
|
||||
}
|
||||
|
||||
public void setMinMoney(Double minMoney) {
|
||||
this.minMoney = minMoney;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
/**
|
||||
* 支付结果对象
|
||||
* 2024年3月19日17:03:25
|
||||
* 崔宝铖
|
||||
*/
|
||||
public class PayResultDTO {
|
||||
|
||||
@ApiModelProperty(name = "orderId", value = "第三方订单ID")
|
||||
private String orderId;
|
||||
|
||||
@ApiModelProperty(name = "orderNo", value = "本地订单编号")
|
||||
private String orderNo;
|
||||
|
||||
@ApiModelProperty(name = "orderStatus", value = "支付结果,1:成功")
|
||||
private String orderStatus;
|
||||
|
||||
@ApiModelProperty(name = "orderSuccessTime", value = "支付成功时间")
|
||||
private String orderSuccessTime;
|
||||
|
||||
@ApiModelProperty(name = "orderMessage", value = "支付结果详情")
|
||||
private String orderMessage;
|
||||
|
||||
@ApiModelProperty(name = "money", value = "订单总金额")
|
||||
private Integer money;
|
||||
|
||||
public String getOrderId() {
|
||||
return orderId == null ? "" : orderId.trim();
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo == null ? "" : orderNo.trim();
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
public String getOrderStatus() {
|
||||
return orderStatus == null ? "" : orderStatus.trim();
|
||||
}
|
||||
|
||||
public void setOrderStatus(String orderStatus) {
|
||||
this.orderStatus = orderStatus;
|
||||
}
|
||||
|
||||
public String getOrderSuccessTime() {
|
||||
return orderSuccessTime == null ? "" : orderSuccessTime.trim();
|
||||
}
|
||||
|
||||
public void setOrderSuccessTime(String orderSuccessTime) {
|
||||
this.orderSuccessTime = orderSuccessTime;
|
||||
}
|
||||
|
||||
public String getOrderMessage() {
|
||||
return orderMessage == null ? "" : orderMessage.trim();
|
||||
}
|
||||
|
||||
public void setOrderMessage(String orderMessage) {
|
||||
this.orderMessage = orderMessage;
|
||||
}
|
||||
|
||||
public Integer getMoney() {
|
||||
return money == null ? 0 : money;
|
||||
}
|
||||
|
||||
public void setMoney(Integer money) {
|
||||
this.money = money;
|
||||
}
|
||||
}
|
@ -1,62 +1,10 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
|
||||
import cn.com.tenlion.projectconfig.util.ProjectConfigUtil;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.payments.model.TransactionAmount;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
import com.wechat.pay.java.service.payments.nativepay.model.*;
|
||||
import ink.wgink.common.base.DefaultBaseService;
|
||||
import ink.wgink.exceptions.SaveException;
|
||||
import ink.wgink.exceptions.SearchException;
|
||||
import ink.wgink.module.file.service.v2.IFileService;
|
||||
import ink.wgink.pojo.pos.FilePO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class PayUtil {
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(DefaultBaseService.class);
|
||||
|
||||
@Autowired
|
||||
private IFileService iFileService;
|
||||
|
||||
private static IFileService iFileStaticService;
|
||||
|
||||
@PostConstruct
|
||||
public void init() throws Exception {
|
||||
iFileStaticService = this.iFileService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将double的金额保留2位小数
|
||||
* @param num
|
||||
@ -86,199 +34,4 @@ public class PayUtil {
|
||||
return i / 100.00;
|
||||
}
|
||||
|
||||
public static void closeOrder(String rechargeOrderId){
|
||||
// 使用自动更新平台证书的RSA配置
|
||||
Config config =
|
||||
new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId("1609461201") // 商户号
|
||||
.privateKeyFromPath("D:\\AH\\apiclient_key.pem") // API证书地址(此处的路径自己调试一下,能找到就行)
|
||||
.merchantSerialNumber("2F16A068181C2998F3EE5271416F720AF0146293") // API证书序列号
|
||||
.apiV3Key("_TSKJ_0471_TSkj_0471_tsKJ_0471__") // API密匙
|
||||
.build();
|
||||
// 构建service
|
||||
NativePayService service = new NativePayService.Builder().config(config).build();
|
||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||
CloseOrderRequest request = new CloseOrderRequest();
|
||||
request.setMchid("1609461201");
|
||||
request.setOutTradeNo(rechargeOrderId);
|
||||
AccountRechargePayResultDTO dto = new AccountRechargePayResultDTO();
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
service.closeOrder(request);
|
||||
}catch (Exception e){
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static AccountRechargePayResultDTO queryOrder(String rechargeOrderId){
|
||||
// 使用自动更新平台证书的RSA配置
|
||||
Config config =
|
||||
new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId("1609461201") // 商户号
|
||||
.privateKeyFromPath("D:\\AH\\apiclient_key.pem") // API证书地址(此处的路径自己调试一下,能找到就行)
|
||||
.merchantSerialNumber("2F16A068181C2998F3EE5271416F720AF0146293") // API证书序列号
|
||||
.apiV3Key("_TSKJ_0471_TSkj_0471_tsKJ_0471__") // API密匙
|
||||
.build();
|
||||
// 构建service
|
||||
NativePayService service = new NativePayService.Builder().config(config).build();
|
||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
||||
request.setMchid("1609461201");
|
||||
request.setOutTradeNo(rechargeOrderId);
|
||||
AccountRechargePayResultDTO dto = new AccountRechargePayResultDTO();
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
Transaction response = service.queryOrderByOutTradeNo(request);
|
||||
String order = response.getTransactionId(); // 第三方订单号
|
||||
Transaction.TradeStateEnum status = response.getTradeState();
|
||||
TransactionAmount amount = response.getAmount();
|
||||
dto.setMoney(amount.getPayerTotal());
|
||||
String time = response.getSuccessTime();
|
||||
dto.setAccountRechargeId(rechargeOrderId);
|
||||
dto.setOrderSuccessTime(status.name().equals("SUCCESS") ? convertToFormattedString(time) : "");
|
||||
dto.setOrderId(order);
|
||||
dto.setOrderStatus(status.name().equals("SUCCESS") ? "1" : "0");
|
||||
}catch (Exception e){
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取5分钟后超时时间
|
||||
* @return
|
||||
*/
|
||||
public static String getTimeExpire() {
|
||||
// 当前时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 5分钟前的时间
|
||||
LocalDateTime fifteenMinutesAgo = now.plusMinutes(5);
|
||||
// 获取时区信息(以北京时间为例)
|
||||
ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // 东八区时区
|
||||
// 将LocalDateTime转换为ZonedDateTime
|
||||
ZonedDateTime zonedDateTime = fifteenMinutesAgo.atZone(zoneId);
|
||||
// 创建一个符合RFC 3339的DateTimeFormatter
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
// 格式化日期时间
|
||||
String formattedDateTime = zonedDateTime.format(formatter);
|
||||
return formattedDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间格式转换
|
||||
* @param inputDateTime
|
||||
* @return
|
||||
*/
|
||||
public static String convertToFormattedString(String inputDateTime) {
|
||||
// 将字符串解析为ZonedDateTime对象
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.parse(inputDateTime);
|
||||
// 将ZonedDateTime对象转换为指定的格式
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
return zonedDateTime.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Native支付下单,获取支付地址
|
||||
* @return 支付地址,前端用于生成支付二维码
|
||||
*/
|
||||
public static String nativePay(String title, String orderId, Integer totalMoney){
|
||||
// 使用自动更新平台证书的RSA配置
|
||||
Config config =
|
||||
new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId("1609461201") // 商户号
|
||||
.privateKeyFromPath("D:\\AH\\apiclient_key.pem") // API证书地址(此处的路径自己调试一下,能找到就行)
|
||||
.merchantSerialNumber("2F16A068181C2998F3EE5271416F720AF0146293") // API证书序列号
|
||||
.apiV3Key("_TSKJ_0471_TSkj_0471_tsKJ_0471__") // API密匙
|
||||
.build();
|
||||
// 构建service
|
||||
NativePayService service = new NativePayService.Builder().config(config).build();
|
||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||
PrepayRequest request = new PrepayRequest();
|
||||
Amount amount = new Amount();
|
||||
amount.setTotal(totalMoney); // 金额
|
||||
request.setAmount(amount);
|
||||
request.setAppid("wxe17874894f7ff27b");
|
||||
request.setMchid("1609461201");
|
||||
request.setTimeExpire(getTimeExpire());
|
||||
request.setDescription(title);// 商品描述
|
||||
request.setNotifyUrl(ProjectConfigUtil.getText("WechatPayCallbackUrl") + "api/account/pay/" + orderId);// 支付成功的回调地址
|
||||
request.setOutTradeNo(orderId);
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
PrepayResponse response = service.prepay(request);
|
||||
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
|
||||
BufferedImage bufferedImage = builderQrCodeImage(generateQRCode(response.getCodeUrl(), 330, 330));
|
||||
// 将支付地址返回
|
||||
return imageToBase64(bufferedImage);
|
||||
}catch (Exception e){
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将BufferdImage转为base64图片
|
||||
* @param image
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String imageToBase64(BufferedImage image) throws IOException {
|
||||
// 将BufferedImage转换为字节数组
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "jpg", baos); // 或者使用 "png" 或 "bmp" 等其他图片格式
|
||||
byte[] imageBytes = baos.toByteArray();
|
||||
// 将字节数组转换为Base64编码的字符串
|
||||
String encodedImage = Base64.getEncoder().encodeToString(imageBytes);
|
||||
return "data:image/jpeg;base64," + encodedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
* @param text
|
||||
* @param width
|
||||
* @param height
|
||||
* @return
|
||||
* @throws WriterException
|
||||
*/
|
||||
public static BufferedImage generateQRCode(String text, int width, int height) throws WriterException {
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
Map<EncodeHintType, ErrorCorrectionLevel> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置错误纠正级别为H
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
return MatrixToImageWriter.toBufferedImage(bitMatrix);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 二维码设置自定义的边框
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage builderQrCodeImage(BufferedImage image) {
|
||||
String bufferedImage = ProjectConfigUtil.getFile("wxPayQrCodeBorderImage");
|
||||
if (StringUtils.isEmpty(bufferedImage)) {
|
||||
return image;
|
||||
}
|
||||
try {
|
||||
FilePO filePo = iFileStaticService.getPO(bufferedImage);
|
||||
File file = new File(filePo.getFilePath());
|
||||
BufferedImage borderImage = ImageIO.read(new File(file.getPath()));
|
||||
BufferedImage image1 = new BufferedImage(image.getWidth() + 100, image.getHeight() + 100, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = image1.createGraphics();
|
||||
//消除文字锯齿
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
//消除图片锯齿
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
//放入二维码
|
||||
graphics.drawImage(image, 50, 50, image.getWidth(), image.getHeight(), null);
|
||||
//放入边框
|
||||
graphics.drawImage(borderImage, 0, 0, image.getWidth() + 100, image.getHeight() + 100, null);
|
||||
return image1;
|
||||
} catch (IOException e) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
92
src/main/java/cn/com/tenlion/operator/util/pay/QRUtils.java
Normal file
92
src/main/java/cn/com/tenlion/operator/util/pay/QRUtils.java
Normal file
@ -0,0 +1,92 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import cn.com.tenlion.projectconfig.util.ProjectConfigUtil;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import ink.wgink.pojo.pos.FilePO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 二维码工具类
|
||||
* 2024年3月19日16:03:24
|
||||
* 崔宝铖
|
||||
*/
|
||||
public class QRUtils {
|
||||
|
||||
/**
|
||||
* 将BufferdImage转为base64图片
|
||||
* @param image
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String imageToBase64(BufferedImage image) throws IOException {
|
||||
// 将BufferedImage转换为字节数组
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "jpg", baos); // 或者使用 "png" 或 "bmp" 等其他图片格式
|
||||
byte[] imageBytes = baos.toByteArray();
|
||||
// 将字节数组转换为Base64编码的字符串
|
||||
String encodedImage = Base64.getEncoder().encodeToString(imageBytes);
|
||||
return "data:image/jpeg;base64," + encodedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
* @param text
|
||||
* @param width
|
||||
* @param height
|
||||
* @return
|
||||
* @throws WriterException
|
||||
*/
|
||||
public static BufferedImage createQrCode(String text, int width, int height) throws WriterException {
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
Map<EncodeHintType, ErrorCorrectionLevel> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置错误纠正级别为H
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
return MatrixToImageWriter.toBufferedImage(bitMatrix);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 为二维码设置自定义的边框
|
||||
* @param image 二维码图片对象
|
||||
* @param borderFilePath 二维码边框文件
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage createQrCodeImage(BufferedImage image, String borderFilePath) {
|
||||
if (StringUtils.isEmpty(borderFilePath)) {
|
||||
return image;
|
||||
}
|
||||
try {
|
||||
BufferedImage borderImage = ImageIO.read(new File(borderFilePath));
|
||||
BufferedImage image1 = new BufferedImage(image.getWidth() + 100, image.getHeight() + 100, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = image1.createGraphics();
|
||||
//消除文字锯齿
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
//消除图片锯齿
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
//放入二维码
|
||||
graphics.drawImage(image, 50, 50, image.getWidth(), image.getHeight(), null);
|
||||
//放入边框
|
||||
graphics.drawImage(borderImage, 0, 0, image.getWidth() + 100, image.getHeight() + 100, null);
|
||||
return image1;
|
||||
} catch (IOException e) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
148
src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java
Normal file
148
src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java
Normal file
@ -0,0 +1,148 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.payments.model.TransactionAmount;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
import com.wechat.pay.java.service.payments.nativepay.model.*;
|
||||
import ink.wgink.exceptions.SaveException;
|
||||
import ink.wgink.exceptions.SearchException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
* 2024年3月19日17:42:14
|
||||
* 崔宝铖
|
||||
*/
|
||||
@Component
|
||||
public class WXPay {
|
||||
|
||||
@Autowired
|
||||
private WxPayProperties wxPayProperties;
|
||||
|
||||
private static WxPayProperties wxPayStaticProperties;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
wxPayStaticProperties = this.wxPayProperties;
|
||||
}
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static void closePay(String orderNo) {
|
||||
NativePayService service = wxPayStaticProperties.getPayUrlServices();
|
||||
CloseOrderRequest request = new CloseOrderRequest();
|
||||
request.setMchid(wxPayStaticProperties.getMchId());
|
||||
request.setOutTradeNo(orderNo);
|
||||
AccountRechargePayResultDTO dto = new AccountRechargePayResultDTO();
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
service.closeOrder(request);
|
||||
}catch (Exception e){
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static PayResultDTO queryPay(String orderNo) {
|
||||
NativePayService service = wxPayStaticProperties.getPayUrlServices();
|
||||
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
||||
request.setMchid(wxPayStaticProperties.getMchId());
|
||||
request.setOutTradeNo(orderNo);
|
||||
PayResultDTO dto = new PayResultDTO();
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
Transaction response = service.queryOrderByOutTradeNo(request);
|
||||
String order = response.getTransactionId(); // 第三方订单号
|
||||
Transaction.TradeStateEnum status = response.getTradeState();
|
||||
TransactionAmount amount = response.getAmount();
|
||||
String time = response.getSuccessTime();
|
||||
dto.setMoney(amount.getPayerTotal());
|
||||
dto.setOrderNo(orderNo);
|
||||
dto.setOrderSuccessTime(status.name().equals("SUCCESS") ? convertToFormattedString(time) : "");
|
||||
dto.setOrderId(order);
|
||||
dto.setOrderStatus(status.name().equals("SUCCESS") ? "1" : "0");
|
||||
}catch (Exception e){
|
||||
throw new SearchException(e.getMessage());
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付的二维码
|
||||
* @param orderNo 本地订单编号(唯一)
|
||||
* @param money 支付金额, 1元为100
|
||||
* @param orderDescription 订单详细说明
|
||||
* @return
|
||||
*/
|
||||
public static String createPay(String orderNo, Integer money, String orderDescription) {
|
||||
if (PayUtil.buiderMoney(money) > wxPayStaticProperties.getMaxMoney() || PayUtil.buiderMoney(money) < wxPayStaticProperties.getMinMoney()) {
|
||||
throw new SaveException("支付金额超出范围");
|
||||
}
|
||||
NativePayService service = wxPayStaticProperties.getPayUrlServices();
|
||||
PrepayRequest request = new PrepayRequest();
|
||||
Amount amount = new Amount();
|
||||
amount.setTotal(money); // 金额
|
||||
request.setAmount(amount);
|
||||
request.setAppid(wxPayStaticProperties.getAppId());
|
||||
request.setMchid(wxPayStaticProperties.getMchId());
|
||||
request.setTimeExpire(getTimeExpire());// 超时时间
|
||||
request.setDescription(orderDescription);// 商品描述
|
||||
String notifyUrl = wxPayStaticProperties.getNotifyUrl().replaceAll("\\{orderNo}", orderNo);
|
||||
request.setNotifyUrl(notifyUrl);// 支付成功的回调地址
|
||||
request.setOutTradeNo(orderNo);
|
||||
// 调用下单方法,得到应答
|
||||
try {
|
||||
// 发送请求
|
||||
PrepayResponse response = service.prepay(request);
|
||||
BufferedImage bufferedImage = QRUtils.createQrCodeImage(QRUtils.createQrCode(response.getCodeUrl(), 330, 330), "");
|
||||
return QRUtils.imageToBase64(bufferedImage);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
throw new SaveException("生成支付二维码失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二维码超时时间
|
||||
* @return
|
||||
*/
|
||||
private static String getTimeExpire() {
|
||||
// 当前时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 5分钟前的时间
|
||||
LocalDateTime fifteenMinutesAgo = now.plusMinutes(Integer.valueOf(wxPayStaticProperties.getTimeOut()));
|
||||
// 获取时区信息(以北京时间为例)
|
||||
ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // 东八区时区
|
||||
// 将LocalDateTime转换为ZonedDateTime
|
||||
ZonedDateTime zonedDateTime = fifteenMinutesAgo.atZone(zoneId);
|
||||
// 创建一个符合RFC 3339的DateTimeFormatter
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
// 格式化日期时间
|
||||
String formattedDateTime = zonedDateTime.format(formatter);
|
||||
return formattedDateTime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 时间格式转换
|
||||
* @param inputDateTime
|
||||
* @return
|
||||
*/
|
||||
private static String convertToFormattedString(String inputDateTime) {
|
||||
// 将字符串解析为ZonedDateTime对象
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.parse(inputDateTime);
|
||||
// 将ZonedDateTime对象转换为指定的格式
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
return zonedDateTime.format(formatter);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package cn.com.tenlion.operator.util.pay;
|
||||
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "pay.wx-pay")
|
||||
public class WxPayProperties {
|
||||
|
||||
// 商户号
|
||||
private String mchId;
|
||||
|
||||
// 商户API证书序列号
|
||||
private String mchNo;
|
||||
|
||||
// 私钥本地存储路径
|
||||
private String privateKeyPath;
|
||||
|
||||
// API v3密钥
|
||||
private String apiV3Key;
|
||||
|
||||
// 小程序APPID
|
||||
private String appId;
|
||||
|
||||
// 超时时间
|
||||
private String timeOut;
|
||||
|
||||
// 微信服务器地址
|
||||
private String url;
|
||||
|
||||
// 接收结果通知地址
|
||||
private String notifyUrl;
|
||||
|
||||
// 单笔最大金额
|
||||
private Double maxMoney;
|
||||
|
||||
// 单笔最小金额
|
||||
private Double minMoney;
|
||||
|
||||
@Bean
|
||||
// 使用自动更新平台证书的RSA配置
|
||||
public Config getConfig(){
|
||||
Config config =
|
||||
new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(mchId)
|
||||
.privateKeyFromPath(privateKeyPath)
|
||||
.merchantSerialNumber(mchNo)
|
||||
.apiV3Key(apiV3Key)
|
||||
.build();
|
||||
return config;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NativePayService getPayUrlServices(){
|
||||
Config config = getConfig();
|
||||
// 构建service
|
||||
NativePayService service = new NativePayService.Builder().config(config).build();
|
||||
return service;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId == null ? "" : mchId.trim();
|
||||
}
|
||||
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public String getMchNo() {
|
||||
return mchNo == null ? "" : mchNo.trim();
|
||||
}
|
||||
|
||||
public void setMchNo(String mchNo) {
|
||||
this.mchNo = mchNo;
|
||||
}
|
||||
|
||||
public String getPrivateKeyPath() {
|
||||
return privateKeyPath == null ? "" : privateKeyPath.trim();
|
||||
}
|
||||
|
||||
public void setPrivateKeyPath(String privateKeyPath) {
|
||||
this.privateKeyPath = privateKeyPath;
|
||||
}
|
||||
|
||||
public String getApiV3Key() {
|
||||
return apiV3Key == null ? "" : apiV3Key.trim();
|
||||
}
|
||||
|
||||
public void setApiV3Key(String apiV3Key) {
|
||||
this.apiV3Key = apiV3Key;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId == null ? "" : appId.trim();
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getTimeOut() {
|
||||
return timeOut == null ? "5" : timeOut.trim();
|
||||
}
|
||||
|
||||
public void setTimeOut(String timeOut) {
|
||||
this.timeOut = timeOut;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url == null ? "" : url.trim();
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getNotifyUrl() {
|
||||
return notifyUrl == null ? "" : notifyUrl.trim();
|
||||
}
|
||||
|
||||
public void setNotifyUrl(String notifyUrl) {
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
|
||||
public Double getMaxMoney() {
|
||||
return maxMoney == null ? 2000 : maxMoney;
|
||||
}
|
||||
|
||||
public void setMaxMoney(Double maxMoney) {
|
||||
this.maxMoney = maxMoney;
|
||||
}
|
||||
|
||||
public Double getMinMoney() {
|
||||
return minMoney == null ? 0.1 : minMoney;
|
||||
}
|
||||
|
||||
public void setMinMoney(Double minMoney) {
|
||||
this.minMoney = minMoney;
|
||||
}
|
||||
}
|
@ -3,7 +3,10 @@ package cn.com.tenlion.operator.util.task;
|
||||
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargeDTO;
|
||||
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
|
||||
import cn.com.tenlion.operator.service.accountrecharge.IAccountRechargeService;
|
||||
import cn.com.tenlion.operator.util.pay.ALiPay;
|
||||
import cn.com.tenlion.operator.util.pay.PayResultDTO;
|
||||
import cn.com.tenlion.operator.util.pay.PayUtil;
|
||||
import cn.com.tenlion.operator.util.pay.WXPay;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -24,20 +27,30 @@ public class WxPayResultCheckTask {
|
||||
iAccountRechargeStaticService = this.iAccountRechargeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2分钟执行一次 | 关闭超时未付款的
|
||||
*/
|
||||
@Scheduled(fixedRate = 60*1000*2)
|
||||
public void close() {
|
||||
// 关闭10分钟之前(未到账)的订单
|
||||
List<AccountRechargeDTO> list = iAccountRechargeStaticService.getNotCloseRechargeList("微信");
|
||||
for(AccountRechargeDTO dto : list) {
|
||||
AccountRechargePayResultDTO payResultDTO = PayUtil.queryOrder(dto.getAccountRechargeId());
|
||||
PayResultDTO payResultDTO = WXPay.queryPay(dto.getAccountRechargeId());
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeStaticService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
}else{
|
||||
PayUtil.closeOrder(dto.getAccountRechargeId());
|
||||
WXPay.closePay(dto.getAccountRechargeId());
|
||||
// 修改状态
|
||||
iAccountRechargeStaticService.updateClose(dto.getAccountRechargeId());
|
||||
}
|
||||
}
|
||||
// 关闭10分钟之前(未到账)的订单
|
||||
List<AccountRechargeDTO> list2 = iAccountRechargeStaticService.getNotCloseRechargeList("支付宝");
|
||||
for(AccountRechargeDTO dto : list2) {
|
||||
PayResultDTO payResultDTO = ALiPay.queryPay(dto.getAccountRechargeId());
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeStaticService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
}else{
|
||||
ALiPay.closePay(dto.getAccountRechargeId());
|
||||
// 修改状态
|
||||
iAccountRechargeStaticService.updateClose(dto.getAccountRechargeId());
|
||||
}
|
||||
@ -52,9 +65,18 @@ public class WxPayResultCheckTask {
|
||||
// 查出来近10分钟(未到账)的订单
|
||||
List<AccountRechargeDTO> list = iAccountRechargeStaticService.getNotCheckRechargeList("微信");
|
||||
for(AccountRechargeDTO dto : list) {
|
||||
AccountRechargePayResultDTO payResultDTO = PayUtil.queryOrder(dto.getAccountRechargeId());
|
||||
PayResultDTO payResultDTO = WXPay.queryPay(dto.getAccountRechargeId());
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(dto.getRechargeMoney())) {
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeStaticService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
}
|
||||
}
|
||||
// 查出来近10分钟(未到账)的订单
|
||||
List<AccountRechargeDTO> list2 = iAccountRechargeStaticService.getNotCheckRechargeList("支付宝");
|
||||
for(AccountRechargeDTO dto : list2) {
|
||||
PayResultDTO payResultDTO = ALiPay.queryPay(dto.getAccountRechargeId());
|
||||
// 成功
|
||||
if (payResultDTO.getOrderStatus().equals("1") && payResultDTO.getMoney().equals(PayUtil.buiderMoney(dto.getRechargeMoney()))) {
|
||||
iAccountRechargeStaticService.saveConfirmOnline(dto.getAccountRechargeId(), payResultDTO.getOrderId(), payResultDTO.getOrderSuccessTime());
|
||||
}
|
||||
}
|
||||
|
@ -222,19 +222,45 @@ sms:
|
||||
template:
|
||||
verification-code: '{sign} 您的验证码为 {content}, 有效时间为120秒,若非本人操作,请忽略。'
|
||||
|
||||
wxpay:
|
||||
pay:
|
||||
wx-pay:
|
||||
# 商户号
|
||||
mchId: 1609461201
|
||||
mch-id: 1609461201
|
||||
# 商户API证书序列号
|
||||
mchSerialNo: 2F16A068181C2998F3EE5271416F720AF0146293
|
||||
# 商户私钥文件
|
||||
# 注意:apiclient_key地址
|
||||
privateKeyPath: D:\AH\apiclient_key.pem
|
||||
mch-no: 2F16A068181C2998F3EE5271416F720AF0146293
|
||||
# 私钥本地存储路径
|
||||
private-key-path: D:\AH\apiclient_key.pem
|
||||
# API v3密钥
|
||||
apiV3Key: _TSKJ_0471_TSkj_0471_tsKJ_0471__
|
||||
# APPID 小程序id
|
||||
appid: wxe17874894f7ff27b
|
||||
# 微信服务器地址
|
||||
domain: https://api.mch.weixin.qq.com
|
||||
# 接收结果通知地址
|
||||
notifyUrl: xxx
|
||||
api-v3-key: _TSKJ_0471_TSkj_0471_tsKJ_0471__
|
||||
# 小程序APPID
|
||||
app-id: wxe17874894f7ff27b
|
||||
# 二维码超时时间/单位:分钟
|
||||
time-out: 5
|
||||
# 微信服务器网关地址
|
||||
url: https://api.mch.weixin.qq.com
|
||||
# 接收结果通知地址.如果需要动态替换订单号,则以 {orderNo} 占位
|
||||
notify-url: https://lg48844529.vicp.fun/operator/api/account/pay-wx/{orderNo}
|
||||
# 单笔最大金额
|
||||
max-money: 2000
|
||||
# 单笔最小金额
|
||||
min-money: 0.1
|
||||
ali-pay:
|
||||
# 应用ID
|
||||
# 西藏 app-id: 2021004137636507
|
||||
app-id: 2021004138650351
|
||||
# 支付宝服务器网关地址
|
||||
url: https://openapi.alipay.com/gateway.do
|
||||
# 应用私钥
|
||||
# 西藏 private-key: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMR1SNMLAfqFnzswWftBv1TnKGgILoDNkthHienFLcEUU1eb0ws7ST8QQZGQEZaHCKSGo82Nvvhwx6+7LGwC5liiu/RGh7CZYEul8+8GwGvsTh7wf1+dEH7YtyfJV1kyUF+p9lL0qRKBbcgUSM8QMyLeCBFE+AVvIqSce8ZLTwetpHSqZFP1VnFuH+gl8c23vDLOySoXCrhqL62Wy3MRmwFtRbOJ6UXicpmU5qxeauERGOlFhQ+5AraPhuRqkvtjN0PnTRbAT1OBEClvW1XXsS+y7i8davSuJWdO4Nmm1PcfUoza1GsspuNKRscgx7znv4SEfjq48HzGf1AJ/ZdhObAgMBAAECggEADSPlZLBp3x1LB8v+O96IO+tUSQsiuA/0DBJ7pgforxqjDAZSVYyP3sfV5W/1LWceG6X65aY+u+o/ngmTzpBUCEjwHiOPUe8s8VZv85pb1CnskWltqnnzPbXfuSK4cWIONsgqRDUw2/YQZilpvXYaIYownIbFh7UdTB7LKfeZB2mm4z76h5wWT90rZtBEXvRuCJrD48xuoksgA5Lul54Jl4MVUBRMB+QyAdnRUddiEaeN47BNOrpsWFSoHQGujTZ9t229VylmRO5+p2Tq1uLrYNR8ZhKbUzhQaVrtUd2lu8TdEMcfCNWWpPTNUry9JdLVKETXoc66+C9fvyTvUo9xEQKBgQDV6UA2CadOOIjhFgya7+Bnn24aaP5wbPAFjjcFgGfQDME9yRRFTovnT5KXQZSvjHxsr+ifETPCj7RMeI0eaE4O/yist4frcvY2BoGgJDE6RmZiG9VGCI68m6y+YvXFXnnZc3lDdXXrkmMKB0uR5vrUR0yrfgEWYsIe8s3BCLSREwKBgQCn4THa1jGoBesRdsGcrQ04CtvIQY83glyjZmxaLjYeFGXxLfOjSJBojK3NfCWrA/0qLS9gN5R3dw0ES7hPPCAA2TBwHfJijfF5U5bODF3S+F9fNP4QuJkNA9PK4oX7KIf7cm8muREwpwyDsAATzr/uc/mSXKS504Wjb4Jfu6pMWQKBgED9L6P7RNhP9s4jy8qazFvPJT1i3sK7ZiTZ8z95ppCf/2nNGJqB5aFuHIRVyV2YWgkPXKZPLKGU1VtSWNV/LRADV5E55VKUR9dcHK/Rrx8cWmi+Ogqf+PW2ekIRgMfpDy4Qliv3mM7sV6ipVL1MJrKtws5rZtstP/r1G6vlAC7/AoGAd2GAnmnq7d0niEe27r9wwwWVvRZBzet6DQhszMRH36QJyjQvKVIUvwQrJBDAiJhRk4iGRBnCDiIus3tVGaNb7r6D33asQsFFkk2K1AOfRMMyrvV0JlffHo42MfRb6nqsGHcL67F3M+3WzF5/75X6josSUq5mxW5RfiNxxrohJCECgYBCeNxjadcyOhwL+BYjr8iIzqX+njguNhunrc0/xfD1WBJjK9QM9hD2TbYrdODUselc1QSM5ZlDLYjdYmEq+COr0gZhok7nHnzLV/SCIkEdT9wLLIestGFZDimcXGTmsKxXqQcGFwrwRnFEu3Xue7/36mG314giD0tIiJtK0CBpyw==
|
||||
private-key: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWIpiransdWYJr9EXA83USVuWjX+hLhCAVHtIJqTPXPFShOW+Rv5aoXHGUsmMfs325DB0lNM/2aYS7Fyym4fzMkLYUHtJoICHafspgJraYpx19jkaSnEkiVgR/UxgDLFFKVubPIszV+zpm8J2xt8PkZHyhuaQEOtBcAGKcNRacDd9DfGZj75vPvhtvVvEFWndeuMZ6d67i2opUVL2c395vPkrjX74Q6GzZ/osfTrCD/3+JHdQXBm0bpOdx7ARJxIyR2sn+7AkPAcXdc3Kz7NoP8C84q09daqwUk6y711ZZfqUmUfAuP4vnh5vMrwcrqlRfc9/LbbH/0U3VFxjtAL2HAgMBAAECggEAMDMLMH0O6W1DIcVaX4fJngmnz7uKqDPS2PT8GX3o1sDXqqr11qTbiVGkZUif6h2Fz1LESJ2b5lAZ/LaD70++CS6sRelfQ26Nb8gk0JmdJYUBQr3ailcCY7OZ3gafPuWLc4JSt01E1a3CIio9dkC48yoPmRwwO+tl2SOGhP/GMnMDtQQ48fzJ/slqofOxyXvGPsZVi+XJz6Ht9mZPEx+jNcdgfOizCGWC6u4IlbOaC/7SP3XVqBk3NlAHk49RoRgJTuZOApU8lS32WMvM/NCRcS/qt5lGjwIFn+TjCOCpmwcqU98yEVGhyJI/xpTJk6/HEEpeCOhJFj+Z0UFjab8SAQKBgQDLGqcS7rW0Q6qNCm9BUvpotXybfoLKF6yjJPprcGe2PtelM5fFgGOurdgafOdnPvLr1lXYe2Ld0d7UioZ2uxTAUrQ3QjeR7I9fACAQHuQ6cJud89ZvGozzWrYhbK1ObZE3tg41+nDfG8qeFnPSY1L5yxreFVH0x+yOBaPhiRhskQKBgQC9PGYwutnIc+UbyS8WU2cRpcXAeAXC2pxQZ14l3gfAXETkUgehh9lKI8R5i0iHxBCvwLMXFSGGJORGQUDj/SVBjWpbuunRJKeaXyYmUnvkthdLSdg1O/KwuJHHfdd1MA4RarKe8Pz4ZqbkGguCKS0sPt39xym7ShZkG26ul3d0lwKBgQC/McHhwrFultxwlUgSWIi+FUrOHhQFJrAvjFno1hHrr9DVBXJ0S96Ky8BJfxdfTBTmCgkaF10Er9Jyhkz6bDamrbRU6JLjXavBpJ6KTmpO0T7NPIO6Z2YUmGonoOSsldxEc6+BBNdIUCM3Gq/BeBreZ2JNegiCw8leENUrNSG24QKBgQCtMu3ZJfuUcza74rw9M+K/DTncuj2TpWCyWpmaEQiJMCpByy5+0oa3S9tU331n/bTEF5wSwV1omLVx8+F/ij+iKtuwz3eX23OnX/Tb2Fza7SqO1yyTNKYgxx1uOCiOcog9uql3vdvbQqD3XzsvS56zw2qNDs+MQvgRceYw2CMWSwKBgGLOf7gdMKmr2D/H86MRI2nGoJ56/2iUu/haRmLmG0rQgc8yV+y9ax2cVm9+2ammCK0MU8bnxZJ4/vatdvCYyKXt+caKOb3JP4aDldayIdJe2wcCr0uh6HK9w317l85QCmc2S6YTYkWJWowf6h4E7UdZtIjGGdIAWfaV1Frzdo0l
|
||||
# 支付宝公钥
|
||||
# 西藏 ali-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhPuhyfS+awhnbd50xA50GC/hbjeuR4SKVPV6mkEWMGJHFYdicVL0+TKkgl3p9I4c/4OKuQjr0w1dGtyTVDAKDCYdRGpi9av0jP1bYqU0Asg8YnHcLNYYO5zc8olV2DpKd1odHx+Lq7KbO40tN2dYsU1CUBYAMBPsqc4bccomdXHSqE48fOAOu0lYVAk3+7Rlm0yZ4Ya87CVr93pfVlyYRwl0TCeOJ0HeNS/5lWoVpAqsbIUnAi1CkoKC0xLWNriibNjjb9x5KjpxrxTylI9L/FA393XpkevVLtAFVPh9mqKCac+VSw8Fo6c8IVqhJRMV1WjLAzEa8pVkIXD29gav5wIDAQAB
|
||||
ali-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Hi1l310TLDfLnmJlpyyaj1V5JgrKyQgbtx3+QPoE/vauRKl/4pKbyIEgvvYWxB9XG5ZAewyCCh+AsXi0Et9/JBvINopBq5ki/gRn0lOmjNjsGXorz25dNPui0uX8b/0el2giH8Cs0VFHQEByISyf0ZsyK00V7yZ/kBIjvWinyPzKu3drSJQr4ukwWf1h31gXPcpn4hF7kuSAG5TRtDMeriG05WMMnWhUj/Ma3a4D8lf4NaeTa7Qvy+Ha2tTFnvwHBP6VSKllLdOa9/GzpzVRSG0UZT3vuTDup5rv8XIGI3184T6oKqFqp7uHvr9UazO06swyYcLA3gjh8CfKjr+6wIDAQAB
|
||||
# 支付&二维码超时时间/单位:分钟
|
||||
time-out: 5
|
||||
# 接收结果通知地址.如果需要动态替换订单号,则以 {orderNo} 占位
|
||||
notify-url: https://lg48844529.vicp.fun/operator/api/account/pay-zfb/{orderNo}
|
||||
# 单笔最大金额
|
||||
max-money: 2000
|
||||
# 单笔最小金额
|
||||
min-money: 0.1
|
||||
|
@ -44,7 +44,7 @@
|
||||
<label class="layui-form-label">付款方式<span style="color: red">*</span></label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="thirdParty" lay-skin="primary" lay-verify="required" value="微信" lay-filter="thirdParty" title="微信">
|
||||
<input type="radio" name="thirdParty" value="支付宝" disabled lay-filter="thirdParty" title="支付宝">
|
||||
<input type="radio" name="thirdParty" value="支付宝" lay-filter="thirdParty" title="支付宝">
|
||||
<input type="radio" name="thirdParty" value="银联" disabled lay-filter="thirdParty" title="银联">
|
||||
<input type="radio" name="thirdParty" value="对公转账" lay-filter="thirdParty" title="对公转账">
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user