feat(payment): 添加支付功能支持微信和支付宝
- 集成微信支付和支付宝支付SDK - 添加支付配置文件和配置类 - 实现支付控制器提供创建订单和处理回调接口 - 更新内容购买服务支持第三方支付方式 - 添加支付订单服务处理支付状态更新 - 修改CMS内容服务添加收藏和查看记录功能 - 更新应用配置文件适配开发环境和Redis连接 - 升级分页插件版本并添加统一SQL解析器依赖
This commit is contained in:
parent
d33d567b81
commit
e16fbdf2d6
27
pom.xml
27
pom.xml
|
|
@ -164,7 +164,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.6</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mybatis</groupId>
|
||||
|
|
@ -198,9 +198,20 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 统一的jsqlparser版本 -->
|
||||
<dependency>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
<version>4.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 核心依赖 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
|
|
@ -257,6 +268,20 @@
|
|||
<version>1.2.83</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信支付SDK -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-pay</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 支付宝SDK -->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.38.0.ALL</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -55,4 +55,31 @@ public class HttpUtil {
|
|||
|
||||
return response.body();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送POST请求到指定URL
|
||||
*
|
||||
* @param url 请求URL
|
||||
* @param requestBody 请求体字符串
|
||||
* @return 响应结果
|
||||
* @throws Exception 异常信息
|
||||
*/
|
||||
public static String post(String url, String requestBody) throws Exception {
|
||||
// 创建HttpClient实例
|
||||
HttpClient client = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(30))
|
||||
.build();
|
||||
|
||||
// 构建HttpRequest
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.header("Content-Type", "application/xml")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
|
||||
.build();
|
||||
|
||||
// 发送请求并获取响应
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
return response.body();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 支付配置类
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "payment")
|
||||
@Data
|
||||
public class PaymentConfig {
|
||||
// 微信支付配置
|
||||
private WechatPayConfig wechat;
|
||||
// 支付宝支付配置
|
||||
private AlipayConfig alipay;
|
||||
|
||||
/**
|
||||
* 微信支付配置
|
||||
*/
|
||||
@Data
|
||||
public static class WechatPayConfig {
|
||||
// 应用ID
|
||||
private String appId;
|
||||
// 商户号
|
||||
private String mchId;
|
||||
// 商户密钥
|
||||
private String mchKey;
|
||||
// 商户API证书序列号
|
||||
private String mchSerialNo;
|
||||
// 商户私钥文件路径
|
||||
private String privateKeyPath;
|
||||
// 微信服务器地址
|
||||
private String domain;
|
||||
// 支付回调地址
|
||||
private String notifyUrl;
|
||||
// 支付成功跳转地址
|
||||
private String returnUrl;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝支付配置
|
||||
*/
|
||||
@Data
|
||||
public static class AlipayConfig {
|
||||
// 应用ID
|
||||
private String appId;
|
||||
// 商户私钥
|
||||
private String privateKey;
|
||||
// 支付宝公钥
|
||||
private String publicKey;
|
||||
// 支付回调地址
|
||||
private String notifyUrl;
|
||||
// 支付成功跳转地址
|
||||
private String returnUrl;
|
||||
// 签名类型
|
||||
private String signType;
|
||||
// 字符编码
|
||||
private String charset;
|
||||
// 支付宝网关
|
||||
private String gatewayUrl;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -170,4 +170,30 @@ public class CmsContentController {
|
|||
public CommonResult<Boolean> deleteById(@PathVariable("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.deleteById(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/addFavorite")
|
||||
@Operation(summary = "添加收藏", description = "添加内容收藏")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> addFavorite(@RequestParam("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.addFavorite(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加查看记录
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/addView")
|
||||
@Operation(summary = "添加查看记录", description = "添加内容查看记录")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> addView(@RequestParam("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.addView(contentId) > 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.PaymentOrder;
|
||||
import com.kexue.skills.service.PayService;
|
||||
import com.kexue.skills.service.PaymentOrderService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付控制器
|
||||
*/
|
||||
@Tag(name = "支付管理 Api")
|
||||
@RestController
|
||||
@RequestMapping("/api/pay")
|
||||
public class PayController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PayController.class);
|
||||
|
||||
@Resource
|
||||
private PayService payService;
|
||||
|
||||
@Resource
|
||||
private PaymentOrderService paymentOrderService;
|
||||
|
||||
/**
|
||||
* 创建微信支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 微信支付参数
|
||||
*/
|
||||
@Operation(summary = "创建微信支付订单", description = "创建微信支付订单")
|
||||
@PostMapping("/wx/create")
|
||||
public CommonResult<Map<String, String>> createWechatPay(@RequestBody PaymentOrder order) {
|
||||
try {
|
||||
// 创建支付订单
|
||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||
// 生成微信支付参数
|
||||
Map<String, String> payParams = payService.createWechatPay(createdOrder);
|
||||
return CommonResult.success(payParams);
|
||||
} catch (Exception e) {
|
||||
logger.error("创建微信支付订单失败", e);
|
||||
return CommonResult.failed("创建微信支付订单失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
@Operation(summary = "处理微信支付回调", description = "处理微信支付回调")
|
||||
@PostMapping("/pay/wx/notify")
|
||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||
return payService.handleWechatPayNotify(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付宝支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 支付宝支付表单
|
||||
*/
|
||||
@Operation(summary = "创建支付宝支付订单", description = "创建支付宝支付订单")
|
||||
@PostMapping("/alipay/create")
|
||||
public CommonResult<String> createAlipay(@RequestBody PaymentOrder order) {
|
||||
try {
|
||||
// 创建支付订单
|
||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||
// 生成支付宝支付表单
|
||||
String form = payService.createAlipay(createdOrder);
|
||||
return CommonResult.success(form);
|
||||
} catch (Exception e) {
|
||||
logger.error("创建支付宝支付订单失败", e);
|
||||
return CommonResult.failed("创建支付宝支付订单失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付宝支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
@Operation(summary = "处理支付宝支付回调", description = "处理支付宝支付回调")
|
||||
@PostMapping("/ali-pay/trade/notify")
|
||||
public String handleAlipayNotify(HttpServletRequest request) {
|
||||
return payService.handleAlipayNotify(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付宝支付同步回调
|
||||
* @param request HTTP请求
|
||||
* @return 同步回调响应
|
||||
*/
|
||||
@Operation(summary = "处理支付宝支付同步回调", description = "处理支付宝支付同步回调")
|
||||
@GetMapping("/ali-pay/trade/return")
|
||||
public CommonResult<Map<String, Object>> handleAlipayReturn(HttpServletRequest request) {
|
||||
Map<String, Object> result = payService.handleAlipayReturn(request);
|
||||
if (result.get("success").equals(true)) {
|
||||
return CommonResult.success(result);
|
||||
} else {
|
||||
return CommonResult.failed(result.get("message").toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,24 @@ public interface CmsContentMapper {
|
|||
*/
|
||||
List<CmsContent> getPageList(CmsContentDto queryDto);
|
||||
|
||||
/**
|
||||
* 带分页的查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 查询结果
|
||||
*/
|
||||
List<CmsContent> getPageListWithPagination(@Param("queryDto") CmsContentDto queryDto, @Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 查询总记录数
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 总记录数
|
||||
*/
|
||||
int getPageListCount(CmsContentDto queryDto);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,15 +37,6 @@ public interface CmsContentService extends BaseService {
|
|||
*/
|
||||
CmsContent queryById(Long contentId);
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据,带用户ID
|
||||
*
|
||||
* @param contentId 主键
|
||||
* @param userId 用户ID
|
||||
* @return 实例对象
|
||||
*/
|
||||
CmsContent queryById(Long contentId, Long userId);
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
|
|
@ -115,27 +106,31 @@ public interface CmsContentService extends BaseService {
|
|||
* 添加收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @param userName 用户名
|
||||
* @return 影响行数
|
||||
*/
|
||||
int addFavorite(Long contentId, Long userId, String userName);
|
||||
int addFavorite(Long contentId);
|
||||
|
||||
/**
|
||||
* 取消收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @return 影响行数
|
||||
*/
|
||||
int removeFavorite(Long contentId, Long userId);
|
||||
int removeFavorite(Long contentId);
|
||||
|
||||
/**
|
||||
* 检查用户是否已收藏该内容
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @return 是否已收藏
|
||||
*/
|
||||
boolean isFavorited(Long contentId, Long userId);
|
||||
boolean isFavorited(Long contentId);
|
||||
|
||||
/**
|
||||
* 添加查看记录
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 影响行数
|
||||
*/
|
||||
int addView(Long contentId);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.kexue.skills.service;
|
||||
|
||||
import com.kexue.skills.entity.PaymentOrder;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付服务接口
|
||||
*/
|
||||
public interface PayService {
|
||||
/**
|
||||
* 创建微信支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 微信支付参数
|
||||
*/
|
||||
Map<String, String> createWechatPay(PaymentOrder order);
|
||||
|
||||
/**
|
||||
* 处理微信支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
String handleWechatPayNotify(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 创建支付宝支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 支付宝支付表单
|
||||
*/
|
||||
String createAlipay(PaymentOrder order);
|
||||
|
||||
/**
|
||||
* 处理支付宝支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
String handleAlipayNotify(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 处理支付宝支付同步回调
|
||||
* @param request HTTP请求
|
||||
* @return 同步回调响应
|
||||
*/
|
||||
Map<String, Object> handleAlipayReturn(HttpServletRequest request);
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
|||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.CmsContentView;
|
||||
import com.kexue.skills.entity.CmsContentLike;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.kexue.skills.entity.dto.CmsContentDto;
|
||||
import com.kexue.skills.mapper.CmsContentMapper;
|
||||
import com.kexue.skills.mapper.CmsContentViewMapper;
|
||||
|
|
@ -17,6 +18,8 @@ import javax.annotation.Resource;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* (CmsContent)表服务实现类
|
||||
*
|
||||
|
|
@ -43,9 +46,26 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
*/
|
||||
@Override
|
||||
public PageInfo<CmsContent> getPageList(CmsContentDto queryDto) {
|
||||
// 添加参数校验,确保分页参数有效
|
||||
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
|
||||
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
|
||||
}
|
||||
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
|
||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 打印分页参数
|
||||
System.out.println("PageNum: " + queryDto.getPageNum() + ", PageSize: " + queryDto.getPageSize());
|
||||
|
||||
// 使用PageHelper进行分页
|
||||
PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageList(queryDto);
|
||||
return new PageInfo<>(list);
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
|
||||
// 打印分页结果
|
||||
System.out.println("Total: " + pageInfo.getTotal() + ", PageSize: " + pageInfo.getPageSize() + ", List Size: " + list.size());
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -67,35 +87,27 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
*/
|
||||
@Override
|
||||
public CmsContent queryById(Long contentId) {
|
||||
return this.cmsContentMapper.queryById(contentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据,带用户ID
|
||||
*
|
||||
* @param contentId 主键
|
||||
* @param userId 用户ID
|
||||
* @return 实例对象
|
||||
*/
|
||||
@Override
|
||||
public CmsContent queryById(Long contentId, Long userId) {
|
||||
CmsContent content = this.cmsContentMapper.queryById(contentId);
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果用户ID不为空,添加用户查看记录
|
||||
if (userId != null) {
|
||||
try {
|
||||
// 尝试获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
// 检查用户是否已经查看过该内容(5分钟内)
|
||||
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
if (existingView == null) {
|
||||
// 新增查看记录
|
||||
CmsContentView viewRecord = new CmsContentView();
|
||||
viewRecord.setUserId(userId);
|
||||
viewRecord.setUserName(StpUtil.getLoginIdAsString());
|
||||
viewRecord.setContentId(contentId);
|
||||
viewRecord.setContentTitle(content.getTitle());
|
||||
viewRecord.setViewTime(new Date());
|
||||
viewRecord.setDeleteFlag(0);
|
||||
viewRecord.setCreateBy(StpUtil.getLoginIdAsString());
|
||||
viewRecord.setUpdateBy(StpUtil.getLoginIdAsString());
|
||||
cmsContentViewMapper.insert(viewRecord);
|
||||
} else {
|
||||
// 检查是否超过5分钟
|
||||
|
|
@ -103,9 +115,12 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
if (existingView.getViewTime().before(fiveMinutesAgo)) {
|
||||
// 更新查看时间
|
||||
existingView.setViewTime(new Date());
|
||||
existingView.setUpdateBy(StpUtil.getLoginIdAsString());
|
||||
cmsContentViewMapper.update(existingView);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 未登录用户,不记录查看历史
|
||||
}
|
||||
|
||||
return content;
|
||||
|
|
@ -253,12 +268,15 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
* 添加收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @param userName 用户名
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
public int addFavorite(Long contentId, Long userId, String userName) {
|
||||
public int addFavorite(Long contentId) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
// 获取当前登录用户名
|
||||
String userName = StpUtil.getLoginIdAsString();
|
||||
|
||||
// 检查内容是否存在
|
||||
CmsContent content = this.cmsContentMapper.queryById(contentId);
|
||||
if (content == null) {
|
||||
|
|
@ -291,11 +309,13 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
* 取消收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
public int removeFavorite(Long contentId, Long userId) {
|
||||
public int removeFavorite(Long contentId) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
|
||||
// 检查用户是否已经收藏过该内容
|
||||
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
if (existingLike == null) {
|
||||
|
|
@ -319,15 +339,69 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
* 检查用户是否已收藏该内容
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param userId 用户ID
|
||||
* @return 是否已收藏
|
||||
*/
|
||||
@Override
|
||||
public boolean isFavorited(Long contentId, Long userId) {
|
||||
if (userId == null) {
|
||||
public boolean isFavorited(Long contentId) {
|
||||
try {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
return existingLike != null;
|
||||
} catch (Exception e) {
|
||||
// 未登录用户,返回false
|
||||
return false;
|
||||
}
|
||||
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
return existingLike != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加查看记录
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
public int addView(Long contentId) {
|
||||
try {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
// 获取当前登录用户名
|
||||
String userName = StpUtil.getLoginIdAsString();
|
||||
|
||||
// 检查内容是否存在
|
||||
CmsContent content = this.cmsContentMapper.queryById(contentId);
|
||||
if (content == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查用户是否已经查看过该内容(5分钟内)
|
||||
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
if (existingView == null) {
|
||||
// 新增查看记录
|
||||
CmsContentView viewRecord = new CmsContentView();
|
||||
viewRecord.setUserId(userId);
|
||||
viewRecord.setUserName(userName);
|
||||
viewRecord.setContentId(contentId);
|
||||
viewRecord.setContentTitle(content.getTitle());
|
||||
viewRecord.setViewTime(new Date());
|
||||
viewRecord.setDeleteFlag(0);
|
||||
viewRecord.setCreateBy(userName);
|
||||
viewRecord.setUpdateBy(userName);
|
||||
return cmsContentViewMapper.insert(viewRecord);
|
||||
} else {
|
||||
// 检查是否超过5分钟
|
||||
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
|
||||
if (existingView.getViewTime().before(fiveMinutesAgo)) {
|
||||
// 更新查看时间
|
||||
existingView.setViewTime(new Date());
|
||||
existingView.setUpdateBy(userName);
|
||||
return cmsContentViewMapper.update(existingView);
|
||||
}
|
||||
return 0; // 5分钟内已查看过,不重复记录
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 未登录用户,不记录查看历史
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
*
|
||||
* @param userId 用户ID
|
||||
* @param contentId 内容ID
|
||||
* @param payType 支付方式:1.余额支付 2.积分支付
|
||||
* @param payType 支付方式:1.余额支付 2.积分支付 3.微信支付 4.支付宝支付
|
||||
* @return 购买结果
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -203,6 +203,11 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
|
||||
// 扣除用户余额
|
||||
this.accountService.reduceBalance(userId, price, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
||||
|
||||
// 6. 更新购买记录状态
|
||||
purchase.setStatus(2); // 已支付
|
||||
purchase.setPurchaseTime(new Date());
|
||||
this.insert(purchase);
|
||||
} else if (payType == 2) {
|
||||
// 积分支付
|
||||
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
||||
|
|
@ -213,15 +218,25 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
|
||||
// 扣除用户积分
|
||||
this.pointsAccountService.reducePoints(userId, points, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
||||
|
||||
// 6. 更新购买记录状态
|
||||
purchase.setStatus(2); // 已支付
|
||||
purchase.setPurchaseTime(new Date());
|
||||
this.insert(purchase);
|
||||
} else if (payType == 3 || payType == 4) {
|
||||
// 微信支付或支付宝支付
|
||||
// 这里只创建购买记录,实际支付由前端调用支付接口完成
|
||||
// 支付完成后通过回调更新购买记录状态
|
||||
BigDecimal price = content.getPrice();
|
||||
purchase.setAmount(price);
|
||||
purchase.setPoints(0);
|
||||
|
||||
// 插入购买记录(状态为待支付)
|
||||
this.insert(purchase);
|
||||
} else {
|
||||
Assert.isTrue(false, "不支持的支付方式");
|
||||
}
|
||||
|
||||
// 6. 更新购买记录状态
|
||||
purchase.setStatus(2); // 已支付
|
||||
purchase.setPurchaseTime(new Date());
|
||||
this.insert(purchase);
|
||||
|
||||
return purchase;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,392 @@
|
|||
package com.kexue.skills.service.impl;
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.alipay.api.response.AlipayTradePagePayResponse;
|
||||
import com.kexue.skills.common.util.HttpUtil;
|
||||
import com.kexue.skills.config.PaymentConfig;
|
||||
import com.kexue.skills.entity.PaymentOrder;
|
||||
import com.kexue.skills.service.PayService;
|
||||
import com.kexue.skills.service.PaymentOrderService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 支付服务实现类
|
||||
*/
|
||||
@Service("payService")
|
||||
public class PayServiceImpl implements PayService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
|
||||
|
||||
@Resource
|
||||
private PaymentConfig paymentConfig;
|
||||
|
||||
@Resource
|
||||
private PaymentOrderService paymentOrderService;
|
||||
|
||||
/**
|
||||
* 生成随机字符串
|
||||
* @return 随机字符串
|
||||
*/
|
||||
private String generateNonceStr() {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成MD5签名
|
||||
* @param params 参数
|
||||
* @param key 密钥
|
||||
* @return 签名
|
||||
*/
|
||||
private String generateSignature(Map<String, String> params, String key) {
|
||||
// 排序参数
|
||||
List<String> keys = new ArrayList<>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
// 构建签名字符串
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String k : keys) {
|
||||
String v = params.get(k);
|
||||
if (v != null && !v.isEmpty()) {
|
||||
sb.append(k).append("=").append(v).append("&");
|
||||
}
|
||||
}
|
||||
sb.append("key=").append(key);
|
||||
|
||||
// 生成MD5
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] bytes = md.digest(sb.toString().getBytes("UTF-8"));
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
String hex = Integer.toHexString(b & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
result.append("0");
|
||||
}
|
||||
result.append(hex);
|
||||
}
|
||||
return result.toString().toUpperCase();
|
||||
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
|
||||
logger.error("生成签名失败", e);
|
||||
throw new RuntimeException("生成签名失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Map转换为XML
|
||||
* @param params 参数
|
||||
* @return XML字符串
|
||||
*/
|
||||
private String mapToXml(Map<String, String> params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<xml>");
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
sb.append("<").append(entry.getKey()).append(">").append(entry.getValue()).append("</").append(entry.getKey()).append(">");
|
||||
}
|
||||
sb.append("</xml>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将XML转换为Map
|
||||
* @param xml XML字符串
|
||||
* @return Map
|
||||
*/
|
||||
private Map<String, String> xmlToMap(String xml) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
try {
|
||||
// 简单的XML解析
|
||||
String content = xml.replaceAll("<xml>", "").replaceAll("</xml>", "");
|
||||
String[] elements = content.split("</");
|
||||
for (String element : elements) {
|
||||
if (element.isEmpty()) continue;
|
||||
int idx = element.indexOf(">");
|
||||
if (idx == -1) continue;
|
||||
String key = element.substring(1, idx);
|
||||
String value = element.substring(idx + 1);
|
||||
map.put(key, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("XML解析失败", e);
|
||||
throw new RuntimeException("XML解析失败", e);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建微信支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 微信支付参数
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> createWechatPay(PaymentOrder order) {
|
||||
try {
|
||||
// 构建微信支付参数
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("appid", paymentConfig.getWechat().getAppId());
|
||||
params.put("mch_id", paymentConfig.getWechat().getMchId());
|
||||
params.put("nonce_str", generateNonceStr());
|
||||
params.put("body", order.getProductName());
|
||||
params.put("out_trade_no", order.getOrderNo());
|
||||
params.put("total_fee", String.valueOf((int) (order.getAmount().doubleValue() * 100)));
|
||||
params.put("spbill_create_ip", "127.0.0.1");
|
||||
params.put("notify_url", paymentConfig.getWechat().getNotifyUrl());
|
||||
params.put("trade_type", "NATIVE");
|
||||
|
||||
// 生成签名
|
||||
String sign = generateSignature(params, paymentConfig.getWechat().getMchKey());
|
||||
params.put("sign", sign);
|
||||
|
||||
// 构建请求XML
|
||||
String xml = mapToXml(params);
|
||||
|
||||
// 发送请求到微信支付接口
|
||||
String xmlResult = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
|
||||
Map<String, String> result = xmlToMap(xmlResult);
|
||||
|
||||
// 处理响应
|
||||
if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
|
||||
Map<String, String> payParams = new HashMap<>();
|
||||
payParams.put("code_url", result.get("code_url"));
|
||||
payParams.put("order_no", order.getOrderNo());
|
||||
return payParams;
|
||||
} else {
|
||||
logger.error("微信支付下单失败: {}", result.get("return_msg"));
|
||||
throw new RuntimeException("微信支付下单失败: " + result.get("return_msg"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("创建微信支付订单失败", e);
|
||||
throw new RuntimeException("创建微信支付订单失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
@Override
|
||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||
try {
|
||||
// 读取回调数据
|
||||
InputStream inputStream = request.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
String xmlData = sb.toString();
|
||||
|
||||
// 解析XML
|
||||
Map<String, String> params = xmlToMap(xmlData);
|
||||
|
||||
// 验证签名
|
||||
String sign = params.get("sign");
|
||||
params.remove("sign");
|
||||
String expectedSign = generateSignature(params, paymentConfig.getWechat().getMchKey());
|
||||
|
||||
if (!sign.equals(expectedSign)) {
|
||||
logger.error("微信支付回调签名验证失败");
|
||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名验证失败]]></return_msg></xml>";
|
||||
}
|
||||
|
||||
// 处理支付结果
|
||||
if ("SUCCESS".equals(params.get("return_code")) && "SUCCESS".equals(params.get("result_code"))) {
|
||||
String orderNo = params.get("out_trade_no");
|
||||
String transactionId = params.get("transaction_id");
|
||||
|
||||
// 更新支付订单状态
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
}
|
||||
|
||||
return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
||||
} else {
|
||||
logger.error("微信支付回调失败: {}", params.get("return_msg"));
|
||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理微信支付回调失败", e);
|
||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付宝支付订单
|
||||
* @param order 支付订单信息
|
||||
* @return 支付宝支付表单
|
||||
*/
|
||||
@Override
|
||||
public String createAlipay(PaymentOrder order) {
|
||||
try {
|
||||
// 初始化支付宝客户端
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
paymentConfig.getAlipay().getGatewayUrl(),
|
||||
paymentConfig.getAlipay().getAppId(),
|
||||
paymentConfig.getAlipay().getPrivateKey(),
|
||||
"JSON",
|
||||
paymentConfig.getAlipay().getCharset(),
|
||||
paymentConfig.getAlipay().getPublicKey(),
|
||||
paymentConfig.getAlipay().getSignType());
|
||||
|
||||
// 创建支付请求
|
||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
||||
request.setNotifyUrl(paymentConfig.getAlipay().getNotifyUrl());
|
||||
request.setReturnUrl(paymentConfig.getAlipay().getReturnUrl());
|
||||
|
||||
// 构建请求参数
|
||||
Map<String, Object> bizContent = new HashMap<>();
|
||||
bizContent.put("out_trade_no", order.getOrderNo());
|
||||
bizContent.put("total_amount", order.getAmount().toString());
|
||||
bizContent.put("subject", order.getProductName());
|
||||
bizContent.put("body", order.getProductDesc());
|
||||
bizContent.put("timeout_express", "30m");
|
||||
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
|
||||
|
||||
request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
|
||||
|
||||
// 生成支付表单
|
||||
AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
|
||||
if (response.isSuccess()) {
|
||||
return response.getBody();
|
||||
} else {
|
||||
logger.error("支付宝支付下单失败: {}", response.getMsg());
|
||||
throw new RuntimeException("支付宝支付下单失败: " + response.getMsg());
|
||||
}
|
||||
} catch (AlipayApiException e) {
|
||||
logger.error("创建支付宝支付订单失败", e);
|
||||
throw new RuntimeException("创建支付宝支付订单失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付宝支付回调
|
||||
* @param request HTTP请求
|
||||
* @return 回调响应
|
||||
*/
|
||||
@Override
|
||||
public String handleAlipayNotify(HttpServletRequest request) {
|
||||
try {
|
||||
// 获取回调参数
|
||||
Map<String, String> params = new HashMap<>();
|
||||
request.getParameterMap().forEach((key, values) -> {
|
||||
params.put(key, values[0]);
|
||||
});
|
||||
|
||||
// 初始化支付宝客户端
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
paymentConfig.getAlipay().getGatewayUrl(),
|
||||
paymentConfig.getAlipay().getAppId(),
|
||||
paymentConfig.getAlipay().getPrivateKey(),
|
||||
"JSON",
|
||||
paymentConfig.getAlipay().getCharset(),
|
||||
paymentConfig.getAlipay().getPublicKey(),
|
||||
paymentConfig.getAlipay().getSignType());
|
||||
|
||||
// 验证签名
|
||||
boolean signVerified = com.alipay.api.internal.util.AlipaySignature.rsaCheckV1(
|
||||
params, paymentConfig.getAlipay().getPublicKey(),
|
||||
paymentConfig.getAlipay().getCharset(),
|
||||
paymentConfig.getAlipay().getSignType());
|
||||
|
||||
if (!signVerified) {
|
||||
logger.error("支付宝支付回调签名验证失败");
|
||||
return "failure";
|
||||
}
|
||||
|
||||
// 处理支付结果
|
||||
String tradeStatus = params.get("trade_status");
|
||||
if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
|
||||
String orderNo = params.get("out_trade_no");
|
||||
String transactionId = params.get("trade_no");
|
||||
|
||||
// 更新支付订单状态
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
}
|
||||
|
||||
return "success";
|
||||
} else {
|
||||
logger.error("支付宝支付回调失败: {}", tradeStatus);
|
||||
return "failure";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理支付宝支付回调失败", e);
|
||||
return "failure";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付宝支付同步回调
|
||||
* @param request HTTP请求
|
||||
* @return 同步回调响应
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> handleAlipayReturn(HttpServletRequest request) {
|
||||
try {
|
||||
// 获取回调参数
|
||||
Map<String, String> params = new HashMap<>();
|
||||
request.getParameterMap().forEach((key, values) -> {
|
||||
params.put(key, values[0]);
|
||||
});
|
||||
|
||||
// 初始化支付宝客户端
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
paymentConfig.getAlipay().getGatewayUrl(),
|
||||
paymentConfig.getAlipay().getAppId(),
|
||||
paymentConfig.getAlipay().getPrivateKey(),
|
||||
"JSON",
|
||||
paymentConfig.getAlipay().getCharset(),
|
||||
paymentConfig.getAlipay().getPublicKey(),
|
||||
paymentConfig.getAlipay().getSignType());
|
||||
|
||||
// 验证签名
|
||||
boolean signVerified = com.alipay.api.internal.util.AlipaySignature.rsaCheckV1(
|
||||
params, paymentConfig.getAlipay().getPublicKey(),
|
||||
paymentConfig.getAlipay().getCharset(),
|
||||
paymentConfig.getAlipay().getSignType());
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (signVerified) {
|
||||
String tradeStatus = params.get("trade_status");
|
||||
if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
|
||||
result.put("success", true);
|
||||
result.put("orderNo", params.get("out_trade_no"));
|
||||
result.put("message", "支付成功");
|
||||
} else {
|
||||
result.put("success", false);
|
||||
result.put("message", "支付失败");
|
||||
}
|
||||
} else {
|
||||
result.put("success", false);
|
||||
result.put("message", "签名验证失败");
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
logger.error("处理支付宝支付同步回调失败", e);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", false);
|
||||
result.put("message", "处理失败");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -30,6 +30,9 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
@Resource
|
||||
private AccountService accountService;
|
||||
|
||||
@Resource
|
||||
private com.kexue.skills.service.ContentPurchaseService contentPurchaseService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
|
|
@ -189,7 +192,7 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
// 更新订单状态
|
||||
this.updateStatus(order.getOrderId(), status, channelOrderNo);
|
||||
|
||||
// 如果支付成功,更新账户余额
|
||||
// 如果支付成功,处理相关业务逻辑
|
||||
if (status == 2) { // 2.已支付
|
||||
// 根据业务类型处理不同的业务逻辑
|
||||
if ("recharge".equals(order.getBusinessType())) {
|
||||
|
|
@ -197,8 +200,17 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
this.accountService.addBalance(order.getUserId(), order.getAmount(), orderNo,
|
||||
order.getBusinessId(), order.getBusinessType(), "充值成功");
|
||||
} else if ("purchase_content".equals(order.getBusinessType())) {
|
||||
// 购买内容业务,这里不需要操作余额,因为余额已经在购买时扣除
|
||||
// 只需要更新订单状态即可
|
||||
// 购买内容业务,更新购买记录状态
|
||||
try {
|
||||
// 查找对应的购买记录并更新状态
|
||||
com.kexue.skills.entity.ContentPurchase purchase = contentPurchaseService.queryByUserIdAndContentId(order.getUserId(), order.getBusinessId());
|
||||
if (purchase != null && purchase.getStatus() == 1) { // 1.待支付
|
||||
contentPurchaseService.updateStatus(purchase.getPurchaseId(), 2); // 2.已支付
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 记录错误但不影响支付回调的处理
|
||||
java.util.logging.Logger.getLogger(getClass().getName()).severe("更新购买记录状态失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
common:
|
||||
# Redis配置
|
||||
redis:
|
||||
# host: 127.0.0.1
|
||||
# port: 6379
|
||||
host: 43.248.97.19
|
||||
port: 16379
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
# host: 43.248.97.19
|
||||
# port: 16379
|
||||
password: 654321
|
||||
database: 1
|
||||
|
|
|
|||
|
|
@ -104,3 +104,26 @@ jetcache:
|
|||
web:
|
||||
upload:
|
||||
path: /kexue/agent-skills/upload/
|
||||
|
||||
# 支付配置
|
||||
payment:
|
||||
# 微信支付配置
|
||||
wechat:
|
||||
appId: wx7d13d99de5be3bfa
|
||||
mchId: 1673321732
|
||||
mchKey: UDuZXDcmy5Eb6o0nTNZhu6ek4DDh4K8B
|
||||
mchSerialNo: 5EFC47D3AA59BFD1AAE548F96B5E19E1C60F067D
|
||||
privateKeyPath: apiclient_key.pem
|
||||
domain: https://api.mch.weixin.qq.com
|
||||
notifyUrl: http://127.0.0.1:19001/pay/wx/notify
|
||||
returnUrl: http://127.0.0.1:19001/pay/success
|
||||
# 支付宝支付配置
|
||||
alipay:
|
||||
appId: 2021004138642603
|
||||
privateKey: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBzqh/sBfx8UsiKIzSaGm3QwMape+PEmHaFYsP0XxRLyRe5d3H1r4JBvE/GBCDarXkZMvJ3PKeUpO61i7LZtNBN7M6XbMvs/eiaipUmWCNF4IK+ilhOqr8GNryjb6tBnO0uzd1c7UmAvxF+MKkxti0qfscP+Tr6pkuF14DofOyITY56x0y36DmEc85rr213llQ/bSX5nVPHWfddtrqB+TNFvrnAN10NxnUurDK+wd7fKq3TgMjYNDINPGxFYbYezeIGvYj6E34mFS3b3wyxTcB5DeL4GV1FAWqJ0Yk+3hHT3OdmK/UnNEr55w+r3liQBCDRBoE4fldbG5CtW2/ER0lAgMBAAECggEAC2kgNMFFCZaddS49Ws2k5WA1qKUHjvsdsO8N32EZ3YUYXGM2gLem0uJSWKqD4RmDTcVyiJcsmLBHnjfvux+Z2HTOA4ZzFvFqBlPwzqkA7MYxP0fIVWyz1R9WN9Yv+cPEbhG7CU8XkHTYuknoylVUfWUn1s7jD736oyuYrxcQdgsHOHpLHngvsELLa1pv2EURohvr4p+zirMjFGuz3BVaGgVpWegn0nJ/8n1y0ZTM04Mvm/zXpGQQxfuUxrK2owQMFViY7BrRQXlPVeUM/IPAx7cvxLkR5hl9UgAl+nH6FCsm5osEvUln6VLhGTmNFBLCN9piX6sZaPEKZKRBCz0GQQKBgQDD4Dq+dGQAoCmnXdkzI6DHGXOePa+sGnj1Y55dRcrPWPKtCPeEnIPxhVCJ2+cqYK49K6youhLYzs3h8y/M4lh0JQLKP4zTSyZnARmdYHW/SyTu9BcHCdiPwZBrmn7bCWotGf3r5QRIJT6ilZEj8cLnF+9+gd0YyLyRE7Rmihq2UQKBgQCpps7qghRv3JIB0Hb4nBCbAeyPMjHj+7BSUsui2Dhdg3MeTk48a7RLl+r139pMzgTm5Pj0VG6qslUeqP2HlQ46o0Z2bPeohfXH4zMJi2amh4MvAFp4t8eNCc6faeqpJPTTQj3hS4drFnHEHBeFfgFCXZKhjYeP7SP2WVLOQvUAlQKBgFIq6fmjEaBBj7ep4sdVFsjuoFWtQthLcppd47z03hMFGSgFLu/uSFs0tYhfOyXH0M/QVmmhRO62Mh+qyE6GVNzD+dultQmd6Mok5/3gzQQmHaQvuMk3FCWZ6V96O+Temi+5S499TsKE/TVu0Kfnbv9KRykmiP0wmAmz3mV1YadBAoGABc5quIX5MxbmfF9pIvscamG3efMq1/WuRDMHOyyRSUoNb5UYgmLhSdEKPp4Jt6U5b7mYd6xIGVl/Jkx8WN6WHRWnfLggBcmH7u5sub/mpH5w0/P8JLONhds3Eieq210jb/ONcJ+II/chr6eSeoQkgOP498SDRj7Eg1LtTZfnEL0CgYBnMeXQWKUae+xES5NsEX7D0lwSCotb7attTHeE6vZOI77TzsURb4jOEAhYVsdJ8lm+J1Sv1Wjnr2yMxiRH2G+I1tUxGcI8OkRT26FxFdMl1RdbTf+gDM8IjMiu+Li+plIzb28VtF8q/Umgd+5LTlSBmM2yoiL8RKtmStjr5iIuhA=="
|
||||
publicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnakP04nUmsoFoveIvOhbLqkA1xQuYtvkrqq2AVvTsbtqpsEOTm9G095e2rBYLp89oDcf6L6BhtJPwdrhnA+qifUyVmACI9sprrsGeRYQgndK7y4c6spQcSnsnakSxlIp22j7pvBXNAZuqud2hQV+TOLKEUh1W3izTgMj/Ejoh3ZsCjgDRtTVgaytzSdHYrhNku+pIrl15/xVGJED99RYXkR8GHawxuK+vWVmxU0tiTCwTsqLz43v6TtCZ+/UfLL/luwp9B4ZvB+0qon82LILYr6oxs10kE2IAvryuDToAc1s/v/36jgt+7DXwqzfUDksHhVLHdJHChyc4ax5HmMsBwIDAQAB"
|
||||
notifyUrl: http://127.0.0.1:19001/pay/ali-pay/trade/notify
|
||||
returnUrl: https://shuziren.xueai.art/alipay-success
|
||||
signType: RSA2
|
||||
charset: UTF-8
|
||||
gatewayUrl: https://openapi.alipay.com/gateway.do
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
spring:
|
||||
profiles:
|
||||
active: prod
|
||||
active: dev
|
||||
application:
|
||||
name: agentSkills
|
||||
version: 1.0.0
|
||||
|
|
|
|||
|
|
@ -100,6 +100,98 @@
|
|||
</if>
|
||||
</select>
|
||||
|
||||
<!--带分页的查询-->
|
||||
<select id="getPageListWithPagination" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time,
|
||||
view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
<where>
|
||||
<if test="queryDto.contentId != null">
|
||||
and content_id = #{queryDto.contentId}
|
||||
</if>
|
||||
<if test="queryDto.title != null and queryDto.title != ''">
|
||||
and (title like concat('%', #{queryDto.title}, '%') or summary like concat('%', #{queryDto.title}, '%'))
|
||||
</if>
|
||||
<if test="queryDto.contentType != null">
|
||||
and content_type = #{queryDto.contentType}
|
||||
</if>
|
||||
<if test="queryDto.authorId != null">
|
||||
and author_id = #{queryDto.authorId}
|
||||
</if>
|
||||
<if test="queryDto.authorName != null and queryDto.authorName != ''">
|
||||
and author_name like concat('%', #{queryDto.authorName}, '%')
|
||||
</if>
|
||||
<if test="queryDto.auditStatus != null">
|
||||
and audit_status = #{queryDto.auditStatus}
|
||||
</if>
|
||||
<if test="queryDto.publishStatus != null">
|
||||
and publish_status = #{queryDto.publishStatus}
|
||||
</if>
|
||||
<if test="queryDto.createBy != null and queryDto.createBy != ''">
|
||||
and create_by like concat('%', #{queryDto.createBy}, '%')
|
||||
</if>
|
||||
<if test="queryDto.deleteFlag != null">
|
||||
and delete_flag = #{queryDto.deleteFlag}
|
||||
</if>
|
||||
<if test="queryDto.isOfficial != null">
|
||||
and is_official = #{queryDto.isOfficial}
|
||||
</if>
|
||||
<if test="queryDto.tagId != null">
|
||||
and find_in_set(#{queryDto.tagId}, tags)
|
||||
</if>
|
||||
</where>
|
||||
<if test="queryDto.sortBy != null and queryDto.sortBy != ''">
|
||||
order by ${queryDto.sortBy} ${queryDto.sortDesc ? 'desc' : 'asc'}
|
||||
</if>
|
||||
<if test="queryDto.sortBy == null or queryDto.sortBy == ''">
|
||||
order by sort asc, create_time desc
|
||||
</if>
|
||||
limit #{offset}, #{limit}
|
||||
</select>
|
||||
|
||||
<!--查询总记录数-->
|
||||
<select id="getPageListCount" resultType="int">
|
||||
select count(*)
|
||||
from cms_content
|
||||
<where>
|
||||
<if test="contentId != null">
|
||||
and content_id = #{contentId}
|
||||
</if>
|
||||
<if test="title != null and title != ''">
|
||||
and (title like concat('%', #{title}, '%') or summary like concat('%', #{title}, '%'))
|
||||
</if>
|
||||
<if test="contentType != null">
|
||||
and content_type = #{contentType}
|
||||
</if>
|
||||
<if test="authorId != null">
|
||||
and author_id = #{authorId}
|
||||
</if>
|
||||
<if test="authorName != null and authorName != ''">
|
||||
and author_name like concat('%', #{authorName}, '%')
|
||||
</if>
|
||||
<if test="auditStatus != null">
|
||||
and audit_status = #{auditStatus}
|
||||
</if>
|
||||
<if test="publishStatus != null">
|
||||
and publish_status = #{publishStatus}
|
||||
</if>
|
||||
<if test="createBy != null and createBy != ''">
|
||||
and create_by like concat('%', #{createBy}, '%')
|
||||
</if>
|
||||
<if test="deleteFlag != null">
|
||||
and delete_flag = #{deleteFlag}
|
||||
</if>
|
||||
<if test="isOfficial != null">
|
||||
and is_official = #{isOfficial}
|
||||
</if>
|
||||
<if test="tagId != null">
|
||||
and find_in_set(#{tagId}, tags)
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!--查询列表-->
|
||||
<select id="getList" resultMap="CmsContentMap">
|
||||
select
|
||||
|
|
|
|||
Loading…
Reference in New Issue