Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
5fa9515ed9
@ -85,4 +85,5 @@ public class EbikeSysRoperatesetController {
|
||||
return JsonResult.success(dto);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -24,4 +24,6 @@ public interface EbikeSysRoperatesetService extends IService<EbikeSysRoperateset
|
||||
* @return
|
||||
*/
|
||||
Boolean deleteByRegionId(String regionId);
|
||||
|
||||
// Boolean save()
|
||||
}
|
||||
|
||||
172
ebike-payment/pom.xml
Normal file
172
ebike-payment/pom.xml
Normal file
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.cdzy</groupId>
|
||||
<artifactId>ebike-share</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ebike-payment</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>ebike-payment</name>
|
||||
<description>ebike-payment-process</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.cdzy</groupId>
|
||||
<artifactId>ebike-common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.cdzy</groupId>
|
||||
<artifactId>ebike-feign</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- 微信支付SDK -->
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
<version>0.2.17</version>
|
||||
</dependency>
|
||||
<!-- mybatis-flex -->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${org.projectlombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>${HikariCP.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<version>${boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<!-- nacos客户端依赖包 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- for test only -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-codegen</artifactId>
|
||||
<version>1.10.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<!--开发环境-->
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<properties>
|
||||
<profile.active>dev</profile.active>
|
||||
<!--谁设置为true 就激活那个环境-->
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</properties>
|
||||
|
||||
</profile>
|
||||
|
||||
<!--生产环境-->
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
<properties>
|
||||
<profile.active>prod</profile.active>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>test</id>
|
||||
<properties>
|
||||
<profile.active>test</profile.active>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${boot.version}</version> <!-- 与项目版本一致 -->
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal> <!-- 必须包含此目标 -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,23 @@
|
||||
package com.cdzy.payment;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 支付模块
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/24
|
||||
* @modified by:
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.cdzy.payment.mapper")
|
||||
//引入Spring Task
|
||||
@EnableScheduling
|
||||
public class EbikePaymentApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(EbikePaymentApplication.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.cdzy.payment.config;
|
||||
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.core.FlexGlobalConfig;
|
||||
import com.mybatisflex.core.audit.AuditManager;
|
||||
import com.mybatisflex.core.dialect.DbType;
|
||||
import com.mybatisflex.core.dialect.DialectFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author attiya
|
||||
*/
|
||||
@Configuration
|
||||
public class MyBatisFlexConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger("mybatis-flex-sql:");
|
||||
|
||||
|
||||
public MyBatisFlexConfiguration() {
|
||||
//开启审计功能
|
||||
AuditManager.setAuditEnable(true);
|
||||
|
||||
//设置 SQL 审计收集器
|
||||
AuditManager.setMessageCollector(auditMessage ->
|
||||
logger.info("{},{}ms", auditMessage.getFullSql()
|
||||
, auditMessage.getElapsedTime())
|
||||
);
|
||||
|
||||
//全局ID生成策略配置
|
||||
FlexGlobalConfig.KeyConfig keyConfig = new FlexGlobalConfig.KeyConfig();
|
||||
keyConfig.setKeyType(KeyType.Generator);
|
||||
keyConfig.setValue("snowFlakeId");
|
||||
keyConfig.setBefore(true);
|
||||
FlexGlobalConfig.getDefaultConfig().setKeyConfig(keyConfig);
|
||||
|
||||
DialectFactory.registerDialect(DbType.MYSQL,new PermissionDialect());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.cdzy.payment.config;
|
||||
|
||||
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
|
||||
import com.mybatisflex.core.query.CPI;
|
||||
import com.mybatisflex.core.query.QueryTable;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author attiya
|
||||
* @since 2025-03-14
|
||||
*/
|
||||
public class PermissionDialect extends CommonsDialectImpl {
|
||||
|
||||
@Override
|
||||
public String forSelectByQuery(QueryWrapper queryWrapper) {
|
||||
|
||||
//用于严重table是否需要添加数据权限查询条件
|
||||
List<QueryTable> tables = CPI.getQueryTables(queryWrapper);
|
||||
//获取当前用户信息,为 queryWrapper 添加额外的条件
|
||||
return super.buildSelectSql(queryWrapper);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package com.cdzy.payment.config;
|
||||
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.core.cipher.RSASigner;
|
||||
import com.wechat.pay.java.core.util.PemUtil;
|
||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||
import com.wechat.pay.java.service.refund.RefundService;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
|
||||
/**
|
||||
* 微信支付配置参数
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/24
|
||||
* @modified by:
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "payment.wx-pay")
|
||||
public class WxPayConfig {
|
||||
/**
|
||||
* 微信小程序 appId
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 微信支付商户号
|
||||
*/
|
||||
private String merchantId;
|
||||
/**
|
||||
* 微信支付商户密钥文件路径
|
||||
*/
|
||||
private String privateKeyPath;
|
||||
/**
|
||||
* 微信支付商户证书序列号
|
||||
*/
|
||||
private String merchantSerialNumber;
|
||||
/**
|
||||
* 微信支付商户 APIv3 密钥
|
||||
*/
|
||||
private String apiV3Key;
|
||||
/**
|
||||
* 微信支付回调地址
|
||||
*/
|
||||
private String payNotifyUrl;
|
||||
/**
|
||||
* 微信支付退款回调地址
|
||||
*/
|
||||
private String refundNotifyUrl;
|
||||
/**
|
||||
* 支付、退款过期时间(分钟)
|
||||
* 默认30分钟,超过30分钟订单会自动关闭
|
||||
*/
|
||||
private Integer expireMinute = 30;
|
||||
|
||||
@Bean("certConfig")
|
||||
private Config certificateConfig() {
|
||||
return new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(merchantId)
|
||||
// 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
|
||||
.privateKeyFromPath(privateKeyPath)
|
||||
.merchantSerialNumber(merchantSerialNumber)
|
||||
.apiV3Key(apiV3Key)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JsapiService wxJsapiService(@Qualifier("certConfig") Config certificateConfig) {
|
||||
return new JsapiService.Builder().config(certificateConfig).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RefundService wxRefundService(@Qualifier("certConfig") Config certificateConfig) {
|
||||
return new RefundService.Builder().config(certificateConfig).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSASigner wxRsaSigner(){
|
||||
PrivateKey privateKey = PemUtil.loadPrivateKeyFromPath(privateKeyPath);
|
||||
return new RSASigner(merchantSerialNumber, privateKey);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package com.cdzy.payment.controller;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cdzy.common.model.JsonResult;
|
||||
import com.cdzy.payment.model.dto.EbikePaymentDto;
|
||||
import com.cdzy.payment.model.dto.EbikeRefundDto;
|
||||
import com.cdzy.payment.service.WxPayService;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.model.Refund;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 用户订单微信支付 控制层。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-24
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/wxPayment")
|
||||
public class EbikeWxPaymentController {
|
||||
|
||||
@Resource
|
||||
private WxPayService wxPayService;
|
||||
|
||||
/**
|
||||
* 微信支付下单
|
||||
*
|
||||
* @param paymentDto 支付信息
|
||||
* @return 下单成功返回true,否则返回false
|
||||
*/
|
||||
@PostMapping("/prepay")
|
||||
public JsonResult<?> prepay(@RequestBody EbikePaymentDto paymentDto) {
|
||||
JSONObject r = wxPayService.prepay(paymentDto.getOrderId(), paymentDto.getDescription(), paymentDto.getGoodsTag(), paymentDto.getOpenId(), paymentDto.getAmount(), paymentDto.getDetail(), paymentDto.getClientIp());
|
||||
return r == null?JsonResult.failed("下单失败"):JsonResult.success(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过交易订单号查询支付订单
|
||||
*
|
||||
* @param transactionId 微信支付订单号
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
@GetMapping("/queryOrderById/{transactionId}")
|
||||
public JsonResult<?> queryOrderById(@PathVariable String transactionId) {
|
||||
Transaction r = wxPayService.queryOrderById(transactionId);
|
||||
return r == null?JsonResult.failed(String.format("交易订单号{%s}查询支付订单失败", transactionId)):JsonResult.success(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过商户(骑行)订单号查询支付订单
|
||||
*
|
||||
* @param outTradeNo 商户(骑行)订单号
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
@GetMapping("/queryOrderByOutTradeNo/{outTradeNo}")
|
||||
public JsonResult<?> queryOrderByOutTradeNo(@PathVariable String outTradeNo) {
|
||||
Transaction r = wxPayService.queryOrderByOutTradeNo(outTradeNo);
|
||||
return r == null?JsonResult.failed(String.format("骑行订单号{%s}查询支付订单失败", outTradeNo)):JsonResult.success(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款申请
|
||||
*
|
||||
* @param refundDto 退款信息
|
||||
* @return 退款成功返回true,否则返回false
|
||||
*/
|
||||
@PostMapping("/refund")
|
||||
public JsonResult<?> refund(@RequestBody EbikeRefundDto refundDto) {
|
||||
String r = wxPayService.refund(refundDto.getPaymentId(), refundDto.getOrderId(), refundDto.getReason(), refundDto.getAmount());
|
||||
return r == null?JsonResult.failed("退款失败"):JsonResult.success(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过退款单号查询退款信息
|
||||
*
|
||||
* @param outRefundNo 商户(骑行)退款单号
|
||||
* @return 退款信息
|
||||
*/
|
||||
@GetMapping("/refundQuery/{outRefundNo}")
|
||||
public JsonResult<?> refundQuery(@PathVariable String outRefundNo) {
|
||||
Refund r = wxPayService.queryRefundByOutNo(outRefundNo);
|
||||
return r == null?JsonResult.failed(String.format("退款单号{%s}查询退款失败", outRefundNo)):JsonResult.success(r);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.cdzy.payment.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
|
||||
/**
|
||||
* 用户订单支付记录 映射层。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-24
|
||||
*/
|
||||
public interface EbikePaymentMapper extends BaseMapper<EbikePayment> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.cdzy.payment.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||
|
||||
/**
|
||||
* 用户订单退款记录 映射层。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-25
|
||||
*/
|
||||
public interface EbikeRefundMapper extends BaseMapper<EbikeRefund> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付金额信息
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/26
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AmountDto implements Serializable {
|
||||
/**
|
||||
* 订单金额(单位:元)
|
||||
*/
|
||||
private Double total;
|
||||
/**
|
||||
* 货币类型(默认:CNY)
|
||||
*/
|
||||
private String currency="CNY";
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 退款信息 (忽略来源明细)
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/26
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AmountRefundDto implements Serializable{
|
||||
/**
|
||||
* 退款金额,单位为元
|
||||
*/
|
||||
private Double refund;
|
||||
/**
|
||||
* 原订单金额,单位为元
|
||||
*/
|
||||
private Double total;
|
||||
/**
|
||||
* 退款币种 (默认CNY)
|
||||
*/
|
||||
private String currency = "CNY";
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付明细信息
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/26
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DetailDto implements Serializable {
|
||||
/**
|
||||
* 订单原价(单位:元)
|
||||
*/
|
||||
private Double costPrice;
|
||||
/**
|
||||
* 商品小票ID(可选)
|
||||
*/
|
||||
private String invoiceId;
|
||||
/**
|
||||
* 收费明显列表
|
||||
*/
|
||||
private List<PayDetailDto> goodsDetail;
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户订单微信支付 请求类。
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EbikePaymentDto {
|
||||
/**
|
||||
* 商户(骑行)订单号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 商品描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 商品标记
|
||||
*/
|
||||
private String goodsTag;
|
||||
/**
|
||||
* 用户标识
|
||||
*/
|
||||
private String openId;
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private AmountDto amount;
|
||||
/**
|
||||
* 费用详情
|
||||
*/
|
||||
private DetailDto detail;
|
||||
/**
|
||||
* 客户端IP
|
||||
*/
|
||||
private String clientIp;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.Detail;
|
||||
import com.wechat.pay.java.service.refund.model.AmountReq;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户订单退款 请求类。
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EbikeRefundDto {
|
||||
/**
|
||||
* 商户(骑行)订单号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 支付交易会话标识
|
||||
*/
|
||||
private String paymentId;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
*/;
|
||||
private String reason;
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private AmountRefundDto amount;
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付费用明细信息
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/26
|
||||
* @modified by:
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PayDetailDto implements Serializable {
|
||||
/**
|
||||
* 费用项目ID
|
||||
*/
|
||||
private String itemId;
|
||||
/**
|
||||
* 费用名称
|
||||
*/
|
||||
private String itemName;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
/**
|
||||
* 单价(单位:元)
|
||||
*/
|
||||
private Double unitPrice;
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package com.cdzy.payment.model.dto;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.wechat.pay.java.core.cipher.RSASigner;
|
||||
import com.wechat.pay.java.core.cipher.SignatureResult;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* JSAPI 调起微信支付参数
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class WxJsapiPromptDto {
|
||||
|
||||
/**
|
||||
* 下单时传入的appid
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 传秒级时间戳
|
||||
*/
|
||||
private String timeStamp;
|
||||
/**
|
||||
* 随机字符串
|
||||
*/
|
||||
private String nonceStr;
|
||||
/**
|
||||
* 订单详情扩展,提交格式如:prepay_id=***
|
||||
*/
|
||||
// json中转为 "package"
|
||||
@JSONField(name = "package")
|
||||
private String extension;
|
||||
/**
|
||||
* 签名类型,固定填RSA
|
||||
*/
|
||||
private String signType = "RSA";
|
||||
/**
|
||||
* 签名,使用字段appId、timeStamp、nonceStr、package计算得出的签名值
|
||||
*/
|
||||
private String paySign;
|
||||
|
||||
public JSONObject toJson(RSASigner rsaSigner) {
|
||||
try{
|
||||
// 计算签名
|
||||
StringJoiner signMsg = new StringJoiner("\n");
|
||||
signMsg.add(appId);
|
||||
signMsg.add(timeStamp);
|
||||
signMsg.add(nonceStr);
|
||||
signMsg.add(extension);
|
||||
SignatureResult sign = rsaSigner.sign(signMsg.toString());
|
||||
this.paySign = sign.getSign();
|
||||
//result.put("package", result.remove("extension"));
|
||||
return JSONObject.parseObject(JSONObject.toJSONString(this));
|
||||
}catch (Exception e){
|
||||
log.error("计算签名失败", e);
|
||||
throw new RuntimeException("计算签名失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package com.cdzy.payment.model.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户订单支付记录 实体类。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-24
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("ebike_payment")
|
||||
public class EbikePayment implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@Id
|
||||
private String recordId;
|
||||
|
||||
/**
|
||||
* 骑行订单号
|
||||
*/
|
||||
@Id
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 支付交易会话标识;有效期为2小时
|
||||
*/
|
||||
private String paymentId;
|
||||
|
||||
/**
|
||||
* 提交时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 支付成功时间
|
||||
*/
|
||||
private LocalDateTime paymentTime;
|
||||
|
||||
/**
|
||||
* 支付方式;wechat/alipay/balance
|
||||
*/
|
||||
private String paymentMethod;
|
||||
|
||||
/**
|
||||
* 支付状态;0支付成功 1退款 2未支付 3关闭 4取消 5支付中 6支付错误 7接受
|
||||
*/
|
||||
private String tradeState;
|
||||
|
||||
|
||||
/**
|
||||
* 订单原价
|
||||
*/
|
||||
private Double costPrice;
|
||||
/**
|
||||
* 货币
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private Double total;
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.cdzy.payment.model.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户订单退款记录 实体类。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-25
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("ebike_refund")
|
||||
public class EbikeRefund implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@Id
|
||||
private String refundId;
|
||||
|
||||
/**
|
||||
* 骑行订单号
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 支付记录id
|
||||
*/
|
||||
private String recordId;
|
||||
|
||||
/**
|
||||
* 支付交易会话标识;有效期为2小时
|
||||
*/
|
||||
private String paymentId;
|
||||
|
||||
/**
|
||||
* 提交时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 退款成功时间
|
||||
*/
|
||||
private LocalDateTime refundTime;
|
||||
|
||||
|
||||
/**
|
||||
* 支付状态;0退款成功 1关闭 2退款中 3异常
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 货币
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
*/
|
||||
private Double refund;
|
||||
|
||||
/**
|
||||
* 退款总金额
|
||||
*/
|
||||
private Double total;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
*/
|
||||
private String reason;
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.cdzy.payment.model.enums;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public enum PayMethod {
|
||||
@SerializedName("wechat")
|
||||
wechat,
|
||||
@SerializedName("alipay")
|
||||
alipay,
|
||||
@SerializedName("balance")
|
||||
balance;
|
||||
|
||||
private PayMethod() {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.cdzy.payment.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户订单支付记录 服务层。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-24
|
||||
*/
|
||||
public interface EbikePaymentService extends IService<EbikePayment> {
|
||||
/**
|
||||
* 查询未支付订单
|
||||
*
|
||||
* @param duration 订单创建时间超过duration分钟,单位分钟
|
||||
* @return 未支付订单列表
|
||||
*/
|
||||
List<EbikePayment> getNoPayOrderByDuration(int duration);
|
||||
|
||||
/**
|
||||
* 更新支付状态
|
||||
*
|
||||
* @param recordId 记录ID
|
||||
* @param transaction 支付结果
|
||||
* @return 更新成功返回true,否则返回false
|
||||
*/
|
||||
Boolean updatePaymentStatus(String recordId, Transaction transaction);
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.cdzy.payment.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.model.Refund;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户订单退款记录 服务层。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-25
|
||||
*/
|
||||
public interface EbikeRefundService extends IService<EbikeRefund> {
|
||||
/**
|
||||
* 保存退款记录
|
||||
*
|
||||
* @param ebikeRefund 退款结果
|
||||
* @return 保存成功返回主键id,否则返回null
|
||||
*/
|
||||
Boolean saveRefundResult(EbikeRefund ebikeRefund);
|
||||
|
||||
/**
|
||||
* 查询未成功退款订单
|
||||
*
|
||||
* @param duration 订单创建时间超过duration分钟,单位分钟
|
||||
* @return 未成功退款订单列表
|
||||
*/
|
||||
List<EbikeRefund> getNoSuccessRefundOrderByDuration(int duration);
|
||||
|
||||
/**
|
||||
* 更新退款状态
|
||||
*
|
||||
* @param refundId 退款ID
|
||||
* @param refund 退款结果
|
||||
* @return 更新成功返回true,否则返回false
|
||||
*/
|
||||
Boolean updateRefundStatus(String refundId, Refund refund);
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package com.cdzy.payment.service;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cdzy.payment.model.dto.AmountDto;
|
||||
import com.cdzy.payment.model.dto.AmountRefundDto;
|
||||
import com.cdzy.payment.model.dto.DetailDto;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.model.Refund;
|
||||
|
||||
/**
|
||||
* 微信支付服务类(JSAPI支付),小程序
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
public interface WxPayService {
|
||||
/**
|
||||
* 关闭订单
|
||||
*
|
||||
* @param outTradeNo 商户(骑行)订单号
|
||||
* @return
|
||||
*/
|
||||
boolean closeOrder(String outTradeNo);
|
||||
/**
|
||||
* JSAPI支付下单
|
||||
*
|
||||
* @param outTradeNo 商户(骑行)订单号
|
||||
* @param description 商品描述
|
||||
* @param goodsTag 商品标记
|
||||
* @param openId 用户标识
|
||||
* @param amount 金额
|
||||
* @param detail 商品详情
|
||||
* @param clientIp 客户端IP
|
||||
* @return 下单成功返回true,否则返回false
|
||||
*/
|
||||
JSONObject prepay(String outTradeNo, String description, String goodsTag, String openId, AmountDto amount, DetailDto detail, String clientIp);
|
||||
/**
|
||||
* 通过交易订单号查询支付订单
|
||||
*
|
||||
* @param transactionId 微信支付订单号
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
Transaction queryOrderById(String transactionId);
|
||||
/**
|
||||
* 通过商户(骑行)订单号查询支付订单
|
||||
*
|
||||
* @param outTradeNo 商户(骑行)订单号
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
Transaction queryOrderByOutTradeNo(String outTradeNo);
|
||||
/**
|
||||
* 退款申请
|
||||
*
|
||||
* @param transactionId 微信支付订单号
|
||||
* @param outTradeNo 商户(骑行)订单号
|
||||
* @param reason 退款原因
|
||||
* @param amount 退款金额
|
||||
* @return 退款信息id
|
||||
*/
|
||||
String refund(String transactionId, String outTradeNo, String reason, AmountRefundDto amount);
|
||||
|
||||
|
||||
/**
|
||||
* 通过商户退款单号查询退款信息
|
||||
*
|
||||
* @param outRefundNo 商户退款订单号
|
||||
* @return 退款信息
|
||||
*/
|
||||
Refund queryRefundByOutNo(String outRefundNo);
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.cdzy.payment.service.impl;
|
||||
|
||||
import com.cdzy.payment.model.enums.PayMethod;
|
||||
import com.ebike.feign.clients.OrdersFeignClient;
|
||||
import com.ebike.feign.model.res.ResFeignOrderPaymentDto;
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
import com.mybatisflex.core.query.QueryMethods;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
import com.cdzy.payment.mapper.EbikePaymentMapper;
|
||||
import com.cdzy.payment.service.EbikePaymentService;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.cdzy.payment.model.entity.table.EbikePaymentTableDef.EBIKE_PAYMENT;
|
||||
|
||||
/**
|
||||
* 用户订单支付记录 服务层实现。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-24
|
||||
*/
|
||||
@Service
|
||||
public class EbikePaymentServiceImpl extends ServiceImpl<EbikePaymentMapper, EbikePayment> implements EbikePaymentService{
|
||||
|
||||
@Resource
|
||||
private OrdersFeignClient ordersFeignClient;
|
||||
|
||||
@Override
|
||||
public List<EbikePayment> getNoPayOrderByDuration(int duration) {
|
||||
QueryColumn time = QueryMethods.secToTime(String.valueOf(duration * 60));
|
||||
// trade_state 等于 NOTPAY未支付的, 并且创建时间超过duration分钟的订单
|
||||
QueryWrapper query = QueryWrapper.create()
|
||||
.where(EBIKE_PAYMENT.TRADE_STATE.eq(Transaction.TradeStateEnum.NOTPAY.ordinal()))
|
||||
.and(QueryMethods.addTime(EBIKE_PAYMENT.CREATE_TIME, time).ge(QueryMethods.now()));
|
||||
return list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updatePaymentStatus(String recordId, Transaction transaction) {
|
||||
EbikePayment ebikePayment = new EbikePayment();
|
||||
ebikePayment.setRecordId(recordId);
|
||||
ebikePayment.setTradeState(String.valueOf(transaction.getTradeState().ordinal()));
|
||||
if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
|
||||
// 支付成功, 更新订单状态
|
||||
double v = transaction.getAmount().getTotal().doubleValue() / 100.0;
|
||||
ebikePayment.setTotal(v);
|
||||
ebikePayment.setPaymentTime(LocalDateTime.now());
|
||||
// 同步支付状态
|
||||
ResFeignOrderPaymentDto paymentParam = new ResFeignOrderPaymentDto();
|
||||
paymentParam.setOrderId(Long.valueOf(transaction.getOutTradeNo()));
|
||||
paymentParam.setPaymentTime(ebikePayment.getPaymentTime());
|
||||
paymentParam.setPaymentMethod(PayMethod.wechat.name());
|
||||
ordersFeignClient.payment(paymentParam);
|
||||
}
|
||||
return updateById(ebikePayment);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.cdzy.payment.service.impl;
|
||||
|
||||
import com.ebike.feign.clients.OrdersFeignClient;
|
||||
import com.mybatisflex.core.query.QueryMethods;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||
import com.cdzy.payment.mapper.EbikeRefundMapper;
|
||||
import com.cdzy.payment.service.EbikeRefundService;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.model.Refund;
|
||||
import com.wechat.pay.java.service.refund.model.Status;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.cdzy.payment.model.entity.table.EbikeRefundTableDef.EBIKE_REFUND;
|
||||
|
||||
/**
|
||||
* 用户订单退款记录 服务层实现。
|
||||
*
|
||||
* @author dingchao
|
||||
* @since 2025-04-25
|
||||
*/
|
||||
@Service
|
||||
public class EbikeRefundServiceImpl extends ServiceImpl<EbikeRefundMapper, EbikeRefund> implements EbikeRefundService{
|
||||
|
||||
@Resource
|
||||
private OrdersFeignClient ordersFeignClient;
|
||||
|
||||
@Override
|
||||
public Boolean saveRefundResult(EbikeRefund ebikeRefund) {
|
||||
// 同步发起退款
|
||||
ordersFeignClient.refund(Long.valueOf(ebikeRefund.getOrderId()));
|
||||
return save(ebikeRefund);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EbikeRefund> getNoSuccessRefundOrderByDuration(int duration) {
|
||||
// trade_state 不等于 SUCCESS退款成功的, 并且创建时间超过duration分钟的订单
|
||||
QueryWrapper query = QueryWrapper.create()
|
||||
.where(EBIKE_REFUND.STATUS.ne(Status.SUCCESS.ordinal()))
|
||||
.and(QueryMethods.addTime(EBIKE_REFUND.CREATE_TIME, QueryMethods.secToTime(String.valueOf(duration * 60))).ge(QueryMethods.now()));
|
||||
return list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateRefundStatus(String refundId, Refund refund) {
|
||||
EbikeRefund ebikeRefund = new EbikeRefund();
|
||||
ebikeRefund.setRefundId(refundId);
|
||||
ebikeRefund.setStatus(String.valueOf(refund.getStatus().ordinal()));
|
||||
if (Status.SUCCESS.equals(refund.getStatus())) {
|
||||
ebikeRefund.setRefundTime(LocalDateTime.now());
|
||||
ebikeRefund.setRefund(refund.getAmount().getRefund().doubleValue() / 100.0);
|
||||
}
|
||||
return updateById(ebikeRefund);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
package com.cdzy.payment.service.impl;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cdzy.payment.config.WxPayConfig;
|
||||
import com.cdzy.payment.model.dto.AmountDto;
|
||||
import com.cdzy.payment.model.dto.AmountRefundDto;
|
||||
import com.cdzy.payment.model.dto.DetailDto;
|
||||
import com.cdzy.payment.model.dto.WxJsapiPromptDto;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||
import com.cdzy.payment.model.enums.PayMethod;
|
||||
import com.cdzy.payment.service.EbikePaymentService;
|
||||
import com.cdzy.payment.service.EbikeRefundService;
|
||||
import com.cdzy.payment.service.WxPayService;
|
||||
import com.cdzy.payment.utils.StringUtil;
|
||||
import com.wechat.pay.java.core.cipher.RSASigner;
|
||||
import com.wechat.pay.java.core.exception.HttpException;
|
||||
import com.wechat.pay.java.core.exception.MalformedMessageException;
|
||||
import com.wechat.pay.java.core.exception.ServiceException;
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.*;
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.GoodsDetail;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.RefundService;
|
||||
import com.wechat.pay.java.service.refund.model.*;
|
||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 微信支付服务类(JSAPI支付),小程序
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WxPayServiceImpl implements WxPayService {
|
||||
|
||||
@Resource
|
||||
private JsapiService wxJsapiService;
|
||||
@Resource
|
||||
private RefundService wxRefundService;
|
||||
@Resource
|
||||
private WxPayConfig wxPayConfig;
|
||||
@Resource
|
||||
private RSASigner wxRsaSigner;
|
||||
@Resource
|
||||
private EbikePaymentService ebikePaymentService;
|
||||
@Resource
|
||||
private EbikeRefundService ebikeRefundService;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean closeOrder(String outTradeNo) {
|
||||
try {
|
||||
CloseOrderRequest request = new CloseOrderRequest();
|
||||
request.setOutTradeNo(outTradeNo);
|
||||
wxJsapiService.closeOrder(request);
|
||||
log.info("关闭订单成功,订单号:{}", outTradeNo);
|
||||
//ebikePaymentService.updatePaymentStatus(outTradeNo, 2);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
logError("关闭订单closeOrder", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject prepay(String outTradeNo, String description, String goodsTag, String openId, AmountDto amount, DetailDto detail, String clientIp) {
|
||||
try {
|
||||
PrepayRequest request = new PrepayRequest();
|
||||
request.setAppid(wxPayConfig.getAppId());
|
||||
request.setMchid(wxPayConfig.getMerchantId());
|
||||
request.setDescription(description);
|
||||
request.setOutTradeNo(outTradeNo);
|
||||
request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
|
||||
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(wxPayConfig.getExpireMinute());
|
||||
request.setTimeExpire(StringUtil.formatLocalDatetime(expireTime));
|
||||
request.setGoodsTag(goodsTag);
|
||||
Amount amountReq = new Amount();
|
||||
amountReq.setTotal(BigDecimal.valueOf(amount.getTotal() * 100.0).intValue());
|
||||
amountReq.setCurrency(amount.getCurrency());
|
||||
request.setAmount(amountReq);
|
||||
Payer payer = new Payer();
|
||||
payer.setOpenid(openId);
|
||||
request.setPayer(payer);
|
||||
Detail detailReq = new Detail();
|
||||
detailReq.setGoodsDetail(detail.getGoodsDetail().stream().map(goodsDetail -> {
|
||||
GoodsDetail goodsDetailReq = new GoodsDetail();
|
||||
goodsDetailReq.setGoodsName(goodsDetail.getItemName());
|
||||
goodsDetailReq.setMerchantGoodsId(goodsDetail.getItemId());
|
||||
goodsDetailReq.setQuantity(goodsDetail.getQuantity());
|
||||
goodsDetailReq.setUnitPrice(BigDecimal.valueOf(goodsDetail.getUnitPrice()*100.0).intValue());
|
||||
return goodsDetailReq;
|
||||
}).toList());
|
||||
detailReq.setCostPrice(BigDecimal.valueOf(detail.getCostPrice()*100.0).intValue());
|
||||
detailReq.setInvoiceId(detail.getInvoiceId());
|
||||
request.setDetail(detailReq);
|
||||
SceneInfo sceneInfo = new SceneInfo();
|
||||
sceneInfo.setPayerClientIp(clientIp);
|
||||
request.setSceneInfo(sceneInfo);
|
||||
|
||||
PrepayResponse response = wxJsapiService.prepay(request);
|
||||
String payId = response.getPrepayId();
|
||||
//入库
|
||||
if (payId != null) {
|
||||
EbikePayment ebikePayment = new EbikePayment();
|
||||
ebikePayment.setOrderId(outTradeNo);
|
||||
ebikePayment.setPaymentId(payId);
|
||||
ebikePayment.setCreateTime(LocalDateTime.now());
|
||||
ebikePayment.setPaymentMethod(PayMethod.wechat.name());
|
||||
ebikePayment.setCostPrice(amount.getTotal());
|
||||
int state = Transaction.TradeStateEnum.NOTPAY.ordinal();
|
||||
ebikePayment.setTradeState(String.valueOf(state));
|
||||
ebikePaymentService.save(ebikePayment);
|
||||
// 返回给小程序的参数(调起微信支付)
|
||||
WxJsapiPromptDto wxJsapiPromptDto = new WxJsapiPromptDto();
|
||||
wxJsapiPromptDto.setAppId(wxPayConfig.getAppId());
|
||||
wxJsapiPromptDto.setTimeStamp(String.valueOf(Instant.now().getEpochSecond()));
|
||||
wxJsapiPromptDto.setNonceStr(RandomUtil.randomStringUpper(32));
|
||||
wxJsapiPromptDto.setExtension("prepay_id=" + payId);
|
||||
return wxJsapiPromptDto.toJson(wxRsaSigner);
|
||||
}
|
||||
log.error("微信支付下单prepay失败,订单号:{}", outTradeNo);
|
||||
return null;
|
||||
}catch (Exception e) {
|
||||
logError("微信支付下单prepay", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction queryOrderById(String transactionId) {
|
||||
try {
|
||||
QueryOrderByIdRequest request = new QueryOrderByIdRequest();
|
||||
request.setTransactionId(transactionId);
|
||||
return wxJsapiService.queryOrderById(request);
|
||||
}catch (Exception e) {
|
||||
logError("通过交易订单号查询支付订单queryOrderById", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction queryOrderByOutTradeNo(String outTradeNo) {
|
||||
try {
|
||||
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
||||
request.setOutTradeNo(outTradeNo);
|
||||
return wxJsapiService.queryOrderByOutTradeNo(request);
|
||||
}catch (Exception e) {
|
||||
logError("通过商户(骑行)订单号查询支付订单queryOrderByOutTradeNo", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String refund(String transactionId, String outTradeNo, String reason, AmountRefundDto amount) {
|
||||
try {
|
||||
// 雪花算法生成退款单号
|
||||
String outRefundNo = StringUtil.generateSnowflakeId("refundId");
|
||||
EbikeRefund ebikeRefund = new EbikeRefund();
|
||||
ebikeRefund.setCreateTime(LocalDateTime.now());
|
||||
// 发起退款
|
||||
CreateRequest request = new CreateRequest();
|
||||
request.setTransactionId(transactionId);
|
||||
request.setOutTradeNo(outTradeNo);
|
||||
request.setOutRefundNo(outRefundNo);
|
||||
request.setReason(reason);
|
||||
request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
|
||||
AmountReq amountReq = new AmountReq();
|
||||
amountReq.setRefund(BigDecimal.valueOf(amount.getRefund() * 100.0).longValue());
|
||||
amountReq.setTotal(BigDecimal.valueOf(amount.getTotal() * 100.0).longValue());
|
||||
amountReq.setCurrency(amount.getCurrency());
|
||||
request.setAmount(amountReq);
|
||||
Refund result = wxRefundService.create(request);
|
||||
// 入库
|
||||
if (result != null) {
|
||||
ebikeRefund.setRefundId(outRefundNo);
|
||||
ebikeRefund.setOrderId(outTradeNo);
|
||||
ebikeRefund.setPaymentId(transactionId);
|
||||
ebikeRefund.setTotal(amount.getTotal());
|
||||
ebikeRefund.setReason(reason);
|
||||
ebikeRefund.setStatus(String.valueOf(result.getStatus().ordinal()));
|
||||
ebikeRefund.setCurrency(amount.getCurrency());
|
||||
ebikeRefundService.saveRefundResult(ebikeRefund);
|
||||
if(Status.SUCCESS.equals(result.getStatus())){
|
||||
ebikeRefund.setRefund(result.getAmount().getRefund().doubleValue() / 100.0);
|
||||
ebikeRefund.setRefundTime(LocalDateTime.now());
|
||||
}
|
||||
ebikeRefundService.saveRefundResult(ebikeRefund);
|
||||
return outRefundNo;
|
||||
}
|
||||
log.error("退款申请refund失败,订单号:{}", outTradeNo);
|
||||
return null;
|
||||
}catch (Exception e) {
|
||||
logError("退款申请refund", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Refund queryRefundByOutNo(String outRefundNo) {
|
||||
try {
|
||||
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
|
||||
request.setOutRefundNo(outRefundNo);
|
||||
return wxRefundService.queryByOutRefundNo(request);
|
||||
}catch (Exception e) {
|
||||
logError("通过商户退款单号查询退款queryByOutRefundNo", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印日志
|
||||
*
|
||||
* @param desc 描述
|
||||
* @param e 异常
|
||||
*/
|
||||
private void logError(String desc, Exception e) {
|
||||
if (e instanceof HttpException httpException) {
|
||||
log.error("{} 发送HTTP请求失败, {}", desc, httpException.getHttpRequest());
|
||||
}
|
||||
else if (e instanceof ServiceException serviceException) {
|
||||
log.error("{} 服务返回状态不正常, {}", desc, serviceException.getResponseBody());
|
||||
}
|
||||
else if (e instanceof MalformedMessageException malformedMessageException) {
|
||||
log.error("{} 返回体类型不合法或者解析返回体失败, {}", desc, malformedMessageException.getMessage());
|
||||
}
|
||||
else {
|
||||
log.error("{} 执行异常, {}", desc, e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.cdzy.payment.task;
|
||||
|
||||
import com.cdzy.payment.config.WxPayConfig;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||
import com.cdzy.payment.service.EbikePaymentService;
|
||||
import com.cdzy.payment.service.EbikeRefundService;
|
||||
import com.cdzy.payment.service.WxPayService;
|
||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||
import com.wechat.pay.java.service.refund.model.Refund;
|
||||
import com.wechat.pay.java.service.refund.model.Status;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户订单支付任务。检测支付状态,更新订单状态。
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/25
|
||||
* @modified by:
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WsPayTask {
|
||||
|
||||
@Resource
|
||||
private WxPayConfig wxPayConfig;
|
||||
@Resource
|
||||
private WxPayService wxPayService;
|
||||
@Resource
|
||||
private EbikePaymentService ebikePaymentService;
|
||||
@Resource
|
||||
private EbikeRefundService ebikeRefundService;
|
||||
|
||||
/**
|
||||
* 从第0秒开始每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单
|
||||
*/
|
||||
@Scheduled(cron = "0/30 * * * * ?")
|
||||
public void orderConfirm() throws Exception {
|
||||
log.info("orderConfirm 执行......");
|
||||
// 1. 查询未支付的订单
|
||||
List<EbikePayment> ebikePaymentList = ebikePaymentService.getNoPayOrderByDuration(wxPayConfig.getExpireMinute());
|
||||
// 2. 遍历订单,查询支付状态
|
||||
for (EbikePayment ebikePayment : ebikePaymentList) {
|
||||
log.warn("超时未支付的订单号 ===> {}", ebikePayment.getOrderId());
|
||||
// 调用微信支付查询接口,查询支付状态
|
||||
Transaction transaction = wxPayService.queryOrderByOutTradeNo(ebikePayment.getOrderId());
|
||||
// 3. 更新订单状态
|
||||
if (transaction != null)
|
||||
ebikePaymentService.updatePaymentStatus(ebikePayment.getRecordId(), transaction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从第0秒开始每隔30秒执行1次,查询创建超过5分钟,并且未成功的退款单
|
||||
*/
|
||||
@Scheduled(cron = "0/30 * * * * ?")
|
||||
public void refundConfirm() throws Exception {
|
||||
log.info("refundConfirm 执行......");
|
||||
|
||||
// 1. 查询未成功的退款单
|
||||
List<EbikeRefund> ebikeRefundList = ebikeRefundService.getNoSuccessRefundOrderByDuration(wxPayConfig.getExpireMinute());
|
||||
// 2. 遍历退款单,查询退款状态
|
||||
for (EbikeRefund ebikeRefund : ebikeRefundList) {
|
||||
log.warn("超时未退款的退款单号 ===> {}", ebikeRefund.getRefundId());
|
||||
// 调用微信退款查询接口,查询退款状态
|
||||
Refund refund = wxPayService.queryRefundByOutNo(ebikeRefund.getRefundId());
|
||||
if (refund!= null&& Status.SUCCESS.equals(refund.getStatus())){
|
||||
// 3. 更新退款单状态
|
||||
//ebikeRefundService.updateRefundStatus(ebikeRefund.getRefundId(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.cdzy.payment.utils;
|
||||
|
||||
import com.mybatisflex.core.keygen.IKeyGenerator;
|
||||
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 字符串处理工具类
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/27
|
||||
* @modified by:
|
||||
*/
|
||||
public class StringUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
* 格式:yyyy-MM-dd'T'HH:mm:ss.SSSX
|
||||
* 示例:2025-04-25T10:10:10.100+08:00
|
||||
* 注意:时区为+8
|
||||
*
|
||||
* @param localDateTime 本地时间
|
||||
* @return
|
||||
*/
|
||||
public static String formatLocalDatetime(LocalDateTime localDateTime) {
|
||||
ZonedDateTime localZoned = localDateTime.atZone(ZoneId.of("+8"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
return localZoned.format(formatter);
|
||||
}
|
||||
|
||||
public static String generateSnowflakeId(String idFieldName) {
|
||||
// 获取名为 "snowFlakeId" 的生成器
|
||||
IKeyGenerator generator = KeyGeneratorFactory.getKeyGenerator("snowFlakeId");
|
||||
Long key = (Long)generator.generate(null, idFieldName);
|
||||
return String.valueOf(key);
|
||||
}
|
||||
|
||||
//public static void main(String[] args) {
|
||||
// System.out.println(formatLocalDatetime(LocalDateTime.now()));
|
||||
// System.out.println(generateSnowflakeId("refundId"));
|
||||
//}
|
||||
}
|
||||
43
ebike-payment/src/main/resources/application-dev.yml
Normal file
43
ebike-payment/src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,43 @@
|
||||
server:
|
||||
port: 10017
|
||||
spring:
|
||||
application:
|
||||
name: ebike-pay
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: 127.0.0.1:8848 # nacos
|
||||
username: nacos
|
||||
password: nacos
|
||||
jackson:
|
||||
serialization:
|
||||
write-dates-as-timestamps: false
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.2.226:3306/ebike_orders?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8
|
||||
username: root
|
||||
password: 970529
|
||||
hikari:
|
||||
## 最小空闲连接数量
|
||||
minimum-idle: 5
|
||||
## 空闲连接存活最大时间,默认600000(10分钟)
|
||||
idle-timeout: 180000
|
||||
## 连接池最大连接数,默认是10
|
||||
maximum-pool-size: 10
|
||||
## 数据库连接超时时间,默认30秒,即30000
|
||||
connection-timeout: 30000
|
||||
connection-test-query: SELECT 1
|
||||
##此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
|
||||
max-lifetime: 1800000
|
||||
mybatis-flex:
|
||||
mapper-locations: classpath:mapper/*.xml
|
||||
payment:
|
||||
wx-pay:
|
||||
app-id: wx097b305458b0757c
|
||||
merchant-id: 1668000369
|
||||
private-key-path: D:\Projects\eBIKE\docs\wechatpay\apiclient_key.pem
|
||||
merchant-serial-number: 5157F09EFDC096DE15EBE81A47057A72********
|
||||
api-v3-key: 5157F09EFDC096DE15EBE81A47057A72********
|
||||
pay-notify_url: http://192.168.2.156:10017/wxPayment/pay-notify
|
||||
refund-notify_url: http://192.168.2.156:10017/wxPayment/refund-notify
|
||||
expire-minutes: 5
|
||||
10
ebike-payment/src/main/resources/application-prod.yml
Normal file
10
ebike-payment/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,10 @@
|
||||
server:
|
||||
port: 10017
|
||||
spring:
|
||||
application:
|
||||
name: ebike-pay
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: 192.168.2.226:8848 # nacos
|
||||
username: nacos
|
||||
password: nacos
|
||||
39
ebike-payment/src/main/resources/application-test.yml
Normal file
39
ebike-payment/src/main/resources/application-test.yml
Normal file
@ -0,0 +1,39 @@
|
||||
server:
|
||||
port: 10017
|
||||
spring:
|
||||
application:
|
||||
name: ebike-pay
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: 192.168.2.226:8848 # nacos
|
||||
username: nacos
|
||||
password: nacos
|
||||
jackson:
|
||||
serialization:
|
||||
write-dates-as-timestamps: false
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.2.226:3306/ebike_user?useSSL=false
|
||||
username: root
|
||||
password: 970529
|
||||
hikari:
|
||||
## 最小空闲连接数量
|
||||
minimum-idle: 5
|
||||
## 空闲连接存活最大时间,默认600000(10分钟)
|
||||
idle-timeout: 180000
|
||||
## 连接池最大连接数,默认是10
|
||||
maximum-pool-size: 10
|
||||
## 数据库连接超时时间,默认30秒,即30000
|
||||
connection-timeout: 30000
|
||||
connection-test-query: SELECT 1
|
||||
##此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
|
||||
max-lifetime: 1800000
|
||||
sql:
|
||||
init:
|
||||
platform: mysql
|
||||
mode: always
|
||||
schema-locations: classpath:db/init.sql
|
||||
data-locations: classpath:db/data.sql
|
||||
mybatis-flex:
|
||||
mapper-locations: classpath:mapper/*.xml
|
||||
3
ebike-payment/src/main/resources/application.yml
Normal file
3
ebike-payment/src/main/resources/application.yml
Normal file
@ -0,0 +1,3 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: @profile.active@
|
||||
@ -0,0 +1,98 @@
|
||||
package com.cdzy.payment;
|
||||
|
||||
import com.mybatisflex.codegen.Generator;
|
||||
import com.mybatisflex.codegen.config.GlobalConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 功能描述
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/24
|
||||
* @modified by:
|
||||
*/
|
||||
public class EbikePaymentApplicationTest {
|
||||
|
||||
private static final String model_path ="D:/Projects/eBIKE/mybatis-flex/ebike-pay";
|
||||
private static final String mapperPath="D:/Projects/eBIKE/mybatis-flex/ebike-pay/resources/mapper";
|
||||
private static final String packageName ="com.cdzy.payment";
|
||||
private static final String[] tables= new String[]{
|
||||
"ebike_payment",
|
||||
"ebike_refund",
|
||||
"ebike_order_details"
|
||||
};
|
||||
|
||||
@Test
|
||||
public void pay_mybatis_code() {
|
||||
//配置数据源
|
||||
HikariDataSource dataSource = new HikariDataSource();
|
||||
dataSource.setJdbcUrl("jdbc:mysql://192.168.2.226:3306/ebike_orders?characterEncoding=utf-8");
|
||||
dataSource.setUsername("root");
|
||||
dataSource.setPassword("970529");
|
||||
//生成全库的
|
||||
GlobalConfig globalConfig = createGlobalConfigUseStyle2();
|
||||
//单表的
|
||||
//GlobalConfig globalConfig = createGlobalConfigUseStyle2();
|
||||
Generator generator = new Generator(dataSource, globalConfig);
|
||||
//生成代码
|
||||
generator.generate();
|
||||
}
|
||||
private GlobalConfig createGlobalConfigUseStyle1() {
|
||||
// 创建配置内容
|
||||
GlobalConfig globalConfig = new GlobalConfig();
|
||||
// 设置项目源目录和基础包
|
||||
globalConfig.getPackageConfig()
|
||||
.setSourceDir(model_path)
|
||||
.setBasePackage(packageName);
|
||||
// 启用生成 entity,并启用 Lombok
|
||||
globalConfig.setEntityGenerateEnable(true);
|
||||
globalConfig.setEntityWithLombok(true);
|
||||
// 设置项目的JDK版本
|
||||
globalConfig.setEntityJdkVersion(17);
|
||||
// 启用生成 mapper、service、controller
|
||||
globalConfig.enableEntity();
|
||||
globalConfig.enableMapper();
|
||||
globalConfig.enableService();
|
||||
globalConfig.enableServiceImpl();
|
||||
globalConfig.enableController();
|
||||
globalConfig.enableMapperXml();
|
||||
globalConfig.setMapperXmlPath(mapperPath);
|
||||
// 配置 Mapper XML 生成路径和文件名
|
||||
globalConfig.getMapperXmlConfig()
|
||||
.setFilePrefix("") // 设置合适的前缀
|
||||
.setFileSuffix("Mapper"); // 确保设置正确的后缀名
|
||||
return globalConfig;
|
||||
}
|
||||
private GlobalConfig createGlobalConfigUseStyle2() {
|
||||
// 创建配置内容
|
||||
GlobalConfig globalConfig = new GlobalConfig();
|
||||
// 设置项目源目录和基础包
|
||||
globalConfig.getPackageConfig()
|
||||
.setSourceDir(model_path)
|
||||
.setBasePackage(packageName);
|
||||
// 启用生成 entity,并启用 Lombok
|
||||
globalConfig.setEntityGenerateEnable(true);
|
||||
globalConfig.setEntityWithLombok(true);
|
||||
// 设置项目的JDK版本
|
||||
globalConfig.setEntityJdkVersion(17);
|
||||
// 启用生成 mapper、service、controller
|
||||
globalConfig.enableEntity();
|
||||
globalConfig.enableMapper();
|
||||
globalConfig.enableService();
|
||||
globalConfig.enableServiceImpl();
|
||||
globalConfig.enableController();
|
||||
globalConfig.enableMapperXml();
|
||||
globalConfig.setMapperXmlPath(mapperPath);
|
||||
// 配置 Mapper XML 生成路径和文件名
|
||||
globalConfig.getMapperXmlConfig()
|
||||
.setFilePrefix("") // 设置合适的前缀
|
||||
.setFileSuffix("Mapper"); // 确保设置正确的后缀名
|
||||
//设置表前缀和只生成哪些表
|
||||
// globalConfig.setTablePrefix("tb_");
|
||||
globalConfig.setGenerateTable(tables);
|
||||
// 返回配置
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
}
|
||||
8
pom.xml
8
pom.xml
@ -21,6 +21,7 @@
|
||||
<module>ebike-operate</module>
|
||||
<module>ebike-orders</module>
|
||||
<module>ebike-report</module>
|
||||
<module>ebike-payment</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
@ -209,6 +210,13 @@
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-launcher</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user