KKSU
2025-02-10 0d7a106782e966984a092746ef6f2e9e049a2c21
feat(mall): 完善会员信息并集成 FIUU 支付

- 在 ModifyMemberInfoDto 和 MallMemberVo 中添加真实姓名和邮箱字段
- 更新 ApiMallMemberServiceImpl 中的会员信息修改逻辑
- 在 FIUUController 中添加会员信息验证逻辑,并使用会员信息进行支付请求
- 新增 FiuuReturnController 中的支付回调处理逻辑
5 files modified
85 ■■■■■ changed files
src/main/java/cc/mrbird/febs/mall/dto/ModifyMemberInfoDto.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/controller/FIUUController.java 16 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/controller/FiuuReturnController.java 56 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ModifyMemberInfoDto.java
@@ -1,10 +1,8 @@
package cc.mrbird.febs.mall.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
 * @author wzy
@@ -25,4 +23,10 @@
    @ApiModelProperty(value = "生日", example = "123")
    private String birthday;
    @ApiModelProperty(value = "真实姓名")
    private String realName;
    @ApiModelProperty(value = "邮箱")
    private String mailAddress;
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -365,6 +365,8 @@
        mallMember.setSex(modifyMemberInfoDto.getSex());
        mallMember.setBirthday(DateUtil.parseDate(modifyMemberInfoDto.getBirthday()));
        mallMember.setRealName(modifyMemberInfoDto.getRealName());
        mallMember.setEmail(modifyMemberInfoDto.getMailAddress());
        this.baseMapper.updateById(mallMember);
        return new FebsResponse().success().message("修改成功");
src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java
@@ -26,6 +26,9 @@
    @ApiModelProperty(value = "邮箱")
    private String email;
    @ApiModelProperty(value = "真实姓名")
    private String realName;
    @ApiModelProperty(value = "性别")
    private String sex;
src/main/java/cc/mrbird/febs/pay/controller/FIUUController.java
@@ -4,8 +4,10 @@
import cc.mrbird.febs.common.enumerates.OrderDeliveryStateEnum;
import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.common.utils.ValidateEntityUtils;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.entity.MallOrderItem;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cc.mrbird.febs.pay.model.FIUUInitPayRequest;
import cn.hutool.core.date.DateUtil;
@@ -34,12 +36,20 @@
    @Resource
    private MallOrderInfoMapper mallOrderInfoMapper;
    @Resource
    private MallMemberMapper mallMemberMapper;
    @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(), "订单已支付");
        MallMember mallMember = ValidateEntityUtils.ensureColumnReturnEntity(mallOrderInfo.getMemberId(), MallMember::getId, mallMemberMapper::selectOne, "用户不存在");
        ValidateEntityUtils.ensureNotEqual(mallMember.getRealName(), null, "请完善个人信息");
        ValidateEntityUtils.ensureNotEqual(mallMember.getEmail(), null, "请完善个人信息");
        ValidateEntityUtils.ensureNotEqual(mallMember.getPhone(), null, "请完善个人信息");
        String amount = mallOrderInfo.getAmount().toString();
        String productNames = getProductNames(mallOrderInfo.getMemberId(), mallOrderInfo.getId());
        try {
@@ -60,9 +70,9 @@
            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_name", mallMember.getRealName());
            params.put("bill_email", mallMember.getEmail());
            params.put("bill_mobile", mallMember.getPhone());
            params.put("bill_desc", productNames);
            params.put("currency", "MYR"); // 默认 MYR
            params.put("vcode", vcode);
src/main/java/cc/mrbird/febs/pay/controller/FiuuReturnController.java
@@ -7,6 +7,8 @@
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
@@ -88,6 +90,60 @@
        return "payment-success";
    }
    public static void main(String[] args) {
        String secretKey = "59c709fc18978a6a83b87f05d37cecbf";
        String ss = "{\"nbcb\":\"2\",\"tranID\":\"2693805878\",\"amount\":\"1.00\",\"orderid\":\"359\",\"channel\":\"alipay\",\"paydate\":\"2025-02-10 10:24:20\",\"error_desc\":\"\",\"domain\":\"e2umart01\",\"skey\":\"29913d009b74cb8bc3650aed84394cfe\",\"error_code\":\"\",\"currency\":\"RM\",\"appcode\":\"2025021022001302841422314686\",\"status\":\"00\"}";
        JSONObject params = JSONUtil.parseObj(ss);
        // 按API文档生成skey
        String tranID = params.getStr("tranID");
        String orderId = params.getStr("orderid");
        String status = params.getStr("status");
        String domain = params.getStr("domain");
        String amount = params.getStr("amount");
        String currency = params.getStr("currency");
        String appcode = params.getStr("appcode");
        String paydate = params.getStr("paydate");
        String receivedSkey = params.getStr("skey");
        // 第一步哈希:pre_skey = md5(txnID + orderID + status + domain + amount + currency)
        String preSkey = DigestUtils.md5Hex(tranID + orderId + status + domain + amount + currency);
        log.info("notify preSkey: {}", preSkey);
        // 第二步哈希:skey = md5(paydate + domain + pre_skey + appcode + secretKey)
        String calculatedSkey = DigestUtils.md5Hex(paydate + domain + preSkey + appcode + secretKey);
        log.info("notify calculatedSkey: {}", calculatedSkey);
        // 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 preSkey1 = DigestUtils.md5Hex(preSkeyInput);
        log.info("callback preSkey生成参数: {}", preSkeyInput);
        log.info("callback preSkey计算结果: {}", preSkey1);
        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 + secretKey;
        String calculatedSkey1 = DigestUtils.md5Hex(skeyInput);
        log.info("callback skey生成参数: {}", skeyInput);
        log.info("callback callback status: {}", status);
        log.info("callback receivedSkey: {}", receivedSkey);
        log.info("callback calculatedSkey: {}", calculatedSkey1);
    }
    private void updateOrderStatus(String orderId, String status, String amount, String paydate, String tranID) {
        // 实现订单状态更新逻辑(如更新数据库)
        MallOrderInfo mallOrderInfo = ValidateEntityUtils.ensureColumnReturnEntity(orderId, MallOrderInfo::getId, mallOrderInfoMapper::selectOne, "订单不存在");