增加支付宝打赏
This commit is contained in:
7
pom.xml
7
pom.xml
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -62,6 +63,12 @@
|
|||||||
<!-- <artifactId>gson</artifactId>-->
|
<!-- <artifactId>gson</artifactId>-->
|
||||||
<!-- <version>2.10.1</version>-->
|
<!-- <version>2.10.1</version>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alipay.sdk</groupId>
|
||||||
|
<artifactId>alipay-sdk-java</artifactId>
|
||||||
|
<version>4.40.806.ALL</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|||||||
27
src/main/java/com/ping/study/config/AlipayConfig.java
Normal file
27
src/main/java/com/ping/study/config/AlipayConfig.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package com.ping.study.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "alipay")
|
||||||
|
public class AlipayConfig {
|
||||||
|
|
||||||
|
private String gatewayUrl;
|
||||||
|
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
private String privateKey;
|
||||||
|
|
||||||
|
private String alipayPublicKey;
|
||||||
|
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
private String charset;
|
||||||
|
|
||||||
|
private String format;
|
||||||
|
|
||||||
|
private String signType;
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ public class WebMvc implements WebMvcConfigurer {
|
|||||||
.allowedOrigins("http://jrs77.xyz","https://jrs77.xyz",
|
.allowedOrigins("http://jrs77.xyz","https://jrs77.xyz",
|
||||||
"http://localhost:5173", "https://nba.1024x.icu",
|
"http://localhost:5173", "https://nba.1024x.icu",
|
||||||
"http://nba.1024x.icu","http://167.253.156.235:9006",
|
"http://nba.1024x.icu","http://167.253.156.235:9006",
|
||||||
"http://116.62.173.2:9001")
|
"http://116.62.173.2:9001","http://dns.1024x.icu:9005")
|
||||||
.allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
|
.allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
|
||||||
.allowedHeaders("X-Timestamp","X-Sign","*")
|
.allowedHeaders("X-Timestamp","X-Sign","*")
|
||||||
.allowCredentials(true) // 若不用 Cookie 也可为 false
|
.allowCredentials(true) // 若不用 Cookie 也可为 false
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ public class NbaController {
|
|||||||
if (loginUser == null){
|
if (loginUser == null){
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("请先登录");
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("请先登录");
|
||||||
}
|
}
|
||||||
log.info("{}:获取直播链接开始",loginUser.getEmail());
|
// log.info("{}:获取直播链接开始",loginUser.getEmail());
|
||||||
String ip = userUtil.getClientIp(request);
|
String ip = userUtil.getClientIp(request);
|
||||||
String url = urlsService.findUrlByGameIdAndType(gameId, playType);
|
String url = urlsService.findUrlByGameIdAndType(gameId, playType);
|
||||||
// log.info("来自ip:{} 用户:{}:获取直播链接成功:{}",ip,loginUser.getEmail(),url);
|
log.info("来自ip:{} 用户:{}:获取直播链接成功:{}",ip,loginUser.getEmail(),url);
|
||||||
return ResponseEntity.ok(url);
|
return ResponseEntity.ok(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.ping.study.controller.pay;
|
||||||
|
|
||||||
|
import com.ping.study.config.AlipayConfig;
|
||||||
|
import com.ping.study.model.dto.pay.CreateRewardOrderDto;
|
||||||
|
import com.ping.study.model.vo.pay.AlipayQrCodeVo;
|
||||||
|
import com.ping.study.model.vo.pay.PayOrderStatusVo;
|
||||||
|
import com.ping.study.pojo.NbaUser;
|
||||||
|
import com.ping.study.service.pay.AlipayService;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/pay/alipay")
|
||||||
|
@Slf4j
|
||||||
|
public class AlipayController {
|
||||||
|
|
||||||
|
private final AlipayService alipayService;
|
||||||
|
private final AlipayConfig alipayConfig;
|
||||||
|
|
||||||
|
public AlipayController(AlipayService alipayService, AlipayConfig alipayConfig) {
|
||||||
|
this.alipayService = alipayService;
|
||||||
|
this.alipayConfig = alipayConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建支付宝打赏二维码订单。
|
||||||
|
* 当前允许匿名打赏;如果用户已登录,会自动绑定 userId。
|
||||||
|
*/
|
||||||
|
@PostMapping("/reward/create")
|
||||||
|
public AlipayQrCodeVo createRewardOrder(@Valid @RequestBody CreateRewardOrderDto dto, HttpSession session) throws Exception {
|
||||||
|
NbaUser loginUser = (NbaUser) session.getAttribute("loginUser");
|
||||||
|
return alipayService.createRewardOrder(dto, loginUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付宝异步通知。
|
||||||
|
* 注意:该接口必须公网可访问,且不能要求登录。支付宝要求处理成功后返回纯文本 success。
|
||||||
|
*/
|
||||||
|
@PostMapping("/notify")
|
||||||
|
public String notify(HttpServletRequest request) throws Exception {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
Map<String, String[]> requestParams = request.getParameterMap();
|
||||||
|
for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
|
||||||
|
String[] values = entry.getValue();
|
||||||
|
if (values != null && values.length > 0) {
|
||||||
|
params.put(entry.getKey(), values[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("收到支付宝异步通知,orderNo={}, tradeStatus={}", params.get("out_trade_no"), params.get("trade_status"));
|
||||||
|
return alipayService.handleNotify(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端展示二维码后可轮询该接口获取支付状态。
|
||||||
|
*/
|
||||||
|
@GetMapping("/status/{orderNo}")
|
||||||
|
public PayOrderStatusVo queryOrderStatus(@PathVariable String orderNo) {
|
||||||
|
return alipayService.queryOrderStatus(orderNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于前端或部署后快速确认 notifyUrl 是否配置正确。
|
||||||
|
*/
|
||||||
|
@GetMapping("/config/notify-url")
|
||||||
|
public String notifyUrl() {
|
||||||
|
return alipayConfig.getNotifyUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package com.ping.study.controller.user;
|
package com.ping.study.controller.user;
|
||||||
|
|
||||||
|
|
||||||
|
import com.ping.study.mapper.PayOrderMapper;
|
||||||
import com.ping.study.model.dto.DtoUpdateUser;
|
import com.ping.study.model.dto.DtoUpdateUser;
|
||||||
import com.ping.study.model.dto.registerUserDto;
|
import com.ping.study.model.dto.registerUserDto;
|
||||||
|
|
||||||
|
import com.ping.study.model.vo.user.CurrentUserVo;
|
||||||
|
|
||||||
import com.ping.study.pojo.NbaUser;
|
import com.ping.study.pojo.NbaUser;
|
||||||
import com.ping.study.service.NbaUserService;
|
import com.ping.study.service.NbaUserService;
|
||||||
import com.ping.study.utils.MailUtil;
|
import com.ping.study.utils.MailUtil;
|
||||||
@@ -38,6 +41,9 @@ public class UserController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserUtil userUtil;
|
private UserUtil userUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PayOrderMapper payOrderMapper;
|
||||||
|
|
||||||
//发送验证码
|
//发送验证码
|
||||||
@RequestMapping("/send")
|
@RequestMapping("/send")
|
||||||
public String send(String email,Integer type) {
|
public String send(String email,Integer type) {
|
||||||
@@ -124,7 +130,7 @@ public class UserController {
|
|||||||
// 1. session 已登录
|
// 1. session 已登录
|
||||||
NbaUser loginUser = (NbaUser) session.getAttribute("loginUser");
|
NbaUser loginUser = (NbaUser) session.getAttribute("loginUser");
|
||||||
if (loginUser != null) {
|
if (loginUser != null) {
|
||||||
return loginUser.getEmail();
|
return buildCurrentUserVo(loginUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 尝试自动登录(记住我)
|
// 2. 尝试自动登录(记住我)
|
||||||
@@ -136,12 +142,17 @@ public class UserController {
|
|||||||
session.setAttribute("loginUser", user);
|
session.setAttribute("loginUser", user);
|
||||||
|
|
||||||
log.info("自动登录成功 -> {}", user.getEmail());
|
log.info("自动登录成功 -> {}", user.getEmail());
|
||||||
return user.getEmail();
|
return buildCurrentUserVo(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "未登录";
|
return "未登录";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CurrentUserVo buildCurrentUserVo(NbaUser user) {
|
||||||
|
int rewardUser = payOrderMapper.countSuccessRewardByUserId(Long.valueOf(user.getId())) > 0 ? 1 : 0;
|
||||||
|
return new CurrentUserVo(user.getEmail(), rewardUser);
|
||||||
|
}
|
||||||
|
|
||||||
// 退出登录(清 session + 清 token + 清 cookie)
|
// 退出登录(清 session + 清 token + 清 cookie)
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
public String logout(
|
public String logout(
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.ping.study.mapper;
|
|||||||
|
|
||||||
import com.ping.study.pojo.NbaUser;
|
import com.ping.study.pojo.NbaUser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
* @description 针对表【nba_user】的数据库操作Mapper
|
* @description 针对表【nba_user】的数据库操作Mapper
|
||||||
@@ -35,4 +37,6 @@ public interface NbaUserMapper {
|
|||||||
NbaUser selectByEmail(String email);
|
NbaUser selectByEmail(String email);
|
||||||
|
|
||||||
void updatePasswordByEmail(String email, String password);
|
void updatePasswordByEmail(String email, String password);
|
||||||
|
|
||||||
|
List<String> selectAllUserEmail();
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/main/java/com/ping/study/mapper/PayOrderMapper.java
Normal file
24
src/main/java/com/ping/study/mapper/PayOrderMapper.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package com.ping.study.mapper;
|
||||||
|
|
||||||
|
import com.ping.study.pojo.PayOrder;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
public interface PayOrderMapper {
|
||||||
|
|
||||||
|
int insert(PayOrder record);
|
||||||
|
|
||||||
|
PayOrder selectByOrderNo(@Param("orderNo") String orderNo);
|
||||||
|
|
||||||
|
int updateQrCodeAndStatus(@Param("orderNo") String orderNo,
|
||||||
|
@Param("qrCode") String qrCode,
|
||||||
|
@Param("status") String status);
|
||||||
|
|
||||||
|
int updatePaidByOrderNo(@Param("orderNo") String orderNo,
|
||||||
|
@Param("alipayTradeNo") String alipayTradeNo,
|
||||||
|
@Param("status") String status);
|
||||||
|
|
||||||
|
int updateStatusByOrderNo(@Param("orderNo") String orderNo,
|
||||||
|
@Param("status") String status);
|
||||||
|
|
||||||
|
int countSuccessRewardByUserId(@Param("userId") Long userId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.ping.study.model.dto.pay;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CreateRewardOrderDto {
|
||||||
|
|
||||||
|
@NotNull(message = "打赏金额不能为空")
|
||||||
|
@DecimalMin(value = "0.01", message = "打赏金额不能小于0.01元")
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
@Size(max = 128, message = "打赏备注不能超过128个字符")
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
@Size(max = 500, message = "留言不能超过500个字符")
|
||||||
|
private String liuyan;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.ping.study.model.vo.pay;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AlipayQrCodeVo {
|
||||||
|
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
private String qrCode;
|
||||||
|
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.ping.study.model.vo.pay;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PayOrderStatusVo {
|
||||||
|
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
private String alipayTradeNo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.ping.study.model.vo.user;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CurrentUserVo {
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为赞赏用户:1 是,0 否
|
||||||
|
*/
|
||||||
|
private Integer rewardUser;
|
||||||
|
}
|
||||||
59
src/main/java/com/ping/study/pojo/PayOrder.java
Normal file
59
src/main/java/com/ping/study/pojo/PayOrder.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package com.ping.study.pojo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PayOrder implements Serializable {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户订单号
|
||||||
|
*/
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户ID,匿名打赏时为空
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单标题/打赏备注
|
||||||
|
*/
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打赏留言
|
||||||
|
*/
|
||||||
|
private String liuyan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付金额
|
||||||
|
*/
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WAIT_PAY / SUCCESS / CLOSED / FAILED
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付宝交易号
|
||||||
|
*/
|
||||||
|
private String alipayTradeNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付宝返回的二维码链接
|
||||||
|
*/
|
||||||
|
private String qrCode;
|
||||||
|
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import com.ping.study.model.dto.DtoUpdateUser;
|
|||||||
import com.ping.study.model.dto.registerUserDto;
|
import com.ping.study.model.dto.registerUserDto;
|
||||||
import com.ping.study.pojo.NbaUser;
|
import com.ping.study.pojo.NbaUser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
* @description 针对表【nba_user】的数据库操作Service
|
* @description 针对表【nba_user】的数据库操作Service
|
||||||
@@ -24,4 +26,6 @@ public interface NbaUserService{
|
|||||||
String updateUser(DtoUpdateUser dtoUpdateUser);
|
String updateUser(DtoUpdateUser dtoUpdateUser);
|
||||||
|
|
||||||
NbaUser findByEmail(String email);
|
NbaUser findByEmail(String email);
|
||||||
|
|
||||||
|
List<String> selectAllUserEmail();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,14 @@ import com.ping.study.pojo.LoginLog;
|
|||||||
import com.ping.study.pojo.NbaUser;
|
import com.ping.study.pojo.NbaUser;
|
||||||
import com.ping.study.service.NbaUserService;
|
import com.ping.study.service.NbaUserService;
|
||||||
|
|
||||||
import com.ping.study.utils.UserUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -109,4 +108,10 @@ public class NbaUserServiceImpl implements NbaUserService {
|
|||||||
return nbaUserMapper.findByEmail(email);
|
return nbaUserMapper.findByEmail(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> selectAllUserEmail() {
|
||||||
|
List<String> emailList = nbaUserMapper.selectAllUserEmail();
|
||||||
|
return emailList;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/main/java/com/ping/study/service/pay/AlipayService.java
Normal file
17
src/main/java/com/ping/study/service/pay/AlipayService.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.ping.study.service.pay;
|
||||||
|
|
||||||
|
import com.ping.study.model.dto.pay.CreateRewardOrderDto;
|
||||||
|
import com.ping.study.model.vo.pay.AlipayQrCodeVo;
|
||||||
|
import com.ping.study.model.vo.pay.PayOrderStatusVo;
|
||||||
|
import com.ping.study.pojo.NbaUser;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface AlipayService {
|
||||||
|
|
||||||
|
AlipayQrCodeVo createRewardOrder(CreateRewardOrderDto dto, NbaUser loginUser) throws Exception;
|
||||||
|
|
||||||
|
String handleNotify(Map<String, String> params) throws Exception;
|
||||||
|
|
||||||
|
PayOrderStatusVo queryOrderStatus(String orderNo);
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package com.ping.study.service.pay.impl;
|
||||||
|
|
||||||
|
import com.alipay.api.AlipayClient;
|
||||||
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
|
import com.alipay.api.internal.util.AlipaySignature;
|
||||||
|
import com.alipay.api.request.AlipayTradePrecreateRequest;
|
||||||
|
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||||
|
import com.alipay.api.domain.AlipayTradePrecreateModel;
|
||||||
|
import com.ping.study.config.AlipayConfig;
|
||||||
|
import com.ping.study.mapper.PayOrderMapper;
|
||||||
|
import com.ping.study.model.dto.pay.CreateRewardOrderDto;
|
||||||
|
import com.ping.study.model.vo.pay.AlipayQrCodeVo;
|
||||||
|
import com.ping.study.model.vo.pay.PayOrderStatusVo;
|
||||||
|
import com.ping.study.pojo.NbaUser;
|
||||||
|
import com.ping.study.pojo.PayOrder;
|
||||||
|
import com.ping.study.service.pay.AlipayService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AlipayServiceImpl implements AlipayService {
|
||||||
|
|
||||||
|
private static final String STATUS_WAIT_PAY = "WAIT_PAY";
|
||||||
|
private static final String STATUS_SUCCESS = "SUCCESS";
|
||||||
|
private static final String STATUS_FAILED = "FAILED";
|
||||||
|
|
||||||
|
private final AlipayConfig alipayConfig;
|
||||||
|
private final PayOrderMapper payOrderMapper;
|
||||||
|
|
||||||
|
public AlipayServiceImpl(AlipayConfig alipayConfig, PayOrderMapper payOrderMapper) {
|
||||||
|
this.alipayConfig = alipayConfig;
|
||||||
|
this.payOrderMapper = payOrderMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AlipayQrCodeVo createRewardOrder(CreateRewardOrderDto dto, NbaUser loginUser) throws Exception {
|
||||||
|
BigDecimal totalAmount = dto.getTotalAmount().setScale(2, RoundingMode.HALF_UP);
|
||||||
|
String subject = StringUtils.hasText(dto.getSubject()) ? dto.getSubject() : "NBA赛事平台打赏";
|
||||||
|
String liuyan = StringUtils.hasText(dto.getLiuyan()) ? dto.getLiuyan() : null;
|
||||||
|
String orderNo = generateOrderNo();
|
||||||
|
|
||||||
|
PayOrder order = new PayOrder();
|
||||||
|
order.setOrderNo(orderNo);
|
||||||
|
order.setUserId(loginUser == null ? null : Long.valueOf(loginUser.getId()));
|
||||||
|
order.setSubject(subject);
|
||||||
|
order.setLiuyan(liuyan);
|
||||||
|
order.setTotalAmount(totalAmount);
|
||||||
|
order.setStatus(STATUS_WAIT_PAY);
|
||||||
|
order.setCreateTime(new Date());
|
||||||
|
order.setUpdateTime(new Date());
|
||||||
|
payOrderMapper.insert(order);
|
||||||
|
|
||||||
|
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
|
||||||
|
request.setNotifyUrl(alipayConfig.getNotifyUrl());
|
||||||
|
|
||||||
|
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||||
|
model.setOutTradeNo(orderNo);
|
||||||
|
model.setTotalAmount(totalAmount.toPlainString());
|
||||||
|
model.setSubject(subject);
|
||||||
|
model.setTimeoutExpress("30m");
|
||||||
|
request.setBizModel(model);
|
||||||
|
|
||||||
|
AlipayTradePrecreateResponse response = buildAlipayClient().execute(request);
|
||||||
|
if (response.isSuccess()) {
|
||||||
|
String qrCode = response.getQrCode();
|
||||||
|
payOrderMapper.updateQrCodeAndStatus(orderNo, qrCode, STATUS_WAIT_PAY);
|
||||||
|
return new AlipayQrCodeVo(orderNo, qrCode, totalAmount, STATUS_WAIT_PAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
payOrderMapper.updateStatusByOrderNo(orderNo, STATUS_FAILED);
|
||||||
|
log.error("支付宝预下单失败,orderNo={}, code={}, subCode={}, msg={}, subMsg={}",
|
||||||
|
orderNo, response.getCode(), response.getSubCode(), response.getMsg(), response.getSubMsg());
|
||||||
|
throw new RuntimeException("支付宝预下单失败:" + response.getSubMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public String handleNotify(Map<String, String> params) throws Exception {
|
||||||
|
boolean signVerified = AlipaySignature.rsaCheckV1(
|
||||||
|
params,
|
||||||
|
alipayConfig.getAlipayPublicKey(),
|
||||||
|
alipayConfig.getCharset(),
|
||||||
|
alipayConfig.getSignType()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!signVerified) {
|
||||||
|
log.warn("支付宝异步通知验签失败:{}", params);
|
||||||
|
return "failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tradeStatus = params.get("trade_status");
|
||||||
|
String outTradeNo = params.get("out_trade_no");
|
||||||
|
String tradeNo = params.get("trade_no");
|
||||||
|
String totalAmount = params.get("total_amount");
|
||||||
|
String appId = params.get("app_id");
|
||||||
|
|
||||||
|
if (!Objects.equals(appId, alipayConfig.getAppId())) {
|
||||||
|
log.warn("支付宝异步通知app_id不匹配,orderNo={}, notifyAppId={}", outTradeNo, appId);
|
||||||
|
return "failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
PayOrder order = payOrderMapper.selectByOrderNo(outTradeNo);
|
||||||
|
if (order == null) {
|
||||||
|
log.warn("支付宝异步通知订单不存在,orderNo={}", outTradeNo);
|
||||||
|
return "failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amountEquals(order.getTotalAmount(), new BigDecimal(totalAmount))) {
|
||||||
|
log.warn("支付宝异步通知金额不匹配,orderNo={}, localAmount={}, notifyAmount={}",
|
||||||
|
outTradeNo, order.getTotalAmount(), totalAmount);
|
||||||
|
return "failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STATUS_SUCCESS.equals(order.getStatus())) {
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
|
||||||
|
payOrderMapper.updatePaidByOrderNo(outTradeNo, tradeNo, STATUS_SUCCESS);
|
||||||
|
log.info("支付宝打赏支付成功,orderNo={}, tradeNo={}, amount={}", outTradeNo, tradeNo, totalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayOrderStatusVo queryOrderStatus(String orderNo) {
|
||||||
|
PayOrder order = payOrderMapper.selectByOrderNo(orderNo);
|
||||||
|
if (order == null) {
|
||||||
|
throw new RuntimeException("订单不存在");
|
||||||
|
}
|
||||||
|
return new PayOrderStatusVo(order.getOrderNo(), order.getStatus(), order.getTotalAmount(), order.getAlipayTradeNo());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlipayClient buildAlipayClient() {
|
||||||
|
return new DefaultAlipayClient(
|
||||||
|
alipayConfig.getGatewayUrl(),
|
||||||
|
alipayConfig.getAppId(),
|
||||||
|
alipayConfig.getPrivateKey(),
|
||||||
|
alipayConfig.getFormat(),
|
||||||
|
alipayConfig.getCharset(),
|
||||||
|
alipayConfig.getAlipayPublicKey(),
|
||||||
|
alipayConfig.getSignType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateOrderNo() {
|
||||||
|
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
|
||||||
|
String random = UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase();
|
||||||
|
return "REWARD" + time + random;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean amountEquals(BigDecimal localAmount, BigDecimal notifyAmount) {
|
||||||
|
return localAmount.setScale(2, RoundingMode.HALF_UP)
|
||||||
|
.compareTo(notifyAmount.setScale(2, RoundingMode.HALF_UP)) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,11 @@ import jakarta.mail.MessagingException;
|
|||||||
import jakarta.mail.internet.MimeMessage;
|
import jakarta.mail.internet.MimeMessage;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.mail.MailAuthenticationException;
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -27,10 +28,12 @@ public class MailUtil {
|
|||||||
private RedisUtil redisUtil;
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
private final JavaMailSender javaMailSender;
|
private final JavaMailSender javaMailSender;
|
||||||
|
private final String fromAddress;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public MailUtil(JavaMailSender javaMailSender) {
|
public MailUtil(JavaMailSender javaMailSender, @Value("${spring.mail.username}") String fromAddress) {
|
||||||
this.javaMailSender = javaMailSender;
|
this.javaMailSender = javaMailSender;
|
||||||
|
this.fromAddress = fromAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +59,7 @@ public class MailUtil {
|
|||||||
String verificationCode = generateVerificationCode();
|
String verificationCode = generateVerificationCode();
|
||||||
// 构造邮件
|
// 构造邮件
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
message.setFrom("xdd9@vip.qq.com");
|
message.setFrom(fromAddress);
|
||||||
message.setTo(to);
|
message.setTo(to);
|
||||||
message.setSubject("【NBA轻松看验证码】");
|
message.setSubject("【NBA轻松看验证码】");
|
||||||
message.setText("您的验证码是:" + verificationCode + ",有效期 5 分钟"+"。请勿回复此邮件。"+"\n反馈邮箱:super@2026123.xyz"+"\n发布页:2026123.xyz");
|
message.setText("您的验证码是:" + verificationCode + ",有效期 5 分钟"+"。请勿回复此邮件。"+"\n反馈邮箱:super@2026123.xyz"+"\n发布页:2026123.xyz");
|
||||||
@@ -87,25 +90,74 @@ public class MailUtil {
|
|||||||
* @param text 邮件内容
|
* @param text 邮件内容
|
||||||
*/
|
*/
|
||||||
public String sendEmail2(String to,String subject,String text) {
|
public String sendEmail2(String to,String subject,String text) {
|
||||||
Assert.hasText(to, "邮箱不能为空");
|
SendMailResult result = sendEmailResult(to, subject, text);
|
||||||
|
return result.isSuccess() ? "发送成功" : "发送邮件失败";
|
||||||
|
}
|
||||||
|
|
||||||
|
public SendMailResult sendEmailResult(String to, String subject, String text) {
|
||||||
|
Assert.hasText(to, "邮箱不能为空");
|
||||||
|
Assert.hasText(subject, "邮件主题不能为空");
|
||||||
|
Assert.hasText(text, "邮件内容不能为空");
|
||||||
|
|
||||||
// 构造邮件
|
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
message.setFrom("xdd9@vip.qq.com");
|
message.setFrom(fromAddress);
|
||||||
message.setTo(to);
|
message.setTo(to);
|
||||||
message.setSubject(subject);
|
message.setSubject(subject);
|
||||||
message.setText(text);
|
message.setText(text);
|
||||||
// message.setText("发布页:2026123.xyz");
|
|
||||||
// 发送邮件
|
|
||||||
try {
|
try {
|
||||||
javaMailSender.send(message);
|
javaMailSender.send(message);
|
||||||
return "发送成功";
|
return SendMailResult.success();
|
||||||
// return verificationCode;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.info("发送邮件失败:{}", e.getMessage());
|
boolean authenticationFailure = isAuthenticationFailure(e);
|
||||||
return "发送邮件失败";
|
log.info("发送邮件失败:{},原因:{}", to, e.getMessage(), e);
|
||||||
|
return SendMailResult.failure(authenticationFailure, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAuthenticationFailure(Throwable throwable) {
|
||||||
|
while (throwable != null) {
|
||||||
|
if (throwable instanceof MailAuthenticationException
|
||||||
|
|| throwable.getClass().getName().contains("AuthenticationFailedException")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throwable = throwable.getCause();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SendMailResult {
|
||||||
|
private final boolean success;
|
||||||
|
private final boolean authenticationFailure;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
private SendMailResult(boolean success, boolean authenticationFailure, String message) {
|
||||||
|
this.success = success;
|
||||||
|
this.authenticationFailure = authenticationFailure;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMailResult success() {
|
||||||
|
return new SendMailResult(true, false, "发送成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMailResult failure(boolean authenticationFailure, String message) {
|
||||||
|
return new SendMailResult(false, authenticationFailure, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthenticationFailure() {
|
||||||
|
return authenticationFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param map
|
* @param map
|
||||||
@@ -115,7 +167,7 @@ public class MailUtil {
|
|||||||
|
|
||||||
// 构造邮件
|
// 构造邮件
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
message.setFrom("xdd9@vip.qq.com");
|
message.setFrom(fromAddress);
|
||||||
message.setTo(map.get("mail"));
|
message.setTo(map.get("mail"));
|
||||||
message.setSubject(map.get("subject"));
|
message.setSubject(map.get("subject"));
|
||||||
message.setText(map.get("text"));
|
message.setText(map.get("text"));
|
||||||
@@ -130,13 +182,14 @@ public class MailUtil {
|
|||||||
* @param subject 邮件主题
|
* @param subject 邮件主题
|
||||||
* @param html HTML 内容
|
* @param html HTML 内容
|
||||||
*/
|
*/
|
||||||
public void sendHtmlEmail(String to, String subject, String html) throws MessagingException, jakarta.mail.MessagingException {
|
public void sendHtmlEmail(String to, String subject, String html) throws MessagingException, MessagingException {
|
||||||
Assert.hasText(to, "邮箱不能为空");
|
Assert.hasText(to, "邮箱不能为空");
|
||||||
Assert.hasText(subject, "邮件主题不能为空");
|
Assert.hasText(subject, "邮件主题不能为空");
|
||||||
Assert.hasText(html, "HTML 内容不能为空");
|
Assert.hasText(html, "HTML 内容不能为空");
|
||||||
|
|
||||||
jakarta.mail.internet.MimeMessage message = javaMailSender.createMimeMessage();
|
MimeMessage message = javaMailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||||
|
helper.setFrom(fromAddress);
|
||||||
helper.setTo(to);
|
helper.setTo(to);
|
||||||
helper.setSubject(subject);
|
helper.setSubject(subject);
|
||||||
helper.setText(html, true); // true 表示支持 HTML
|
helper.setText(html, true); // true 表示支持 HTML
|
||||||
@@ -151,14 +204,15 @@ public class MailUtil {
|
|||||||
* @param text 邮件内容
|
* @param text 邮件内容
|
||||||
* @param attachments 附件文件列表
|
* @param attachments 附件文件列表
|
||||||
*/
|
*/
|
||||||
public void sendEmailWithAttachments(String to, String subject, String text, List<File> attachments) throws MessagingException, jakarta.mail.MessagingException {
|
public void sendEmailWithAttachments(String to, String subject, String text, List<File> attachments) throws MessagingException, MessagingException {
|
||||||
Assert.hasText(to, "收件人邮箱不能为空");
|
Assert.hasText(to, "收件人邮箱不能为空");
|
||||||
Assert.hasText(subject, "邮件主题不能为空");
|
Assert.hasText(subject, "邮件主题不能为空");
|
||||||
Assert.hasText(text, "邮件内容不能为空");
|
Assert.hasText(text, "邮件内容不能为空");
|
||||||
Assert.notEmpty(attachments, "附件列表不能为空");
|
Assert.notEmpty(attachments, "附件列表不能为空");
|
||||||
|
|
||||||
jakarta.mail.internet.MimeMessage message = javaMailSender.createMimeMessage();
|
MimeMessage message = javaMailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||||
|
helper.setFrom(fromAddress);
|
||||||
helper.setTo(to);
|
helper.setTo(to);
|
||||||
helper.setSubject(subject);
|
helper.setSubject(subject);
|
||||||
helper.setText(text);
|
helper.setText(text);
|
||||||
@@ -179,7 +233,7 @@ public class MailUtil {
|
|||||||
* @param html HTML 内容
|
* @param html HTML 内容
|
||||||
* @param inlineFiles 内联资源文件列表
|
* @param inlineFiles 内联资源文件列表
|
||||||
*/
|
*/
|
||||||
public void sendHtmlEmailWithInline(String to, String subject, String html, List<File> inlineFiles) throws MessagingException, jakarta.mail.MessagingException {
|
public void sendHtmlEmailWithInline(String to, String subject, String html, List<File> inlineFiles) throws MessagingException, MessagingException {
|
||||||
Assert.hasText(to, "收件人邮箱不能为空");
|
Assert.hasText(to, "收件人邮箱不能为空");
|
||||||
Assert.hasText(subject, "邮件主题不能为空");
|
Assert.hasText(subject, "邮件主题不能为空");
|
||||||
Assert.hasText(html, "HTML 内容不能为空");
|
Assert.hasText(html, "HTML 内容不能为空");
|
||||||
@@ -187,6 +241,7 @@ public class MailUtil {
|
|||||||
|
|
||||||
MimeMessage message = javaMailSender.createMimeMessage();
|
MimeMessage message = javaMailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||||
|
helper.setFrom(fromAddress);
|
||||||
helper.setTo(to);
|
helper.setTo(to);
|
||||||
helper.setSubject(subject);
|
helper.setSubject(subject);
|
||||||
helper.setText(html, true);
|
helper.setText(html, true);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ server:
|
|||||||
cookie:
|
cookie:
|
||||||
same-site: None
|
same-site: None
|
||||||
secure: true # 生产是 https 必须 true
|
secure: true # 生产是 https 必须 true
|
||||||
port: 9001
|
port: 9005
|
||||||
#spring:
|
#spring:
|
||||||
# data:
|
# data:
|
||||||
# redis:
|
# redis:
|
||||||
@@ -29,8 +29,8 @@ spring:
|
|||||||
name: NBA
|
name: NBA
|
||||||
datasource:
|
datasource:
|
||||||
#mysql5.7.4配置
|
#mysql5.7.4配置
|
||||||
driver-class-name: com.mysql.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://localhost:3306/nba?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
url: jdbc:mysql://localhost:3306/nba?useSSL=true&trustServerCertificate=true&serverTimezone=UTC
|
||||||
# url: jdbc:mysql://116.62.173.2:3306/nba?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
# url: jdbc:mysql://116.62.173.2:3306/nba?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||||
# url: jdbc:mysql://154.36.154.211:9002/nba?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
# url: jdbc:mysql://154.36.154.211:9002/nba?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||||
username: root
|
username: root
|
||||||
@@ -43,24 +43,32 @@ spring:
|
|||||||
mail:
|
mail:
|
||||||
host: smtp.qq.com
|
host: smtp.qq.com
|
||||||
port: 465
|
port: 465
|
||||||
username: xdd9@vip.qq.com
|
username: ${MAIL_USERNAME:xdd9@vip.qq.com}
|
||||||
password: qhcladjicfydbejj
|
password: ${MAIL_PASSWORD:qhcladjicfydbejj}
|
||||||
default-encoding: UTF-8
|
default-encoding: UTF-8
|
||||||
properties:
|
properties:
|
||||||
|
mail.smtp.auth: true
|
||||||
|
mail.smtp.ssl.enable: true
|
||||||
|
mail.smtp.ssl.trust: smtp.qq.com
|
||||||
|
mail.smtp.starttls.enable: false
|
||||||
|
mail.smtp.starttls.required: false
|
||||||
mail.smtp.connectiontimeout: 5000 # 连接超时 5 秒
|
mail.smtp.connectiontimeout: 5000 # 连接超时 5 秒
|
||||||
mail.smtp.timeout: 5000 # 读超时 5 秒
|
mail.smtp.timeout: 5000 # 读超时 5 秒
|
||||||
mail.smtp.writetimeout: 5000 # 写超时 5 秒
|
mail.smtp.writetimeout: 5000 # 写超时 5 秒
|
||||||
mail:
|
|
||||||
smtp:
|
|
||||||
auth: true
|
|
||||||
ssl:
|
|
||||||
enable: true
|
|
||||||
starttls:
|
|
||||||
enable: true
|
|
||||||
required: true
|
|
||||||
mybatis:
|
mybatis:
|
||||||
configuration:
|
configuration:
|
||||||
map-underscore-to-camel-case: true
|
map-underscore-to-camel-case: true
|
||||||
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||||
type-aliases-package: com.ping.study.pojo
|
type-aliases-package: com.ping.study.pojo
|
||||||
mapper-locations: classpath:mapper/*.xml
|
mapper-locations: classpath:mapper/*.xml
|
||||||
|
alipay:
|
||||||
|
# 沙箱网关:https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
||||||
|
# 正式网关:https://openapi.alipay.com/gateway.do
|
||||||
|
gateway-url: ${ALIPAY_GATEWAY_URL:https://openapi.alipay.com/gateway.do}
|
||||||
|
app-id: ${ALIPAY_APP_ID:2021002176680273}
|
||||||
|
private-key: ${ALIPAY_PRIVATE_KEY:MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDuAjvOJA0WdAkKIJu/TVUqjtA7eSB1HjYpfPWSRB1wE7N+J5Wf8aw9ieI9UIlaO5KzhL6+fRy6hKtZoFtVZarKhSmbZhL3ccgP3ulK5FZwe6UgqQi13J9Akr8sRy/XTBrRmPyntjktKTO8830K5s5it1KT5einVWf4T976WQnyz0/MQ2dMT0Cpatl+d8LYZeeGrW7tlpKY+dEBORLF+nI2OXCakeprnAPcDjqEccdLcA8rwVyduDJrrJwhp/tKmOPjzG/B7GOciv9M/N6IXHmQJbqQDy6Qgku+ALuvu9HJsdWZuetv8K9nX7ofJhdApKZLYBiap7GrMrDK5QwtMANXAgMBAAECggEATzp/HgfyM189AxoHvo7HovsXZjTUESiVbwoh1SbHhd+JCJ20uSGB7JpRrYd5sYfTNd8if9a2EYDIaXVv8eV+DRx21TwNZEGED4RstHl+LMN8HHsoYyGmAaDX8q1fx5OV+d+re0i1j8r/Zg7HuTFL0qCj5IfMAqfzjD1KRJwPK7wit6nNTn9t6RPQRo0QHSazkGjoHKAcYkKTxor9D6HKVU/fQnoI6Hu6bnsTC7VXSY28am+Is79z0cvMc4n3PpBQBdA2VRKowc0frBkusDLhdMvWrvCOgRsKtgrbvZRT3qo+YJdPC5QKokslVlY3nC51dCWxAfR9YQyBEXWIGOBOgQKBgQD9MoQroPOSRN5TwfDLRDZYEL+tzeVTkDXKum40vca3WL9mT5Xuq1NVv9kHQzfmpmTEphsqZX0qjN9Vteic5J644jHVq1gP/xC75U81Lk74KwI/2/OU4YjxZrZU+zksGLUZxrk6ZkvHu4uvamf0hMTv0ThHXWaNc26fcYIPe5RQfwKBgQDwpK1uo/rv6Y0R3ZpSPLULMyFhTiiNBHWpO3Ks53PrCLpKqhDIvzJltLEZQ/Gm1HyHihvhQo4dupH3SoizQY76ZoSWFVjttRC6tQWvP+/SOeS6scUTm+YoStVpJAjHc51L5AV7xqyfsBQp2wCfv6bOAm05ojNZeXT/0Xh3aJFhKQKBgCbkop7dC201fP1atjVTFhHzCK6XCRoL9eddOd6KJEM3s7bwlLRjxtpOLPVLowOgHayDY3rguhhWKVxOJBwtliAKRuNufYl/gb+LGt6tbV37pU3P6Ju/BT0nrOxi5sZaST9bYkqROiTFL1DTxIIv/txjxARaWY1y5NRDKFpefkrbAoGAZ4VgOoV+cPDWyAW92nzVIVFIndSCq09s0nWJeopDGqvxgCcy+zkNFCWsPgM1lKA6RhCKt9fqzS0yl+BPeFXOjTfG982NKQ1IehlfralioNxY4luRPUNGurSepBFlWXAKDdi05y9rmXKk6fCVjyNiPaNbm3yEfIw8YcSZ/zxTtikCgYBMQAUvZrsgeHj0RXIBY2HPHOjjB/lpAXwvjkjeHInjnDUP2jbY2SJxmU2kn37QnjayvTCdMtDDdEcAajyXMJ7RC8uICIRXLVckx1JJvyEnogsaucPVAm4CbXRDaFNc8R+HoO+LbWE3c6gHY3mL8nNYUTdzkOULfCVvUy2vr/lKMg==}
|
||||||
|
alipay-public-key: ${ALIPAY_PUBLIC_KEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh8inNmeH0tPN5U4AW1+o7EJjaDqLs+gk+4ZnBX/ZkgOldB7NAeXCPzzANNyNYih7cR/M0DnwoH9URm4m4b3fKRlYq18/SrxG0jF6wISMhgc3EMQRBzQ3mkn5Szs/YEwrg/UjcAleLbKl89eDRneXrHv6R6ArFgkwPNtsVCac3P0yEu6F+pCLDsKCDQQIOWUbnjKvOFUebh53nXVnUIGSiWC9fYS7KpdM2JetjnD+u9lH4b/7RlM/R06+K3cPZx6LmANksFfH8gO/dtwaklavNq1KnSVCjgnejocj8zEi2PRmOEZpTHqM+T/0dMCN4zvwji/xoQ8sLV3ywm52o9Ew7wIDAQAB}
|
||||||
|
notify-url: ${ALIPAY_NOTIFY_URL:https://api9.jrs77.xyz/pay/alipay/notify}
|
||||||
|
charset: UTF-8
|
||||||
|
format: JSON
|
||||||
|
sign-type: RSA2
|
||||||
|
|||||||
@@ -136,4 +136,10 @@
|
|||||||
update nba_user set password = #{password} where email = #{email}
|
update nba_user set password = #{password} where email = #{email}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<select id="selectAllUserEmail">
|
||||||
|
select email from nba_user where email is not null
|
||||||
|
-- select email from nba_user where email like "113130%"
|
||||||
|
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
69
src/main/resources/mapper/PayOrderMapper.xml
Normal file
69
src/main/resources/mapper/PayOrderMapper.xml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ping.study.mapper.PayOrderMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="com.ping.study.pojo.PayOrder">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="orderNo" column="order_no"/>
|
||||||
|
<result property="userId" column="user_id"/>
|
||||||
|
<result property="subject" column="subject"/>
|
||||||
|
<result property="liuyan" column="liuyan"/>
|
||||||
|
<result property="totalAmount" column="total_amount"/>
|
||||||
|
<result property="status" column="status"/>
|
||||||
|
<result property="alipayTradeNo" column="alipay_trade_no"/>
|
||||||
|
<result property="qrCode" column="qr_code"/>
|
||||||
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="updateTime" column="update_time"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, order_no, user_id, subject, liuyan, total_amount, status, alipay_trade_no, qr_code, create_time, update_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="com.ping.study.pojo.PayOrder" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
|
||||||
|
insert into pay_order
|
||||||
|
(order_no, user_id, subject, liuyan, total_amount, status, alipay_trade_no, qr_code, create_time, update_time)
|
||||||
|
values
|
||||||
|
(#{orderNo}, #{userId}, #{subject}, #{liuyan}, #{totalAmount}, #{status}, #{alipayTradeNo}, #{qrCode}, #{createTime}, #{updateTime})
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<select id="selectByOrderNo" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
from pay_order
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<update id="updateQrCodeAndStatus">
|
||||||
|
update pay_order
|
||||||
|
set qr_code = #{qrCode},
|
||||||
|
status = #{status},
|
||||||
|
update_time = now()
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updatePaidByOrderNo">
|
||||||
|
update pay_order
|
||||||
|
set alipay_trade_no = #{alipayTradeNo},
|
||||||
|
status = #{status},
|
||||||
|
update_time = now()
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
and status != 'SUCCESS'
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateStatusByOrderNo">
|
||||||
|
update pay_order
|
||||||
|
set status = #{status},
|
||||||
|
update_time = now()
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
</update>
|
||||||
|
<select id="countSuccessRewardByUserId" resultType="int">
|
||||||
|
select count(1)
|
||||||
|
from pay_order
|
||||||
|
where user_id = #{userId}
|
||||||
|
and status = 'SUCCESS'
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user