KKSU
2025-02-05 5020fb3688151906fda0c03b96d9490624716dd8
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
package cc.mrbird.febs.pay.controller;
 
import cc.mrbird.febs.common.entity.FebsResponse;
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.entity.MallOrderItem;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cc.mrbird.febs.pay.model.FIUUInitPayRequest;
import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Slf4j
@RestController
@Api(value = "FIUUController", tags = "FIUU支付")
@RequestMapping(value = "/api/fuPay")
public class FIUUController {
 
    @Resource
    private MallOrderInfoMapper mallOrderInfoMapper;
    @ApiOperation(value = "初始化FIUU支付信息", notes = "初始化FIUU支付信息")
    @PostMapping("/initPayment")
    public FebsResponse initPayment(@RequestBody FIUUInitPayRequest orderRequest) {
        Long orderId = orderRequest.getOrderId();
        MallOrderInfo mallOrderInfo = ValidateEntityUtils.ensureColumnReturnEntity(orderId, MallOrderInfo::getId, mallOrderInfoMapper::selectOne, "订单不存在");
        ValidateEntityUtils.ensureNotEqual("1", mallOrderInfo.getPayResult(), "订单已支付");
        String amount = mallOrderInfo.getAmount().toString();
        String productNames = getProductNames(mallOrderInfo.getMemberId(), mallOrderInfo.getId());
        try {
            String merchantId = "e2umart01";
            String verifyKey = "4e3a4ed58e62ddbfacf41f6d5ec56bf2";
            String returnUrl = "https://api.mye2u.com/api/fuPay/callback"; // 支付结果回调地址
 
            // 生成 vcode(MD5(amount + merchantId + orderId + verifyKey))
            String vcode = DigestUtils.md5Hex(
                    amount +
                            merchantId +
                            orderRequest.getOrderId() +
                            verifyKey
            );
 
            // 返回支付参数
            Map<String, String> params = new HashMap<>();
            params.put("merchant_id", merchantId);
            params.put("orderid", String.valueOf(orderId));
            params.put("amount", amount);
            params.put("bill_name", orderRequest.getBuyerName());
            params.put("bill_email", orderRequest.getBuyerEmail());
            params.put("bill_mobile", orderRequest.getBuyerMobile());
            params.put("bill_desc", productNames);
            params.put("currency", "MYR"); // 默认 MYR
            params.put("vcode", vcode);
            params.put("returnurl", returnUrl);
 
            return new FebsResponse().success().data(params);
        } catch (Exception e) {
            return new FebsResponse().fail().message("支付参数校验失败");
        }
    }
 
    // Java 回调接口
    @PostMapping("/callback")
    public FebsResponse handlePaymentCallback(@RequestParam Map<String, String> params) {
        try {
            String secretKey = "59c709fc18978a6a83b87f05d37cecbf";
            String tranID = params.get("tranID");
            String orderId = params.get("orderid");
            String status = params.get("status");
            String domain = params.get("domain");
            String amount = params.get("amount");
            String currency = params.get("currency");
            String paydate = params.get("paydate");
            String skey = params.get("skey");
 
            // 计算 skey 验证
            String preSkey = DigestUtils.md5Hex(tranID + orderId + status + domain + amount + currency);
            String calculatedSkey = DigestUtils.md5Hex(paydate + domain + preSkey + secretKey);
 
            if (!calculatedSkey.equals(skey)) {
                throw new FebsException("订单回调失败,---"+orderId);
            }
 
            MallOrderInfo mallOrderInfo = ValidateEntityUtils.ensureColumnReturnEntity(orderId, MallOrderInfo::getId, mallOrderInfoMapper::selectOne, "订单不存在");
            ValidateEntityUtils.ensureEqual(mallOrderInfo.getPayResult(), "1", "订单已支付");
            ValidateEntityUtils.ensureEqual(mallOrderInfo.getAmount().toString(), amount, "订单金额异常");
            // 更新订单状态
            if ("00".equals(status)) {
                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);
            }
            return new FebsResponse().success().message("OK");
        } catch (Exception e) {
            return new FebsResponse().fail().message("Internal Error");
        }
    }
 
    /**
     * 根据用户ID和订单ID获取所购买商品名称
     * @return 所含商品名称(多个以","隔开)
     */
    public String getProductNames(Long memberId, Long orderId) {
        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderByMemberIdAndId(memberId, orderId);
        List<MallOrderItem> details = mallOrderInfo.getItems();
        if (CollectionUtils.isEmpty(details)) {
            return "";
        }
        StringBuffer productNameBuffer = new StringBuffer();
        Integer maxLength = 30;
        for (int i = 0; i< details.size(); i++) {
            MallOrderItem mallOrderItem = details.get(i);
            String goodsName = mallOrderItem.getGoodsName();
            if (goodsName == null) {
                continue;
            }
            if (i == 0 && goodsName.length() > maxLength) {
                productNameBuffer.append(goodsName.substring(0, maxLength) + "...");
                break;
            }
            if ((productNameBuffer.length() + goodsName.length()) > maxLength) {
                productNameBuffer.append("等");
                break;
            }
            productNameBuffer.append(goodsName + ",");
        }
        String productNames = productNameBuffer.toString();
        if (productNames.endsWith(",")) {
            productNames = productNames.substring(0, productNames.length() - 1);
        }
        if (productNames.endsWith(",等")) {
            productNames = productNames.substring(0, productNames.length() - 2) + "等";
        }
        return productNames;
    }
}