Commit b1398588 authored by 33's avatar 33

优化代码

parent b836bdb3
package com.fzm.admin.controller;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.CopyrightLog;
import com.fzm.common.entity.vo.CopyrightApplyVo;
import com.fzm.common.entity.vo.CopyrightVo;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.CopyrightApplyService;
import com.fzm.common.service.CopyrightLogService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
......@@ -13,8 +15,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.List;
/**
* @author tangtuo
......@@ -27,6 +28,7 @@ import java.util.concurrent.ExecutionException;
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CopyrightApplyController {
private final CopyrightApplyService copyrightApplyService;
private final CopyrightLogService copyrightLogService;
@GetMapping(value = "/pages")
@ApiOperation(value = "分页查询")
......@@ -43,21 +45,28 @@ public class CopyrightApplyController {
@PostMapping(value = "/pass")
@ApiOperation(value = "通过")
public ResponseModel<Boolean> pass(@RequestParam Integer id) throws ExecutionException, InterruptedException {
public ResponseModel<Boolean> pass(@RequestParam Integer id) {
boolean result = copyrightApplyService.pass(id);
return ResponseModel.success(result);
}
@PostMapping(value = "/reject")
@ApiOperation(value = "驳回")
public ResponseModel<Boolean> reject(@RequestParam Integer id, @RequestParam String rejectReason) throws IOException, InterruptedException {
public ResponseModel<Boolean> reject(@RequestParam Integer id, @RequestParam String rejectReason) {
boolean result = copyrightApplyService.reject(id, rejectReason);
return ResponseModel.success(result);
}
@GetMapping(value = "/detail")
@ApiOperation(value = "获取详情")
public ResponseModel<CopyrightVo> details(@RequestParam Integer id) throws ExecutionException, InterruptedException {
public ResponseModel<CopyrightVo> details(@RequestParam Integer id) {
return ResponseModel.success(copyrightApplyService.getDetail(id));
}
@GetMapping(value = "/log")
@ApiOperation(value = "操作记录")
public ResponseModel<List<CopyrightLog>> log(@RequestParam Integer id) {
List<CopyrightLog> logs = copyrightLogService.logs(id);
return ResponseModel.success(logs);
}
}
......@@ -17,8 +17,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* @author tangtuo
* @date 2022/2/9 10:16
......@@ -48,7 +46,7 @@ public class RefundController {
@GetMapping("/submit")
@ApiOperation(value = "提交退款申请")
public ResponseModel<Boolean> submit(@ApiParam(required = true, value = "订单id") @RequestParam String orderId) throws IOException, InterruptedException {
public ResponseModel<Boolean> submit(@ApiParam(required = true, value = "订单id") @RequestParam String orderId) {
long oid;
try {
oid = Long.parseLong(orderId);
......
......@@ -47,13 +47,17 @@ public class CopyrightApiTask {
*/
@Scheduled(cron = "0 */10 * * * ?")
@Transactional(rollbackFor = Exception.class)
public void updateCopyrightState() throws InterruptedException {
public void updateCopyrightState() {
// 加锁,防止集群部署时,定时任务在多个节点上执行
RLock lock = redisson.getLock("update:copyright:api:state");
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
if (log.isDebugEnabled()) {
log.debug("更新版权状态的定时任务已在其他节点运行");
try {
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
if (log.isDebugEnabled()) {
log.debug("更新版权状态的定时任务已在其他节点运行");
}
return;
}
} catch (InterruptedException e) {
return;
}
try {
......
......@@ -68,13 +68,17 @@ public class CopyrightTask {
*/
@Scheduled(cron = "0 */10 * * * ?")
@Transactional(rollbackFor = Exception.class)
public void updateCopyrightState() throws InterruptedException {
public void updateCopyrightState() {
// 加锁,防止集群部署时,定时任务在多个节点上执行
RLock lock = redisson.getLock("update:copyright:state");
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
if (log.isDebugEnabled()) {
log.debug("更新版权状态的定时任务已在其他节点运行");
try {
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
if (log.isDebugEnabled()) {
log.debug("更新版权状态的定时任务已在其他节点运行");
}
return;
}
} catch (InterruptedException e) {
return;
}
try {
......
......@@ -23,5 +23,5 @@ public interface CommemorateNftService extends IService<CommemorateNft> {
* @param id
* @return
*/
Boolean receive(Integer id) throws InterruptedException;
Boolean receive(Integer id);
}
......@@ -8,9 +8,7 @@ import com.fzm.common.entity.vo.CopyrightCertificateVo;
import com.fzm.common.entity.vo.CopyrightVo;
import com.github.pagehelper.PageInfo;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* @author tangtuo
......@@ -41,7 +39,7 @@ public interface CopyrightApplyService extends IService<CopyrightApply> {
* @param id
* @return
*/
Boolean withdraw(Integer id) throws IOException, InterruptedException;
Boolean withdraw(Integer id);
/**
......@@ -58,7 +56,7 @@ public interface CopyrightApplyService extends IService<CopyrightApply> {
* @param id
* @return
*/
CopyrightVo getDetail(Integer id) throws ExecutionException, InterruptedException;
CopyrightVo getDetail(Integer id);
/**
* 修改
......@@ -88,7 +86,7 @@ public interface CopyrightApplyService extends IService<CopyrightApply> {
* @param rejectReason
* @return
*/
boolean reject(Integer id, String rejectReason) throws IOException, InterruptedException;
boolean reject(Integer id, String rejectReason);
/**
* 审核通过
......@@ -96,7 +94,7 @@ public interface CopyrightApplyService extends IService<CopyrightApply> {
* @param id
* @return
*/
boolean pass(Integer id) throws ExecutionException, InterruptedException;
boolean pass(Integer id);
/**
* 获取存证成功的总数量
......@@ -119,7 +117,7 @@ public interface CopyrightApplyService extends IService<CopyrightApply> {
* @param nftHash
* @return
*/
CopyrightVo getByNftHash(String nftHash) throws ExecutionException, InterruptedException;
CopyrightVo getByNftHash(String nftHash);
/**
* 查看证书
......
......@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.fzm.common.entity.CopyrightLog;
import com.fzm.common.enums.CopyrightLogType;
import java.util.List;
/**
* @author wt
* @date 2022/5/24
......@@ -15,4 +17,6 @@ public interface CopyrightLogService extends IService<CopyrightLog> {
void saveTask(Integer cid, Integer typeId, String opInfo);
CopyrightLog selectByIdAndType(Integer cid, Integer typeId);
List<CopyrightLog> logs(Integer cid);
}
......@@ -9,7 +9,6 @@ import com.fzm.common.params.NftTransferParam;
import com.github.pagehelper.PageInfo;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* @author tangtuo
......@@ -166,7 +165,7 @@ public interface NftService extends IService<Nft> {
* @param nftHash
* @return
*/
NftVo getDetail(String nftHash) throws ExecutionException, InterruptedException;
NftVo getDetail(String nftHash);
/**
* 修改当前nfthash的是否已委托的状态
......
......@@ -6,7 +6,6 @@ import com.fzm.common.entity.dto.OrderDto;
import com.fzm.common.entity.vo.OrderVo;
import com.fzm.common.enums.OrderStatus;
import java.io.IOException;
import java.util.List;
/**
......@@ -73,7 +72,7 @@ public interface OrderService extends IService<Order> {
* @param orderId
* @return
*/
Boolean renewOrderStatus(Long orderId) throws IOException, InterruptedException;
Boolean renewOrderStatus(Long orderId);
/**
* 查询超时的订单
......
......@@ -5,8 +5,6 @@ import com.fzm.common.entity.Refund;
import com.fzm.common.entity.vo.PaymentVo;
import com.github.pagehelper.PageInfo;
import java.io.IOException;
/**
* @author tangtuo
* @date 2022/1/24 14:26
......@@ -27,7 +25,7 @@ public interface RefundService extends IService<Refund> {
* @param orderId
* @return
*/
Boolean submit(Long orderId) throws IOException, InterruptedException;
Boolean submit(Long orderId);
/**
* 分页查询待处理的退款订单
......
......@@ -4,7 +4,6 @@ import cn.hutool.json.JSONObject;
import com.fzm.common.entity.dto.JsapiPayDto;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
/**
......@@ -20,9 +19,7 @@ public interface WxPayService {
* @return
* @throws Exception
*/
Map<String, Object> payJsapi(JsapiPayDto jsapiPayDto) throws Exception;
String encryptByPrivateKey(String data) throws Exception;
Map<String, Object> payJsapi(JsapiPayDto jsapiPayDto);
Boolean notifyH5(HttpServletRequest request);
......@@ -31,9 +28,9 @@ public interface WxPayService {
*
* @param jsonObject
*/
void processOrder(JSONObject jsonObject) throws InterruptedException;
void processOrder(JSONObject jsonObject);
String queryOrder(Long orderId) throws IOException, InterruptedException;
String queryOrder(Long orderId);
/**
* 退款
......@@ -41,7 +38,7 @@ public interface WxPayService {
* @param orderId 订单id
* @param channel 退款发起渠道
*/
Boolean refund(Long orderId, Integer channel) throws IOException, InterruptedException;
Boolean refund(Long orderId, Integer channel);
/**
* 退款回调
......@@ -49,12 +46,12 @@ public interface WxPayService {
* @param request
* @return
*/
Boolean notifyRefund(HttpServletRequest request);
void notifyRefund(HttpServletRequest request);
/**
* 处理退款成功后的订单
*
* @param jsonObject
*/
void processRefund(JSONObject jsonObject) throws InterruptedException;
void processRefund(JSONObject jsonObject);
}
......@@ -98,12 +98,17 @@ public class CommemorateNftServiceImpl extends ServiceImpl<CommemorateNftMapper,
}
@Override
public Boolean receive(Integer id) throws InterruptedException {
public Boolean receive(Integer id) {
User user = userService.getUserByToken();
// 加锁,避免一个用户可以并发领取
RLock lock = redisson.getLock("receive:nft:" + user.getId());
boolean tryLock = lock.tryLock(30, TimeUnit.SECONDS);
boolean tryLock;
try {
tryLock = lock.tryLock(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.RECEIVE_ERROR, "操作频繁");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.RECEIVE_ERROR, "操作频繁");
}
......
......@@ -38,13 +38,11 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
......@@ -170,7 +168,7 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
}
@Override
public Boolean withdraw(Integer id) throws IOException, InterruptedException {
public Boolean withdraw(Integer id) {
CopyrightApply copyright = getById(id);
if (copyright == null) {
throw GlobalException.newException(ResultCode.DATA_ERROR, "此版权登记记录不存在,请核对后重试");
......@@ -225,7 +223,7 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
}
@Override
public CopyrightVo getDetail(Integer id) throws ExecutionException, InterruptedException {
public CopyrightVo getDetail(Integer id) {
// 使用异步编排查询
CompletableFuture<CopyrightVo> applyFuture = CompletableFuture.supplyAsync(() -> {
CopyrightApply copyrightApply = getById(id);
......@@ -257,8 +255,12 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
result.setAuthorities(authorities);
}, threadPoolTaskExecutor);
// 等所有异步任务都完成以后返回结果
CompletableFuture.allOf(categoryFuture, filesFuture, authorsFuture, ownerFuture, authoritiesFuture).get();
return applyFuture.get();
try {
CompletableFuture.allOf(categoryFuture, filesFuture, authorsFuture, ownerFuture, authoritiesFuture).get();
return applyFuture.get();
} catch (Exception e) {
throw GlobalException.newException(ResultCode.SELECT_FAILED);
}
}
@Override
......@@ -337,7 +339,7 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
}
@Override
public boolean reject(Integer id, String rejectReason) throws IOException, InterruptedException {
public boolean reject(Integer id, String rejectReason) {
CopyrightApply copyright = getById(id);
if (copyright == null) {
throw GlobalException.newException(ResultCode.DATA_ERROR, "此版权登记记录不存在,请核对后重试");
......@@ -364,9 +366,14 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
}
@Override
public boolean pass(Integer id) throws ExecutionException, InterruptedException {
public boolean pass(Integer id) {
RLock lock = redisson.getLock("copyright:apply:" + id);
boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS);
boolean tryLock;
try {
tryLock = lock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
......@@ -443,7 +450,7 @@ public class CopyrightApplyServiceImpl extends ServiceImpl<CopyrightApplyMapper,
}
@Override
public CopyrightVo getByNftHash(String nftHash) throws ExecutionException, InterruptedException {
public CopyrightVo getByNftHash(String nftHash) {
QueryWrapper<CopyrightApply> wrapper = new QueryWrapper<>();
wrapper.eq("nft_hash", nftHash);
CopyrightApply copyrightApply = this.getOne(wrapper);
......
......@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* @author wt
......@@ -31,12 +32,16 @@ public class CopyrightLogServiceImpl extends ServiceImpl<CopyrightLogMapper, Cop
copyrightLog.setOpUserId(LoginUserInfo.getLoginUser().getUserId());
copyrightLog.setOpUserName(LoginUserInfo.getLoginUser().getUsername());
copyrightLog.setOpTime(new Date());
this.save(copyrightLog);
save(copyrightLog);
}
@Override
public void saveTask(Integer cid, Integer typeId, String opInfo) {
CopyrightLogType logType = CopyrightLogType.getById(typeId);
if (logType == null) {
return;
}
CopyrightLog copyrightLog = new CopyrightLog();
copyrightLog.setCopyrightId(cid);
......@@ -46,7 +51,8 @@ public class CopyrightLogServiceImpl extends ServiceImpl<CopyrightLogMapper, Cop
copyrightLog.setOpUserId(0);
copyrightLog.setOpUserName("版权局");
copyrightLog.setOpTime(new Date());
this.save(copyrightLog);
save(copyrightLog);
}
@Override
......@@ -56,4 +62,11 @@ public class CopyrightLogServiceImpl extends ServiceImpl<CopyrightLogMapper, Cop
queryWrapper.eq("op_type_id", typeId);
return getOne(queryWrapper);
}
@Override
public List<CopyrightLog> logs(Integer cid) {
QueryWrapper<CopyrightLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("copyright_id", cid);
return list(queryWrapper);
}
}
......@@ -45,7 +45,6 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
/**
......@@ -225,7 +224,7 @@ public class NftServiceImpl extends ServiceImpl<NftMapper, Nft> implements NftSe
}
@Override
public NftVo getDetail(String nftHash) throws ExecutionException, InterruptedException {
public NftVo getDetail(String nftHash) {
Nft nft = this.getByNftHash(nftHash);
if (nft == null) {
throw GlobalException.newException(ResultCode.SELECT_FAILED, "没找到此nft详情,请核对后再试");
......
......@@ -18,7 +18,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
......@@ -161,7 +160,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
}
@Override
public Boolean renewOrderStatus(Long orderId) throws IOException, InterruptedException {
public Boolean renewOrderStatus(Long orderId) {
Order order = this.getById(orderId);
if (order == null) {
throw GlobalException.newException(ResultCode.DATA_ERROR, "unknown orderId: " + orderId);
......
......@@ -18,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.List;
/**
......@@ -41,7 +40,7 @@ public class RefundServiceImpl extends ServiceImpl<RefundMapper, Refund> impleme
}
@Override
public Boolean submit(Long orderId) throws IOException, InterruptedException {
public Boolean submit(Long orderId) {
return wxPayService.refund(orderId, RefundLaunchChannel.ADMIN.getCode());
}
......
......@@ -32,12 +32,6 @@ import com.fzm.common.utils.ObsUtil;
import com.fzm.common.utils.RedisUtil;
import com.fzm.common.utils.SmsUtil;
import com.fzm.common.utils.TencentApi;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.faceid.v20180301.FaceidClient;
import com.tencentcloudapi.faceid.v20180301.models.IdCardOCRVerificationRequest;
import com.tencentcloudapi.faceid.v20180301.models.IdCardOCRVerificationResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......
......@@ -76,9 +76,15 @@ public class WxPayServiceImpl implements WxPayService {
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> payJsapi(JsapiPayDto jsapiPayDto) throws Exception {
public Map<String, Object> payJsapi(JsapiPayDto jsapiPayDto) {
RLock lock = redisson.getLock("pay-" + jsapiPayDto.getOrderId());
if (!lock.tryLock(10, TimeUnit.SECONDS)) {
boolean tryLock;
try {
tryLock = lock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.PAY_FAILED, "当前订单正在支付中,请勿重复点击");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.PAY_FAILED, "当前订单正在支付中,请勿重复点击");
}
try {
......@@ -102,13 +108,20 @@ public class WxPayServiceImpl implements WxPayService {
.put("total", order.getFee());
rootNode.putObject("payer")
.put("openid", jsapiPayDto.getOpenid());
String json = objectMapper.writeValueAsString(rootNode);
log.info("h5下单接口请求参数: {}", json);
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = JSONUtil.parseObj(bodyAsString);
JSONObject jsonObject;
try {
String json = objectMapper.writeValueAsString(rootNode);
log.info("h5下单接口请求参数: {}", json);
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
jsonObject = JSONUtil.parseObj(bodyAsString);
} catch (Exception e) {
throw GlobalException.newException(ResultCode.PAY_FAILED, "微信支付下单失败");
}
if (StringUtils.isBlank(jsonObject.getStr("prepay_id"))) {
throw GlobalException.newException(ResultCode.PAY_FAILED, "微信支付下单失败");
}
......@@ -122,7 +135,7 @@ public class WxPayServiceImpl implements WxPayService {
nonceStr + "\n" +
packageInfo + "\n";
log.info("签名字符串为: {}", signStr);
String paySign = this.encryptByPrivateKey(signStr);
String paySign = encryptByPrivateKey(signStr);
Map<String, Object> result = new HashMap<>();
result.put("appId", appId);
result.put("timeStamp", timeStamp);
......@@ -145,14 +158,17 @@ public class WxPayServiceImpl implements WxPayService {
*
* @param data 需要加密的数据
* @return 加密后的数据
* @throws Exception 异常信息
*/
public String encryptByPrivateKey(String data) throws Exception {
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(wxPrivateKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
byte[] signed = signature.sign();
return Base64Utils.encodeToString(signed);
public String encryptByPrivateKey(String data) {
try {
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(wxPrivateKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
byte[] signed = signature.sign();
return Base64Utils.encodeToString(signed);
} catch (Exception e) {
throw GlobalException.newException(ResultCode.FAILED);
}
}
@Override
......@@ -178,38 +194,47 @@ public class WxPayServiceImpl implements WxPayService {
@Override
@Transactional(rollbackFor = Exception.class)
public void processOrder(JSONObject jsonObject) throws InterruptedException {
public void processOrder(JSONObject jsonObject) {
// 获取订单号
Long out_trade_no = jsonObject.getLong("out_trade_no");
// 加锁,避免接口幂等性问题
RLock lock = redisson.getLock("pay-notify-" + out_trade_no);
// 修改订单状态
try {
if (lock.tryLock(10, TimeUnit.SECONDS)) {
Order order = orderService.getById(out_trade_no);
// 如果订单状态不是待支付,直接返回
if (!OrderStatus.PAYING.getStatus().equals(order.getOrderStatus())) {
log.warn("当前订单已处理完成, 订单号:==> {}", out_trade_no);
return;
}
// 修改订单状态
orderService.updateOrderStatus(out_trade_no, OrderStatus.PAYED);
// 插入支付流水记录
Payment payment = new Payment();
payment.setOrderId(out_trade_no);
payment.setTradeType(jsonObject.getStr("trade_type"));
payment.setTotalFee(jsonObject.getJSONObject("amount").getInt("payer_total"));
payment.setTransactionId(jsonObject.getStr("transaction_id"));
payment.setSuccessTime(jsonObject.getStr("success_time"));
payment.setContent(JSONUtil.toJsonStr(jsonObject));
paymentService.save(payment);
boolean tryLock;
try {
tryLock = lock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
// 订单支付成功后,给mq发送一条消息,处理nft发行或版权申请的状态
Integer productId = order.getProductId();
OrderProcessMsg orderProcessMsg = new OrderProcessMsg(out_trade_no, productId, order.getPayScene());
rabbitTemplate.convertAndSend("order-exchange", "order.process", orderProcessMsg);
Order order = orderService.getById(out_trade_no);
// 如果订单状态不是待支付,直接返回
if (!OrderStatus.PAYING.getStatus().equals(order.getOrderStatus())) {
log.warn("当前订单已处理完成, 订单号:==> {}", out_trade_no);
return;
}
// 修改订单状态
orderService.updateOrderStatus(out_trade_no, OrderStatus.PAYED);
// 插入支付流水记录
Payment payment = new Payment();
payment.setOrderId(out_trade_no);
payment.setTradeType(jsonObject.getStr("trade_type"));
payment.setTotalFee(jsonObject.getJSONObject("amount").getInt("payer_total"));
payment.setTransactionId(jsonObject.getStr("transaction_id"));
payment.setSuccessTime(jsonObject.getStr("success_time"));
payment.setContent(JSONUtil.toJsonStr(jsonObject));
paymentService.save(payment);
// 订单支付成功后,给mq发送一条消息,处理nft发行或版权申请的状态
Integer productId = order.getProductId();
OrderProcessMsg orderProcessMsg = new OrderProcessMsg(out_trade_no, productId, order.getPayScene());
rabbitTemplate.convertAndSend("order-exchange", "order.process", orderProcessMsg);
} finally {
lock.unlock();
}
......@@ -218,28 +243,38 @@ public class WxPayServiceImpl implements WxPayService {
@Override
@Transactional(rollbackFor = Exception.class)
public String queryOrder(Long orderId) throws IOException, InterruptedException {
public String queryOrder(Long orderId) {
String url = String.format("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s", orderId, wxPayProperties.getMchId());
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpGet);
String result = EntityUtils.toString(response.getEntity());
log.info("查询微信支付订单状态, 当前订单号: {}, 返回结果:{}", orderId, result);
JSONObject jsonObject = JSONUtil.parseObj(result);
// 支付成功
if (WxPayStatus.SUCCESS.getStatus().equals(jsonObject.getStr("trade_state"))) {
processOrder(jsonObject);
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
String result = EntityUtils.toString(response.getEntity());
log.info("查询微信支付订单状态, 当前订单号: {}, 返回结果:{}", orderId, result);
JSONObject jsonObject = JSONUtil.parseObj(result);
// 支付成功
if (WxPayStatus.SUCCESS.getStatus().equals(jsonObject.getStr("trade_state"))) {
processOrder(jsonObject);
}
return jsonObject.getStr("trade_state");
} catch (IOException e) {
throw GlobalException.newException(ResultCode.SELECT_FAILED);
}
return jsonObject.getStr("trade_state");
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean refund(Long orderId, Integer channel) throws IOException, InterruptedException {
public Boolean refund(Long orderId, Integer channel) {
boolean result;
RLock lock = redisson.getLock("refund-" + orderId);
if (!lock.tryLock(10, TimeUnit.SECONDS)) {
boolean tryLock;
try {
tryLock = lock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.REFUND_FAILED, "当前订单正在退款中,请勿重复点击");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.REFUND_FAILED, "当前订单正在退款中,请勿重复点击");
}
try {
......@@ -282,15 +317,23 @@ public class WxPayServiceImpl implements WxPayService {
.put("refund", order.getFee())
.put("total", order.getFee())
.put("currency", "CNY");
String json = objectMapper.writeValueAsString(rootNode);
log.info("退款接口请求参数: {}", json);
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
log.info("退款接口返回参数: {}", bodyAsString);
JSONObject jsonObject = JSONUtil.parseObj(bodyAsString);
int statusCode = response.getStatusLine().getStatusCode();
JSONObject jsonObject;
int statusCode;
try {
String json = objectMapper.writeValueAsString(rootNode);
log.info("退款接口请求参数: {}", json);
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
log.info("退款接口返回参数: {}", bodyAsString);
jsonObject = JSONUtil.parseObj(bodyAsString);
statusCode = response.getStatusLine().getStatusCode();
} catch (Exception e) {
throw GlobalException.newException(ResultCode.REFUND_FAILED);
}
// 发起退款成功
if (statusCode == 200 || statusCode == 204) {
refund.setRefundId(jsonObject.getStr("refund_id"));
......@@ -306,6 +349,7 @@ public class WxPayServiceImpl implements WxPayService {
refund.setFailMessage(jsonObject.getStr("message"));
result = false;
}
// 插入退款信息
refund.setId(out_refund_no);
refund.setFee(order.getFee());
......@@ -325,7 +369,7 @@ public class WxPayServiceImpl implements WxPayService {
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean notifyRefund(HttpServletRequest request) {
public void notifyRefund(HttpServletRequest request) {
try {
String requestBodyData = this.getRequestBodyData(request);
log.info("接收微信退款接口回调请求, 请求参数: {}", requestBodyData);
......@@ -335,38 +379,45 @@ public class WxPayServiceImpl implements WxPayService {
log.info("解密后的明文信息为: {}", plainText);
JSONObject obj = JSONUtil.parseObj(plainText);
processRefund(obj);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
throw GlobalException.newException(ResultCode.FAILED);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void processRefund(JSONObject obj) throws InterruptedException {
public void processRefund(JSONObject obj) {
Long out_trade_no = obj.getLong("out_trade_no");
Long out_refund_no = obj.getLong("out_refund_no");
RLock lock = redisson.getLock("refund-" + out_trade_no);
try {
if (lock.tryLock(10, TimeUnit.SECONDS)) {
Refund refund = refundService.getById(out_refund_no);
if (RefundStatus.SUCCESS.getStatus().equals(refund.getRefundStatus())) {
return;
}
// 更新退款信息
refund.setRefundStatus(RefundStatus.SUCCESS.getStatus());
refund.setSuccessTime(obj.getStr("success_time"));
refund.setContent(JSONUtil.toJsonStr(obj));
refund.setFailMessage("");
refundService.updateById(refund);
// 更新流水的退款状态
Payment payment = paymentService.getByOrderId(out_trade_no);
payment.setIsRefund(SystemConstant.BOOLEAN_DATA_TRUE);
paymentService.updateById(payment);
// 修改订单状态为退款成功
orderService.updateOrderStatus(out_trade_no, OrderStatus.REFUNDED);
boolean tryLock;
try {
tryLock = lock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
if (!tryLock) {
throw GlobalException.newException(ResultCode.FAILED, "操作频繁");
}
Refund refund = refundService.getById(out_refund_no);
if (RefundStatus.SUCCESS.getStatus().equals(refund.getRefundStatus())) {
return;
}
// 更新退款信息
refund.setRefundStatus(RefundStatus.SUCCESS.getStatus());
refund.setSuccessTime(obj.getStr("success_time"));
refund.setContent(JSONUtil.toJsonStr(obj));
refund.setFailMessage("");
refundService.updateById(refund);
// 更新流水的退款状态
Payment payment = paymentService.getByOrderId(out_trade_no);
payment.setIsRefund(SystemConstant.BOOLEAN_DATA_TRUE);
paymentService.updateById(payment);
// 修改订单状态为退款成功
orderService.updateOrderStatus(out_trade_no, OrderStatus.REFUNDED);
} finally {
lock.unlock();
}
......
......@@ -83,7 +83,7 @@ public class CommemorateNftController {
@Authentication
@PostMapping("/receive")
@ApiOperation(value = "领取纪念版nft")
public ResponseModel<Boolean> receive(@RequestParam Integer id) throws InterruptedException {
public ResponseModel<Boolean> receive(@RequestParam Integer id) {
Boolean result = commemorateNftService.receive(id);
return ResponseModel.success(result);
}
......
......@@ -20,9 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* @author tangtuo
......@@ -57,7 +55,7 @@ public class CopyrightApplyController {
@Authentication
@PostMapping(value = "/withdraw")
@ApiOperation(value = "撤回")
public ResponseModel<Boolean> withdraw(@RequestParam Integer id) throws IOException, InterruptedException {
public ResponseModel<Boolean> withdraw(@RequestParam Integer id) {
Boolean result = copyrightApplyService.withdraw(id);
return ResponseModel.success(result);
}
......@@ -72,7 +70,7 @@ public class CopyrightApplyController {
@GetMapping(value = "/detail")
@ApiOperation(value = "获取详情")
public ResponseModel<CopyrightVo> getById(@RequestParam Integer id) throws ExecutionException, InterruptedException {
public ResponseModel<CopyrightVo> getById(@RequestParam Integer id) {
CopyrightVo copyrightVo = copyrightApplyService.getDetail(id);
return ResponseModel.success(copyrightVo);
}
......
......@@ -32,7 +32,6 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* @author tangtuo
......@@ -78,7 +77,7 @@ public class NftController {
@GetMapping("get/{nftHash}")
@ApiOperation(value = "获取nft详情")
public ResponseModel<NftVo> get(@PathVariable String nftHash) throws ExecutionException, InterruptedException {
public ResponseModel<NftVo> get(@PathVariable String nftHash) {
NftVo nftVo = nftService.getDetail(nftHash);
if (nftVo.getCopyright() != null && !nftVo.getCopyright().getRegisterState().equals(CopyrightApplyState.SUCCEEDED.getCode())) {
nftVo.setCopyright(null);
......
......@@ -13,7 +13,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
/**
......@@ -62,7 +61,7 @@ public class OrderController {
@PostMapping("/renew-order-status")
@ApiOperation("更新订单状态")
public ResponseModel<Boolean> renewOrderStatus(@RequestParam Long orderId) throws IOException, InterruptedException {
public ResponseModel<Boolean> renewOrderStatus(@RequestParam Long orderId) {
return ResponseModel.success(orderService.renewOrderStatus(orderId));
}
......
......@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
......@@ -58,12 +57,12 @@ public class WxPayController {
@PostMapping("/notify/refund")
public Map<String, String> notifyRefund(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> result = new HashMap<>();
Boolean refund = wxPayService.notifyRefund(request);
if (refund) {
try {
wxPayService.notifyRefund(request);
result.put("code", "SUCCESS");
result.put("message", "成功");
response.setStatus(HttpStatus.HTTP_OK);
} else {
} catch (Exception e) {
result.put("code", "FAILED");
result.put("message", "系统异常");
response.setStatus(HttpStatus.HTTP_INTERNAL_ERROR);
......@@ -73,7 +72,7 @@ public class WxPayController {
@GetMapping("/refund/{orderId}")
public ResponseModel<String> refund(@PathVariable Long orderId) throws IOException, InterruptedException {
public ResponseModel<String> refund(@PathVariable Long orderId) {
wxPayService.refund(orderId, RefundLaunchChannel.USER.getCode());
return ResponseModel.success("退款成功");
}
......
......@@ -29,11 +29,15 @@ public class DraftTask {
* 删除创建时间大于7天的草稿
*/
@Scheduled(cron = "0 */15 * * * ?")
public void deleteTimeoutDraft() throws InterruptedException {
public void deleteTimeoutDraft() {
RLock lock = redisson.getLock("delete-draft");
// 加锁,避免集群环境下多个节点同事运行此定时任务
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
log.warn("删除超时草稿的任务正在运行中");
try {
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
log.warn("删除超时草稿的任务正在运行中");
return;
}
} catch (InterruptedException e) {
return;
}
try {
......
......@@ -35,11 +35,15 @@ public class PayTask {
* 定时关单的任务
*/
@Scheduled(cron = "0 */5 * * * ?")
public void closeOrder() throws InterruptedException {
public void closeOrder() {
RLock lock = redisson.getLock("close-order");
// 加锁,避免集群环境下多个节点同事运行此定时任务
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
log.warn("关单任务正在运行中");
try {
if (!lock.tryLock(30, TimeUnit.SECONDS)) {
log.warn("关单任务正在运行中");
return;
}
} catch (InterruptedException e) {
return;
}
try {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment