无关风月
2024-08-20 f237a61c412870933f47316a011237cd538de9bc
guns-admin/src/main/java/com/stylefeng/guns/modular/api/SportsController.java
@@ -1,12 +1,26 @@
package com.stylefeng.guns.modular.api;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.security.KeyFactory;
import java.security.PrivilegedAction;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.sql.Timestamp;
import java.time.LocalTime;
import java.util.Date;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.modular.system.dto.AddUserWatchDTO;
import com.stylefeng.guns.modular.system.model.*;
@@ -16,6 +30,8 @@
import com.stylefeng.guns.modular.system.util.Page;
import com.stylefeng.guns.modular.system.vo.*;
import com.stylefeng.guns.modular.system.dto.CourseQuery;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModelProperty;
@@ -86,6 +102,7 @@
        return "LO" + sdf.format(new Date()) + UUIDUtil.getRandomCode(5);
    }
    @Autowired
    private IRechargeService rechargeService;
    @PostMapping("/iospay")
@@ -153,11 +170,32 @@
                          BigDecimal realMoney) throws Exception {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        BaseWarpper baseWarpper = new BaseWarpper();
        switch (buyType){
            case 1:
                Course course = courseService.selectById(id);
                BigDecimal amount = fitnessPositionService.selectById(course.getPositionId()).getAmount();
                FitnessPosition fitnessPosition = fitnessPositionService.selectById(course.getPositionId());
                BigDecimal amount = new BigDecimal(BigInteger.ZERO);
                    switch (course.getDifficulty()){
                        case 1:
                            amount = fitnessPosition.getAmount();
                            break;
                        case 2:
                            amount = fitnessPosition.getAmount2();
                            break;
                        case 3:
                            amount = fitnessPosition.getAmount3();
                            break;
                        case 4:
                            amount = fitnessPosition.getAmount4();
                            break;
                        case 5:
                            amount = fitnessPosition.getAmount5();
                            break;
                    }
                // 购买课程
                OrderCourse orderCourse = new OrderCourse();
                orderCourse.setCode(this.getOrderNum());
@@ -218,7 +256,68 @@
        }
        return ResultUtil.success();
    }
    /**
     * 购买套餐微信支付回调
     *
     * @param request
     * @param response
     */
    @ResponseBody
    @PostMapping("/base/testApple")
    public void testApple(HttpServletRequest request, HttpServletResponse response) {
        try {
            Map<String, String> params = new HashMap<String, String>();
            System.err.println("请求"+request);
            BufferedReader reader = request.getReader();
            String string1 = reader.toString();
            System.err.println("请求reader"+string1);
            StringBuilder requestBody = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
            }
            System.err.println("全部请求体"+requestBody);
            org.json.JSONObject jsonObject1 = new org.json.JSONObject(requestBody.toString());
            System.err.println("json串"+jsonObject1);
            String o = jsonObject1.getString("signedPayload");
            JSONObject payload = verifyAndGet(o);
            String notificationType = payload.get("notificationType").toString();
            JSONObject data = payload.getJSONObject("data");
            String signedTransactionInfo = data.get("signedTransactionInfo").toString();
            String environment = data.get("environment").toString();
            JSONObject transactionInfo = verifyAndGet(signedTransactionInfo);
            String transactionId = transactionInfo.get("transactionId").toString();
            String originalTransactionId = transactionInfo.get("originalTransactionId").toString();
            String productId = transactionInfo.get("productId").toString();
            System.err.println("json串"+transactionInfo);
            System.err.println("data"+data);
            // 苹果流水号
            String string = transactionInfo.getString("originalTransactionId");
            System.err.println("苹果流水号"+string);
            Recharge orderNumber = rechargeService.selectOne(new EntityWrapper<Recharge>()
                    .eq("orderNumber", string));
            if (orderNumber!=null){
                if (orderNumber.getState()!=2){
                    // 进入
                    orderNumber.setState(2);
                    orderNumber.setPayTime(new Date());
                    rechargeService.updateById(orderNumber);
                    BigDecimal amount = orderNumber.getAmount();
                    AppUser appUser = appUserService.selectById(orderNumber.getUserId());
                    BigDecimal add = appUser.getBalance().add(amount);
                    appUser.setBalance(add);
                    appUserService.updateById(appUser);
                }
            }
            PrintWriter out = response.getWriter();
            out.write("success");
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 购买套餐微信支付回调
     *
@@ -246,6 +345,67 @@
                order.setPayTime(new Date());
                order.setPayType(1);
                orderService.updateById(order);
                BigDecimal divisor = new BigDecimal("100");
                // 计算提成
                SysSet sysSet = sysSetService.selectById(1);
                // 邀请人可获得被邀请人消费金额比例
                String people = sysSet.getPeople();
                // 团队长可获得团员消费金额比例
                String header = sysSet.getHeader();
                // 邀请人比例
                BigDecimal bigDecimal = new BigDecimal(people).divide(divisor);
                // 获取金额
                BigDecimal multiply = order.getRealMoney().multiply(bigDecimal);
                BigDecimal bigDecimal1 = multiply.setScale(2, BigDecimal.ROUND_DOWN);
                // 如果使用了优惠券将优惠券修改为已消费
                if (order.getCouponId()!=null){
                    CouponReceive couponReceive1 = couponReceiveService.selectById(order.getCouponId());
                    couponReceive1.setState(2);
                    couponReceiveService.updateById(couponReceive1);
                }
                AppUser appUser = appUserService.selectById(order.getUserId());
                // 如果当前用户有邀请人
                if (appUser.getInviteUserId()!=null){
                    if (StringUtils.hasLength(people)){
                        Invite invite = new Invite();
                        invite.setUserId(appUser.getId());
                        invite.setInsertTime(new Date());
                        invite.setAmount(bigDecimal1);
                        invite.setConsume(order.getRealMoney());
                        invite.setGiftUserId(appUser.getInviteUserId());
                        invite.setType(1);
                        inviteService.insert(invite);
                        // 给用户加余额
                        AppUser appUser1 = appUserService.selectById(appUser.getInviteUserId());
                        BigDecimal balance1 = appUser1.getBalance();
                        BigDecimal add = balance1.add(bigDecimal1);
                        appUser1.setBalance(add);
                        appUserService.updateById(appUser1);
                    }
                    if (StringUtils.hasLength(header)){
                        // 先判断当前用户有没有团队长
                        if (appUserService.selectById(appUser.getInviteUserId()).getInviteUserId()!=null){
                            // 有团队长
                            BigDecimal bigDecimal2 = new BigDecimal(header).divide(divisor);
                            BigDecimal multiply1 = order.getRealMoney().multiply(bigDecimal2);
                            BigDecimal bigDecimal3 = multiply1.setScale(2, BigDecimal.ROUND_DOWN);
                            Invite invite = new Invite();
                            invite.setUserId(appUser.getId());
                            invite.setInsertTime(new Date());
                            invite.setAmount(bigDecimal3);
                            invite.setConsume(order.getRealMoney());
                            invite.setGiftUserId(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            invite.setType(2);
                            inviteService.insert(invite);
                            // 给用户加余额
                            AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            BigDecimal balance1 = appUser1.getBalance();
                            BigDecimal add = balance1.add(bigDecimal1);
//                            appUser1.setBalance(add);
                            appUserService.updateById(appUser1);
                        }
                    }
                }
                PrintWriter out = response.getWriter();
                out.write(result);
                out.flush();
@@ -282,6 +442,68 @@
                orderCourse.setPayType(1);
                orderCourse.setPayTime(new Date());
                orderCourseService.updateById(orderCourse);
                // 如果使用了优惠券将优惠券修改为已消费
                if (orderCourse.getCouponId()!=null){
                    CouponReceive couponReceive1 = couponReceiveService.selectById(orderCourse.getCouponId());
                    couponReceive1.setState(2);
                    couponReceiveService.updateById(couponReceive1);
                }
                BigDecimal divisor = new BigDecimal("100");
                // 计算提成
                SysSet sysSet = sysSetService.selectById(1);
                // 邀请人可获得被邀请人消费金额比例
                String people = sysSet.getPeople();
                // 团队长可获得团员消费金额比例
                String header = sysSet.getHeader();
                // 邀请人比例
                BigDecimal bigDecimal = new BigDecimal(people).divide(divisor);
                // 获取金额
                BigDecimal multiply = orderCourse.getRealMoney().multiply(bigDecimal);
                BigDecimal bigDecimal1 = multiply.setScale(2, BigDecimal.ROUND_DOWN);
                AppUser appUser = appUserService.selectById(orderCourse.getUserId());
                // 如果当前用户有邀请人
                if (appUser.getInviteUserId()!=null){
                    if (StringUtils.hasLength(people)){
                        Invite invite = new Invite();
                        invite.setUserId(appUser.getId());
                        invite.setInsertTime(new Date());
                        invite.setAmount(bigDecimal1);
                        invite.setConsume(orderCourse.getRealMoney());
                        invite.setGiftUserId(appUser.getInviteUserId());
                        invite.setType(1);
                        inviteService.insert(invite);
                        // 给用户加余额
                        AppUser appUser1 = appUserService.selectById(appUser.getInviteUserId());
                        BigDecimal balance1 = appUser1.getBalance();
                        BigDecimal add = balance1.add(bigDecimal1);
                        appUser1.setBalance(add);
                        appUserService.updateById(appUser1);
                    }
                    if (StringUtils.hasLength(header)){
                        // 先判断当前用户有没有团队长
                        if (appUserService.selectById(appUser.getInviteUserId()).getInviteUserId()!=null){
                            // 有团队长
                            BigDecimal bigDecimal2 = new BigDecimal(header).divide(divisor);
                            BigDecimal multiply1 = orderCourse.getRealMoney().multiply(bigDecimal2);
                            BigDecimal bigDecimal3 = multiply1.setScale(2, BigDecimal.ROUND_DOWN);
                            Invite invite = new Invite();
                            invite.setUserId(appUser.getId());
                            invite.setInsertTime(new Date());
                            invite.setAmount(bigDecimal3);
                            invite.setConsume(orderCourse.getRealMoney());
                            invite.setGiftUserId(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            invite.setType(2);
                            inviteService.insert(invite);
                            // 给用户加余额
                            AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            BigDecimal balance1 = appUser1.getBalance();
                            BigDecimal add = balance1.add(bigDecimal1);
//                            appUser1.setBalance(add);
                            appUserService.updateById(appUser1);
                        }
                    }
                }
                PrintWriter out = response.getWriter();
                out.write(result);
                out.flush();
@@ -320,7 +542,11 @@
                recharge.setPayTime(new Date());
                recharge.setPayType(1);
                rechargeService.updateById(recharge);
                AppUser appUser = appUserService.selectById(recharge.getUserId());
                BigDecimal balance = appUser.getBalance();
                BigDecimal add = balance.add(recharge.getAmount());
                appUser.setBalance(add);
                appUserService.updateById(appUser);
                PrintWriter out = response.getWriter();
                out.write(result);
                out.flush();
@@ -330,8 +556,90 @@
            e.printStackTrace();
        }
    }
    @ResponseBody
    @PostMapping("/base/applePayResult")
    public void applePayResult(HttpServletRequest request, HttpServletResponse response) {
    }
    @Autowired
    private IInviteService inviteService;
    @ResponseBody
    @PostMapping("/base/sports/payApple")
    @ApiOperation(value = "苹果支付补偿", tags = {"运动"})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "Bearer eyJhbGciOiJIUzUxMiJ....", required = true, paramType = "header"),
            @ApiImplicitParam(name = "id", value = "课程id或者套餐id", required = true),
            @ApiImplicitParam(name = "buyType", value = "购买类型 1=购买课程 2=购买套餐 ", required = true),
            @ApiImplicitParam(name = "transactionReceipt", value = "苹果账单"),
    })
    public ResultUtil payApple(
                          Integer id,
                          Integer buyType,
                          String transactionReceipt) throws Exception {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        switch (buyType){
            case 1:
                Course orderCourse1 = courseService.selectById(id);
                FitnessPosition fitnessPosition = fitnessPositionService.selectById(orderCourse1.getPositionId());
                switch (orderCourse1.getDifficulty()){
                    case 1:
                        fitnessPosition.setAmount(fitnessPosition.getAppleAmount());
                        break;
                    case 2:
                        fitnessPosition.setAmount(fitnessPosition.getAppleAmount2());
                        break;
                    case 3:
                        fitnessPosition.setAmount(fitnessPosition.getAppleAmount3());
                        break;
                    case 4:
                        fitnessPosition.setAmount(fitnessPosition.getAppleAmount4());
                        break;
                    case 5:
                        fitnessPosition.setAmount(fitnessPosition.getAppleAmount5());
                        break;
                }
                Boolean success1 = IosPalUtils.isSuccess(transactionReceipt);
                if (success1){
                    OrderCourse orderCourse = new OrderCourse();
                    orderCourse.setCode(this.getOrderNum());
                    orderCourse.setOrderNumber(this.getOrderNum());
                    orderCourse.setUserId(appUser.getId());
                    orderCourse.setPayTime(new Date());
                    orderCourse.setInsertTime(new Date());
                    orderCourse.setPayType(4);
                    orderCourse.setAmount(fitnessPosition.getAppleAmount());
                    orderCourse.setCouponId(null);
                    orderCourse.setRealMoney(fitnessPosition.getAppleAmount());
                    orderCourse.setState(2);
                    orderCourse.setCourseId(id);
                    orderCourseService.insert(orderCourse);
                }
                break;
            case 2:
                Package orderCourse2 = packageService.selectById(id);
                Boolean success2 = IosPalUtils.isSuccess(transactionReceipt);
                if (success2){
                    Order orderCourse = new Order();
                    orderCourse.setCode(this.getOrderNum());
                    orderCourse.setOrderNumber(this.getOrderNum());
                    orderCourse.setUserId(appUser.getId());
                    orderCourse.setPayTime(new Date());
                    orderCourse.setInsertTime(new Date());
                    orderCourse.setPayType(4);
                    orderCourse.setAmount(orderCourse2.getAppleAmount());
                    orderCourse.setCouponId(null);
                    orderCourse.setRealMoney(orderCourse2.getAppleAmount());
                    orderCourse.setState(2);
                    orderCourse.setPackageId(id);
                    orderService.insert(orderCourse);
                }
                break;
        }
        return ResultUtil.success();
    }
    @ResponseBody
    @PostMapping("/base/sports/pay")
    @ApiOperation(value = "支付", tags = {"运动"})
