package com.dsh.competition.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeOrderSettleModel;
import com.alipay.api.domain.OpenApiRoyaltyDetailInfoPojo;
import com.alipay.api.domain.RoyaltyDetailInfos;
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest;
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.competition.entity.*;
import com.dsh.competition.enums.CompetitionStatusEnum;
import com.dsh.competition.feignclient.account.AppUserClient;
import com.dsh.competition.feignclient.account.StudentClient;
import com.dsh.competition.feignclient.account.model.AppUser;
import com.dsh.competition.feignclient.account.model.Student;
import com.dsh.competition.feignclient.account.model.TStudent;
import com.dsh.competition.feignclient.course.CoursePackagePaymentClient;
import com.dsh.competition.feignclient.course.model.PaymentDeductionClassHour;
import com.dsh.competition.feignclient.model.CompetitionUser;
import com.dsh.competition.feignclient.other.StoreClient;
import com.dsh.competition.feignclient.other.model.Store;
import com.dsh.competition.mapper.CompetitionMapper;
import com.dsh.competition.model.*;
import com.dsh.competition.service.CompetitionService;
import com.dsh.competition.service.IParticipantService;
import com.dsh.competition.service.IPaymentCompetitionService;
import com.dsh.competition.service.UserCompetitionService;
import com.dsh.competition.util.*;
import com.dsh.competition.util.wx.WxV3PayConfig;
import cn.mb.cloud.common.core.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 服务实现类
*
*
* @author jqs
* @since 2023-06-26
*/
@Service
public class CompetitionServiceImpl extends ServiceImpl implements CompetitionService {
@Resource
private StoreClient storeClient;
@Autowired
private IPaymentCompetitionService paymentCompetitionService;
@Autowired
private UserCompetitionService userCompetitionService;
@Autowired
private IParticipantService participantService;
@Resource
private AppUserClient appUserClient;
@Resource
private StudentClient studentClient;
@Resource
private CoursePackagePaymentClient coursePackagePaymentClient;
@Autowired
private PayMoneyUtil payMoneyUtil;
@Autowired
private CompetitionService cttService;
/**
* 修改活动,并确保修改不会破坏既有报名记录。
*
* @param competition 管理端提交的活动信息
* @throws BusinessException 活动不存在、时间范围非法或人数容量不足时抛出
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCompetition(Competition competition) throws BusinessException {
validateUpdateRequest(competition);
// STEP 1: 读取原活动,避免前端传入部分字段时覆盖既有数据。
Competition originalCompetition = getById(competition.getId());
if (originalCompetition == null) {
throw new BusinessException("活动不存在或已删除");
}
// STEP 2: 校验人数容量,保证已报名记录始终处于有效的活动容量内。
validateApplicantsNumber(competition);
// STEP 3: 仅更新活动配置;支付订单金额为快照,价格调整不会修改既有订单。
competition.setStatus(resolveCompetitionStatus(originalCompetition, competition));
updateById(competition);
}
/**
* 校验编辑请求中必填字段和基础数值范围。
*
* @param competition 待校验的活动信息
*/
private void validateUpdateRequest(Competition competition) throws BusinessException {
if (competition == null || competition.getId() == null) {
throw new BusinessException("活动编号不能为空");
}
if (competition.getStartTime() == null || competition.getEndTime() == null
|| competition.getRegisterEndTime() == null) {
throw new BusinessException("活动时间和截止报名时间不能为空");
}
if (competition.getApplicantsNumber() == null || competition.getApplicantsNumber() < 0) {
throw new BusinessException("报名人数必须为非负整数");
}
if (competition.getBaseNumber() != null && competition.getBaseNumber() < 0) {
throw new BusinessException("基础报名人数必须为非负整数");
}
if (competition.getStartAge() != null && competition.getEndAge() != null
&& competition.getStartAge() > competition.getEndAge()) {
throw new BusinessException("报名最小年龄不能大于最大年龄");
}
validatePrices(competition);
}
/**
* 校验各支付价格不可为负数。
*
* @param competition 待校验的活动信息
*/
private void validatePrices(Competition competition) throws BusinessException {
if ((competition.getCashPrice() != null && competition.getCashPrice() < 0)
|| (competition.getPlayPaiCoin() != null && competition.getPlayPaiCoin() < 0)
|| (competition.getClassPrice() != null && competition.getClassPrice() < 0)) {
throw new BusinessException("支付价格不能小于零");
}
}
/**
* 校验调整后的容量不会小于当前已报名人数。
*
* @param competition 待校验的活动信息
*/
private void validateApplicantsNumber(Competition competition) throws BusinessException {
int registeredCount = userCompetitionService.count(new LambdaQueryWrapper()
.eq(UserCompetition::getCompetitionId, competition.getId()));
if (competition.getApplicantsNumber() < registeredCount) {
throw new BusinessException("报名人数不能小于已报名人数" + registeredCount);
}
}
/**
* 根据当前时间刷新活动状态,并保持已取消活动的取消状态。
*
* @param originalCompetition 数据库中的原活动
* @param competition 待保存的活动信息
* @return 计算后的活动状态编码
*/
private Integer resolveCompetitionStatus(Competition originalCompetition, Competition competition) {
if (CompetitionStatusEnum.CANCELED.getCode().equals(originalCompetition.getStatus())) {
return CompetitionStatusEnum.CANCELED.getCode();
}
Date currentTime = new Date();
if (currentTime.before(competition.getStartTime())) {
return CompetitionStatusEnum.NOT_STARTED.getCode();
}
if (currentTime.before(competition.getEndTime())) {
return CompetitionStatusEnum.IN_PROGRESS.getCode();
}
return CompetitionStatusEnum.ENDED.getCode();
}
private String aliAppid = "2021004105665036";//支付宝appid
private String appPrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCi5i9nW/hGLJ3A06cZxTQdviFC7THpdSihoTYGLr9q006hu0V26ecBMY/o4w5bvIX0Ok/yofmZsVcCJpAPvbXL/uqVrIjnRRxXiaeBFThlxoBUTdunvbUSDYfzlEhJr5NvUKI6H6lz2niXlQGx4qy8Hau4ccWit9kM8jwUvsBVQoFgJA+xrjMvooA7YLopQtpOD+UJr5thApTSf1xrnr1W12yolTLEH15JmNV372cqXrYUuqnY0QsaPtxeqJUGAOcGdVLllQ7easEznP8DFBvDdHATcmp2SHNQDUEWN6MCVPbMgY06NQVqAXxqjTAYSVh+6TRu6bofPmpYC3TZB003AgMBAAECggEBAJAcR2+PA3NBYUYHeFrqBRMS8uX8ZR19kjZ7IgoSLTFaQsP9opRylPSPXhrPVBKAE5leRQAHn4MCSlESwHvMfxo7KFjFTFAc6dffZZpipYQUOc9bGampwJh58/3e/pyBgVMG6J23CPf/HJQtNFSkjd/V9+ayb/9l2dUEL3bC0fAZ/dbx8HsxdLw8wn3fLlWLj68hOMqa2deCZe3JdSVsPbeWqkh56FFsMLug0Nd+Ar4TgRl9/jnhXF0JWiD0LmPUYLhboY7EfUBzN4w1iYbDi1P+3zvoOYsiVKAXox9GMhQ2VzOO2UcSTuizSza2e98mGpabl/GpKmCz+RDFjtkX6eECgYEA2MyCij65eO3aGIm3FUe93DULRBYTfX8qJQSJq2WOWA3mmQlEW6L3O2B5/lG2h+8WmN6iLEs9eHpgycGYp7vAqgrANEn16ACVcuyx0scFtrZfZ+kmHMzFfiUWxJjVYk/6YngsGVBLdw6ueM42C8TTP67X9tU5TdVGoGWuqEj4W98CgYEAwFqwprXOch5Pqk/RPbb49r0Ou03K/UbciWnWWKzUhFFNS8MdlQPoDvQZbMwHLeWsa2VhaKITK3x5biLQb3U+0GLOn6lTvEyrEUH+ucREyLgVYTRAvwBPtnvlrzpyxPk2HnslQjju8WrvvLLBMKWUjlTrTOzhaHT21gz3pHMiOakCgYEAhLmfaXdBITGshb054sNLDtdCkGpbgEcrzAHdLps769iGxkYQHXHFngpQZUwtTUcoNGqIKknd1jZFrv7gsD+XkgKG7PwimehRlkwmCX5ilxtLiVgJRzRt6+5U5AMVD90a0tHzXYP0z2yjj73fBJF5KtGl0a10KZxaYrQdm1UhB00CgYBZZgzx/k9rtHC8LAqIj1CYhHejT92G53c6Gkl3vyOqN4sgKhfGmSEySfrDGPRBPZxr8ZtbIPCd5mUdberH0osWGMYFaJI1UsCy7aQwvGpniz7MhZeN7dweaOjwDs8mgtjHQ96mL4XGCDhR0BZ/wIURvZ/6iaGdhbbu9unlsWj3uQKBgQCmZYdsbbZkd3ev6f8rwyvMz+DrCQyYpY44cegBYuJgrZiQnL2fJioeN7ixX0UM48SfwsZEIrzshP/LGAwnc2MdjxKUl4jLN8SEe0NAjXOnz9Zaw740+aOmLpXcLWdP4uM2gIhWsvW1tEkQZCXmm7c9s/RsU8Pmzv+YL3+fSijOzA==";//支付宝开发者应用私钥
private String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAouYvZ1v4RiydwNOnGcU0Hb4hQu0x6XUooaE2Bi6/atNOobtFdunnATGP6OMOW7yF9DpP8qH5mbFXAiaQD721y/7qlayI50UcV4mngRU4ZcaAVE3bp721Eg2H85RISa+Tb1CiOh+pc9p4l5UBseKsvB2ruHHForfZDPI8FL7AVUKBYCQPsa4zL6KAO2C6KULaTg/lCa+bYQKU0n9ca569VtdsqJUyxB9eSZjVd+9nKl62FLqp2NELGj7cXqiVBgDnBnVS5ZUO3mrBM5z/AxQbw3RwE3JqdkhzUA1BFjejAlT2zIGNOjUFagF8ao0wGElYfuk0bum6Hz5qWAt02QdNNwIDAQAB";//支付宝应用公钥
private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmu8n/4yTHWbn7VOrNc9OsLtDL1bEQ8gC1dHkj8Wy5z0mkaOsjJRIG/28ze12M0V8jdCKuuDr5Z1OPKiqf+XO3ypguEh+mYUVMBM/cZodDFQfTY1TKLWjvQCuaqlA+QUTCK6f7T7stsgyQ1o9Jj0rXZDz6PM4QHSTzjrLIBaeqM5WIBvH+fy/X+QG5Utd+/UT0kc0JyvuKhZ65yVUd/C9VcwJJAPliRsAQNrqYterwAJ9zvw9tF11wj9W0XgJ8Ccu4x3gR1vrlLRJJo/OA97RmxPQ+5hSacWQZCUd1dwiBq+YCrKVHGTj14izRHXrLc0yBlRXo7tBOIqcy3IsvKVthQIDAQAB";//支付宝支付公钥
private String smid = "2088330203191220";//平台支付宝商户号
/**
* 获取赛事列表
*
* @param content
* @param registerCondition
* @param heat
* @return
*/
@Override
public List queryCompetitionList(String cityCode, String content, Integer registerCondition, String heat) throws Exception {
List competitionListVos = this.baseMapper.queryCompetitionList(cityCode, content, registerCondition, heat);
for (CompetitionListVo competitionListVo : competitionListVos) {
Integer counts = this.baseMapper.counts(competitionListVo.getId());
competitionListVo.setHeat(competitionListVo.getHeat() + counts);
}
return competitionListVos;
}
/**
* 获取赛事详情
*
* @param uid
* @param id
* @return
* @throws Exception
*/
@Override
public CompetitionInfo queryCompetitionInfo(Integer uid, Integer id, String lon, String lat) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Competition competition = this.getById(id);
CompetitionInfo competitionInfo = new CompetitionInfo();
competitionInfo.setId(competition.getId().longValue());
competitionInfo.setImgs(competition.getImgs());
competitionInfo.setName(competition.getName());
competitionInfo.setRegisterCondition(competition.getRegisterCondition());
// 2.0
ArrayList