无关风月
2025-04-09 cda724da35beb1ffd84955cc42bda5ab399ebbe1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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;
    }
 
}