@@ -351,26 +659,57 @@
                          String transactionIdentifier,
                          BigDecimal orderMoney) throws Exception {
        AppUser appUser = appUserService.getAppUser();
        OrderCourse orderCourse = orderCourseService.selectOne(new EntityWrapper<OrderCourse>()
        .eq("id",id)
        .eq("userId",appUser.getId()));
        Order order = orderService.selectOne(new EntityWrapper<Order>()
                .eq("id",id)
                .eq("userId",appUser.getId()));
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        switch (buyType){
            case 1:
                OrderCourse orderCourse = orderCourseService.selectOne(new EntityWrapper<OrderCourse>()
                        .eq("id",id)
                        .eq("userId",appUser.getId()));
//                if (orderCourse != null){
//                    payType = orderCourse.getPayType();
//                }
                break;
            case 2:
                Order order = orderService.selectOne(new EntityWrapper<Order>()
                        .eq("id",id)
                        .eq("userId",appUser.getId()));
//                if (order!=null){
//                    payType = order.getPayType();
//                }
                break;
            case 3:
                Recharge recharge1 = rechargeService.selectOne(new EntityWrapper<Recharge>()
                        .eq("id",id)
                        .eq("userId",appUser.getId()));
                if (recharge1 != null){
                    if (payType == 4){
                        recharge1.setPayType(3);
                    }else{
                        recharge1.setPayType(payType);
                    }
//                    payType = recharge1.getPayType();
                    recharge1.setOrderNumber(transactionIdentifier);
                    rechargeService.updateById(recharge1);
                }
                break;
        }
        Recharge recharge1 = rechargeService.selectOne(new EntityWrapper<Recharge>()
                .eq("id",id)
                .eq("userId",appUser.getId()));
        if (recharge1 != null){
            payType = recharge1.getPayType();
        }else if (order!=null){
            payType = order.getPayType();
        } else if (orderCourse != null){
            payType = orderCourse.getPayType();
        }
        OrderCourse orderCourse = orderCourseService.selectOne(new EntityWrapper<OrderCourse>()
                .eq("id",id)
                .eq("userId",appUser.getId()));
        Order order = orderService.selectOne(new EntityWrapper<Order>()
                .eq("id",id)
                .eq("userId",appUser.getId()));
        switch (payType){
            case 1:
                switch (buyType){
                    case 1:
                        return payMoneyUtil.weixinpay
                                ("购买课程下单支付", "",
                                        id + "_" +buyType+"_"+
@@ -378,6 +717,7 @@
                                        orderCourse.getRealMoney().toString(),
                                        "/base/wxPayBuyCourse", "APP", "");
                    case 2:
                        return payMoneyUtil.weixinpay
                                ("购买套餐下单支付", "",
                                        id + "_" +buyType+"_"+
@@ -385,6 +725,7 @@
                                        order.getRealMoney().toString(),
                                        "/base/wxPayBuyPackage", "APP", "");
                    case 3:
                        return payMoneyUtil.weixinpay
                                ("充值余额下单支付", "",
                                        id + "_" +buyType+"_"+
@@ -494,7 +835,7 @@
                                    AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                                    BigDecimal balance1 = appUser1.getBalance();
                                    BigDecimal add = balance1.add(bigDecimal1);
                                    appUser1.setBalance(add);
//                                    appUser1.setBalance(add);
                                    appUserService.updateById(appUser1);
                                }
                            }
@@ -565,7 +906,7 @@
                                    AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                                    BigDecimal balance5 = appUser1.getBalance();
                                    BigDecimal add = balance5.add(bigDecimal3);
                                    appUser1.setBalance(add);
//                                    appUser1.setBalance(add);
                                    appUserService.updateById(appUser1);
                                }
                            }
@@ -578,57 +919,39 @@
                    // 苹果支付 全部用余额来购买 如果余额不足 提示购买余额
                    case 1:
                        // 购买课程
                        BigDecimal realMoney = orderCourse.getRealMoney();
                        if (appUser.getBalance().compareTo(realMoney)<0) {
                            return ResultUtil.error("余额不足");
                        Boolean success = IosPalUtils.isSuccess(transactionReceipt);
                        if (success){
                            // 购买成功 将支付状态修改为已支付
                            orderCourse.setState(2);
                            orderCourse.setPayTime(new Date());
                            orderCourse.setPayType(4);
                            orderCourseService.updateById(orderCourse);
                        }
                        break;
                    case 2:
                        BigDecimal realMoney1 = order.getRealMoney();
                        if (appUser.getBalance().compareTo(realMoney1)<0) {
                            return ResultUtil.error("余额不足");
                        // 购买课程
                        Boolean success1 = IosPalUtils.isSuccess(transactionReceipt);
                        if (success1){
                            // 购买成功 将支付状态修改为已支付
                            order.setState(2);
                            order.setPayTime(new Date());
                            order.setPayType(4);
                            orderService.updateById(order);
                        }
                        break;
                        // todo 2.0ios取消余额
                    case 3:
                        recharge1.setState(2);
                        recharge1.setPayType(3);
                        rechargeService.updateById(recharge1);
                        BigDecimal amount = recharge1.getAmount();
                        BigDecimal add = appUser.getBalance().add(amount);
                        appUser.setBalance(add);
                        appUserService.updateById(appUser);
                        break;
                        Boolean success3 = IosPalUtils.isSuccess(transactionReceipt);
//                        if (success3){
//                            recharge1.setState(2);
//                            rechargeService.updateById(recharge1);
//                            BigDecimal amount = recharge1.getAmount();
//                            BigDecimal add = appUser.getBalance().add(amount);
//                            appUser.setBalance(add);
//                            appUserService.updateById(appUser);
//                            break;
//                        }
                }
//                if (StringUtils.hasLength(transactionReceipt)){
//                    // 调用苹果 查询支付结果
//                    String verifyResult  = IosVerifyUtil.buyAppVerify(transactionReceipt, 0);
//                    if (verifyResult == null) {
//                        return ResultUtil.error("苹果验证失败,返回数据为空");
//                    }else{
//                        JSONObject appleReturn = JSONObject.parseObject(verifyResult);
//                        String states = appleReturn.getString("status");
//                        //无数据则沙箱环境验证
//                        if ("21007".equals(states)) {
//                            verifyResult = IosVerifyUtil.buyAppVerify(transactionReceipt, 0);
//                            System.err.println("沙盒环境,苹果平台返回JSON:" + verifyResult);;
//                            appleReturn = JSONObject.parseObject(verifyResult);
//                            states = appleReturn.getString("status");
//                        }
//                        if (states.equals("0")) {
//                            String receipt1 = appleReturn.getString("receipt");
//                            JSONObject returnJson = JSONObject.parseObject(receipt1);
//                            String inApp = returnJson.getString("in_app");
//                            List<HashMap> inApps = JSONObject.parseArray(inApp, HashMap.class);
//                            if (inApps!=null) {
//                                // 判断交易列表有没有包含当前订单
//                            }
//                            return ResultUtil.error("未能获取获取到交易列表");
//                        } else {
//                            return ResultUtil.error("支付失败,错误码:" + states);
//                        }
//                    }
//                }
                break;
        }
        return ResultUtil.success();
@@ -718,7 +1041,7 @@
                            AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            BigDecimal balance1 = appUser1.getBalance();
                            BigDecimal add = balance1.add(bigDecimal1);
                            appUser1.setBalance(add);
//                            appUser1.setBalance(add);
                            appUserService.updateById(appUser1);
                        }
                    }
@@ -814,7 +1137,7 @@
                            AppUser appUser1 = appUserService.selectById(appUserService.selectById(appUser.getInviteUserId()).getInviteUserId());
                            BigDecimal balance1 = appUser1.getBalance();
                            BigDecimal add = balance1.add(bigDecimal1);
                            appUser1.setBalance(add);
//                            appUser1.setBalance(add);
                            appUserService.updateById(appUser1);
                        }
                    }
