KKSU
2025-02-10 566124b07d1ced752942a48f5c422906a6428696
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
package cc.mrbird.febs.pay.controller;
 
import cc.mrbird.febs.common.enumerates.OrderDeliveryStateEnum;
import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.ValidateEntityUtils;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
 
@Slf4j
@Controller
//@RestController
@Api(value = "FiuuReturnController", tags = "FIUU支付-ReturnURL")
@RequestMapping(value = "/api/fuPayReturn")
public class FiuuReturnController {
 
    private static final String SECRET_KEY = "59c709fc18978a6a83b87f05d37cecbf";
    @Resource
    private MallOrderInfoMapper mallOrderInfoMapper;
 
    @PostMapping("/payment/callback")
    public String handlePaymentCallback(
            @RequestParam("amount") String amount,
            @RequestParam("orderid") String orderId,
            @RequestParam("tranID") String tranId,
            @RequestParam("status") String status,
            @RequestParam("domain") String domain,
            @RequestParam("currency") String currency,
            @RequestParam("appcode") String appcode,
            @RequestParam("paydate") String payDate,
            @RequestParam("skey") String receivedSkey,
            Model model)  {
 
        // 1. 格式化amount为两位小数(确保与Fiuu传递的格式一致)
        BigDecimal amountDecimal;
        try {
            amountDecimal = new BigDecimal(amount).setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            throw new FebsException("金额格式错误: " + amount);
        }
        String formattedAmount = amountDecimal.toPlainString(); // 例如 "100.00"
 
        // 2. 生成preSkey(严格按照参数顺序拼接)
        log.info("callback Parameters for preSkey: tranId={}, orderId={}, status={}, domain={}, amount={}, currency={}", tranId, orderId, status, domain, amount, currency);
        // 第一步哈希:pre_skey = md5(txnID + orderID + status + domain + amount + currency)
        String preSkeyInput = tranId + orderId + status + domain + formattedAmount + currency;
        String preSkey = DigestUtils.md5Hex(preSkeyInput);
        log.info("callback preSkey生成参数: {}", preSkeyInput);
        log.info("callback preSkey计算结果: {}", preSkey);
        log.info("callback Parameters for calculatedSkey: payDate={}, domain={}, preSkey={}, appcode={}, SECRET_KEY={}", payDate, domain, preSkey, appcode, SECRET_KEY);
        // 第二步哈希:skey = md5(paydate + domain + pre_skey + appcode + secret_key)
        String skeyInput = payDate + domain + preSkey + appcode + SECRET_KEY;
        String calculatedSkey = DigestUtils.md5Hex(skeyInput);
 
        log.info("callback skey生成参数: {}", skeyInput);
        log.info("callback callback status: {}", status);
        log.info("callback receivedSkey: {}", receivedSkey);
        log.info("callback calculatedSkey: {}", calculatedSkey);
 
        if (!calculatedSkey.equalsIgnoreCase(receivedSkey)) {
            // 记录安全警告日志
            throw new FebsException("订单回调失败,---" + orderId);
        }
 
        // 将支付结果信息传递给支付成功页面
        model.addAttribute("amount", amount);
        model.addAttribute("orderId", orderId);
        model.addAttribute("tranId", tranId);
        model.addAttribute("status", status);
        model.addAttribute("currency", currency);
        model.addAttribute("payDate", payDate);
        updateOrderStatus(orderId, status, amount, payDate, tranId);
 
        // 跳转到支付成功页面
        return "payment-success";
    }
 
    private void updateOrderStatus(String orderId, String status, String amount, String paydate, String tranID) {
        // 实现订单状态更新逻辑(如更新数据库)
        MallOrderInfo mallOrderInfo = ValidateEntityUtils.ensureColumnReturnEntity(orderId, MallOrderInfo::getId, mallOrderInfoMapper::selectOne, "订单不存在");
        ValidateEntityUtils.ensureNotEqual(mallOrderInfo.getPayResult(), "1", "订单已支付");
        ValidateEntityUtils.ensureEqual(mallOrderInfo.getAmount().toString(), amount, "订单金额异常");
        // 更新订单状态
        mallOrderInfo.setPayMethod("FIUU支付");
        mallOrderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue());
        mallOrderInfo.setPayResult("1");
        mallOrderInfo.setPayTime(DateUtil.parseDateTime(paydate));
        mallOrderInfo.setDeliveryState(OrderDeliveryStateEnum.DELIVERY_WAIT.getValue());
        mallOrderInfo.setPayOrderNo(tranID);
        mallOrderInfoMapper.updateById(mallOrderInfo);
    }
}