fix
This commit is contained in:
@@ -3,42 +3,35 @@ package com.starry.admin.modules.weichat.controller;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.XmlUtil;
|
||||
import com.github.wxpay.sdk.WXPayUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
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.conf.ThreadLocalRequestDetail;
|
||||
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.service.IPlayCustomUserInfoService;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
|
||||
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
||||
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.common.result.R;
|
||||
import com.starry.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
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.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author admin
|
||||
@@ -48,19 +41,14 @@ import java.util.TreeMap;
|
||||
@RequestMapping("/wx/pay/")
|
||||
public class WxPlayController {
|
||||
|
||||
|
||||
@Resource
|
||||
private SysTenantServiceImpl tenantService;
|
||||
|
||||
|
||||
@Resource
|
||||
private IPlayCustomUserInfoService customUserInfoService;
|
||||
|
||||
@Resource
|
||||
private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService;
|
||||
|
||||
@Resource
|
||||
private IPlayOrderInfoService orderInfoService;
|
||||
@Resource
|
||||
private WxCustomMpService mpService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -70,35 +58,67 @@ public class WxPlayController {
|
||||
* @since 2024/5/8 11:25
|
||||
**/
|
||||
@GetMapping("/jsCallback")
|
||||
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();
|
||||
public String wxPayNotify(@RequestBody String xmlData) {
|
||||
log.info("****************接受到微信支付回调:{}", xmlData);
|
||||
this.dealNotify(xmlData);
|
||||
|
||||
// 解析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);
|
||||
return WxPayNotifyResponse.success("成功");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// TODO如果支付状态不是待支付
|
||||
if (!orderInfoEntity.getOrderStatus().equals(RepairStatusEnum.NOT_PAY.name())) {
|
||||
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
|
||||
@GetMapping("/custom/createOrder")
|
||||
@@ -120,18 +140,40 @@ public class WxPlayController {
|
||||
String orderId = IdUtil.fastSimpleUUID();
|
||||
orderInfoService.createRechargeOrder(orderId, new BigDecimal(totalFee * 1.0 / 100), new BigDecimal(totalFee * 1.0 / 100), customUserInfo.getId());
|
||||
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 {
|
||||
String nonceStr = WxCustomPayUtils.generateNonceStr();
|
||||
Map<String, String> playRequestParameters = WxCustomPayUtils.getPayRequestParameters(customUserInfo.getOpenid(), entity.getAppId(), entity.getMchId(), orderId, nonceStr, "127.0.0.1", body, SecurityUtils.getTenantId(), totalFee);
|
||||
log.info(WXPayUtil.mapToXml(playRequestParameters));
|
||||
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());
|
||||
orderResult = wxPayService.unifiedOrder(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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.play.wx.WeChatConstants;
|
||||
import com.starry.admin.modules.platform.entity.SysTenantEntity;
|
||||
import com.starry.admin.modules.platform.service.impl.SysTenantServiceImpl;
|
||||
import com.starry.admin.utils.SecurityUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -39,5 +44,30 @@ public class WxCustomMpService {
|
||||
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