@@ -878,6 +1201,10 @@
            @ApiImplicitParam(value = "订单id", name = "orderId", dataType = "int", required = true),
    })
    public ResultUtil<CouponVO> success(Integer orderId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        CouponVO couponVO = new CouponVO();
        // 查询后台有没有配置首次下单赠送奖品
        SysSet sysSet = sysSetService.selectById(1);
@@ -1099,6 +1426,10 @@
            @ApiImplicitParam(value = "课程id", name = "courseId", dataType = "int", required = true)
    })
    public ResultUtil<BuyDetailVO> buyCourse(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        BuyDetailVO buyDetailVO = new BuyDetailVO();
        buyDetailVO.setId(courseId);
        // 查询课程
@@ -1108,8 +1439,29 @@
        FitnessPosition fitnessPosition = fitnessPositionService.selectById(positionId);
        FitnessType fitnessType = fitnessTypeService.selectById(fitnessPosition.getTypeId());
        if (fitnessPosition!=null && fitnessType!=null){
            typeName.append(fitnessType.getName()+"|"+fitnessPosition.getName());
            buyDetailVO.setAmount(fitnessPosition.getAmount());
            typeName.append(fitnessType.getName()+"|"+fitnessPosition.getName()+"|H"+course.getDifficulty());
            switch (course.getDifficulty()){
                case 1:
                    buyDetailVO.setAmount(fitnessPosition.getAmount());
                    buyDetailVO.setAppleAmount(fitnessPosition.getAppleAmount());
                    break;
                case 2:
                    buyDetailVO.setAmount(fitnessPosition.getAmount2());
                    buyDetailVO.setAppleAmount(fitnessPosition.getAppleAmount2());
                    break;
                case 3:
                    buyDetailVO.setAmount(fitnessPosition.getAmount3());
                    buyDetailVO.setAppleAmount(fitnessPosition.getAppleAmount3());
                    break;
                case 4:
                    buyDetailVO.setAmount(fitnessPosition.getAmount4());
                    buyDetailVO.setAppleAmount(fitnessPosition.getAppleAmount4());
                    break;
                case 5:
                    buyDetailVO.setAmount(fitnessPosition.getAmount5());
                    buyDetailVO.setAppleAmount(fitnessPosition.getAppleAmount5());
                    break;
            }
        }
        buyDetailVO.setTypeName(typeName.toString());
        int size = courseService.selectList(new EntityWrapper<Course>()
@@ -1119,7 +1471,7 @@
        // 查询和这个课程同类型同部位的课程数量
        buyDetailVO.setCount(size);
        // 查询可选套餐列表 查询包含当前购买部位的课程的套餐
        List<PackageListVO> packageListVOS = new ArrayList<PackageListVO>();
        List<PackageListVO> packageListVOS = new ArrayList<>();
        List<Package> packages = packageService.selectList(new EntityWrapper<Package>()
                .eq("state", 1));
        for (Package aPackage : packages) {
@@ -1131,8 +1483,10 @@
                    packageListVO.setPackageName(aPackage.getName());
                    if (aPackage.getAmount()!=null){
                        packageListVO.setAmount(aPackage.getAmount());
                        packageListVO.setAppleAmount(aPackage.getAppleAmount());
                    }else{
                        packageListVO.setAmount(aPackage.getTotal());
                        packageListVO.setAmount(new BigDecimal(0));
                    }
                    packageListVO.setPrice(aPackage.getPrice());
                    packageListVO.setIds(aPackage.getPositions());
@@ -1151,11 +1505,12 @@
                FitnessPosition fitnessPosition1 = fitnessPositionService.selectById(Integer.valueOf(s));
                FitnessType fitnessType1 = fitnessTypeService.selectById(fitnessPosition1.getTypeId());
                if (fitnessPosition1!=null && fitnessType1!=null){
                    temp.append(fitnessType1.getName()+"|"+fitnessPosition1.getName());
                    temp.append(fitnessType1.getName()+"|"+fitnessPosition1.getName()+"|H"+course.getDifficulty());
                }
                courseVO.setTypeName(temp.toString());
                List<Course> courses = courseService.selectList(new EntityWrapper<Course>()
                        .eq("state", 1)
                        .eq("difficulty", course.getDifficulty())
                        .eq("positionId", Integer.valueOf(s)));
//                Integer tem = 0;
//                for (Course cours : courses) {
@@ -1171,7 +1526,6 @@
        }
        buyDetailVO.setPackageListVOList(packageListVOS);
        // 查询可以使用的优惠券列表
        AppUser appUser = appUserService.getAppUser();
        List<CouponReceive> couponReceives = couponReceiveService.selectList
                (new EntityWrapper<CouponReceive>()
                .eq("userId", appUser.getId())
@@ -1247,6 +1601,10 @@
            @ApiImplicitParam(name = "Authorization", value = "Bearer eyJhbGciOiJIUzUxMiJ....", required = true, paramType = "header"),
    })
    public ResultUtil<StartVO> riskInfo() {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        String riskInfo = sysSetService.selectById(1).getRiskInfo();
        StartVO startVO = new StartVO();
        startVO.setRiskInfo(riskInfo);
@@ -1269,6 +1627,10 @@
            @ApiImplicitParam(name = "courseId", value = "课程id", required = true)
    })
    public ResultUtil<StartTrainVO> startTrain(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        StartTrainVO startTrainVO = new StartTrainVO();
        // 根据课程id和用户id 查询用户上次播放位置
        Integer id = appUserService.getAppUser().getId();
@@ -1286,6 +1648,11 @@
        List<CourseVideo> courseVideos = courseVideoService.selectList(new EntityWrapper<CourseVideo>()
                .eq("courseId", courseId)
                .eq("isDelete", 0));
        for (CourseVideo courseVideo : courseVideos) {
            String courseVideo1 = courseVideo.getCourseVideo();
            String replace = courseVideo1.replace("https://jkjianshen.obs.cn-north-4.myhuaweicloud.com/", "http://cdn.jkcyl.cn/");
            courseVideo.setCourseVideo(replace);
        }
        int totalTime = courseVideos.stream()
                .mapToInt(CourseVideo::getTime)
                .sum();
@@ -1297,7 +1664,10 @@
                startTrainVO.setBeforeTime(0);
                startTrainVO.setBeforeVideoId(courseVideos.get(0).getId());
                startTrainVO.setRealTime(0);
                startTrainVO.setCourseVideo(courseVideos.get(0).getCourseVideo());
                // 手动替换为cdn域名
                String courseVideo = courseVideos.get(0).getCourseVideo();
                String replace = courseVideo.replace("https://jkjianshen.obs.cn-north-4.myhuaweicloud.com/", "http://cdn.jkcyl.cn/");
                startTrainVO.setCourseVideo(replace);
                startTrainVO.setVideoName(courseVideos.get(0).getVideoName());
                startTrainVO.setVideos(courseVideos);
                startTrainVO.setPosition("1/"+courseVideos.size());
@@ -1309,7 +1679,8 @@
            CourseVideo courseVideo = courseVideoService.selectById(beforeVideoId);
            if (courseVideo!=null){
                startTrainVO.setTime(courseVideo.getTime());
                startTrainVO.setCourseVideo(courseVideo.getCourseVideo());
                String replace = courseVideo.getCourseVideo().replace("https://jkjianshen.obs.cn-north-4.myhuaweicloud.com/", "http://cdn.jkcyl.cn/");
                startTrainVO.setCourseVideo(replace);
                startTrainVO.setVideoName(courseVideo.getVideoName());
                startTrainVO.setBeforeTime(beforeTime);
                startTrainVO.setBeforeVideoId(beforeVideoId);
@@ -1317,7 +1688,8 @@
            }else{
                // 如果为空 那么定位到课程下的第一条视频的0秒处
                startTrainVO.setTime(courseVideos.get(0).getTime());
                startTrainVO.setCourseVideo(courseVideos.get(0).getCourseVideo());
                String replace = courseVideos.get(0).getCourseVideo().replace("https://jkjianshen.obs.cn-north-4.myhuaweicloud.com/", "http://cdn.jkcyl.cn/");
                startTrainVO.setCourseVideo(replace);
                startTrainVO.setVideoName(courseVideos.get(0).getVideoName());
                startTrainVO.setBeforeTime(0);
                startTrainVO.setBeforeVideoId(courseVideos.get(0).getId());
@@ -1343,6 +1715,10 @@
            @ApiImplicitParam(name = "Authorization", value = "Bearer eyJhbGciOiJIUzUxMiJ....", required = true, paramType = "header"),
    })
    public ResultUtil exit(AddUserWatchDTO dto) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        Integer id = appUserService.getAppUser().getId();
        Integer courseId = dto.getCourseId();
        UserWatch userWatches = userWatchService.selectOne(new EntityWrapper<UserWatch>()
@@ -1377,6 +1753,10 @@
            @ApiImplicitParam(name = "courseId", value = "课程id", required = true)
    })
    public ResultUtil<CompeleteVO> clockIn(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        Integer isFree = courseService.selectById(courseId).getIsFree();
        CompeleteVO compeleteVO = new CompeleteVO();
        Integer id = appUserService.getAppUser().getId();
@@ -1385,7 +1765,6 @@
                .eq("userId", id));
        userWatches.setClockTime(new Date());
        userWatchService.updateById(userWatches);
        AppUser appUser = appUserService.getAppUser();
        // 查询优惠券列表是否有打卡赠送 且未过期的优惠券
        List<Coupon> coupons = couponService.selectList(new EntityWrapper<Coupon>()
                .eq("grantType", 1)
@@ -1634,6 +2013,10 @@
            @ApiImplicitParam(name = "courseId", value = "课程id", required = true)
    })
    public ResultUtil<CompeleteVO> completeInfo(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        Date compeleteTime = appUserService.getAppUser().getCompeleteTime();
        if (compeleteTime!=null){
            Date date = new Date();
@@ -1641,13 +2024,11 @@
            if (format.format(date).equals(format.format(compeleteTime))) {
                // 同一天那么不计算坚持运动天数
            }else{
                AppUser appUser = appUserService.getAppUser();
                appUser.setCompeleteTime(new Date());
                appUser.setTime(appUser.getTime()+1);
                appUserService.updateById(appUser);
            }
        }else{
            AppUser appUser = appUserService.getAppUser();
            appUser.setTime(appUser.getTime()+1);
            appUser.setCompeleteTime(new Date());
            appUserService.updateById(appUser);
@@ -1657,9 +2038,28 @@
                .eq("courseId", courseId)
                .eq("userId", id));
        if (userWatches!=null){
            // 打卡后 将观看记录初始化
            // 将观看记录初始化
            userWatches.setBeforeTime(0);
            userWatches.setRealTime(0);
            // 获取上次播放到的视频id
//            Integer beforeVideoId = userWatches.getBeforeVideoId();
            List<CourseVideo> courseVideos = courseVideoService.selectList(new EntityWrapper<CourseVideo>()
                    .eq("courseId", courseId)
                    .eq("isDelete", 0));
//            int index = 0;
//            for (CourseVideo courseVideo : courseVideos) {
//                if (courseVideo.getId().equals(beforeVideoId)){
//                    // 如果courseVieo不是最后一条数据 那么将courseVieo的下一条数据设置为beforeVideoId
//                    if (index<courseVideos.size()-1){
//                        userWatches.setBeforeVideoId(courseVideos.get(index+1).getId());
//                    }else{
//                        // 如果courseVieo是最后一条数据 那么设置为从第一节开始播放
//                        userWatches.setBeforeVideoId(courseVideos.get(0).getId());
//                    }
//                }
//                index++;
//            }
            userWatches.setBeforeVideoId(courseVideos.get(0).getId());
            userWatchService.updateById(userWatches);
        }else{
            UserWatch userWatch = new UserWatch();
@@ -1674,7 +2074,7 @@
            userWatch.setRealTime(0);
            userWatchService.insert(userWatch);
        }
        AppUser appUser = appUserService.getAppUser();
        // 返回页面内容
        Course course = courseService.selectById(courseId);
        CompeleteVO compeleteVO = new CompeleteVO();
@@ -1697,6 +2097,10 @@
            @ApiImplicitParam(value = "课程id", name = "courseId", dataType = "int", required = true)
    })
    public ResultUtil collectCourse(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        Integer id = appUserService.getAppUser().getId();
        // 先判断用户是否收藏了该课程
        UserCollect userCollect1 = collectService.selectOne(new EntityWrapper<UserCollect>()
@@ -1724,6 +2128,12 @@
            @ApiImplicitParam(value = "课程id", name = "courseId", dataType = "int", required = true)
    })
    public ResultUtil<CourseDetailVO> courseDetail(Integer courseId) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        // 推荐课程3个 相同类型 相同难度 按sort排序
        Course course = courseService.selectById(courseId);
        Integer userId = appUserService.getAppUser().getId();
        CourseDetailVO res = new CourseDetailVO();
        List<Integer> list = new ArrayList<>();
