New file |
| | |
| | | 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 state = jsonInfo.getString("state"); |
| | | WithdrawDetail withdrawDetail = withdrawDetailService.lambdaQuery().eq(WithdrawDetail::getOutBatchNo, transferBillNo).one(); |
| | | Withdraw withdraw = withdrawService.getById(withdrawDetail.getWithdrawId()); |
| | | Order order = orderService.getById(withdraw.getOrderId()); |
| | | UserDto data = userClient.getUser(order.getUserId()).getData(); |
| | | if ("SUCCESS".equals(state)){ |
| | | order.setIsWithdrawal(1); |
| | | 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(WechatConstants.OUT_BATCH_NO)); |
| | | postMap.put(WechatConstants.OPEN_ID, openId); |
| | | // 转账金额 |
| | | postMap.put("transfer_amount", transferAmount); |
| | | // 转账备注 |
| | | postMap.put("transfer_remark", transferAmount); |
| | | // 回调地址 |
| | | postMap.put("notify_url", transferAmount); |
| | | // 转账场景报备信息 |
| | | 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", |
| | | "E:\\ershoucert\\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(0); |
| | | orderService.updateById(order); |
| | | } |
| | | } else { |
| | | allTransfersSuccessful = false; |
| | | break; |
| | | } |
| | | |
| | | } |
| | | |
| | | return allTransfersSuccessful; |
| | | } |
| | | |
| | | } |