| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- package com.cyksj.service.register.impl;
- import cn.hutool.core.bean.BeanUtil;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.util.StrUtil;
- import com.baomidou.mybatisplus.core.toolkit.Wrappers;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.cyksj.common.exception.BusinessRuntimeException;
- import com.cyksj.common.snowflake.Sequence;
- import com.cyksj.common.util.Codec;
- import com.cyksj.common.util.Jsons;
- import com.cyksj.common.util.Xmls;
- import com.cyksj.config.WeChatConfig;
- import com.cyksj.dto.RedisKey;
- import com.cyksj.dto.Result;
- import com.cyksj.enums.GatewayResponse;
- import com.cyksj.mapper.AppleAutoRegisterDataMapper;
- import com.cyksj.mapper.RegisterOrderDonMapper;
- import com.cyksj.mapper.SpotifyUnLimitRecordMapper;
- import com.cyksj.mapper.UserMapper;
- import com.cyksj.mapper.manage.coupon.CouponMapper;
- import com.cyksj.model.dto.H5JsPayParams;
- import com.cyksj.model.entity.*;
- import com.cyksj.model.manage.request.RegisterReq;
- import com.cyksj.model.request.OrderAttach;
- import com.cyksj.model.request.WxOrderRefundReq;
- import com.cyksj.model.views.CouponUserView;
- import com.cyksj.redis.RedisService;
- import com.cyksj.service.mange.coupon.CouponCommonService;
- import com.cyksj.service.register.RegisterOrderDonService;
- import com.cyksj.service.register.SpotifyService;
- import com.cyksj.service.sys.SysConfigService;
- import com.cyksj.service.wechat.WeChatService;
- import com.cyksj.task.JobManager;
- import com.ejlchina.searcher.BeanSearcher;
- import com.ejlchina.searcher.param.Operator;
- import com.ejlchina.searcher.util.MapUtils;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.math.BigDecimal;
- import java.util.Map;
- /**
- * @author chan
- * @date 2022/11/7 2:39 PM
- */
- @Service
- @Slf4j
- @RequiredArgsConstructor
- public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMapper ,RegisterOrderDon> implements RegisterOrderDonService {
- private static final Sequence SEQUENCE = new Sequence(0);
- private static final String REGISTER_PRICE_KEY = "register_price";
- private final SpotifyService spotifyService;
- private final RedisService redisService;
- private final WeChatService weChatService;
- private final WeChatConfig weChatConfig;
- private final SysConfigService sysConfigService;
- private final UserMapper userMapper;
- private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
- private final JobManager jobManager;
- private final RegisterOrderDonMapper registerOrderDonMapper;
- private final CouponMapper couponMapper;
- private final CouponCommonService couponCommonService;
- private final SpotifyUnLimitRecordMapper spotifyUnLimitRecordMapper;
- private final BeanSearcher beanSearcher;
- private static final Long EXPIRY_TIME = 1000 * 60 * 5L;
- /**
- * 判断是否免费
- * @author chan
- * @date 2022-11-07 3:34 PM
- */
- @Override
- public boolean isFree(long userId, String platform) {
- int count = count(Wrappers.lambdaQuery(RegisterOrderDon.class)
- .eq(RegisterOrderDon::getUserId, userId)
- .ne(RegisterOrderDon::getStatus, RegisterOrderDon.Status.noPayment)
- .eq(RegisterOrderDon::getIsFree, true));
- if(count > 0){
- return false;
- }
- Long num = redisService.decr(RedisKey.SPOTIFY_FREE_NUM, 1L);
- if(num >= 0){
- return true;
- }else {
- redisService.incr(RedisKey.SPOTIFY_FREE_NUM, 1L);
- }
- return false;
- }
- /**
- * 保存注册资料
- * @author chan
- * @date 2022-11-07 3:34 PM
- */
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public RegisterOrderDon saveOrder(long userId, RegisterReq req, boolean isFree) throws Exception {
- RegisterOrderDon orderDon = new RegisterOrderDon();
- User user = userMapper.selectById(userId);
- BeanUtil.copyProperties(req,orderDon);
- SysConfig register_price = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "register_price").last("limit 1"));
- Map<String, Integer> map = Jsons.toMap(register_price.getSysValue());
- orderDon.setOrderNo(SEQUENCE.nextId() + "");
- orderDon.setUserId(userId);
- orderDon.setOpenId(user.getOpenId());
- orderDon.setIsFree(isFree);
- orderDon.setMoney(isFree ? BigDecimal.ZERO : BigDecimal.valueOf(("apple".equals(req.getPlatform()) && "auto".equals(req.getAppleRegisterType())) ? map.get("appleAuto") : map.get(req.getPlatform())));
- orderDon.setStatus(isFree ? RegisterOrderDon.Status.hasPayment : RegisterOrderDon.Status.noPayment);
- save(orderDon);
- //apple
- handleAppleIdAuto(userId, req, orderDon);
- return orderDon;
- }
- /**
- * Apple ID自动注册
- */
- private void handleAppleIdAuto(long userId, RegisterReq req, RegisterOrderDon orderDon) {
- if ("apple".equals(req.getPlatform()) && "auto".equals(req.getAppleRegisterType())) {
- //是否有未支付的国家或区域的订单
- Integer exists = appleAutoRegisterDataMapper.checkNoPayOrder(userId, req.getCountryOrArea());
- if (exists != null) {
- throw BusinessRuntimeException.getInstance(String.format("您有%s随机生成Apple ID未支付的订单", req.getCountryOrArea().getDesc()));
- }
- if (req.getCountryOrArea() == null) {
- throw BusinessRuntimeException.getInstance("请选择对应的国家或地区");
- }
- //查看是否有空余账号
- AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getCountryOrArea, req.getCountryOrArea()).eq(AppleAutoRegisterData::getStatus, false).select(AppleAutoRegisterData::getId).last("limit 1"));
- if (appleAutoRegisterData == null) {
- throw BusinessRuntimeException.getInstance("自动生成Apple ID库存不足");
- }
- appleAutoRegisterData.setUserId(userId);
- appleAutoRegisterData.setStatus(true);
- appleAutoRegisterData.setOrderId(orderDon.getId());
- int update = appleAutoRegisterDataMapper.update(appleAutoRegisterData, Wrappers.lambdaUpdate(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getStatus, false).eq(AppleAutoRegisterData::getId, appleAutoRegisterData.getId()));
- if (update != 1) {
- throw BusinessRuntimeException.getInstance("系统异常,请重新操作");
- }
- jobManager.addJob(EXPIRY_TIME, () -> {
- updateAppleAutoStatus(orderDon.getId());
- });
- }
- }
- @Override
- public void updateAppleAutoStatus(Long orderId) {
- log.info("校验appleID自动注册订单 orderId:{}", orderId);
- RegisterOrderDon registerOrderDon = this.getById(orderId);
- if (registerOrderDon != null && RegisterOrderDon.Status.noPayment == registerOrderDon.getStatus()) {
- AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getOrderId, orderId).last("limit 1"));
- if (appleAutoRegisterData != null) {
- appleAutoRegisterData.setStatus(false);
- appleAutoRegisterData.setUserId(0l);
- appleAutoRegisterData.setOrderId(0l);
- appleAutoRegisterDataMapper.updateById(appleAutoRegisterData);
- //订单关闭
- registerOrderDon.setStatus(RegisterOrderDon.Status.close);
- registerOrderDonMapper.updateById(registerOrderDon);
- log.info("未支付appleID自动注册订单:{},修改appleID使用状态", orderId);
- }
- }
- }
- @Override
- public CouponUserView spotifyUnLimit(SpotifyUnLimitRecord spotifyUnLimitRecord) {
- RegisterOrderDon registerOrderDon = this.getOne(Wrappers.lambdaQuery(RegisterOrderDon.class).eq(RegisterOrderDon::getUserId, spotifyUnLimitRecord.getUserId()).eq(RegisterOrderDon::getEmail, spotifyUnLimitRecord.getAccount()).select(RegisterOrderDon::getPassword, RegisterOrderDon::getUsername).last("limit 1"));
- if (registerOrderDon == null) {
- throw BusinessRuntimeException.getInstance("仅接受银河录像局注册成功的Spotify邮箱");
- }
- if (registerOrderDon.getStatus() != RegisterOrderDon.Status.complete) {
- throw BusinessRuntimeException.getInstance("您的Spotify账号暂未注册成功");
- }
- Boolean isFlag = false;
- Long spotifyCouponId = null;
- //是否配置了优惠券
- SysConfig spotify_coupon_id = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "spotify_coupon_id").last("limit 1"));
- if (spotify_coupon_id != null) {
- spotifyCouponId = Long.parseLong(spotify_coupon_id.getSysValue());
- Coupon coupon = couponMapper.selectById(spotifyCouponId);
- if (coupon != null) {
- isFlag = couponCommonService.sendCouponToUser(spotifyUnLimitRecord.getUserId(), spotifyCouponId, null, null, null, CouponUser.Channel.manual);
- }
- }
- spotifyUnLimitRecordMapper.insert(spotifyUnLimitRecord);
- return isFlag ? beanSearcher.searchFirst(CouponUserView.class, MapUtils.builder()
- .field(CouponUserView::getUserId, spotifyUnLimitRecord.getUserId()).op(Operator.Equal)
- .field(CouponUserView::getCouponId, spotifyCouponId).op(Operator.Equal)
- .build()) : null;
- }
- @Override
- public H5JsPayParams pay(Long orderId) throws Exception {
- log.info("注册 账号调起微信支付[start] orderId:{}", orderId);
- RegisterOrderDon orderDon = this.getById(orderId);
- if (orderDon.getStatus() == RegisterOrderDon.Status.close) {
- throw BusinessRuntimeException.getInstance("订单已关闭");
- }
- OrderAttach attach = new OrderAttach();
- attach.setO(orderDon.getId());
- String toWechatAttach = Codec.DoBase64.custom()
- .setData(Jsons.toJson(attach)).encodeAsText();
- H5JsPayParams params = weChatService.getJsPayParams(
- weChatConfig.getAppid(),
- ShopConfig.WX_DEFAULT_APP_ID,
- orderDon.getOpenId(),
- orderDon.getMoney().intValue(),
- orderDon.getOrderNo(),
- weChatConfig.getDomain() + "applets/register/prepay/notify",
- toWechatAttach,
- "注册服务",
- "JSAPI",
- null
- );
- log.info("微信支付成功[end]");
- return params;
- }
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void prepayNotify(Map<String, String> map) throws Exception {
- /* 此处处理订单等业务逻辑 */
- // 获取订单 和 微信订单号 和 支付的金额
- String attach = Codec.DoBase64.custom().setData(map.get("attach")).decodeAsText();
- OrderAttach orderAttach = Jsons.parseObject(attach, OrderAttach.class);
- final Long oid = orderAttach.getO();
- //final Long shareId = orderAttach.getShared();
- RegisterOrderDon order = this.getById(oid);
- if (null == order) {
- throw BusinessRuntimeException.getInstance("订单不存在.");
- }
- // 校验签名
- boolean f = weChatService.checkSignWithMd5(map, weChatConfig.getShopKey());
- if (!f) {
- log.error("回调数据:{}", map);
- throw BusinessRuntimeException.getInstance("支付成功回调, 校验签名失败.");
- }
- String transactionId = map.get("transaction_id");
- if (order.getStatus().equals(RegisterOrderDon.Status.hasPayment)) {
- log.info("已回调,重复修改状态 id:{}", order.getId());
- return;
- }
- // 更改订单状态
- order.setTransactionId(transactionId);
- order.setStatus(RegisterOrderDon.Status.hasPayment);
- AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getOrderId, order.getId()).eq(AppleAutoRegisterData::getStatus, true));
- if (appleAutoRegisterData != null) {
- order.setStatus(RegisterOrderDon.Status.complete);
- }
- order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
- if (StringUtils.isBlank(order.getOpenId())) {
- order.setOpenId(map.get("openid"));
- }
- this.updateById(order);
- }
- @Override
- public Result<String> wxRefund(WxOrderRefundReq wxOrderRefundReq) throws Exception {
- RegisterOrderDon registerOrderDon = this.getById(wxOrderRefundReq.getOrderId());
- if (registerOrderDon == null) {
- throw BusinessRuntimeException.getInstance("该订单不存在");
- }
- if (registerOrderDon.getStatus() == RegisterOrderDon.Status.refund) {
- throw BusinessRuntimeException.getInstance("该订单已退款");
- }
- if (registerOrderDon.getStatus() != RegisterOrderDon.Status.error && registerOrderDon.getStatus() != RegisterOrderDon.Status.hasPayment) {
- throw BusinessRuntimeException.getInstance("该订单状态不允许退款");
- }
- if (registerOrderDon.getMoney().compareTo(BigDecimal.ZERO) <= 0) {
- throw BusinessRuntimeException.getInstance("该订单金额为0,无需退款");
- }
- if (!redisService.setNx(String.format("%s", wxOrderRefundReq.getOrderId()), wxOrderRefundReq.getOrderId(), 10l)) {
- throw BusinessRuntimeException.getInstance("请勿重复点击,正在退款中..");
- }
- long time = System.currentTimeMillis();
- //退款订单号
- String outRefundNo = Codec.DoDigest.custom()
- .setAlgorithm(Codec.DoDigest.Algorithm.MD5)
- .setStringData(time + String.valueOf(registerOrderDon.getId()))
- .toHexString();
- wxOrderRefundReq.setRefundMoney(registerOrderDon.getMoney());
- weChatService.refundWxOrder(weChatConfig.getAppid(),
- ShopConfig.WX_DEFAULT_APP_ID,
- registerOrderDon.getTransactionId(),
- outRefundNo,
- registerOrderDon.getMoney(),
- wxOrderRefundReq.getRefundMoney(),
- weChatConfig.getDomain() + "manage/register/wx/refund/notify");
- //修改订单状态
- registerOrderDon.setStatus(RegisterOrderDon.Status.refund);
- this.updateById(registerOrderDon);
- return GatewayResponse.SUCCESS.newBuilder().toResult("退款成功");
- }
- @Override
- public void wxRefundNotify(Map<String, String> map) throws Exception {
- // 对退款数据 解密
- String md5Key = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(weChatConfig.getShopKey()).toHexString();
- String reqInfoXml = Codec.DoCipher.custom().setAlgorithm(Codec.DoCipher.Trans.AES_ECB_PKCS7Padding).setBase64Data(map.get("req_info")).setStringKey(md5Key).ofDecrypt().toText();
- log.info("=== 退款数据解密: \n {}", reqInfoXml);
- Map<String, String> reqInfoMap = Xmls.toMap(reqInfoXml);
- // 退款失败
- if (StrUtil.equals("CHANGE", reqInfoMap.get("refund_status"))) {
- throw BusinessRuntimeException.getInstance("退款异常.");
- } else if (StrUtil.equals("REFUNDCLOSE", reqInfoMap.get("refund_status"))) {
- throw BusinessRuntimeException.getInstance("退款关闭.");
- }
- /* 此处处理业务逻辑 */
- String outRefundNo = reqInfoMap.get("out_refund_no");
- String transactionId = reqInfoMap.get("transaction_id");
- RegisterOrderDon registerOrderDon = this.getOne(Wrappers.lambdaQuery(RegisterOrderDon.class).eq(RegisterOrderDon::getTransactionId, transactionId).last("limit 1"));
- if (registerOrderDon == null) {
- log.error("退款回调,transactionId:{}订单不存在", transactionId);
- }
- if (registerOrderDon.getStatus() != RegisterOrderDon.Status.refund) {
- registerOrderDon.setStatus(RegisterOrderDon.Status.refund);
- this.updateById(registerOrderDon);
- }
- log.info("微信退款: 退款单号[{}] 退款成功.", outRefundNo);
- }
- }
|