@@ -1761,7 +2171,8 @@
        if (res.getIsBuy()!=1){
            for (Order aPackage : packages) {
                Integer packageId = aPackage.getPackageId();
                String positions = packageService.selectById(packageId).getPositions();
                Package aPackage1 = packageService.selectById(packageId);
                String positions = aPackage1.getPositions();
                if (StringUtils.hasLength(positions)){
                    String[] split = positions.split(",");
                    // 通过部位ids 获取到课程ids
@@ -1770,19 +2181,26 @@
                            .collect(Collectors.toList());
                    if (positionId.contains(courseId)){
                        res.setIsBuy(1);
                        break;
                        // todo 新增需求 套餐设置指定难度 需要再判断一次难度
//                        Integer difficulty = course.getDifficulty();
//                        if (difficulty.equals(aPackage1.getDifficulty())){
//                            break;
//                       }
                    }
                }
            }
        }
        // 推荐课程3个 相同类型 相同难度 按sort排序
        if (res.getIsBuy() != 1){
            // 先查询出和这个课程同类型同部位
            Course course1 = courseService.selectById(courseId);
            // 相同的课程id
            // 相同的课程id 部位和难度相同
            List<Integer> positionId = courseService.selectList(new EntityWrapper<Course>()
                    .eq("positionId", course1.getPositionId())).stream().map(Course::getId).collect(Collectors.toList());
                    .eq("positionId", course1.getPositionId())
                    .eq("difficulty",course1.getDifficulty())
            ).stream().map(Course::getId).collect(Collectors.toList());
            // 查询下用户有没有购买其他相同部位和类型的课程 如果有 那么就算已购买
            // 查询下用户有没有购买其他相同部位和类型和难度的课程 如果有 那么就算已购买
            // 查询用户已购买的课程
            List<OrderCourse> orderCourses = orderCourseService.selectList(new EntityWrapper<OrderCourse>()
                    .eq("userId", appUserService.getAppUser().getId())
@@ -1794,8 +2212,7 @@
        }
        // 推荐课程3个 相同类型 相同难度 按sort排序
        Course course = courseService.selectById(courseId);
        Integer difficulty = course.getDifficulty();
        Integer typeId = course.getTypeId();
        List<String> strings = new ArrayList<>();
@@ -1814,6 +2231,10 @@
        List<CourseVideo> courseVideos = courseVideoService.selectList(new EntityWrapper<CourseVideo>()
                .eq("courseId", courseId)
                .eq("isDelete", 0));
        for (CourseVideo courseVideo : courseVideos) {
            String replace = courseVideo.getCourseVideo().replace("https://jkjianshen.obs.cn-north-4.myhuaweicloud.com/", "http://cdn.jkcyl.cn/");
            courseVideo.setCourseVideo(replace);
        }
        res.setVideos(courseVideos);
        return ResultUtil.success(res);
