src/main/java/com/mzl/flower/component/SequenceNo.java
@@ -22,6 +22,9 @@ public static final String ORDER_SETTLEMENT = "order_settlement";//结算单 public static final String ORDER_PRODUCT = "order_product";//订单 public String getSeqNo(String code){ try{ List<Object> parameterList = new ArrayList<>(); src/main/java/com/mzl/flower/config/PyamentV3Configurer.java
@@ -21,7 +21,7 @@ /** 商户API私钥路径 */ //public static String privateKeyPath = "/opt/pay/wx/v3/apiclient_key.pem"; public static String privateKeyPath = "E://huamanyuan/apiclient_key.pem"; public static String privateKeyPath = "D://apiclient_key.pem"; /** 商户证书序列号 */ public static String merchantSerialNumber = "37A08A552943EF34883614DBC8DE281598148757"; src/main/java/com/mzl/flower/dto/request/productOrders/ProductOrdersCreateDTO.java
对比新文件 @@ -0,0 +1,52 @@ package com.mzl.flower.dto.request.productOrders; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; @Data @NoArgsConstructor @AllArgsConstructor public class ProductOrdersCreateDTO { /** * 订单名称 */ @ApiModelProperty(value = "订单名称") @NotEmpty(message = "订单名称不能为空") private String orderName; /** * 订单类型(连续包月、年卡等) */ @ApiModelProperty(value = "订单类型") @NotEmpty(message = "订单类型不能为空") private String orderType; /** * 原价 */ @ApiModelProperty(value = "原价") @NotNull(message = "原价不能为空") private BigDecimal originalPrice; /** * 现价_订单金额 */ @ApiModelProperty(value = "现价") @NotNull(message = "现价不能为空") private BigDecimal currentPrice; /** * 支付方式(支付宝alipay、微信wechat等) */ // @ApiModelProperty(value = "支付方式") // @NotEmpty(message = "支付方式不能为空") // private String paymentMethod; } src/main/java/com/mzl/flower/entity/customer/Customer.java
@@ -6,6 +6,8 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; @Data @TableName("t_customer_info") @@ -45,4 +47,9 @@ private Boolean isEnabled; @ApiModelProperty("等级id") private Long levelId; @ApiModelProperty("会员到期时间") private LocalDateTime memberOvertime; @ApiModelProperty("是否会员") private Boolean isMember; } src/main/java/com/mzl/flower/entity/productOrders/ProductOrdersDO.java
对比新文件 @@ -0,0 +1,69 @@ package com.mzl.flower.entity.productOrders; import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.TableName; import java.time.LocalDateTime; import com.mzl.flower.base.BaseEntity; import com.mzl.flower.base.BaseNoIdEntity; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * @author generator@TaoJie * @since 2025-03-31 */ @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) @TableName("t_product_orders") public class ProductOrdersDO extends BaseEntity { /** * 用户id */ private String userId; /** * 订单编号(唯一编号) */ private String orderNo; /** * 订单名称 */ private String orderName; /** * 订单类型(连续包月、年卡等) */ private String orderType; /** * 原价 */ private BigDecimal originalPrice; /** * 现价_订单金额 */ private BigDecimal currentPrice; /** * 支付方式(支付宝alipay、微信wechat等) */ private String paymentMethod; /** * 订单状态(待支付paying、已支付paid 、取消cancel等) */ private String paymentStatus; /** * 支付时间 */ private LocalDateTime paymentTime; } src/main/java/com/mzl/flower/enums/PayStatusEnum.java
对比新文件 @@ -0,0 +1,23 @@ package com.mzl.flower.enums; import lombok.Getter; public enum PayStatusEnum { PAYING("PAYING","待支付"), PAID("PAID","已支付"), CANCEL("CANCEL","取消"), FINISHED("FINISHED","完成"), ; @Getter private String name; private String desc; private PayStatusEnum(String name, String desc){ this.name=name; this.desc=desc; } } src/main/java/com/mzl/flower/enums/PayTypeEnum.java
对比新文件 @@ -0,0 +1,21 @@ package com.mzl.flower.enums; import lombok.Getter; public enum PayTypeEnum { ALIPAY("alipay","支付宝"), WECHAT("wechat","微信"), ; @Getter private String name; private String desc; private PayTypeEnum(String name, String desc){ this.name=name; this.desc=desc; } } src/main/java/com/mzl/flower/enums/ProductTypeEnum.java
对比新文件 @@ -0,0 +1,22 @@ package com.mzl.flower.enums; import lombok.Getter; public enum ProductTypeEnum { MONTH_CONTINUED("连续包月","连续包月"), YEAR("年卡","年卡"), MONTH("月卡","月卡") ; @Getter private String name; private String desc; private ProductTypeEnum(String name, String desc){ this.name=name; this.desc=desc; } } src/main/java/com/mzl/flower/enums/alipay/AlipayResultEnum.java
对比新文件 @@ -0,0 +1,23 @@ package com.mzl.flower.enums.alipay; import lombok.Getter; public enum AlipayResultEnum { WAIT_BUYER_PAY("WAIT_BUYER_PAY","交易创建,等待买家付款。"), TRADE_CLOSED("TRADE_CLOSED","未付款交易超时关闭,或支付完成后全额退款。"), TRADE_SUCCESS("TRADE_SUCCESS","交易支付成功。"), TRADE_FINISHED("TRADE_FINISHED","交易结束,不可退款。"), ; @Getter private String name; private String desc; private AlipayResultEnum(String name, String desc){ this.name=name; this.desc=desc; } } src/main/java/com/mzl/flower/mapper/productOrders/ProductOrdersMapper.java
对比新文件 @@ -0,0 +1,16 @@ package com.mzl.flower.mapper.productOrders; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * <p> * Mapper 接口 * </p> * * @author generator@TaoJie * @since 2025-03-31 */ public interface ProductOrdersMapper extends BaseMapper<ProductOrdersDO> { } src/main/java/com/mzl/flower/service/customer/CustomerService.java
@@ -26,6 +26,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import javax.annotation.Resource; @@ -264,4 +265,15 @@ customerByPhone.setContactTel(phone); return customerByPhone; } public Customer getByUserId(String userId) { List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().eq(Customer::getUserId, userId).eq(Customer::getDeleted, TrueOrFalseEnum.FALSE.isFlag())); if(!CollectionUtils.isEmpty(customers)){ return customers.get(0); } return null; } public void updateMemberInfo(Customer customer) { customerMapper.updateById(customer); } } src/main/java/com/mzl/flower/service/impl/productOrders/ProductOrdersServiceImpl.java
对比新文件 @@ -0,0 +1,170 @@ package com.mzl.flower.service.impl.productOrders; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.mzl.flower.component.SequenceNo; import com.mzl.flower.config.security.SecurityUtils; import com.mzl.flower.dto.request.productOrders.ProductOrdersCreateDTO; import com.mzl.flower.entity.customer.Customer; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.mzl.flower.enums.PayStatusEnum; import com.mzl.flower.enums.ProductTypeEnum; import com.mzl.flower.enums.alipay.AlipayResultEnum; import com.mzl.flower.mapper.productOrders.ProductOrdersMapper; import com.mzl.flower.service.customer.CustomerService; import com.mzl.flower.service.productOrders.ProductOrdersService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mzl.flower.utils.DateUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.util.List; import java.util.Map; /** * <p> * 服务实现类 * </p> * * @author generator@TaoJie * @since 2025-03-31 */ @Service public class ProductOrdersServiceImpl extends ServiceImpl<ProductOrdersMapper, ProductOrdersDO> implements ProductOrdersService { @Autowired private ProductOrdersMapper productOrdersMapper; @Autowired private SequenceNo sequenceNo; @Autowired private CustomerService customerService; @Transactional @Override public ProductOrdersDO createProductOrders(ProductOrdersDO productOrdersDO) { String userId = SecurityUtils.getUserId(); // ProductOrdersDO productOrdersDO = new ProductOrdersDO(); productOrdersDO.setId(IdUtil.simpleUUID()); productOrdersDO.setUserId(userId); // 待支付 productOrdersDO.setPaymentStatus(PayStatusEnum.PAYING.getName()); productOrdersDO.setOrderNo(getSalesNo()); productOrdersDO.create(userId); int insert = productOrdersMapper.insert(productOrdersDO); return productOrdersMapper.selectById(productOrdersDO.getId()); } @Transactional @Override public Boolean updateProductOrderStatus(Map<String, String> params) { String orderNo = params.get("out_trade_no"); // 本系统对应的订单好 String tradeNo = params.get("trade_no"); //支付宝交易号。支付宝交易凭证号。 String tradeStatus = params.get("trade_status"); //交易状态。咨询目前所处的状态。 String gmtPayment = params.get("gmt_payment"); // 交易 付款时间。该笔交易的买家付款时间。格式为 yyyy-MM-dd HH:mm:ss。 String gmtRefund = params.get("gmt_refund"); // 交易退款时间。该笔交易的退款时间。格式 为 yyyy-MM-dd HH:mm:ss.SS。 String gmtClose = params.get("gmt_close"); // 交易退款时间。该笔交易的退款时间。格式 为 yyyy-MM-dd HH:mm:ss.SS。 // 根据orderNo 查找订单 QueryWrapper<ProductOrdersDO> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(ProductOrdersDO::getDeleted, false) .eq(ProductOrdersDO::getOrderNo, orderNo); List<ProductOrdersDO> productOrdersDOS = productOrdersMapper.selectList(queryWrapper); if(!CollectionUtils.isEmpty(productOrdersDOS)){ ProductOrdersDO productOrdersDO = productOrdersDOS.get(0); if(tradeStatus.equals(AlipayResultEnum.TRADE_CLOSED.getName())){ // 未付款交易超时关闭,或支付完成后全额退款 productOrdersDO.setPaymentStatus(PayStatusEnum.CANCEL.getName()); } if(tradeStatus.equals(AlipayResultEnum.TRADE_SUCCESS.getName())){ // 交易支付成功 productOrdersDO.setPaymentStatus(PayStatusEnum.PAID.getName()); } if(tradeStatus.equals(AlipayResultEnum.TRADE_FINISHED.getName())){ // 交易完成(交易结束,不可退款) productOrdersDO.setPaymentStatus(PayStatusEnum.FINISHED.getName()); } // 将yyyy-MM-dd HH:mm:ss转换成LocalDateTime if(gmtPayment != null){ productOrdersDO.setPaymentTime(DateUtils.dateTimeStringToLocalDateTime(gmtPayment)); } // 更新用户到期时间 if(!StringUtils.isEmpty(productOrdersDO.getUserId())){ Customer customer = customerService.getByUserId(productOrdersDO.getUserId()); if(customer != null){ LocalDateTime overTime = null; // 根据年卡,月卡、月卡持续计算到期时间 if(productOrdersDO.getOrderType().equals(ProductTypeEnum.MONTH_CONTINUED.getName())){ if(null!=customer.getMemberOvertime()){ // 在当前时间上增加一个月 overTime = customer.getMemberOvertime().plusMonths(1); }else{ // 当前时间上增加一个月 overTime =LocalDateTime.now().plusMonths(1); } } if(productOrdersDO.getOrderType().equals(ProductTypeEnum.MONTH.getName())){ if(null!=customer.getMemberOvertime()){ // 在当前时间上增加一个月 overTime = customer.getMemberOvertime().plusMonths(1); }else{ // 当前时间上增加一个月 overTime =LocalDateTime.now().plusMonths(1); } } if(productOrdersDO.getOrderType().equals(ProductTypeEnum.YEAR.getName())){ if(null!=customer.getMemberOvertime()){ // 在当前时间上增加一个月 overTime = customer.getMemberOvertime().plusYears(1); }else{ // 当前时间上增加一个月 overTime = customer.getMemberOvertime().plusYears(1); } } // 设置过期时间 customer.setMemberOvertime(overTime); customer.setIsMember(true); // 会员 } // 更新会员信息 customerService.updateMemberInfo(customer); } return productOrdersMapper.updateById(productOrdersDO)>0; } return false; } private String getSalesNo(){ String seq = sequenceNo.getSeqNo(SequenceNo.ORDER_PRODUCT); return "PO" + DateUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss") + seq; } } src/main/java/com/mzl/flower/service/productOrders/ProductOrdersService.java
对比新文件 @@ -0,0 +1,27 @@ package com.mzl.flower.service.productOrders; import com.mzl.flower.dto.request.productOrders.ProductOrdersCreateDTO; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.baomidou.mybatisplus.extension.service.IService; import java.util.Map; /** * <p> * 服务类 * </p> * * @author generator@TaoJie * @since 2025-03-31 */ public interface ProductOrdersService extends IService<ProductOrdersDO> { /** * 创建订单 * @param productOrdersDO * @return */ ProductOrdersDO createProductOrders(ProductOrdersDO productOrdersDO); Boolean updateProductOrderStatus(Map<String, String> params); } src/main/java/com/mzl/flower/utils/DateUtils.java
@@ -4,6 +4,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; @@ -113,6 +114,14 @@ } public static String format(LocalDateTime dateTime, String format) { if (dateTime == null || format == null) { return null; } DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format).withZone(ZoneId.of("Asia/Shanghai")); return dateTimeFormatter.format(dateTime); } public static void main(String[] args) { // 定义日期时间字符串 src/main/java/com/mzl/flower/web/v2/ProductOrdersController.java
对比新文件 @@ -0,0 +1,24 @@ package com.mzl.flower.web.v2; import com.mzl.flower.base.BaseController; import com.mzl.flower.service.productOrders.ProductOrdersService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author generator@TaoJie * @since 2025-03-31 */ @RestController @RequestMapping("/v1/product-orders") public class ProductOrdersController extends BaseController { @Autowired private ProductOrdersService productOrdersService; } src/main/java/com/mzl/flower/web/v2/pay/AlipayController.java
@@ -10,13 +10,19 @@ import com.mzl.flower.base.BaseController; import com.mzl.flower.base.R; import com.mzl.flower.config.pay.AlipayProperties; import com.mzl.flower.dto.request.productOrders.ProductOrdersCreateDTO; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.mzl.flower.enums.PayTypeEnum; import com.mzl.flower.service.productOrders.ProductOrdersService; import com.mzl.flower.utils.alipay.OrderInfoUtil2_0; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.*; @@ -38,33 +44,36 @@ @Autowired AlipayClient alipayClient; @Autowired private ProductOrdersService productOrdersService; /** * 获取订单支付请求参数 * @param * @return * @throws Exception */ @GetMapping(value = "/pay-order-info") @PostMapping(value = "/pay-order-info") @ApiOperation(value = "获取订单支付请求参数") public ResponseEntity getPayOrderInfo() throws Exception { public ResponseEntity getPayOrderInfo(@Validated @RequestBody ProductOrdersCreateDTO productOrdersCreateDTO) throws Exception { String orderId=" "; String totalAmount="0.01"; String subject="测试支付"; String body="我是测试支付"; // 创建订单 // createAlipayOrder(orderId,totalAmount,subject); // 创建订单 // 当前的支付类型是微信支付 ProductOrdersDO productOrdersDTO=new ProductOrdersDO(); BeanUtils.copyProperties(productOrdersCreateDTO,productOrdersDTO); productOrdersDTO.setPaymentMethod(PayTypeEnum.ALIPAY.getName()); ProductOrdersDO productOrdersDO=productOrdersService.createProductOrders(productOrdersDTO); //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setBody("我是测试数据"); model.setSubject("App支付测试Java"); model.setOutTradeNo(OrderInfoUtil2_0.getOutTradeNo()); // model.setOutTradeNo(orderId); model.setBody(productOrdersDO.getOrderType()+"_"+productOrdersDO.getCurrentPrice()); model.setSubject(productOrdersDO.getOrderName()); model.setOutTradeNo(productOrdersDO.getOrderNo()); model.setTotalAmount(productOrdersDO.getCurrentPrice()+""); model.setTimeoutExpress("30m"); model.setTotalAmount("0.01"); model.setProductCode("QUICK_MSECURITY_PAY"); request.setBizModel(model); request.setNotifyUrl(alipayProperties.getNotifyUrl()); @@ -111,6 +120,9 @@ // 查看验签结果 System.out.println(rsa2); if(rsa2){ // 更新支付状态 productOrdersService.updateProductOrderStatus(params); return "success"; } src/main/resources/mapper/productOrders/ProductOrdersMapper.xml
对比新文件 @@ -0,0 +1,27 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mzl.flower.mapper.productOrders.ProductOrdersMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.mzl.flower.entity.productOrders.ProductOrdersDO"> <id column="id" property="id" /> <result column="create_time" property="createTime" /> <result column="update_time" property="updateTime" /> <result column="delete_time" property="deleteTime" /> <result column="user_id" property="userId" /> <result column="order_no" property="orderNo" /> <result column="order_name" property="orderName" /> <result column="order_type" property="orderType" /> <result column=" original_price" property=" originalPrice" /> <result column="current_price" property="currentPrice" /> <result column="payment_method" property="paymentMethod" /> <result column="payment_status" property="paymentStatus" /> <result column="payment_time" property="paymentTime" /> <result column="update_by" property="updateBy" /> <result column="create_by" property="createBy" /> <result column="deleted" property="deleted" /> </resultMap> </mapper>