diff --git a/yudao-module-mall/yudao-module-shop-biz/src/main/java/cn/iocoder/yudao/module/shop/task/ReplenishmentTask.java b/yudao-module-mall/yudao-module-shop-biz/src/main/java/cn/iocoder/yudao/module/shop/task/ReplenishmentTask.java new file mode 100644 index 000000000..73be6d6dd --- /dev/null +++ b/yudao-module-mall/yudao-module-shop-biz/src/main/java/cn/iocoder/yudao/module/shop/task/ReplenishmentTask.java @@ -0,0 +1,288 @@ +package cn.iocoder.yudao.module.shop.task; + +import cn.iocoder.yudao.framework.pay.properties.WxPayProperties; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.shop.dal.dataobject.recharge.RechargeOrderDO; +import cn.iocoder.yudao.module.shop.dal.mysql.recharge.RechargeOrderMapper; +import cn.iocoder.yudao.module.shop.service.order.StoreOrderService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +/** + * @Title:ReplenishmentTask + * @Description: 会员充值补单定时任务 + * @author: tangqian + * @date: 2023/6/19 11:33 + * @version: V1.0.0 + */ +@Component +@Slf4j +public class ReplenishmentTask { + @Autowired + private WxPayProperties properties; + @Autowired + private RechargeOrderMapper rechargeOrderMapper; + @Autowired + private StoreOrderService storeOrderService; + + /** + * 每天上午8点和下午3点执行补单计划 + */ +// @Scheduled(cron = "0 0 8,15 * * ?") + @TenantIgnore + public void replenishmentTask() { + /** + * 1.扫描表里面未付款的订单 + * 2.根据订单号查询微信支付结果 + * 3.处理相关逻辑c + */ + List orderDOS = rechargeOrderMapper.selectList(Wrappers.lambdaQuery() + .eq(RechargeOrderDO::getPaid, 0) + .eq(RechargeOrderDO::getIsReplenishment, 0)); + if (!CollectionUtils.isEmpty(orderDOS)) { + orderDOS.forEach(e -> { + execute(e.getOrderId()); + }); + } + } + + public void execute(String outTradeNo) { + RechargeOrderDO orderDO = rechargeOrderMapper.selectOne(Wrappers.lambdaQuery().eq(RechargeOrderDO::getOrderId, outTradeNo)); + if (null == orderDO) { + log.info("订单号:{}未查询数据", outTradeNo); + return; + } + String appId = properties.getAppId(); + String mchId = properties.getMchId(); + // 生成随机字符串 + String nonceStr = generateNonceStr(); + // 商户密钥 + String key = properties.getMchKey(); + + // 构建请求参数 + Map params = new HashMap<>(); + params.put("appid", appId); + params.put("mch_id", mchId); + params.put("out_trade_no", outTradeNo); + params.put("nonce_str", nonceStr); + // 生成签名 + String sign = generateSign(params, key); + params.put("sign", sign); + + // 发起HTTP请求 + String requestUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; + String response = sendRequest(requestUrl, mapToXml(params)); + log.info("根据订单编号:{},查询微信支付结果出参:{}", outTradeNo, response); + Map map = parseResponse(response); + if ("SUCCESS".equals(map.get("trade_state")) && "SUCCESS".equals(map.get("result_code"))) { + // 修改订单状态 +// orderDO.setPaid(1); +// orderDO.setIsReplenishment(1); +// orderDO.setReplenishmentName(map.toString()); +// rechargeOrderMapper.updateById(orderDO); +// // 写入 充值档位记录表 +// storeOrderService.addPhone(orderDO, outTradeNo); + } + } + + + /** + * 解析出参 + * + * @param response + */ + private static Map parseResponse(String response) { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + ByteArrayInputStream input = new ByteArrayInputStream(response.getBytes("UTF-8")); + Document document = builder.parse(input); + + Element root = document.getDocumentElement(); + NodeList nodeList = root.getChildNodes(); + Map map = new HashMap<>(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + String tagName = element.getTagName(); + String textContent = element.getTextContent(); + map.put(tagName, textContent); + } + } + log.info("出参结果:{}", map.toString()); + return map; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 生成随机字符串 + * + * @return + */ + private static String generateNonceStr() { + return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); + } + + /** + * 生成签名 + * + * @param params 相关参数 + * @param key 商户密钥 + * @return + */ + private static String generateSign(Map params, String key) { + List keys = new ArrayList<>(params.keySet()); + Collections.sort(keys); + StringBuilder sb = new StringBuilder(); + for (String k : keys) { + String v = params.get(k); + if (v != null && !v.isEmpty()) { + sb.append(k).append("=").append(v).append("&"); + } + } + sb.append("key=").append(key); + return md5(sb.toString()).toUpperCase(); + } + + /** + * 发送HTTP请求 + * + * @param url + * @param data + * @return + */ + private static String sendRequest(String url, String data) { + // 使用Java的HTTP请求库发送POST请求,这里需要根据你使用的具体库进行实现 + // 示例代码中的sendPostRequest方法是一个自定义的方法,你需要使用适合你的HTTP请求库进行替换 + return sendPostRequest(url, data); + } + + + /** + * Map转换为XML格式 + * + * @param map + * @return + */ + private static String mapToXml(Map map) { + StringBuilder sb = new StringBuilder(); + sb.append(""); + for (Map.Entry entry : map.entrySet()) { + sb.append("<").append(entry.getKey()).append(">"); + sb.append(""); + sb.append(""); + } + sb.append(""); + return sb.toString(); + } + + public static String md5(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(input.getBytes()); + + // Convert byte array to hexadecimal string + StringBuilder hexString = new StringBuilder(); + for (byte b : messageDigest) { + String hex = Integer.toHexString(0xFF & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + private static String sendPostRequest(String url, String data) { + try { + URL requestUrl = new URL(url); + HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + + // 设置请求头 + connection.setRequestProperty("Content-Type", "application/xml;charset=UTF-8"); + + // 发送请求数据 + OutputStream outputStream = connection.getOutputStream(); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8")); + writer.write(data); + writer.flush(); + writer.close(); + outputStream.close(); + + // 获取响应数据 + int responseCode = connection.getResponseCode(); + InputStream inputStream; + if (responseCode >= 200 && responseCode < 300) { + inputStream = connection.getInputStream(); + } else { + inputStream = connection.getErrorStream(); + } + + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + inputStream.close(); + + connection.disconnect(); + + return response.toString(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +// public static void main(String[] args) { +// String appId = "wx7e503d9cded34c07"; +// String mchId = "1641073271"; +// String nonceStr = generateNonceStr(); // 生成随机字符串 +// String key = "cyywl123456cyywl654321cyywl12345"; // 商户密钥 +// +// // 构建请求参数 +// Map params = new HashMap<>(); +// params.put("appid", appId); +// params.put("mch_id", mchId); +// params.put("out_trade_no", "MEMBER_16700496905020866571"); +// params.put("nonce_str", nonceStr); +// String sign = generateSign(params, key); // 生成签名 +// params.put("sign", sign); +// +// // 发起HTTP请求 +// String requestUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; +// String response = sendRequest(requestUrl, mapToXml(params)); +// System.out.println(response); +// parseResponse(response); +// } +}