@@ -1828,6 +2249,10 @@
    })
    public ResultUtil<List<CourseList>> myCourse(CourseQuery req) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        req.setUserId(appUser.getId());
        if (StringUtils.hasLength(req.getTime())){
            for (String s : req.getTime().split(",")) {
@@ -1888,12 +2313,18 @@
        List<Integer> list = new ArrayList<>();
        // 根据套餐ids 查询课程ids
        for (Integer integer : collect) {
            String positions = packageService.selectById(integer).getPositions();
            Package aPackage = packageService.selectById(integer);
            String positions = aPackage.getPositions();
            String difficulty = aPackage.getDifficulty();
            if (StringUtils.hasLength(positions)){
                String[] split = positions.split(",");
                // 难度ids
                String[] split1 = difficulty.split(",");
                // 通过部位ids 获取到课程ids
                List<Integer> positionId = courseService.selectList(new EntityWrapper<Course>()
                        .in("positionId", split)).stream().map(Course::getId)
                        .in("positionId", split)
                        .in("difficulty", split1)
                        ).stream().map(Course::getId)
                        .collect(Collectors.toList());
                list.addAll(positionId);
            }
@@ -1918,7 +2349,9 @@
                    // 和当前课程同类型同部位的课程
                    List<Integer> collect1 = courseService.selectList(new EntityWrapper<Course>()
                            .eq("state", 1)
                            .eq("positionId", positionId)).stream().map(Course::getId).collect(Collectors.toList());
                            .eq("positionId", positionId)
                            .eq("difficulty", course.getDifficulty())
                    ).stream().map(Course::getId).collect(Collectors.toList());
                    if (collect1.size()>0){
                        list1.addAll(collect1);
                    }
@@ -1981,6 +2414,10 @@
            @ApiImplicitParam(name = "Authorization", value = "Bearer eyJhbGciOiJIUzUxMiJ....", required = true, paramType = "header")
    })
    public ResultUtil<List<CourseList>> courseSearch(CourseQuery req) {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        req.setPageNum((req.getPageNum() - 1) * req.getPageSize());
        if (StringUtils.hasLength(req.getTime())){
            for (String s : req.getTime().split(",")) {
@@ -2044,6 +2481,10 @@
            @ApiImplicitParam(name = "Authorization", value = "Bearer eyJhbGciOiJIUzUxMiJ....", required = true, paramType = "header")
    })
    public ResultUtil<List<Banner>> getBanner() {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        List<String> strings = new ArrayList<>();
        strings.add("sort");
        List<Banner> state = bannerService.selectList(new EntityWrapper<Banner>()
@@ -2059,6 +2500,9 @@
    })
    public ResultUtil<SearchList> getList() {
        AppUser appUser = appUserService.getAppUser();
        if (appUser == null){
            return ResultUtil.tokenErr("登录失效");
        }
        // 查询用户有哪些课程购买了的
        List<OrderCourse> orderCourses = orderCourseService.selectList(new EntityWrapper<OrderCourse>()
@@ -2080,17 +2524,29 @@
            for (Order order1 : order) {
                for (String s : packageService.selectById(order1.getPackageId())
                        .getPositions().split(",")) {
                    List<Integer> positionId = courseService.selectList(new EntityWrapper<Course>()
                            .eq("positionId", s)).stream().map(Course::getId)
                    List<Integer> cId = courseService.selectList(new EntityWrapper<Course>()
                            .eq("positionId", s)
                                    .eq("state",1)).stream().map(Course::getId)
                            .collect(Collectors.toList());
                    packages.addAll(positionId);
                    packages.addAll(cId);
                }
            }
             packages = packages.stream().distinct().collect(Collectors.toList());
        }
        course.addAll(packages);
        if (packages.size()==0){
            packages.add(-1);
        }
        List<Integer> collect5 = courseService.selectList(new EntityWrapper<Course>()
                        .eq("state", 1)
                        .in("id", packages)).stream().map(Course::getId)
                .collect(Collectors.toList());
        course.addAll(collect5);
        if (course.isEmpty()){
            course.add(-1);
        }
        // 所有用户的课程ids
        List<Integer> collect = course.stream().distinct().collect(Collectors.toList());
        // 查询包含的类型和部位
        List<Integer> collect1 = courseService.selectList(new EntityWrapper<Course>()
                .in("id", collect).eq("state", 1)).stream().map(Course::getPositionId)
@@ -2099,6 +2555,12 @@
                .in("id", collect).eq("state", 1)).stream().map(Course::getTypeId)
                .collect(Collectors.toList());
        List<String> strings = new ArrayList<>();
        for (Integer i : collect1) {
            FitnessPosition fitnessPosition = fitnessPositionService.selectById(i);
            if (!strings.contains(fitnessPosition.getName())){
                strings.add(fitnessPosition.getName());
            }
        }
        List<FitnessPosition> fitnessPositions = new ArrayList<>();
        List<DifficultyVO> d = new ArrayList<>();
        List<DifficultyVO> t = new ArrayList<>();
@@ -2123,17 +2585,12 @@
        for (FitnessPosition position : positions) {
            position.setIsUse(0);
            if (strings.contains(position.getName())){
                continue;
                position.setIsUse(1);
                fitnessPositions.add(position);
            }else{
                strings.add(position.getName());
                fitnessPositions.add(position);
            }
            for (Integer integer : collect1) {
                if (position.getId().equals(integer)){
                    position.setIsUse(1);
                    break;
                }
            }
        }
        List<FitnessType> types = fitnessTypeService.selectList(new EntityWrapper<FitnessType>()
                .eq("isDelete", 0));
@@ -2153,7 +2610,7 @@
                .eq("state", 1)
                .in("id", collect));
        // 获取所有课程的时间
        List<String> collect4 = courses.stream().map(Course::getTime).distinct().collect(Collectors.toList());
        List<String> collect4 = courses.stream().map(Course::getTime).collect(Collectors.toList());
        for (String s : collect4) {
            Integer integer = Integer.valueOf(s);
            if (integer>1200){
@@ -2176,7 +2633,7 @@
            }
        }
        // 获取所有的难度
        List<Integer> collect3 = courses.stream().map(Course::getDifficulty).distinct().collect(Collectors.toList());
        List<Integer> collect3 = courses.stream().map(Course::getDifficulty).collect(Collectors.toList());
        if (collect3.contains(1)){
            DifficultyVO difficultyVO = new DifficultyVO();
            difficultyVO.setIsUse(1);
@@ -2245,15 +2702,91 @@
        searchList.setDifficulty(d);
        searchList.setTime(t);
        searchList.setFitnessPosition(fitnessPositions);
        Map<String, FitnessPosition> resultMap = new HashMap<>();
        for (FitnessPosition position : fitnessPositions) {
            if (resultMap.containsKey(position.getName())) {
                FitnessPosition existingPosition = resultMap.get(position.getName());
                if (existingPosition.getIsUse() == 0 && position.getIsUse() == 1) {
                    existingPosition.setIsUse(1);
                }
            } else {
                resultMap.put(position.getName(), position);
            }
        }
        List<FitnessPosition> resultPositions = new ArrayList<>(resultMap.values());
        searchList.setFitnessPosition(resultPositions);
        searchList.setFitnessType(types);
        return ResultUtil.success(searchList);
    }
    public static void main(String[] args) throws Exception {
        BigDecimal divisor = new BigDecimal("100");
        BigDecimal res = new BigDecimal("0.8");
        BigDecimal bigDecimal = res.divide(divisor);
        System.err.println(bigDecimal);
    public static void main(String[] args) {
        String t= "{\"signedPayload\":\"eyJhbGciOiJFUzI1NiIsIng1YyI6WyJNSUlFTURDQ0E3YWdBd0lCQWdJUWZUbGZkMGZOdkZXdnpDMVlJQU5zWGpBS0JnZ3Foa2pPUFFRREF6QjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSell4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJek1Ea3hNakU1TlRFMU0xb1hEVEkxTVRBeE1URTVOVEUxTWxvd2daSXhRREErQmdOVkJBTU1OMUJ5YjJRZ1JVTkRJRTFoWXlCQmNIQWdVM1J2Y21VZ1lXNWtJR2xVZFc1bGN5QlRkRzl5WlNCU1pXTmxhWEIwSUZOcFoyNXBibWN4TERBcUJnTlZCQXNNSTBGd2NHeGxJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnVW1Wc1lYUnBiMjV6TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRUZFWWUvSnFUcXlRdi9kdFhrYXVESENTY1YxMjlGWVJWLzB4aUIyNG5DUWt6UWYzYXNISk9OUjVyMFJBMGFMdko0MzJoeTFTWk1vdXZ5ZnBtMjZqWFNqZ2dJSU1JSUNCREFNQmdOVkhSTUJBZjhFQWpBQU1COEdBMVVkSXdRWU1CYUFGRDh2bENOUjAxREptaWc5N2JCODVjK2xrR0taTUhBR0NDc0dBUVVGQndFQkJHUXdZakF0QmdnckJnRUZCUWN3QW9ZaGFIUjBjRG92TDJObGNuUnpMbUZ3Y0d4bExtTnZiUzkzZDJSeVp6WXVaR1Z5TURFR0NDc0dBUVVGQnpBQmhpVm9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQXpMWGQzWkhKbk5qQXlNSUlCSGdZRFZSMGdCSUlCRlRDQ0FSRXdnZ0VOQmdvcWhraUc5Mk5rQlFZQk1JSCtNSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRFlHQ0NzR0FRVUZCd0lCRmlwb2RIUndPaTh2ZDNkM0xtRndjR3hsTG1OdmJTOWpaWEowYVdacFkyRjBaV0YxZEdodmNtbDBlUzh3SFFZRFZSME9CQllFRkFNczhQanM2VmhXR1FsekUyWk9FK0dYNE9vL01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0Jnc0JCQUlGQURBS0JnZ3Foa2pPUFFRREF3Tm9BREJsQWpFQTh5Uk5kc2twNTA2REZkUExnaExMSndBdjVKOGhCR0xhSThERXhkY1BYK2FCS2pqTzhlVW85S3BmcGNOWVVZNVlBakFQWG1NWEVaTCtRMDJhZHJtbXNoTnh6M05uS20rb3VRd1U3dkJUbjBMdmxNN3ZwczJZc2xWVGFtUllMNGFTczVrPSIsIk1JSURGakNDQXB5Z0F3SUJBZ0lVSXNHaFJ3cDBjMm52VTRZU3ljYWZQVGp6Yk5jd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NakV3TXpFM01qQXpOekV3V2hjTk16WXdNekU1TURBd01EQXdXakIxTVVRd1FnWURWUVFERER0QmNIQnNaU0JYYjNKc1pIZHBaR1VnUkdWMlpXeHZjR1Z5SUZKbGJHRjBhVzl1Y3lCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEVMTUFrR0ExVUVDd3dDUnpZeEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVic1FLQzk0UHJsV21aWG5YZ3R4emRWSkw4VDBTR1luZ0RSR3BuZ24zTjZQVDhKTUViN0ZEaTRiQm1QaENuWjMvc3E2UEYvY0djS1hXc0w1dk90ZVJoeUo0NXgzQVNQN2NPQithYW85MGZjcHhTdi9FWkZibmlBYk5nWkdoSWhwSW80SDZNSUgzTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0h3WURWUjBqQkJnd0ZvQVV1N0Rlb1ZnemlKcWtpcG5ldnIzcnI5ckxKS3N3UmdZSUt3WUJCUVVIQVFFRU9qQTRNRFlHQ0NzR0FRVUZCekFCaGlwb2RIUndPaTh2YjJOemNDNWhjSEJzWlM1amIyMHZiMk56Y0RBekxXRndjR3hsY205dmRHTmhaek13TndZRFZSMGZCREF3TGpBc29DcWdLSVltYUhSMGNEb3ZMMk55YkM1aGNIQnNaUzVqYjIwdllYQndiR1Z5YjI5MFkyRm5NeTVqY213d0hRWURWUjBPQkJZRUZEOHZsQ05SMDFESm1pZzk3YkI4NWMrbGtHS1pNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVFCZ29xaGtpRzkyTmtCZ0lCQkFJRkFEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkFYaFNxNUl5S29nTUNQdHc0OTBCYUI2NzdDYUVHSlh1ZlFCL0VxWkdkNkNTamlDdE9udU1UYlhWWG14eGN4ZmtDTVFEVFNQeGFyWlh2TnJreFUzVGtVTUkzM3l6dkZWVlJUNHd4V0pDOTk0T3NkY1o0K1JHTnNZRHlSNWdtZHIwbkRHZz0iLCJNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtBPT0iXX0.eyJub3RpZmljYXRpb25UeXBlIjoiT05FX1RJTUVfQ0hBUkdFIiwibm90aWZpY2F0aW9uVVVJRCI6IjhmMzFkZjhiLWJiNzMtNDY0NC05ODY3LWYwMzYzZWFiMjRkZSIsImRhdGEiOnsiYXBwQXBwbGVJZCI6NjQ5OTEyMzYyNywiYnVuZGxlSWQiOiJjb20uc2luYXRhLkpLRml0bmVzcyIsImJ1bmRsZVZlcnNpb24iOiIxMyIsImVudmlyb25tZW50IjoiU2FuZGJveCIsInNpZ25lZFRyYW5zYWN0aW9uSW5mbyI6ImV5SmhiR2NpT2lKRlV6STFOaUlzSW5nMVl5STZXeUpOU1VsRlRVUkRRMEUzWVdkQmQwbENRV2RKVVdaVWJHWmtNR1pPZGtaWGRucERNVmxKUVU1eldHcEJTMEpuWjNGb2EycFBVRkZSUkVGNlFqRk5WVkYzVVdkWlJGWlJVVVJFUkhSQ1kwaENjMXBUUWxoaU0wcHpXa2hrY0ZwSFZXZFNSMVl5V2xkNGRtTkhWbmxKUmtwc1lrZEdNR0ZYT1hWamVVSkVXbGhLTUdGWFduQlpNa1l3WVZjNWRVbEZSakZrUjJoMlkyMXNNR1ZVUlV4TlFXdEhRVEZWUlVOM2QwTlNlbGw0UlhwQlVrSm5UbFpDUVc5TlEydEdkMk5IZUd4SlJXeDFXWGswZUVONlFVcENaMDVXUWtGWlZFRnNWbFJOUWpSWVJGUkplazFFYTNoTmFrVTFUbFJGTVUweGIxaEVWRWt4VFZSQmVFMVVSVFZPVkVVeFRXeHZkMmRhU1hoUlJFRXJRbWRPVmtKQlRVMU9NVUo1WWpKUloxSlZUa1JKUlRGb1dYbENRbU5JUVdkVk0xSjJZMjFWWjFsWE5XdEpSMnhWWkZjMWJHTjVRbFJrUnpsNVdsTkNVMXBYVG14aFdFSXdTVVpPY0ZveU5YQmliV040VEVSQmNVSm5UbFpDUVhOTlNUQkdkMk5IZUd4SlJtUjJZMjE0YTJReWJHdGFVMEpGV2xoYWJHSkhPWGRhV0VsblZXMVdjMWxZVW5CaU1qVjZUVkpOZDBWUldVUldVVkZMUkVGd1FtTklRbk5hVTBKS1ltMU5kVTFSYzNkRFVWbEVWbEZSUjBWM1NsWlZla0phVFVKTlIwSjVjVWRUVFRRNVFXZEZSME5EY1VkVFRUUTVRWGRGU0VFd1NVRkNSVVpGV1dVdlNuRlVjWGxSZGk5a2RGaHJZWFZFU0VOVFkxWXhNamxHV1ZKV0x6QjRhVUl5Tkc1RFVXdDZVV1l6WVhOSVNrOU9ValZ5TUZKQk1HRk1ka28wTXpKb2VURlRXazF2ZFhaNVpuQnRNalpxV0ZOcVoyZEpTVTFKU1VOQ1JFRk5RbWRPVmtoU1RVSkJaamhGUVdwQlFVMUNPRWRCTVZWa1NYZFJXVTFDWVVGR1JEaDJiRU5PVWpBeFJFcHRhV2M1TjJKQ09EVmpLMnhyUjB0YVRVaEJSME5EYzBkQlVWVkdRbmRGUWtKSFVYZFpha0YwUW1kbmNrSm5SVVpDVVdOM1FXOVphR0ZJVWpCalJHOTJUREpPYkdOdVVucE1iVVozWTBkNGJFeHRUblppVXprelpESlNlVnA2V1hWYVIxWjVUVVJGUjBORGMwZEJVVlZHUW5wQlFtaHBWbTlrU0ZKM1QyazRkbUl5VG5walF6Vm9ZMGhDYzFwVE5XcGlNakIyWWpKT2VtTkVRWHBNV0dReldraEtiazVxUVhsTlNVbENTR2RaUkZaU01HZENTVWxDUmxSRFEwRlNSWGRuWjBWT1FtZHZjV2hyYVVjNU1rNXJRbEZaUWsxSlNDdE5TVWhFUW1kbmNrSm5SVVpDVVdORFFXcERRblJuZVVKek1VcHNZa2RzYUdKdFRteEpSemwxU1VoU2IyRllUV2RaTWxaNVpFZHNiV0ZYVG1oa1IxVm5XVzVyWjFsWE5UVkpTRUpvWTI1U05VbEhSbnBqTTFaMFdsaE5aMWxYVG1wYVdFSXdXVmMxYWxwVFFuWmFhVUl3WVVkVloyUkhhR3hpYVVKb1kwaENjMkZYVG1oWmJYaHNTVWhPTUZsWE5XdFpXRXByU1VoU2JHTnRNWHBKUjBaMVdrTkNhbUl5Tld0aFdGSndZakkxZWtsSE9XMUpTRlo2V2xOM1oxa3lWbmxrUjJ4dFlWZE9hR1JIVldkalJ6bHpZVmRPTlVsSFJuVmFRMEpxV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxJUW5sWlYwNHdZVmRPYkVsSVRqQlpXRkpzWWxkV2RXUklUWFZOUkZsSFEwTnpSMEZSVlVaQ2QwbENSbWx3YjJSSVVuZFBhVGgyWkROa00weHRSbmRqUjNoc1RHMU9kbUpUT1dwYVdFb3dZVmRhY0ZreVJqQmFWMFl4WkVkb2RtTnRiREJsVXpoM1NGRlpSRlpTTUU5Q1FsbEZSa0ZOY3poUWFuTTJWbWhYUjFGc2VrVXlXazlGSzBkWU5FOXZMMDFCTkVkQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlVVSm5iM0ZvYTJsSE9USk9hMEpuYzBKQ1FVbEdRVVJCUzBKblozRm9hMnBQVUZGUlJFRjNUbTlCUkVKc1FXcEZRVGg1VWs1a2MydHdOVEEyUkVaa1VFeG5hRXhNU25kQmRqVktPR2hDUjB4aFNUaEVSWGhrWTFCWUsyRkNTMnBxVHpobFZXODVTM0JtY0dOT1dWVlpOVmxCYWtGUVdHMU5XRVZhVEN0Uk1ESmhaSEp0YlhOb1RuaDZNMDV1UzIwcmIzVlJkMVUzZGtKVWJqQk1kbXhOTjNad2N6SlpjMnhXVkdGdFVsbE1OR0ZUY3pWclBTSXNJazFKU1VSR2FrTkRRWEI1WjBGM1NVSkJaMGxWU1hOSGFGSjNjREJqTW01MlZUUlpVM2xqWVdaUVZHcDZZazVqZDBObldVbExiMXBKZW1vd1JVRjNUWGRhZWtWaVRVSnJSMEV4VlVWQmQzZFRVVmhDZDJKSFZXZFZiVGwyWkVOQ1JGRlRRWFJKUldONlRWTlpkMHBCV1VSV1VWRk1SRUl4UW1OSVFuTmFVMEpFV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxGUmpGa1IyaDJZMjFzTUdWVVJWUk5Ra1ZIUVRGVlJVTm5kMHRSV0VKM1lrZFZaMU5YTldwTWFrVk1UVUZyUjBFeFZVVkNhRTFEVmxaTmQwaG9ZMDVOYWtWM1RYcEZNMDFxUVhwT2VrVjNWMmhqVGsxNldYZE5la1UxVFVSQmQwMUVRWGRYYWtJeFRWVlJkMUZuV1VSV1VWRkVSRVIwUW1OSVFuTmFVMEpZWWpOS2MxcElaSEJhUjFWblVrZFdNbHBYZUhaalIxWjVTVVpLYkdKSFJqQmhWemwxWTNsQ1JGcFlTakJoVjFwd1dUSkdNR0ZYT1hWSlJVWXhaRWRvZG1OdGJEQmxWRVZNVFVGclIwRXhWVVZEZDNkRFVucFplRVY2UVZKQ1owNVdRa0Z2VFVOclJuZGpSM2hzU1VWc2RWbDVOSGhEZWtGS1FtZE9Wa0pCV1ZSQmJGWlVUVWhaZDBWQldVaExiMXBKZW1vd1EwRlJXVVpMTkVWRlFVTkpSRmxuUVVWaWMxRkxRemswVUhKc1YyMWFXRzVZWjNSNGVtUldTa3c0VkRCVFIxbHVaMFJTUjNCdVoyNHpUalpRVkRoS1RVVmlOMFpFYVRSaVFtMVFhRU51V2pNdmMzRTJVRVl2WTBkalMxaFhjMHcxZGs5MFpWSm9lVW8wTlhnelFWTlFOMk5QUWl0aFlXODVNR1pqY0hoVGRpOUZXa1ppYm1sQllrNW5Xa2RvU1dod1NXODBTRFpOU1VnelRVSkpSMEV4VldSRmQwVkNMM2RSU1UxQldVSkJaamhEUVZGQmQwaDNXVVJXVWpCcVFrSm5kMFp2UVZWMU4wUmxiMVpuZW1sS2NXdHBjRzVsZG5JemNuSTVja3hLUzNOM1VtZFpTVXQzV1VKQ1VWVklRVkZGUlU5cVFUUk5SRmxIUTBOelIwRlJWVVpDZWtGQ2FHbHdiMlJJVW5kUGFUaDJZakpPZW1ORE5XaGpTRUp6V2xNMWFtSXlNSFppTWs1NlkwUkJla3hYUm5kalIzaHNZMjA1ZG1SSFRtaGFlazEzVG5kWlJGWlNNR1pDUkVGM1RHcEJjMjlEY1dkTFNWbHRZVWhTTUdORWIzWk1NazU1WWtNMWFHTklRbk5hVXpWcVlqSXdkbGxZUW5kaVIxWjVZakk1TUZreVJtNU5lVFZxWTIxM2QwaFJXVVJXVWpCUFFrSlpSVVpFT0hac1EwNVNNREZFU20xcFp6azNZa0k0TldNcmJHdEhTMXBOUVRSSFFURlZaRVIzUlVJdmQxRkZRWGRKUWtKcVFWRkNaMjl4YUd0cFJ6a3lUbXRDWjBsQ1FrRkpSa0ZFUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRa0ZZYUZOeE5VbDVTMjluVFVOUWRIYzBPVEJDWVVJMk56ZERZVVZIU2xoMVpsRkNMMFZ4V2tka05rTlRhbWxEZEU5dWRVMVVZbGhXV0cxNGVHTjRabXREVFZGRVZGTlFlR0Z5V2xoMlRuSnJlRlV6Vkd0VlRVa3pNM2w2ZGtaV1ZsSlVOSGQ0VjBwRE9UazBUM05rWTFvMEsxSkhUbk5aUkhsU05XZHRaSEl3YmtSSFp6MGlMQ0pOU1VsRFVYcERRMEZqYldkQmQwbENRV2RKU1V4aldEaHBUa3hHVXpWVmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhkYWVrVmlUVUpyUjBFeFZVVkJkM2RUVVZoQ2QySkhWV2RWYlRsMlpFTkNSRkZUUVhSSlJXTjZUVk5aZDBwQldVUldVVkZNUkVJeFFtTklRbk5hVTBKRVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsRlJqRmtSMmgyWTIxc01HVlVSVlJOUWtWSFFURlZSVU5uZDB0UldFSjNZa2RWWjFOWE5XcE1ha1ZNVFVGclIwRXhWVVZDYUUxRFZsWk5kMGhvWTA1TlZGRjNUa1JOZDAxVVozaFBWRUV5VjJoalRrMTZhM2RPUkUxM1RWUm5lRTlVUVRKWGFrSnVUVkp6ZDBkUldVUldVVkZFUkVKS1FtTklRbk5hVTBKVFlqSTVNRWxGVGtKSlF6Qm5VbnBOZUVwcVFXdENaMDVXUWtGelRVaFZSbmRqUjNoc1NVVk9iR051VW5CYWJXeHFXVmhTY0dJeU5HZFJXRll3WVVjNWVXRllValZOVWsxM1JWRlpSRlpSVVV0RVFYQkNZMGhDYzFwVFFrcGliVTExVFZGemQwTlJXVVJXVVZGSFJYZEtWbFY2UWpKTlFrRkhRbmx4UjFOTk5EbEJaMFZIUWxOMVFrSkJRV2xCTWtsQlFrcHFjRXg2TVVGamNWUjBhM2xLZVdkU1RXTXpVa05XT0dOWGFsUnVTR05HUW1KYVJIVlhiVUpUY0ROYVNIUm1WR3BxVkhWNGVFVjBXQzh4U0RkWmVWbHNNMG8yV1ZKaVZIcENVRVZXYjBFdlZtaFpSRXRZTVVSNWVFNUNNR05VWkdSeFdHdzFaSFpOVm5wMFN6VXhOMGxFZGxsMVZsUmFXSEJ0YTA5c1JVdE5ZVTVEVFVWQmQwaFJXVVJXVWpCUFFrSlpSVVpNZFhjemNVWlpUVFJwWVhCSmNWb3pjalk1TmpZdllYbDVVM0pOUVRoSFFURlZaRVYzUlVJdmQxRkdUVUZOUWtGbU9IZEVaMWxFVmxJd1VFRlJTQzlDUVZGRVFXZEZSMDFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbWRCVFVkVlEwMVJRMFEyWTBoRlJtdzBZVmhVVVZreVpUTjJPVWQzVDBGRldreDFUaXQ1VW1oSVJrUXZNMjFsYjNsb2NHMTJUM2RuVUZWdVVGZFVlRzVUTkdGMEszRkplRlZEVFVjeGJXbG9SRXN4UVROVlZEZ3lUbEY2TmpCcGJVOXNUVEkzYW1Ka2IxaDBNbEZtZVVaTmJTdFphR2xrUkd0TVJqRjJURlZoWjAwMlFtZEVOVFpMZVV0QlBUMGlYWDAuZXlKMGNtRnVjMkZqZEdsdmJrbGtJam9pTWpBd01EQXdNRFkyTXpRM05qY3lOaUlzSW05eWFXZHBibUZzVkhKaGJuTmhZM1JwYjI1SlpDSTZJakl3TURBd01EQTJOak0wTnpZM01qWWlMQ0ppZFc1a2JHVkpaQ0k2SW1OdmJTNXphVzVoZEdFdVNrdEdhWFJ1WlhOeklpd2ljSEp2WkhWamRFbGtJam9pWTI5dExtcHJabWwwYm1WemN5NWhMbkJ5YVdObExqRWlMQ0p3ZFhKamFHRnpaVVJoZEdVaU9qRTNNakUyTlRBM056SXdNREFzSW05eWFXZHBibUZzVUhWeVkyaGhjMlZFWVhSbElqb3hOekl4TmpVd056Y3lNREF3TENKeGRXRnVkR2wwZVNJNk1Td2lkSGx3WlNJNklrTnZibk4xYldGaWJHVWlMQ0pwYmtGd2NFOTNibVZ5YzJocGNGUjVjR1VpT2lKUVZWSkRTRUZUUlVRaUxDSnphV2R1WldSRVlYUmxJam94TnpJeE5qVXdOemt4TWpRM0xDSmxiblpwY205dWJXVnVkQ0k2SWxOaGJtUmliM2dpTENKMGNtRnVjMkZqZEdsdmJsSmxZWE52YmlJNklsQlZVa05JUVZORklpd2ljM1J2Y21WbWNtOXVkQ0k2SWtOSVRpSXNJbk4wYjNKbFpuSnZiblJKWkNJNklqRTBNelEyTlNJc0luQnlhV05sSWpvNU9EQXdNQ3dpWTNWeWNtVnVZM2tpT2lKRFRsa2lmUS5ES3JibWNYZkNGSDBadlJBNlZXWGkzLWN6cC03WHptTjhIM25PRUs4UnZxUFRXZ3VFYThqWUxhWHU5dHBLc1lQWlNvV0d4NHFXUy1nVXFMVFV1bXNlZyJ9LCJ2ZXJzaW9uIjoiMi4wIiwic2lnbmVkRGF0ZSI6MTcyMTY1MDc5MTI2OX0.imD544tZ0FLw4lPrcpRB279O_SpRab_6z5aUJRoPoe_3CzhT4pwonOmM74PYItQQwpMYwB79SCQaCVVLMsPV1w\"}";
        org.json.JSONObject jsonObject = new org.json.JSONObject(t);
        System.err.println(jsonObject.getString("signedPayload"));
    }
//    public static void main(String[] args) throws CertificateException {
//        try {
//            JSONObject payload = verifyAndGet("eyJhbGciOiJFUzI1NiIsIng1YyI6WyJNSUlFTURDQ0E3YWdBd0lCQWdJUWZUbGZkMGZOdkZXdnpDMVlJQU5zWGpBS0JnZ3Foa2pPUFFRREF6QjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSell4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJek1Ea3hNakU1TlRFMU0xb1hEVEkxTVRBeE1URTVOVEUxTWxvd2daSXhRREErQmdOVkJBTU1OMUJ5YjJRZ1JVTkRJRTFoWXlCQmNIQWdVM1J2Y21VZ1lXNWtJR2xVZFc1bGN5QlRkRzl5WlNCU1pXTmxhWEIwSUZOcFoyNXBibWN4TERBcUJnTlZCQXNNSTBGd2NHeGxJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnVW1Wc1lYUnBiMjV6TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRUZFWWUvSnFUcXlRdi9kdFhrYXVESENTY1YxMjlGWVJWLzB4aUIyNG5DUWt6UWYzYXNISk9OUjVyMFJBMGFMdko0MzJoeTFTWk1vdXZ5ZnBtMjZqWFNqZ2dJSU1JSUNCREFNQmdOVkhSTUJBZjhFQWpBQU1COEdBMVVkSXdRWU1CYUFGRDh2bENOUjAxREptaWc5N2JCODVjK2xrR0taTUhBR0NDc0dBUVVGQndFQkJHUXdZakF0QmdnckJnRUZCUWN3QW9ZaGFIUjBjRG92TDJObGNuUnpMbUZ3Y0d4bExtTnZiUzkzZDJSeVp6WXVaR1Z5TURFR0NDc0dBUVVGQnpBQmhpVm9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQXpMWGQzWkhKbk5qQXlNSUlCSGdZRFZSMGdCSUlCRlRDQ0FSRXdnZ0VOQmdvcWhraUc5Mk5rQlFZQk1JSCtNSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRFlHQ0NzR0FRVUZCd0lCRmlwb2RIUndPaTh2ZDNkM0xtRndjR3hsTG1OdmJTOWpaWEowYVdacFkyRjBaV0YxZEdodmNtbDBlUzh3SFFZRFZSME9CQllFRkFNczhQanM2VmhXR1FsekUyWk9FK0dYNE9vL01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0Jnc0JCQUlGQURBS0JnZ3Foa2pPUFFRREF3Tm9BREJsQWpFQTh5Uk5kc2twNTA2REZkUExnaExMSndBdjVKOGhCR0xhSThERXhkY1BYK2FCS2pqTzhlVW85S3BmcGNOWVVZNVlBakFQWG1NWEVaTCtRMDJhZHJtbXNoTnh6M05uS20rb3VRd1U3dkJUbjBMdmxNN3ZwczJZc2xWVGFtUllMNGFTczVrPSIsIk1JSURGakNDQXB5Z0F3SUJBZ0lVSXNHaFJ3cDBjMm52VTRZU3ljYWZQVGp6Yk5jd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NakV3TXpFM01qQXpOekV3V2hjTk16WXdNekU1TURBd01EQXdXakIxTVVRd1FnWURWUVFERER0QmNIQnNaU0JYYjNKc1pIZHBaR1VnUkdWMlpXeHZjR1Z5SUZKbGJHRjBhVzl1Y3lCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEVMTUFrR0ExVUVDd3dDUnpZeEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVic1FLQzk0UHJsV21aWG5YZ3R4emRWSkw4VDBTR1luZ0RSR3BuZ24zTjZQVDhKTUViN0ZEaTRiQm1QaENuWjMvc3E2UEYvY0djS1hXc0w1dk90ZVJoeUo0NXgzQVNQN2NPQithYW85MGZjcHhTdi9FWkZibmlBYk5nWkdoSWhwSW80SDZNSUgzTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0h3WURWUjBqQkJnd0ZvQVV1N0Rlb1ZnemlKcWtpcG5ldnIzcnI5ckxKS3N3UmdZSUt3WUJCUVVIQVFFRU9qQTRNRFlHQ0NzR0FRVUZCekFCaGlwb2RIUndPaTh2YjJOemNDNWhjSEJzWlM1amIyMHZiMk56Y0RBekxXRndjR3hsY205dmRHTmhaek13TndZRFZSMGZCREF3TGpBc29DcWdLSVltYUhSMGNEb3ZMMk55YkM1aGNIQnNaUzVqYjIwdllYQndiR1Z5YjI5MFkyRm5NeTVqY213d0hRWURWUjBPQkJZRUZEOHZsQ05SMDFESm1pZzk3YkI4NWMrbGtHS1pNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVFCZ29xaGtpRzkyTmtCZ0lCQkFJRkFEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkFYaFNxNUl5S29nTUNQdHc0OTBCYUI2NzdDYUVHSlh1ZlFCL0VxWkdkNkNTamlDdE9udU1UYlhWWG14eGN4ZmtDTVFEVFNQeGFyWlh2TnJreFUzVGtVTUkzM3l6dkZWVlJUNHd4V0pDOTk0T3NkY1o0K1JHTnNZRHlSNWdtZHIwbkRHZz0iLCJNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtBPT0iXX0.eyJub3RpZmljYXRpb25UeXBlIjoiT05FX1RJTUVfQ0hBUkdFIiwibm90aWZpY2F0aW9uVVVJRCI6ImFkMGEyODJiLWI0ZmEtNGE5ZS05YTk3LWEzYjZiNTQ2NWQ1OCIsImRhdGEiOnsiYXBwQXBwbGVJZCI6NjQ5OTEyMzYyNywiYnVuZGxlSWQiOiJjb20uc2luYXRhLkpLRml0bmVzcyIsImJ1bmRsZVZlcnNpb24iOiIxMyIsImVudmlyb25tZW50IjoiU2FuZGJveCIsInNpZ25lZFRyYW5zYWN0aW9uSW5mbyI6ImV5SmhiR2NpT2lKRlV6STFOaUlzSW5nMVl5STZXeUpOU1VsRlRVUkRRMEUzWVdkQmQwbENRV2RKVVdaVWJHWmtNR1pPZGtaWGRucERNVmxKUVU1eldHcEJTMEpuWjNGb2EycFBVRkZSUkVGNlFqRk5WVkYzVVdkWlJGWlJVVVJFUkhSQ1kwaENjMXBUUWxoaU0wcHpXa2hrY0ZwSFZXZFNSMVl5V2xkNGRtTkhWbmxKUmtwc1lrZEdNR0ZYT1hWamVVSkVXbGhLTUdGWFduQlpNa1l3WVZjNWRVbEZSakZrUjJoMlkyMXNNR1ZVUlV4TlFXdEhRVEZWUlVOM2QwTlNlbGw0UlhwQlVrSm5UbFpDUVc5TlEydEdkMk5IZUd4SlJXeDFXWGswZUVONlFVcENaMDVXUWtGWlZFRnNWbFJOUWpSWVJGUkplazFFYTNoTmFrVTFUbFJGTVUweGIxaEVWRWt4VFZSQmVFMVVSVFZPVkVVeFRXeHZkMmRhU1hoUlJFRXJRbWRPVmtKQlRVMU9NVUo1WWpKUloxSlZUa1JKUlRGb1dYbENRbU5JUVdkVk0xSjJZMjFWWjFsWE5XdEpSMnhWWkZjMWJHTjVRbFJrUnpsNVdsTkNVMXBYVG14aFdFSXdTVVpPY0ZveU5YQmliV040VEVSQmNVSm5UbFpDUVhOTlNUQkdkMk5IZUd4SlJtUjJZMjE0YTJReWJHdGFVMEpGV2xoYWJHSkhPWGRhV0VsblZXMVdjMWxZVW5CaU1qVjZUVkpOZDBWUldVUldVVkZMUkVGd1FtTklRbk5hVTBKS1ltMU5kVTFSYzNkRFVWbEVWbEZSUjBWM1NsWlZla0phVFVKTlIwSjVjVWRUVFRRNVFXZEZSME5EY1VkVFRUUTVRWGRGU0VFd1NVRkNSVVpGV1dVdlNuRlVjWGxSZGk5a2RGaHJZWFZFU0VOVFkxWXhNamxHV1ZKV0x6QjRhVUl5Tkc1RFVXdDZVV1l6WVhOSVNrOU9ValZ5TUZKQk1HRk1ka28wTXpKb2VURlRXazF2ZFhaNVpuQnRNalpxV0ZOcVoyZEpTVTFKU1VOQ1JFRk5RbWRPVmtoU1RVSkJaamhGUVdwQlFVMUNPRWRCTVZWa1NYZFJXVTFDWVVGR1JEaDJiRU5PVWpBeFJFcHRhV2M1TjJKQ09EVmpLMnhyUjB0YVRVaEJSME5EYzBkQlVWVkdRbmRGUWtKSFVYZFpha0YwUW1kbmNrSm5SVVpDVVdOM1FXOVphR0ZJVWpCalJHOTJUREpPYkdOdVVucE1iVVozWTBkNGJFeHRUblppVXprelpESlNlVnA2V1hWYVIxWjVUVVJGUjBORGMwZEJVVlZHUW5wQlFtaHBWbTlrU0ZKM1QyazRkbUl5VG5walF6Vm9ZMGhDYzFwVE5XcGlNakIyWWpKT2VtTkVRWHBNV0dReldraEtiazVxUVhsTlNVbENTR2RaUkZaU01HZENTVWxDUmxSRFEwRlNSWGRuWjBWT1FtZHZjV2hyYVVjNU1rNXJRbEZaUWsxSlNDdE5TVWhFUW1kbmNrSm5SVVpDVVdORFFXcERRblJuZVVKek1VcHNZa2RzYUdKdFRteEpSemwxU1VoU2IyRllUV2RaTWxaNVpFZHNiV0ZYVG1oa1IxVm5XVzVyWjFsWE5UVkpTRUpvWTI1U05VbEhSbnBqTTFaMFdsaE5aMWxYVG1wYVdFSXdXVmMxYWxwVFFuWmFhVUl3WVVkVloyUkhhR3hpYVVKb1kwaENjMkZYVG1oWmJYaHNTVWhPTUZsWE5XdFpXRXByU1VoU2JHTnRNWHBKUjBaMVdrTkNhbUl5Tld0aFdGSndZakkxZWtsSE9XMUpTRlo2V2xOM1oxa3lWbmxrUjJ4dFlWZE9hR1JIVldkalJ6bHpZVmRPTlVsSFJuVmFRMEpxV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxJUW5sWlYwNHdZVmRPYkVsSVRqQlpXRkpzWWxkV2RXUklUWFZOUkZsSFEwTnpSMEZSVlVaQ2QwbENSbWx3YjJSSVVuZFBhVGgyWkROa00weHRSbmRqUjNoc1RHMU9kbUpUT1dwYVdFb3dZVmRhY0ZreVJqQmFWMFl4WkVkb2RtTnRiREJsVXpoM1NGRlpSRlpTTUU5Q1FsbEZSa0ZOY3poUWFuTTJWbWhYUjFGc2VrVXlXazlGSzBkWU5FOXZMMDFCTkVkQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlVVSm5iM0ZvYTJsSE9USk9hMEpuYzBKQ1FVbEdRVVJCUzBKblozRm9hMnBQVUZGUlJFRjNUbTlCUkVKc1FXcEZRVGg1VWs1a2MydHdOVEEyUkVaa1VFeG5hRXhNU25kQmRqVktPR2hDUjB4aFNUaEVSWGhrWTFCWUsyRkNTMnBxVHpobFZXODVTM0JtY0dOT1dWVlpOVmxCYWtGUVdHMU5XRVZhVEN0Uk1ESmhaSEp0YlhOb1RuaDZNMDV1UzIwcmIzVlJkMVUzZGtKVWJqQk1kbXhOTjNad2N6SlpjMnhXVkdGdFVsbE1OR0ZUY3pWclBTSXNJazFKU1VSR2FrTkRRWEI1WjBGM1NVSkJaMGxWU1hOSGFGSjNjREJqTW01MlZUUlpVM2xqWVdaUVZHcDZZazVqZDBObldVbExiMXBKZW1vd1JVRjNUWGRhZWtWaVRVSnJSMEV4VlVWQmQzZFRVVmhDZDJKSFZXZFZiVGwyWkVOQ1JGRlRRWFJKUldONlRWTlpkMHBCV1VSV1VWRk1SRUl4UW1OSVFuTmFVMEpFV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxGUmpGa1IyaDJZMjFzTUdWVVJWUk5Ra1ZIUVRGVlJVTm5kMHRSV0VKM1lrZFZaMU5YTldwTWFrVk1UVUZyUjBFeFZVVkNhRTFEVmxaTmQwaG9ZMDVOYWtWM1RYcEZNMDFxUVhwT2VrVjNWMmhqVGsxNldYZE5la1UxVFVSQmQwMUVRWGRYYWtJeFRWVlJkMUZuV1VSV1VWRkVSRVIwUW1OSVFuTmFVMEpZWWpOS2MxcElaSEJhUjFWblVrZFdNbHBYZUhaalIxWjVTVVpLYkdKSFJqQmhWemwxWTNsQ1JGcFlTakJoVjFwd1dUSkdNR0ZYT1hWSlJVWXhaRWRvZG1OdGJEQmxWRVZNVFVGclIwRXhWVVZEZDNkRFVucFplRVY2UVZKQ1owNVdRa0Z2VFVOclJuZGpSM2hzU1VWc2RWbDVOSGhEZWtGS1FtZE9Wa0pCV1ZSQmJGWlVUVWhaZDBWQldVaExiMXBKZW1vd1EwRlJXVVpMTkVWRlFVTkpSRmxuUVVWaWMxRkxRemswVUhKc1YyMWFXRzVZWjNSNGVtUldTa3c0VkRCVFIxbHVaMFJTUjNCdVoyNHpUalpRVkRoS1RVVmlOMFpFYVRSaVFtMVFhRU51V2pNdmMzRTJVRVl2WTBkalMxaFhjMHcxZGs5MFpWSm9lVW8wTlhnelFWTlFOMk5QUWl0aFlXODVNR1pqY0hoVGRpOUZXa1ppYm1sQllrNW5Xa2RvU1dod1NXODBTRFpOU1VnelRVSkpSMEV4VldSRmQwVkNMM2RSU1UxQldVSkJaamhEUVZGQmQwaDNXVVJXVWpCcVFrSm5kMFp2UVZWMU4wUmxiMVpuZW1sS2NXdHBjRzVsZG5JemNuSTVja3hLUzNOM1VtZFpTVXQzV1VKQ1VWVklRVkZGUlU5cVFUUk5SRmxIUTBOelIwRlJWVVpDZWtGQ2FHbHdiMlJJVW5kUGFUaDJZakpPZW1ORE5XaGpTRUp6V2xNMWFtSXlNSFppTWs1NlkwUkJla3hYUm5kalIzaHNZMjA1ZG1SSFRtaGFlazEzVG5kWlJGWlNNR1pDUkVGM1RHcEJjMjlEY1dkTFNWbHRZVWhTTUdORWIzWk1NazU1WWtNMWFHTklRbk5hVXpWcVlqSXdkbGxZUW5kaVIxWjVZakk1TUZreVJtNU5lVFZxWTIxM2QwaFJXVVJXVWpCUFFrSlpSVVpFT0hac1EwNVNNREZFU20xcFp6azNZa0k0TldNcmJHdEhTMXBOUVRSSFFURlZaRVIzUlVJdmQxRkZRWGRKUWtKcVFWRkNaMjl4YUd0cFJ6a3lUbXRDWjBsQ1FrRkpSa0ZFUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRa0ZZYUZOeE5VbDVTMjluVFVOUWRIYzBPVEJDWVVJMk56ZERZVVZIU2xoMVpsRkNMMFZ4V2tka05rTlRhbWxEZEU5dWRVMVVZbGhXV0cxNGVHTjRabXREVFZGRVZGTlFlR0Z5V2xoMlRuSnJlRlV6Vkd0VlRVa3pNM2w2ZGtaV1ZsSlVOSGQ0VjBwRE9UazBUM05rWTFvMEsxSkhUbk5aUkhsU05XZHRaSEl3YmtSSFp6MGlMQ0pOU1VsRFVYcERRMEZqYldkQmQwbENRV2RKU1V4aldEaHBUa3hHVXpWVmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhkYWVrVmlUVUpyUjBFeFZVVkJkM2RUVVZoQ2QySkhWV2RWYlRsMlpFTkNSRkZUUVhSSlJXTjZUVk5aZDBwQldVUldVVkZNUkVJeFFtTklRbk5hVTBKRVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsRlJqRmtSMmgyWTIxc01HVlVSVlJOUWtWSFFURlZSVU5uZDB0UldFSjNZa2RWWjFOWE5XcE1ha1ZNVFVGclIwRXhWVVZDYUUxRFZsWk5kMGhvWTA1TlZGRjNUa1JOZDAxVVozaFBWRUV5VjJoalRrMTZhM2RPUkUxM1RWUm5lRTlVUVRKWGFrSnVUVkp6ZDBkUldVUldVVkZFUkVKS1FtTklRbk5hVTBKVFlqSTVNRWxGVGtKSlF6Qm5VbnBOZUVwcVFXdENaMDVXUWtGelRVaFZSbmRqUjNoc1NVVk9iR051VW5CYWJXeHFXVmhTY0dJeU5HZFJXRll3WVVjNWVXRllValZOVWsxM1JWRlpSRlpSVVV0RVFYQkNZMGhDYzFwVFFrcGliVTExVFZGemQwTlJXVVJXVVZGSFJYZEtWbFY2UWpKTlFrRkhRbmx4UjFOTk5EbEJaMFZIUWxOMVFrSkJRV2xCTWtsQlFrcHFjRXg2TVVGamNWUjBhM2xLZVdkU1RXTXpVa05XT0dOWGFsUnVTR05HUW1KYVJIVlhiVUpUY0ROYVNIUm1WR3BxVkhWNGVFVjBXQzh4U0RkWmVWbHNNMG8yV1ZKaVZIcENVRVZXYjBFdlZtaFpSRXRZTVVSNWVFNUNNR05VWkdSeFdHdzFaSFpOVm5wMFN6VXhOMGxFZGxsMVZsUmFXSEJ0YTA5c1JVdE5ZVTVEVFVWQmQwaFJXVVJXVWpCUFFrSlpSVVpNZFhjemNVWlpUVFJwWVhCSmNWb3pjalk1TmpZdllYbDVVM0pOUVRoSFFURlZaRVYzUlVJdmQxRkdUVUZOUWtGbU9IZEVaMWxFVmxJd1VFRlJTQzlDUVZGRVFXZEZSMDFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbWRCVFVkVlEwMVJRMFEyWTBoRlJtdzBZVmhVVVZreVpUTjJPVWQzVDBGRldreDFUaXQ1VW1oSVJrUXZNMjFsYjNsb2NHMTJUM2RuVUZWdVVGZFVlRzVUTkdGMEszRkplRlZEVFVjeGJXbG9SRXN4UVROVlZEZ3lUbEY2TmpCcGJVOXNUVEkzYW1Ka2IxaDBNbEZtZVVaTmJTdFphR2xrUkd0TVJqRjJURlZoWjAwMlFtZEVOVFpMZVV0QlBUMGlYWDAuZXlKMGNtRnVjMkZqZEdsdmJrbGtJam9pTWpBd01EQXdNRFkyTXpNMU5ESXlPQ0lzSW05eWFXZHBibUZzVkhKaGJuTmhZM1JwYjI1SlpDSTZJakl3TURBd01EQTJOak16TlRReU1qZ2lMQ0ppZFc1a2JHVkpaQ0k2SW1OdmJTNXphVzVoZEdFdVNrdEdhWFJ1WlhOeklpd2ljSEp2WkhWamRFbGtJam9pWTI5dExtcHJabWwwYm1WemN5NWhMbkJ5YVdObExqRWlMQ0p3ZFhKamFHRnpaVVJoZEdVaU9qRTNNakUyTkRVNE1qWXdNREFzSW05eWFXZHBibUZzVUhWeVkyaGhjMlZFWVhSbElqb3hOekl4TmpRMU9ESTJNREF3TENKeGRXRnVkR2wwZVNJNk1Td2lkSGx3WlNJNklrTnZibk4xYldGaWJHVWlMQ0pwYmtGd2NFOTNibVZ5YzJocGNGUjVjR1VpT2lKUVZWSkRTRUZUUlVRaUxDSnphV2R1WldSRVlYUmxJam94TnpJeE5qUTFPRFF5TkRnNExDSmxiblpwY205dWJXVnVkQ0k2SWxOaGJtUmliM2dpTENKMGNtRnVjMkZqZEdsdmJsSmxZWE52YmlJNklsQlZVa05JUVZORklpd2ljM1J2Y21WbWNtOXVkQ0k2SWtOSVRpSXNJbk4wYjNKbFpuSnZiblJKWkNJNklqRTBNelEyTlNJc0luQnlhV05sSWpvNU9EQXdNQ3dpWTNWeWNtVnVZM2tpT2lKRFRsa2lmUS5nTC1UVThvRV9NY2Q5TGpQb2g0LWxuT3JZek04N1FOY1RxYXFqZ05KT3VSWHMxZGpKQ1VnSVR0Vmd5cWdvMXozVGpGc3BYd1RpYklQeVN1NFg3QUd5dyJ9LCJ2ZXJzaW9uIjoiMi4wIiwic2lnbmVkRGF0ZSI6MTcyMTY0NTg0MjUwNn0.bQeSZOF1IDCD--iN3i711ADUVwhrIoqCLklkBUHsebpFPgTH5TtAJjaeSFkmrqCXzZYLb_m-5acirt5xnWMubQ");
//            String notificationType = payload.get("notificationType").toString();
//            JSONObject data = payload.getJSONObject("data");
//            String signedTransactionInfo = data.get("signedTransactionInfo").toString();
//            String environment = data.get("environment").toString();
//            JSONObject transactionInfo = verifyAndGet(signedTransactionInfo);
//            String transactionId = transactionInfo.get("transactionId").toString();
//            String originalTransactionId = transactionInfo.get("originalTransactionId").toString();
//            String productId = transactionInfo.get("productId").toString();
//            System.err.println("json串"+transactionInfo);
//            System.err.println("data"+data);
//            if ("DID_RENEW".equals(notificationType)) {
//                // todo 处理订阅续期业务逻辑
//
//            } else if ("REFUND".equals(notificationType)) {
//                // todo 处理退款业务逻辑
//
//            } else {
//            }
//
//        } catch (CertificateException e) {
//        }
//
//
//    }
    public static JSONObject verifyAndGet(String jws) throws CertificateException {
        DecodedJWT decodedJWT = JWT.decode(jws);
        // 拿到 header 中 x5c 数组中第一个
        String header = new String(java.util.Base64.getDecoder().decode(decodedJWT.getHeader()));
        String x5c = JSONObject.parseObject(header).getJSONArray("x5c").getString(0);
        // 获取公钥
        PublicKey publicKey = getPublicKeyByX5c(x5c);
        // 验证 token
        Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) publicKey, null);
        try {
            algorithm.verify(decodedJWT);
        } catch (SignatureVerificationException e) {
            throw new RuntimeException("签名验证失败");
        }
        // 解析数据
        return JSONObject.parseObject(new String(java.util.Base64.getDecoder().decode(decodedJWT.getPayload())));
    }
    /**
     * 获取公钥
     * @param x5c
     * @return
     * @throws
     */
    private static PublicKey getPublicKeyByX5c(String x5c) throws CertificateException {
        byte[] x5c0Bytes = java.util.Base64.getDecoder().decode(x5c);
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
        X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(x5c0Bytes));
        return cer.getPublicKey();
    }
}