fix
This commit is contained in:
@@ -94,6 +94,12 @@
|
|||||||
<artifactId>jave-nativebin-linux64</artifactId>
|
<artifactId>jave-nativebin-linux64</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>weixin-java-pay</artifactId>
|
||||||
|
<version>4.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.tencentcloudapi</groupId>
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
<artifactId>tencentcloud-sdk-java-dnspod</artifactId>
|
<artifactId>tencentcloud-sdk-java-dnspod</artifactId>
|
||||||
|
|||||||
@@ -3,42 +3,35 @@ package com.starry.admin.modules.weichat.controller;
|
|||||||
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.core.util.XmlUtil;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.github.wxpay.sdk.WXPayUtil;
|
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
||||||
|
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
||||||
|
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
|
||||||
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
|
import com.github.binarywang.wxpay.util.SignUtils;
|
||||||
import com.starry.admin.common.aspect.CustomUserLogin;
|
import com.starry.admin.common.aspect.CustomUserLogin;
|
||||||
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
|
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
|
||||||
import com.starry.admin.common.exception.CustomException;
|
import com.starry.admin.common.exception.CustomException;
|
||||||
import com.starry.admin.common.play.wx.WeChatConstants;
|
|
||||||
import com.starry.admin.common.play.wx.WxCustomPayUtils;
|
|
||||||
import com.starry.admin.modules.balance.service.IPlayBalanceDetailsInfoService;
|
|
||||||
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
|
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
|
||||||
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
||||||
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
|
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
|
||||||
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
||||||
import com.starry.admin.modules.platform.service.impl.SysTenantServiceImpl;
|
import com.starry.admin.modules.platform.service.impl.SysTenantServiceImpl;
|
||||||
import com.starry.admin.modules.weichat.entity.WxPayReturnVo;
|
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||||
import com.starry.admin.utils.SecurityUtils;
|
import com.starry.admin.utils.SecurityUtils;
|
||||||
import com.starry.common.result.R;
|
import com.starry.common.result.R;
|
||||||
import com.starry.common.utils.StringUtils;
|
import com.starry.common.utils.StringUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.dom4j.Document;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.dom4j.DocumentHelper;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.dom4j.Element;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.util.*;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author admin
|
* @author admin
|
||||||
@@ -48,19 +41,14 @@ import java.util.TreeMap;
|
|||||||
@RequestMapping("/wx/pay/")
|
@RequestMapping("/wx/pay/")
|
||||||
public class WxPlayController {
|
public class WxPlayController {
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SysTenantServiceImpl tenantService;
|
private SysTenantServiceImpl tenantService;
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IPlayCustomUserInfoService customUserInfoService;
|
private IPlayCustomUserInfoService customUserInfoService;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IPlayOrderInfoService orderInfoService;
|
private IPlayOrderInfoService orderInfoService;
|
||||||
|
@Resource
|
||||||
|
private WxCustomMpService mpService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,34 +58,66 @@ public class WxPlayController {
|
|||||||
* @since 2024/5/8 11:25
|
* @since 2024/5/8 11:25
|
||||||
**/
|
**/
|
||||||
@GetMapping("/jsCallback")
|
@GetMapping("/jsCallback")
|
||||||
public void jsCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
public String wxPayNotify(@RequestBody String xmlData) {
|
||||||
// 读取回调数据
|
log.info("****************接受到微信支付回调:{}", xmlData);
|
||||||
InputStream inputStream = request.getInputStream();
|
this.dealNotify(xmlData);
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
String s;
|
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
|
||||||
while ((s = in.readLine()) != null) {
|
|
||||||
sb.append(s);
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
inputStream.close();
|
|
||||||
|
|
||||||
// 解析xml成map
|
return WxPayNotifyResponse.success("成功");
|
||||||
Map<String, Object> m = XmlUtil.xmlToMap(sb.toString());
|
|
||||||
// 过滤空 设置 TreeMap
|
|
||||||
SortedMap<Object, Object> packageParams = new TreeMap<>();
|
|
||||||
for (String parameter : m.keySet()) {
|
|
||||||
Object parameterValue = m.get(parameter);
|
|
||||||
String v = "";
|
|
||||||
if (null != parameterValue) {
|
|
||||||
v = parameterValue.toString().trim();
|
|
||||||
}
|
}
|
||||||
packageParams.put(parameter, v);
|
|
||||||
|
private void dealNotify(String xmlData) {
|
||||||
|
try {
|
||||||
|
Map<String, String> orderMap = readStringXmlOut(xmlData);
|
||||||
|
String outTradeNo = orderMap.get("out_trade_no");
|
||||||
|
PlayOrderInfoEntity orderInfoEntity = orderInfoService.getById(outTradeNo);
|
||||||
|
if (Objects.isNull(orderInfoEntity)) {
|
||||||
|
log.error("*********未查询到对应的支付记录,订单号:{}", outTradeNo);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
log.info("packageParams=" + packageParams);
|
// TODO如果支付状态不是待支付
|
||||||
String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
if (!orderInfoEntity.getOrderStatus().equals(RepairStatusEnum.NOT_PAY.name())) {
|
||||||
response.getWriter().write(resXml);
|
log.error("*********支付记录状态异常,支付记录:{}", JSONObject.toJSONString(repair));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
Date nowDate = new Date();
|
||||||
|
repair.setPaySuccessTime(nowDate);
|
||||||
|
repair.setPayStatus(RepairStatusEnum.PAID.name());
|
||||||
|
repair.setStatus(RepairStatusEnum.REPAIRING.name());
|
||||||
|
orderInfoService.updateById(orderInfoEntity);
|
||||||
|
|
||||||
|
log.info("*********支付处理完成");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//public void jsCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
// // 读取回调数据
|
||||||
|
// InputStream inputStream = request.getInputStream();
|
||||||
|
// StringBuilder sb = new StringBuilder();
|
||||||
|
// String s;
|
||||||
|
// BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||||
|
// while ((s = in.readLine()) != null) {
|
||||||
|
// sb.append(s);
|
||||||
|
// }
|
||||||
|
// in.close();
|
||||||
|
// inputStream.close();
|
||||||
|
//
|
||||||
|
// // 解析xml成map
|
||||||
|
// Map<String, Object> m = XmlUtil.xmlToMap(sb.toString());
|
||||||
|
// // 过滤空 设置 TreeMap
|
||||||
|
// SortedMap<Object, Object> packageParams = new TreeMap<>();
|
||||||
|
// for (String parameter : m.keySet()) {
|
||||||
|
// Object parameterValue = m.get(parameter);
|
||||||
|
// String v = "";
|
||||||
|
// if (null != parameterValue) {
|
||||||
|
// v = parameterValue.toString().trim();
|
||||||
|
// }
|
||||||
|
// packageParams.put(parameter, v);
|
||||||
|
// }
|
||||||
|
// log.info("packageParams=" + packageParams);
|
||||||
|
// String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
||||||
|
// response.getWriter().write(resXml);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
@CustomUserLogin
|
@CustomUserLogin
|
||||||
@@ -120,18 +140,40 @@ public class WxPlayController {
|
|||||||
String orderId = IdUtil.fastSimpleUUID();
|
String orderId = IdUtil.fastSimpleUUID();
|
||||||
orderInfoService.createRechargeOrder(orderId, new BigDecimal(totalFee * 1.0 / 100), new BigDecimal(totalFee * 1.0 / 100), customUserInfo.getId());
|
orderInfoService.createRechargeOrder(orderId, new BigDecimal(totalFee * 1.0 / 100), new BigDecimal(totalFee * 1.0 / 100), customUserInfo.getId());
|
||||||
String body = "树洞充值";
|
String body = "树洞充值";
|
||||||
|
|
||||||
|
WxPayService wxPayService = mpService.getWxPay();
|
||||||
|
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
|
||||||
|
request.setOpenid(customUserInfo.getOpenid());
|
||||||
|
// 订单总金额,单位为分(开发阶段固定设置为支付1分钱)
|
||||||
|
request.setTotalFee(1);
|
||||||
|
request.setOutTradeNo(orderId);
|
||||||
|
request.setTradeType("JSAPI");
|
||||||
|
request.setSpbillCreateIp("101.43.206.16");
|
||||||
|
request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl());
|
||||||
|
request.setBody("船票充值");
|
||||||
|
WxPayUnifiedOrderResult orderResult;
|
||||||
try {
|
try {
|
||||||
String nonceStr = WxCustomPayUtils.generateNonceStr();
|
orderResult = wxPayService.unifiedOrder(request);
|
||||||
Map<String, String> playRequestParameters = WxCustomPayUtils.getPayRequestParameters(customUserInfo.getOpenid(), entity.getAppId(), entity.getMchId(), orderId, nonceStr, "127.0.0.1", body, SecurityUtils.getTenantId(), totalFee);
|
} catch (WxPayException e) {
|
||||||
log.info(WXPayUtil.mapToXml(playRequestParameters));
|
throw new RuntimeException(e);
|
||||||
String sign = WxCustomPayUtils.generateSignature(playRequestParameters, entity.getMchKey());
|
|
||||||
String prepayId = WxCustomPayUtils.unifiedOrderJsApi(playRequestParameters, sign, entity.getMchKey());
|
|
||||||
WxPayReturnVo vo = new WxPayReturnVo(entity.getMchKey(), String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))), nonceStr, WeChatConstants.SignType.MD5.toString(), sign, prepayId, WeChatConstants.NOTIFY_URL);
|
|
||||||
return R.ok(vo);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("创建微信预支付订单失败,error=", e);
|
|
||||||
throw new CustomException("创建支付订单失败," + e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String prepayId = orderResult.getPrepayId();
|
||||||
|
//组合参数构建支付
|
||||||
|
Map<String, String> paySignInfo = new HashMap<>(5);
|
||||||
|
String timeStamp = String.valueOf(System.currentTimeMillis());
|
||||||
|
String nonceStr = "dalfhh241lnandnsklajax";
|
||||||
|
paySignInfo.put("appId", wxPayService.getConfig().getAppId());
|
||||||
|
paySignInfo.put("nonceStr", nonceStr);
|
||||||
|
paySignInfo.put("timeStamp", timeStamp);
|
||||||
|
paySignInfo.put("signType", "MD5");
|
||||||
|
paySignInfo.put("package", "prepay_id=" + prepayId);
|
||||||
|
String[] signInfo = new String[0];
|
||||||
|
String paySign = SignUtils.createSign(paySignInfo, "MD5", wxPayService.getConfig().getMchKey(), signInfo);
|
||||||
|
|
||||||
|
//组合支付参数
|
||||||
|
JSONObject jsonObject = new JSONObject().fluentPut("appId", wxPayService.getConfig().getAppId()).fluentPut("timeStamp", timeStamp).fluentPut("nonceStr", nonceStr).fluentPut("package", "prepay_id=" + prepayId).fluentPut("signType", "MD5").fluentPut("paySign", paySign);
|
||||||
|
return R.ok(jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -152,7 +194,38 @@ public class WxPlayController {
|
|||||||
return totalFee;
|
return totalFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static Map<String, String> readStringXmlOut(String xml) {
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
Document doc;
|
||||||
|
try {
|
||||||
|
doc = DocumentHelper.parseText(xml); // 将字符串转为XML
|
||||||
|
Element rootElt = doc.getRootElement(); // 获取根节点
|
||||||
|
List<Element> list = rootElt.elements();//获取根节点下所有节点
|
||||||
|
for (Element element : list) { //遍历节点
|
||||||
|
map.put(element.getName(), element.getText()); //节点的name为map的key,text为map的value
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
// 参数示例
|
||||||
|
//<xml>
|
||||||
|
// <appid><![CDATA[wx846289ab0b2e9f89]]></appid>
|
||||||
|
// <bank_type><![CDATA[OTHERS]]></bank_type>
|
||||||
|
// <cash_fee><![CDATA[1]]></cash_fee>
|
||||||
|
// <fee_type><![CDATA[CNY]]></fee_type>
|
||||||
|
// <is_subscribe><![CDATA[N]]></is_subscribe>
|
||||||
|
// <mch_id><![CDATA[1616729997]]></mch_id>
|
||||||
|
// <nonce_str><![CDATA[1692338418306]]></nonce_str>
|
||||||
|
// <openid><![CDATA[oNHh06-KauVEor1BfSWsBr2Xil-I]]></openid>
|
||||||
|
// <out_trade_no><![CDATA[gameno20230818140018j5kc]]></out_trade_no>
|
||||||
|
// <result_code><![CDATA[SUCCESS]]></result_code>
|
||||||
|
// <return_code><![CDATA[SUCCESS]]></return_code>
|
||||||
|
// <sign><![CDATA[639C5B46EB11B42A354E38A5F96683CC]]></sign>
|
||||||
|
// <time_end><![CDATA[20230818140028]]></time_end>
|
||||||
|
// <total_fee>1</total_fee>
|
||||||
|
// <trade_type><![CDATA[JSAPI]]></trade_type>
|
||||||
|
// <transaction_id><![CDATA[4200001910202308187726172728]]></transaction_id>
|
||||||
|
//</xml>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
package com.starry.admin.modules.weichat.service;
|
package com.starry.admin.modules.weichat.service;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||||
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
|
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
||||||
import com.starry.admin.common.exception.CustomException;
|
import com.starry.admin.common.exception.CustomException;
|
||||||
|
import com.starry.admin.common.play.wx.WeChatConstants;
|
||||||
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
||||||
import com.starry.admin.modules.platform.service.impl.SysTenantServiceImpl;
|
import com.starry.admin.modules.platform.service.impl.SysTenantServiceImpl;
|
||||||
import com.starry.admin.utils.SecurityUtils;
|
import com.starry.admin.utils.SecurityUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -39,5 +44,30 @@ public class WxCustomMpService {
|
|||||||
return wxMpService.switchoverTo(entity.getAppId());
|
return wxMpService.switchoverTo(entity.getAppId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WxPayService getWxPay() {
|
||||||
|
String tenantId = SecurityUtils.getTenantId();
|
||||||
|
if (StrUtil.isBlankIfStr(tenantId)) {
|
||||||
|
throw new CustomException("系统错误,租户ID不能为空");
|
||||||
|
}
|
||||||
|
SysTenantEntity entity = tenantService.selectSysTenantByTenantId(tenantId);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new CustomException("系统错误,租户ID不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(entity.getMchId())) throw new CustomException("商户号不能为空,请联系平台方进行配置");
|
||||||
|
WxPayConfig payConfig = new WxPayConfig();
|
||||||
|
payConfig.setAppId(StringUtils.trimToNull(entity.getAppId()));
|
||||||
|
payConfig.setMchId(StringUtils.trimToNull(entity.getMchId()));
|
||||||
|
payConfig.setMchKey(StringUtils.trimToNull(entity.getMchKey()));
|
||||||
|
|
||||||
|
payConfig.setNotifyUrl(StringUtils.trimToNull(WeChatConstants.NOTIFY_URL));
|
||||||
|
payConfig.setTradeType("JSAPI");
|
||||||
|
payConfig.setSignType("MD5");
|
||||||
|
// 可以指定是否使用沙箱环境
|
||||||
|
payConfig.setUseSandboxEnv(false);
|
||||||
|
WxPayService wxPayService = new WxPayServiceImpl();
|
||||||
|
wxPayService.setConfig(payConfig);
|
||||||
|
return wxPayService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user