ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/entity/Order.java
@@ -194,5 +194,6 @@ @ApiModelProperty("回收单凭证(多张照片 ','隔开)") @TableField("paper_pic") private String paperPic; @ApiModelProperty("拉起确认收款页面参数") private String packageInfo; } ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/entity/WithdrawDetailVO.java
@@ -20,6 +20,8 @@ @ApiModelProperty("订单编号") private String orderNumber; @ApiModelProperty("拉起确认收款参数") private String packageInfo; @ApiModelProperty("下单用户id") private Integer userId; ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/WechatConstants.java
@@ -57,9 +57,13 @@ public static final String TRANSFER_DETAIL_LIST = "transfer_detail_list"; /** * 微信商家转账到用户零钱接口地址(前缀) * 微信商家转账到用户零钱接口地址(前缀)弃用 */ public static final String WE_CHAT_URL_PRE = "https://api.mch.weixin.qq.com/v3/transfer/batches"; /** * 微信发起转账(前缀) */ public static final String WE_CHAT_PAY_URL_PRE = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills"; /** * 微信商家转账到用户零钱接口地址(后缀) ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/UserDto.java
@@ -12,4 +12,5 @@ private String profilePicture; private String phone; private String userNo; private String openId; } ruoyi-service/ruoyi-order/pom.xml
@@ -19,7 +19,10 @@ </properties> <dependencies> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/WithdrawController.java
@@ -340,6 +340,7 @@ withdrawDetailVO.setWithdrawalState(withdraw.getState()); withdrawDetailVO.setWithdrawalTime(withdraw.getCreateTime()); } withdrawDetailVO.setPackageInfo(order.getPackageInfo()); withdrawDetailVO.setAddress(order.getAddress()); if (null != serveRecord) { withdrawDetailVO.setPhoto(serveRecord.getPhoto()); ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/WxChatPayCallBack.java
New file @@ -0,0 +1,203 @@ package com.ruoyi.order.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.WechatConstants; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.GlobalException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.vo.UserDto; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.order.entity.ChangeDispatch; import com.ruoyi.order.entity.Order; import com.ruoyi.order.entity.Withdraw; import com.ruoyi.order.entity.WithdrawDetail; import com.ruoyi.order.request.ChangeDispatchRequest; import com.ruoyi.order.service.ChangeDispatchService; import com.ruoyi.order.service.OrderService; import com.ruoyi.order.service.WithdrawDetailService; import com.ruoyi.order.service.WithdrawService; import com.ruoyi.order.vx.HttpUtil; import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.user.api.feignClient.UserClient; import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.core.notification.NotificationConfig; import com.wechat.pay.java.core.notification.NotificationParser; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; 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.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * <p> * 商家转账回调 * </p> * * @author hjl * @since 2024-05-31 */ @RestController @RequestMapping("/wx") public class WxChatPayCallBack { @Autowired private WithdrawDetailService withdrawDetailService; @Resource private OrderService orderService; @Autowired private WithdrawService withdrawService; @Autowired private UserClient userClient; /** * 微信商户零线转账 - 回调通知 * @Context注解 把HTTP请求上下文对象注入进来,HttpServletRequest、HttpServletResponse、UriInfo 等 * @return */ @PostMapping("/wxChatPay") public String wxPayCallback(HttpServletRequest request) { Map<String, String> map = new HashMap<>(); Map<String,String> errMap = new HashMap<>(); try { System.err.println("请求"+request); BufferedReader reader = request.getReader(); String string1 = reader.toString(); System.err.println("请求reader"+string1); StringBuilder requestBody = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { requestBody.append(line); } System.err.println("全部请求体"+requestBody); JSONObject jsonObject = JSONObject.parseObject(requestBody.toString()); JSONObject resource = jsonObject.getJSONObject("resource"); AesUtil aesUtil = new AesUtil("TA2npSNWmS0GcB0tFFRWA94rm1M0iSFs".getBytes(StandardCharsets.UTF_8)); String decryptedData = aesUtil.decryptToString(resource.getString("associated_data").getBytes(StandardCharsets.UTF_8), resource.getString("nonce").getBytes(StandardCharsets.UTF_8), resource.getString("ciphertext")); System.err.println("微信解密的字符串信息"+decryptedData); JSONObject jsonInfo = (JSONObject) JSONObject.parse(decryptedData); String transferBillNo = jsonInfo.getString("transfer_bill_no"); String outBillNo = jsonInfo.getString("out_bill_no"); String state = jsonInfo.getString("state"); WithdrawDetail withdrawDetail = withdrawDetailService.lambdaQuery().eq(WithdrawDetail::getOutBatchNo, outBillNo).one(); Withdraw withdraw = withdrawService.getById(withdrawDetail.getWithdrawId()); Order order = orderService.getById(withdraw.getOrderId()); UserDto data = userClient.getUser(order.getUserId()).getData(); if (order.getIsWithdrawal()==3){ return "SUCCESS"; } if ("SUCCESS".equals(state)){ order.setIsWithdrawal(3); withdrawDetail.setStatus("SUCCESS"); withdrawDetailService.updateById(withdrawDetail); orderService.updateById(order); }else if ("CANCELLED".equals(state)){ // 校验提现 List<Withdraw> list = withdrawService.lambdaQuery().eq(Withdraw::getUserId, order.getUserId()) .eq(Withdraw::getOrderId, order.getId()).list(); List<Integer> stateList = list.stream().map(Withdraw::getState).collect(Collectors.toList()); if (stateList.contains(Constants.ONE)) { throw new GlobalException("当前订单提现申请已通过!"); } // 超时未收款 撤销 重新发起转账 更新packageInfo weChatPay(order.getOrderMoney(), data.getOpenId(),list.get(0).getId(),order.getServeName()); } map.put("code", "SUCCESS"); map.put("message", "成功"); } catch (Exception e) { errMap.put("code", "FAIL"); errMap.put("message", "服务器内部错误"); } return JSON.toJSONString(map); } private boolean weChatPay(BigDecimal orderMoney, String openId, String withdrawId, String serverName) { if (StringUtils.isBlank(openId)) { return false; } BigDecimal maxTransferAmount = new BigDecimal("200000"); // 单次转账限额,单位为分 int totalTransfers = orderMoney.multiply(new BigDecimal("100")).divide(maxTransferAmount, 0, RoundingMode.UP).intValue(); boolean allTransfersSuccessful = true; for (int i = 0; i < totalTransfers; i++) { BigDecimal transferAmount; if (i < totalTransfers - 1) { transferAmount = maxTransferAmount; } else { // 最后一笔转账,金额为剩余金额 transferAmount = orderMoney.multiply(new BigDecimal("100")).subtract(maxTransferAmount.multiply(new BigDecimal(i))).setScale(0, RoundingMode.DOWN); } Map<String, Object> postMap = new HashMap<>(8); postMap.put(WechatConstants.APP_ID, "wx98563d0ec9cf21c8"); // 订单号 String s = String.valueOf(UUID.randomUUID()).replaceAll("-", ""); postMap.put("out_bill_no", s); System.err.println("====="+postMap.get("out_bill_no")); postMap.put(WechatConstants.OPEN_ID, openId); // 转账金额 postMap.put("transfer_amount", transferAmount); // 转账备注 postMap.put("transfer_remark", "二手回收提现确认收款"); // 回调地址 postMap.put("notify_url", "https://hyhsbqgc.com/api/ruoyi-order/wx/wxChatPay"); // 转账场景报备信息 Map<String, Object> info = new HashMap<>(); info.put("info_type","回收商品名称"); info.put("info_content",serverName); postMap.put("transfer_scene_report_infos", com.alibaba.fastjson2.JSONObject.toJSONString(info)); String result = HttpUtil.postTransBatRequest( WechatConstants.WE_CHAT_PAY_URL_PRE, com.alibaba.fastjson2.JSONObject.toJSONString(postMap), "7EEA04429B006E12AAA421C002EC48BBEED5BE94", "1665330417", "/usr/local/vx/apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(result); // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); if (jsonObject.containsKey(WechatConstants.CREATE_TIME)) { String string = jsonObject.getString("package_info"); Withdraw withdraw = withdrawService.getById(withdrawId); WithdrawDetail one = withdrawDetailService.lambdaQuery().eq(WithdrawDetail::getWithdrawId, withdrawId).last("limit 1").one(); if (one!=null){ one.setOutBatchNo(s); one.setStatus("FAIL"); withdrawDetailService.updateById(one); Order order = orderService.getById(withdraw.getOrderId()); order.setPackageInfo(string); order.setIsWithdrawal(2); orderService.updateById(order); } } else { allTransfersSuccessful = false; break; } } return allTransfersSuccessful; } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/entity/Order.java
@@ -61,7 +61,9 @@ @ApiModelProperty("站点名称") @TableField("site_name") private String siteName; @ApiModelProperty("拉起确认收款页面参数") @TableField("package_info") private String packageInfo; @ApiModelProperty("回收服务id") @TableField("serve_id") private Integer serveId; @@ -145,7 +147,7 @@ @TableField("subsidy") private BigDecimal subsidy; @ApiModelProperty("是否已提现(0:未提现,1:已提现)") @ApiModelProperty("是否已提现(0:未提现,1:审核中 2审核通过 3:已确认收款)") @TableField("is_withdrawal") private Integer isWithdrawal; ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/WithdrawServiceImpl.java
@@ -138,7 +138,7 @@ throw new GlobalException("当前订单提现申请已通过!"); } return weChatPay(order.getOrderMoney(), openId,list.get(0).getId()); return weChatPay(order.getOrderMoney(), openId,list.get(0).getId(),order.getServeName()); } @Override @@ -252,7 +252,7 @@ // 已通过 withdraw.setState(Constants.ONE); // 商家微信打款至微信零钱 boolean update = weChatPay(order.getOrderMoney(), openId,withdraw.getId()); boolean update = weChatPay(order.getOrderMoney(), openId,withdraw.getId(),order.getServerName()); // if (!update) { // throw new GlobalException("交易提现失败,请检查是否绑定微信!"); // } @@ -272,15 +272,94 @@ @Resource private WithdrawDetailService withdrawDetailService; private boolean weChatPay(BigDecimal orderMoney, String openId,String withdrawId) { // private boolean weChatPay(BigDecimal orderMoney, String openId,String withdrawId) { // if (StringUtils.isBlank(openId)) { // return false; // } // // BigDecimal maxTransferAmount = new BigDecimal("20000"); // 单次转账限额,单位为分 // int totalTransfers = orderMoney.multiply(new BigDecimal("100")).divide(maxTransferAmount, 0, RoundingMode.UP).intValue(); // boolean allTransfersSuccessful = true; // // for (int i = 0; i < totalTransfers; i++) { // BigDecimal transferAmount; // if (i < totalTransfers - 1) { // transferAmount = maxTransferAmount; // } else { // // 最后一笔转账,金额为剩余金额 // transferAmount = orderMoney.multiply(new BigDecimal("100")).subtract(maxTransferAmount.multiply(new BigDecimal(i))).setScale(0, RoundingMode.DOWN); // } // // Map<String, Object> postMap = new HashMap<>(8); // postMap.put(WechatConstants.APP_ID, "wx98563d0ec9cf21c8"); // postMap.put(WechatConstants.OUT_BATCH_NO, String.valueOf(UUID.randomUUID()).replaceAll("-", "")); // System.err.println("====="+postMap.get(WechatConstants.OUT_BATCH_NO)); // postMap.put(WechatConstants.BATCH_NAME, "二手回收提现"); // postMap.put(WechatConstants.BATCH_REMARK, "二手回收提现"); // postMap.put(WechatConstants.TOTAL_AMOUNT, transferAmount); // postMap.put(WechatConstants.TOTAL_NUM, Constants.ONE); // // List<Map<String, Object>> list = new ArrayList<>(); // Map<String, Object> subMap = new HashMap<>(4); // subMap.put(WechatConstants.OUT_DETAIL_NO, String.valueOf(SNOW_FLAKE_ID_WORKER.nextId())); // subMap.put(WechatConstants.TRANSFER_AMOUNT, transferAmount); // subMap.put(WechatConstants.TRANSFER_REMARK, "二手回收提现到账"); // subMap.put(WechatConstants.OPEN_ID, openId); // list.add(subMap); // postMap.put(WechatConstants.TRANSFER_DETAIL_LIST, list); // // // 使用类加载器获取资源 URL //// String path = ClassLoader.getSystemResource("/usr/local/vx/apiclient_key.pem").getPath(); // //// String result = HttpUtil.postTransBatRequest( //// WechatConstants.WE_CHAT_URL_PRE, //// JSONObject.toJSONString(postMap), //// "7EEA04429B006E12AAA421C002EC48BBEED5BE94", //// "1665330417", //// "/usr/local/vx/apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); // String result = HttpUtil.postTransBatRequest( // WechatConstants.WE_CHAT_URL_PRE, // JSONObject.toJSONString(postMap), // "7EEA04429B006E12AAA421C002EC48BBEED5BE94", // "1665330417", // "D:\\study\\JiaDianHuiShou\\ruoyi-service\\ruoyi-order\\src\\main\\java\\com\\ruoyi\\order\\vx\\apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); // // JSONObject jsonObject = JSONObject.parseObject(result); // // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); // // if (jsonObject.containsKey(WechatConstants.CREATE_TIME)) { // // 转账成功 // //保存转账明细 //// WithdrawDetail withdrawDetail = new WithdrawDetail(); //// withdrawDetail.setWithdrawId(withdrawId); //// withdrawDetail.setMoney(transferAmount); //// withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); //// withdrawDetailService.save(withdrawDetail); // // // } else { // allTransfersSuccessful = false; // break; // } // // } // // return allTransfersSuccessful; // } // 上架打款到用户零钱接口已弃用 用新版商家转账接口 private boolean weChatPay(BigDecimal orderMoney, String openId,String withdrawId,String serverName) { if (StringUtils.isBlank(openId)) { return false; } BigDecimal maxTransferAmount = new BigDecimal("20000"); // 单次转账限额,单位为分 BigDecimal maxTransferAmount = new BigDecimal("200000"); // 单次转账限额,单位为分 int totalTransfers = orderMoney.multiply(new BigDecimal("100")).divide(maxTransferAmount, 0, RoundingMode.UP).intValue(); boolean allTransfersSuccessful = true; for (int i = 0; i < totalTransfers; i++) { BigDecimal transferAmount; if (i < totalTransfers - 1) { @@ -292,54 +371,57 @@ Map<String, Object> postMap = new HashMap<>(8); postMap.put(WechatConstants.APP_ID, "wx98563d0ec9cf21c8"); postMap.put(WechatConstants.OUT_BATCH_NO, String.valueOf(UUID.randomUUID()).replaceAll("-", "")); System.err.println("====="+postMap.get(WechatConstants.OUT_BATCH_NO)); postMap.put(WechatConstants.BATCH_NAME, "二手回收提现"); postMap.put(WechatConstants.BATCH_REMARK, "二手回收提现"); postMap.put(WechatConstants.TOTAL_AMOUNT, transferAmount); postMap.put(WechatConstants.TOTAL_NUM, Constants.ONE); // 订单号 postMap.put("out_bill_no", String.valueOf(UUID.randomUUID()).replaceAll("-", "")); System.err.println("====="+postMap.get("out_bill_no")); postMap.put(WechatConstants.OPEN_ID, openId); // 转账金额 postMap.put("transfer_amount", transferAmount); postMap.put("transfer_scene_id", "1010"); // 转账备注 postMap.put("transfer_remark", "二手回收提现确认收款"); // 回调地址 postMap.put("notify_url", "https://hyhsbqgc.com/api/ruoyi-order/wx/wxChatPay"); // 转账场景报备信息 List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> subMap = new HashMap<>(4); subMap.put(WechatConstants.OUT_DETAIL_NO, String.valueOf(SNOW_FLAKE_ID_WORKER.nextId())); subMap.put(WechatConstants.TRANSFER_AMOUNT, transferAmount); subMap.put(WechatConstants.TRANSFER_REMARK, "二手回收提现到账"); subMap.put(WechatConstants.OPEN_ID, openId); list.add(subMap); postMap.put(WechatConstants.TRANSFER_DETAIL_LIST, list); // 使用类加载器获取资源 URL // String path = ClassLoader.getSystemResource("/usr/local/vx/apiclient_key.pem").getPath(); // String result = HttpUtil.postTransBatRequest( // WechatConstants.WE_CHAT_URL_PRE, // JSONObject.toJSONString(postMap), // "7EEA04429B006E12AAA421C002EC48BBEED5BE94", // "1665330417", // "/usr/local/vx/apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); Map<String, Object> info = new HashMap<>(); info.put("info_type","回收商品名称"); info.put("info_content",serverName); list.add(info); postMap.put("transfer_scene_report_infos", list); String result = HttpUtil.postTransBatRequest( WechatConstants.WE_CHAT_URL_PRE, WechatConstants.WE_CHAT_PAY_URL_PRE, JSONObject.toJSONString(postMap), "7EEA04429B006E12AAA421C002EC48BBEED5BE94", "1665330417", "/usr/local/vx/apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); "/usr/local/vx/apiclient_key.pem", "/v3/fund-app/mch-transfer/transfer-bills"); JSONObject jsonObject = JSONObject.parseObject(result); WithdrawDetail withdrawDetail = new WithdrawDetail(); withdrawDetail.setWithdrawId(withdrawId); withdrawDetail.setMoney(transferAmount); withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); withdrawDetailService.save(withdrawDetail); // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); System.err.println(jsonObject); // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); if (jsonObject.containsKey(WechatConstants.CREATE_TIME)) { String string = jsonObject.getString("package_info"); Withdraw withdraw = this.getById(withdrawId); Order order = orderService.getById(withdraw.getOrderId()); order.setIsWithdrawal(2); order.setPackageInfo(string); orderService.updateById(order); // 转账成功 //保存转账明细 // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); WithdrawDetail withdrawDetail = new WithdrawDetail(); withdrawDetail.setWithdrawId(withdrawId); withdrawDetail.setMoney(transferAmount); withdrawDetail.setOutBatchNo(postMap.get("out_bill_no")+""); withdrawDetailService.save(withdrawDetail); } else { @@ -352,34 +434,6 @@ return allTransfersSuccessful; } public static void main(String[] args) { Map<String, Object> postMap = new HashMap<>(8); postMap.put(WechatConstants.APP_ID, "wx98563d0ec9cf21c8"); postMap.put(WechatConstants.OUT_BATCH_NO, String.valueOf(UUID.randomUUID()).replaceAll("-", "")); System.err.println("====="+postMap.get(WechatConstants.OUT_BATCH_NO)); postMap.put(WechatConstants.BATCH_NAME, "二手回收提现"); postMap.put(WechatConstants.BATCH_REMARK, "二手回收提现"); postMap.put(WechatConstants.TOTAL_AMOUNT, 1); postMap.put(WechatConstants.TOTAL_NUM, Constants.ONE); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> subMap = new HashMap<>(4); subMap.put(WechatConstants.OUT_DETAIL_NO, String.valueOf(SNOW_FLAKE_ID_WORKER.nextId())); subMap.put(WechatConstants.TRANSFER_AMOUNT, 1); subMap.put(WechatConstants.TRANSFER_REMARK, "二手回收提现到账"); subMap.put(WechatConstants.OPEN_ID, "ouqOk6-Bp6PnNnlHoQSV-6lzoVoU"); list.add(subMap); postMap.put(WechatConstants.TRANSFER_DETAIL_LIST, list); String result = HttpUtil.postTransBatRequest( WechatConstants.WE_CHAT_URL_PRE, JSONObject.toJSONString(postMap), "7EEA04429B006E12AAA421C002EC48BBEED5BE94", "1665330417", "E:\\ershoucert\\apiclient_key.pem", WechatConstants.WE_CHAT_URL_SUF); JSONObject jsonObject = JSONObject.parseObject(result); System.err.println(jsonObject); } /** * 根据当前月份获取当前季度的开始月份 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/task/TaskUtil.java
@@ -22,40 +22,40 @@ private WithdrawDetailService withdrawDetailService; /** * 每隔一分钟去处理的定时任务 */ @Scheduled(fixedRate = 10000 * 60) public void taskMinute(){ try { List<WithdrawDetail> list = withdrawDetailService.lambdaQuery().ne(WithdrawDetail::getStatus, "SUCCESS").ne(WithdrawDetail::getStatus, "FAIL").list(); for (WithdrawDetail withdrawDetail : list) { String s = GetTransferBatchByOutNo.checkStatus(withdrawDetail.getOutBatchNo()); if (s.equals("SUCCESS")) { withdrawDetail.setStatus("SUCCESS"); withdrawDetailService.updateById(withdrawDetail); //执行订单提现成功,增加提现成功金额 //查询订单 //增加已提现金额 } else if (s.equals("FAIL")) { withdrawDetail.setStatus("FAIL"); withdrawDetailService.updateById(withdrawDetail); }else { withdrawDetail.setStatus(s); withdrawDetailService.updateById(withdrawDetail); } } } catch (Exception e) { e.printStackTrace(); } } // /** // * 每隔一分钟去处理的定时任务 // */ // @Scheduled(fixedRate = 10000 * 60) // public void taskMinute(){ // try { // // List<WithdrawDetail> list = withdrawDetailService.lambdaQuery().ne(WithdrawDetail::getStatus, "SUCCESS").ne(WithdrawDetail::getStatus, "FAIL").list(); // // for (WithdrawDetail withdrawDetail : list) { // String s = GetTransferBatchByOutNo.checkStatus(withdrawDetail.getOutBatchNo()); // if (s.equals("SUCCESS")) { // withdrawDetail.setStatus("SUCCESS"); // withdrawDetailService.updateById(withdrawDetail); // //执行订单提现成功,增加提现成功金额 // //查询订单 // // //增加已提现金额 // // // } else if (s.equals("FAIL")) { // withdrawDetail.setStatus("FAIL"); // withdrawDetailService.updateById(withdrawDetail); // }else { // withdrawDetail.setStatus(s); // withdrawDetailService.updateById(withdrawDetail); // } // // } // // } catch (Exception e) { // e.printStackTrace(); // } // } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/WithdrawDetailVO.java
@@ -17,7 +17,8 @@ @ApiModelProperty("订单id") private String orderId; @ApiModelProperty("拉起确认收款参数") private String packageInfo; @ApiModelProperty("订单编号") private String orderNumber; ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vx/QuickStart.java
New file @@ -0,0 +1,45 @@ package com.ruoyi.order.vx; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.service.payments.nativepay.NativePayService; import com.wechat.pay.java.service.payments.nativepay.model.Amount; import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest; import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; /** Native 支付下单为例 */ public class QuickStart { /** 商户号 */ public static String merchantId = "190000****"; /** 商户API私钥路径 */ public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem"; /** 商户证书序列号 */ public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********"; /** 商户APIV3密钥 */ public static String apiV3key = "..."; public static void main(String[] args) { // 使用自动更新平台证书的RSA配置 // 建议将 config 作为单例或全局静态对象,避免重复的下载浪费系统资源 Config config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .apiV3Key(apiV3key) .build(); // 构建service NativePayService service = new NativePayService.Builder().config(config).build(); // request.setXxx(val)设置所需参数,具体参数可见Request定义 PrepayRequest request = new PrepayRequest(); Amount amount = new Amount(); amount.setTotal(100); request.setAmount(amount); request.setAppid("wxa9d9651ae******"); request.setMchid("190000****"); request.setDescription("测试商品标题"); request.setNotifyUrl("https://notify_url"); request.setOutTradeNo("out_trade_no_001"); // 调用下单方法,得到应答 PrepayResponse response = service.prepay(request); // 使用微信扫描 code_url 对应的二维码,即可体验Native支付 System.out.println(response.getCodeUrl()); } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vx/TestWxPay.java
New file @@ -0,0 +1,83 @@ package com.ruoyi.order.vx; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.core.constant.WechatConstants; import com.ruoyi.common.core.utils.StringUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; public class TestWxPay { public static void main(String[] args) { weChatPay(BigDecimal.valueOf(0.1), "ouqOk6xtWA3JDmpd9HpZf9ijESIs", "1", "空调挂机"); } private static boolean weChatPay(BigDecimal orderMoney, String openId, String withdrawId, String serverName) { if (StringUtils.isBlank(openId)) { return false; } BigDecimal maxTransferAmount = new BigDecimal("200000"); // 单次转账限额,单位为分 int totalTransfers = orderMoney.multiply(new BigDecimal("100")).divide(maxTransferAmount, 0, RoundingMode.UP).intValue(); boolean allTransfersSuccessful = true; for (int i = 0; i < totalTransfers; i++) { BigDecimal transferAmount; if (i < totalTransfers - 1) { transferAmount = maxTransferAmount; } else { // 最后一笔转账,金额为剩余金额 transferAmount = orderMoney.multiply(new BigDecimal("100")).subtract(maxTransferAmount.multiply(new BigDecimal(i))).setScale(0, RoundingMode.DOWN); } Map<String, Object> postMap = new HashMap<>(8); postMap.put(WechatConstants.APP_ID, "wx98563d0ec9cf21c8"); // 订单号 postMap.put("out_bill_no", String.valueOf(UUID.randomUUID()).replaceAll("-", "")); System.err.println("====="+postMap.get("out_bill_no")); postMap.put(WechatConstants.OPEN_ID, openId); // 转账金额 postMap.put("transfer_amount", transferAmount); postMap.put("transfer_scene_id", "1010"); // 转账备注 postMap.put("transfer_remark", "二手回收提现确认收款"); // 回调地址 postMap.put("notify_url", "https://hyhsbqgc.com/api/ruoyi-order/wx/wxChatPay"); // 转账场景报备信息 List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> info = new HashMap<>(); info.put("info_type","回收商品名称"); info.put("info_content",serverName); list.add(info); postMap.put("transfer_scene_report_infos", list); String result = HttpUtil.postTransBatRequest( WechatConstants.WE_CHAT_PAY_URL_PRE, JSONObject.toJSONString(postMap), "7EEA04429B006E12AAA421C002EC48BBEED5BE94", "1665330417", "/usr/local/vx/apiclient_key.pem", "/v3/fund-app/mch-transfer/transfer-bills"); JSONObject jsonObject = JSONObject.parseObject(result); // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); System.err.println(jsonObject); if (jsonObject.containsKey(WechatConstants.CREATE_TIME)) { // 转账成功 //保存转账明细 // WithdrawDetail withdrawDetail = new WithdrawDetail(); // withdrawDetail.setWithdrawId(withdrawId); // withdrawDetail.setMoney(transferAmount); // withdrawDetail.setOutBatchNo((String) postMap.get(WechatConstants.OUT_BATCH_NO)); // withdrawDetailService.save(withdrawDetail); } else { allTransfersSuccessful = false; break; } } return allTransfersSuccessful; } } ruoyi-service/ruoyi-order/src/main/resources/mybatis-config.xml
@@ -5,7 +5,7 @@ <settings> <!-- 打印查询语句 不会写入到日志文件中--> <setting name="logImpl" value="STDOUT_LOGGING"/> <!--<setting name="logImpl" value="LOG4J" />--> <!-- <setting name="logImpl" value="LOG4J" />--> <!-- 控制全局缓存(二级缓存),按美团技术团队的说法,尽量别用缓存机制 emmmm.... --> <setting name="cacheEnabled" value="true"/> <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false --> ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/controller/RecoveryServeController.java
@@ -161,7 +161,9 @@ UserRecipient userRecipient = userRecipientService.lambdaQuery() .eq(UserRecipient::getIsDefault, Constants.ONE) .eq(UserRecipient::getUserId, loginUser.getUserid()) .eq(UserRecipient::getIsDelete, Constants.ZERO).one(); .eq(UserRecipient::getIsDelete, Constants.ZERO) .last("limit 1") .one(); return R.ok(new ServeDetailVO(recoveryServe, userRecipient)); } ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/service/impl/WithdrawServiceImpl.java
@@ -82,6 +82,7 @@ withdrawOrder.setCompleteTime(order.getCreateTime()); withdrawOrder.setIsWithdrawal(order.getIsWithdrawal()); withdrawOrder.setMoney(order.getOrderMoney()); withdrawOrder.setPackageInfo(order.getPackageInfo()); if (order.getAddress()!=null) { withdrawOrder.setAddress(order.getReservationAddress() + order.getAddress()); }else { ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vo/WithdrawOrderVO.java
@@ -44,5 +44,7 @@ @ApiModelProperty("订单金额") private BigDecimal money; @ApiModelProperty("拉起确认收款页面参数") private String packageInfo; }