64个文件已修改
1个文件已删除
19个文件已添加
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module version="4"> |
| | | <component name="FacetManager"> |
| | | <facet type="Spring" name="Spring"> |
| | | <configuration /> |
| | | </facet> |
| | | </component> |
| | | </module> |
| | | <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.dsh.account.entity.TAppUser; |
| | | import com.dsh.account.entity.TCourseInfoRecord; |
| | | import com.dsh.account.model.*; |
| | | import com.dsh.account.service.IVipPaymentService; |
| | | import com.dsh.account.service.TAppUserService; |
| | | import com.dsh.account.service.TCourseInfoRecordService; |
| | | import com.dsh.account.util.PayMoneyUtil; |
| | | import com.dsh.account.util.ResultUtil; |
| | | import com.dsh.account.util.TokenUtil; |
| | |
| | | |
| | | @Autowired |
| | | private TokenUtil tokenUtil; |
| | | |
| | | @Autowired |
| | | private TCourseInfoRecordService courseInfoRecordService; |
| | | |
| | | |
| | | |
| | |
| | | public List<TAppUser> queryAppUserListByName(@RequestBody String name){ |
| | | return appUserService.list(new QueryWrapper<TAppUser>().eq("state", 1).like("name", name)); |
| | | } |
| | | |
| | | |
| | | |
| | | @PostMapping("/appUser/addCourseInfoRecord") |
| | | public Boolean addCourseInfoRecord(@RequestBody TCourseInfoRecord tCourseInfoRecord){ |
| | | boolean save = courseInfoRecordService.save(tCourseInfoRecord); |
| | | return save; |
| | | } |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.dsh.account.entity.TAppGift; |
| | | import com.dsh.account.entity.TStudent; |
| | | import com.dsh.account.feignclient.competition.model.PurchaseRecordVo; |
| | | import com.dsh.account.feignclient.course.model.RecordAppoint; |
| | |
| | | import com.dsh.account.model.vo.sourceDetail.CouponStuAvailableVo; |
| | | import com.dsh.account.model.vo.sourceDetail.CourseDetailsOfContinuationResp; |
| | | import com.dsh.account.model.vo.sourceDetail.RecordTimeRequest; |
| | | import com.dsh.account.service.EvaluateStudentService; |
| | | import com.dsh.account.service.StudentHonorService; |
| | | import com.dsh.account.service.TAppUserService; |
| | | import com.dsh.account.service.TStudentService; |
| | | import com.dsh.account.service.*; |
| | | import com.dsh.account.util.*; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | |
| | | |
| | | @Autowired |
| | | private TokenUtil tokenUtil; |
| | | |
| | | @Autowired |
| | | private TAppGiftService appGiftService; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/weeksOfGetHours") |
| | | @ApiOperation(value = "上课首页获取未分配课时-课程列表", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | }) |
| | | public ResultUtil<Integer> weeksOfGetHours(){ |
| | | try { |
| | | Integer appUserId = tokenUtil.getUserIdFormRedis(); |
| | | if(null == appUserId){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, appUserId)); |
| | | |
| | | return ResultUtil.success(one==null?0:one.getNum()); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/weeksOfAddHours") |
| | | @ApiOperation(value = "上课首页分配课时-课程列表", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | @ApiImplicitParam(value = "分配给课包id", name = "packetId", required = true, dataType = "string"), |
| | | }) |
| | | public ResultUtil<Integer> weeksOfAddHours(Integer packetId){ |
| | | try { |
| | | Integer appUserId = tokenUtil.getUserIdFormRedis(); |
| | | if(null == appUserId){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, appUserId)); |
| | | Boolean b= false; |
| | | if(one!=null && one.getNum()>0){ |
| | | b =appGiftService.weeksOfAddHours(packetId,appUserId,one.getNum()); |
| | | } |
| | | if(b){ |
| | | // 送完清0 |
| | | one.setNum(0); |
| | | appGiftService.updateById(one); |
| | | return ResultUtil.success(); |
| | | }else { |
| | | return ResultUtil.runErr(); |
| | | } |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/queryPhysical") |
| | |
| | | @PostMapping("/base/introduce/useOfRewards") |
| | | public List<PurchaseRecordVo> queryAppUsersofIntroduce(@RequestBody IntrduceOfUserRequest request); |
| | | |
| | | @PostMapping("/base/introduce/getGiftList") |
| | | Integer getGiftList(@RequestBody String cityCode); |
| | | |
| | | |
| | | } |
| | |
| | | @PostMapping("/base/coursePack/getCoursePackagePaymentOfCode") |
| | | List<TCoursePackagePayment> getCoursePackagePaymentOfCode(@RequestBody String code); |
| | | |
| | | @PostMapping("/base/coursePack/sendHours") |
| | | Boolean sendHours(String s); |
| | | |
| | | @PostMapping("/base/coursePack/getClassHour") |
| | | Integer getClassHour(Integer courseConfigId); |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "预约状态") |
| | | private Integer status; |
| | | @ApiModelProperty(value = "总学时数") |
| | | Integer allNum; |
| | | @ApiModelProperty(value = "已扣学时数") |
| | | Integer useNum; |
| | | @ApiModelProperty(value = "剩余学时数") |
| | | Integer lastNum; |
| | | } |
| | |
| | | @ApiModelProperty(value = "门店名称+地址") |
| | | private String storeNameAddr; |
| | | |
| | | @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消)") |
| | | @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消 5已请假 6旷课)") |
| | | private Integer status; |
| | | |
| | | } |
| | |
| | | private String password; |
| | | @ApiModelProperty(value = "邀请人id", dataType = "int", required = false) |
| | | private Integer referralUserId; |
| | | |
| | | private String lon; |
| | | private String lat; |
| | | |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "预约状态:1=未预约,2=已预约") |
| | | Integer status; |
| | | @ApiModelProperty(value = "总学时数") |
| | | Integer allNum; |
| | | @ApiModelProperty(value = "已扣学时数") |
| | | Integer useNum; |
| | | @ApiModelProperty(value = "剩余学时数") |
| | | Integer lastNum; |
| | | |
| | | } |
| | | |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | |
| | | @Data |
| | | public class Goods { |
| | |
| | | |
| | | @ApiModelProperty(value = "已兑换数量") |
| | | private Integer nums; |
| | | @ApiModelProperty(value = "门店id") |
| | | private List<Integer> shopIds; |
| | | |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "商品类型: 1实物 2课包 3门票 4优惠券") |
| | | private Integer goodsType; |
| | | @ApiModelProperty(value = "门店id") |
| | | private Integer shopId; |
| | | |
| | | @ApiModelProperty(value = "搜索内容") |
| | | private String search; |
| | |
| | | @ApiModelProperty(value = "兑换方式(1=积分,2=积分+现金)") |
| | | private Integer exchangeType; |
| | | |
| | | @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") |
| | | private Integer cardType; |
| | | } |
| | |
| | | @ApiModelProperty(value = "商品类型 1实物 2课包 3门票 4优惠券") |
| | | private Integer goodType; |
| | | |
| | | @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") |
| | | private Integer cardType; |
| | | |
| | | } |
| | |
| | | package com.dsh.account.service.impl; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.dsh.account.entity.*; |
| | | import com.dsh.account.enums.RechargeRecordEnum; |
| | | import com.dsh.account.feignclient.activity.IntroduceRewardsClient; |
| | | import com.dsh.account.feignclient.activity.MerChandiseClient; |
| | | import com.dsh.account.feignclient.activity.MerChandiseStoreClient; |
| | | import com.dsh.account.feignclient.activity.UserConponClient; |
| | |
| | | import com.dsh.account.feignclient.competition.DeductionCompetitionsClient; |
| | | import com.dsh.account.feignclient.competition.model.BillingDataRequestVo; |
| | | import com.dsh.account.feignclient.competition.model.PaymentCompetition; |
| | | import com.dsh.account.feignclient.competition.model.PurchaseRecordVo; |
| | | import com.dsh.account.feignclient.course.CoursePackageClient; |
| | | import com.dsh.account.feignclient.course.CoursePackageConfigClient; |
| | | import com.dsh.account.feignclient.course.CoursePaymentClient; |
| | |
| | | import com.dsh.account.model.vo.classDetails.RegisteredCourse; |
| | | import com.dsh.account.model.vo.classDetails.classInsVo.ClassInfoVo; |
| | | import com.dsh.account.model.vo.userBenefitDetail.*; |
| | | import com.dsh.account.service.TAppGiftService; |
| | | import com.dsh.account.service.TAppUserService; |
| | | import com.dsh.account.util.*; |
| | | import com.dsh.account.util.akeylogin.Md5Util; |
| | |
| | | @Resource |
| | | private SiteClient stClient; |
| | | |
| | | @Autowired |
| | | private TAppGiftService appGiftService; |
| | | |
| | | @Autowired |
| | | private IntroduceRewardsClient introduceRewardsClient; |
| | | @Override |
| | | public ClassInfoVo queryUserOfStus(Integer id) { |
| | | TAppUser tAppUser = this.baseMapper.selectById(id); |
| | |
| | | couList.setTimeStr(courseOfStoreVo.getClassStartTime() + "-" + courseOfStoreVo.getClassEndTime()); |
| | | couList.setDetail("¥" + courseOfStoreVo.getCoursePrice() + "/会员扣2学时"); |
| | | couList.setStatus(courseOfStoreVo.getStatus()); |
| | | |
| | | couList.setAllNum(courseOfStoreVo.getAllNum()); |
| | | couList.setUseNum(courseOfStoreVo.getUseNum()); |
| | | couList.setLastNum(courseOfStoreVo.getLastNum()); |
| | | courses.add(couList); |
| | | } |
| | | courseVenue.setCourses(courses); |
| | |
| | | tAppUser.setState(1); |
| | | tAppUser.setInsertTime(new Date()); |
| | | this.baseMapper.insert(tAppUser); |
| | | |
| | | |
| | | // 介绍有礼 |
| | | if(addAppUserVo.getReferralUserId()!=null){ |
| | | Map<String, String> geocode = gdMapGeocodingUtil.geocode(addAppUserVo.getLon(), addAppUserVo.getLat()); |
| | | Integer num=0; |
| | | if(null != geocode){ |
| | | String province = geocode.get("province"); |
| | | String provinceCode = geocode.get("provinceCode"); |
| | | String city = geocode.get("city"); |
| | | String cityCode = geocode.get("cityCode"); |
| | | num = introduceRewardsClient.getGiftList(cityCode); |
| | | } |
| | | TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, addAppUserVo.getReferralUserId())); |
| | | if(one!=null){ |
| | | one.setNum(one.getNum()+num); |
| | | appGiftService.updateById(one); |
| | | }else { |
| | | TAppGift tAppGift = new TAppGift(); |
| | | tAppGift.setUserId(addAppUserVo.getReferralUserId()); |
| | | tAppGift.setNum(num); |
| | | appGiftService.save(tAppGift); |
| | | } |
| | | |
| | | } |
| | | |
| | | return ResultUtil.success(); |
| | | } |
| | | |
| | |
| | | commodity.setBelongsType(vicinityGood.getUserPopulation()); |
| | | commodity.setGoodsType(1); |
| | | commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); |
| | | List<Integer> integers = mcsClient.queryPointMerStoreIds(vicinityGood.getId()); |
| | | commodity.setShopIds(integers); |
| | | break; |
| | | case 2: |
| | | commodity.setGoodId(vicinityGood.getCoursePackageId()); |
| | |
| | | commodity.setBelongsType(vicinityGood.getUserPopulation()); |
| | | commodity.setGoodsType(2); |
| | | commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); |
| | | commodity.setShopIds(mcsClient.queryPointMerStoreIds(vicinityGood.getId())); |
| | | break; |
| | | case 3: |
| | | commodity.setGoodId(vicinityGood.getId()); |
| | |
| | | commodity.setBelongsType(vicinityGood.getUserPopulation()); |
| | | commodity.setGoodsType(3); |
| | | commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); |
| | | commodity.setShopIds(mcsClient.queryPointMerStoreIds(vicinityGood.getId())); |
| | | break; |
| | | default: |
| | | break; |
| | |
| | | goods.add(commodity); |
| | | } |
| | | } |
| | | |
| | | if (StringUtils.hasText(request.getSearch())){ |
| | | if (goods.size() > 0 ){ |
| | | goods = goods.stream() |
| | |
| | | .collect(Collectors.toList()); |
| | | } |
| | | } |
| | | // 2.0 门店筛选 |
| | | if (request.getShopId()!=null){ |
| | | if (goods.size() > 0 ){ |
| | | goods = goods.stream() |
| | | .filter(merchandise -> merchandise.getShopIds().contains(request.getShopId())) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | } |
| | | |
| | | if (null != request.getRank()){ |
| | | switch (request.getRank()){ |
| | | case 1: |
| | |
| | | import com.dsh.account.dto.TStudentDto; |
| | | import com.dsh.account.entity.Coach; |
| | | import com.dsh.account.entity.TAppUser; |
| | | import com.dsh.account.entity.TCourseInfoRecord; |
| | | import com.dsh.account.entity.TStudent; |
| | | import com.dsh.account.feignclient.activity.IntroduceRewardsClient; |
| | | import com.dsh.account.feignclient.activity.UserConponClient; |
| | |
| | | import com.dsh.account.model.vo.sourceDetail.CourseDetailsOfContinuationResp; |
| | | import com.dsh.account.model.vo.sourceDetail.RecordTimeRequest; |
| | | import com.dsh.account.model.vo.userBenefitDetail.Goods; |
| | | import com.dsh.account.service.TCourseInfoRecordService; |
| | | import com.dsh.account.service.TStudentService; |
| | | import com.dsh.account.util.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | @Resource |
| | | private CourseListClient culisClient; |
| | | |
| | | @Autowired |
| | | private TCourseInfoRecordService courseInfoRecordService; |
| | | |
| | | |
| | | |
| | |
| | | getStuSourseList.setStartTime(startTime); |
| | | getStuSourseList.setEndTime(endTime); |
| | | getStuSourseList.setAppUserId(appUserId); |
| | | // 报名赛事 |
| | | List<PurchaseRecordVo> stuSourseList = dcttClient.getStuSourseList(getStuSourseList); |
| | | purchaseRecordVoList.addAll(stuSourseList); |
| | | |
| | |
| | | getStuSessionList.setEndTime(endTime); |
| | | getStuSessionList.setStuId(timeRequest.getStuId()); |
| | | getStuSessionList.setAppUserId(appUserId); |
| | | // 购买课包 |
| | | List<PurchaseRecordVo> purchaseRecordVos = sessionNameClient.queryCourseDetails(getStuSessionList); |
| | | purchaseRecordVoList.addAll(purchaseRecordVos); |
| | | List<TAppUser> tAppUsers = tauMapper.selectList(new QueryWrapper<TAppUser>() |
| | |
| | | request.setStartTime(startTime); |
| | | request.setEndTime(endTime); |
| | | request.setUserIds(userIds); |
| | | // 介绍有礼 |
| | | List<PurchaseRecordVo> purchaseRecordVos1 = idrClient.queryAppUsersofIntroduce(request); |
| | | purchaseRecordVoList.addAll(purchaseRecordVos1); |
| | | } |
| | | |
| | | LambdaQueryWrapper<TCourseInfoRecord> eq = new LambdaQueryWrapper<TCourseInfoRecord>().eq(TCourseInfoRecord::getUserId, appUserId); |
| | | if(timeRequest.getType()!=null){ |
| | | eq.eq(TCourseInfoRecord::getType,timeRequest.getType()); |
| | | } |
| | | // 2.0其他记录 |
| | | List<TCourseInfoRecord> list = courseInfoRecordService.list(eq); |
| | | List<PurchaseRecordVo> list1=new ArrayList<>(); |
| | | for (TCourseInfoRecord tCourseInfoRecord : list) { |
| | | PurchaseRecordVo purchaseRecordVo = new PurchaseRecordVo(); |
| | | purchaseRecordVo.setPurchaseTime(new SimpleDateFormat("MM-dd HH:mm").format(tCourseInfoRecord.getTime())); |
| | | purchaseRecordVo.setPurchaseType(tCourseInfoRecord.getName()); |
| | | if(tCourseInfoRecord.getType()==1){ |
| | | purchaseRecordVo.setPurchaseAmount("+"+tCourseInfoRecord.getNum()); |
| | | }else { |
| | | purchaseRecordVo.setPurchaseAmount("-"+tCourseInfoRecord.getNum()); |
| | | } |
| | | list1.add(purchaseRecordVo); |
| | | } |
| | | purchaseRecordVoList.addAll(list1); |
| | | |
| | | if (purchaseRecordVoList.size() > 0 ){ |
| | | purchaseRecordVoList = purchaseRecordVoList.stream() |
| | |
| | | packagePayment.setInsertTime(new Date()); |
| | | couPayClient.savePaymentCoursePackage(packagePayment); |
| | | |
| | | Integer hour = couPayClient.getClassHour(request.getCourseConfigId()); |
| | | |
| | | try { |
| | | switch (request.getPayType()) { |
| | | case 1: |
| | | return WeChatPayment(code,request.getPayAmount()); |
| | | return WeChatPayment(code,request.getPayAmount(),hour); |
| | | case 2: |
| | | return AlipayPayment(code,request.getPayAmount()); |
| | | return AlipayPayment(code,request.getPayAmount(),hour); |
| | | case 3: |
| | | int i = PlaypaiGoldPayment(code,request); |
| | | switch (i){ |
| | |
| | | } |
| | | |
| | | |
| | | public ResultUtil WeChatPayment(String code,BigDecimal amount) throws Exception { |
| | | public ResultUtil WeChatPayment(String code,BigDecimal amount,Integer hour) throws Exception { |
| | | ResultUtil weixinpay = payMoneyUtil.weixinpay("课包续费", "", code, amount.toString(), |
| | | "/base/coursePackage/wechatPaymentCallback", "APP", ""); |
| | | if(weixinpay.getCode() == 200){ |
| | |
| | | } |
| | | if("SUCCESS".equals(s)){ |
| | | coursePackagePayment.setPayStatus(2); |
| | | coursePackagePayment.setTotalClassHours(hour); |
| | | coursePackagePayment.setLaveClassHours(hour); |
| | | coursePackagePayment.setOrderNumber(transaction_id); |
| | | couPayClient.updatePaymentCoursePackage(coursePackagePayment); |
| | | break; |
| | |
| | | return weixinpay; |
| | | } |
| | | |
| | | public ResultUtil AlipayPayment(String code,BigDecimal amount){ |
| | | public ResultUtil AlipayPayment(String code,BigDecimal amount,Integer hour){ |
| | | ResultUtil alipay = payMoneyUtil.alipay("课包续费", "课包续费", "", code, amount.toString(), |
| | | "/base/coursePackage/alipayPaymentCallback"); |
| | | if(alipay.getCode() == 200){ |
| | |
| | | } |
| | | if("TRADE_SUCCESS".equals(s)){ |
| | | coursePackagePayment.setPayStatus(2); |
| | | coursePackagePayment.setTotalClassHours(hour); |
| | | coursePackagePayment.setLaveClassHours(hour); |
| | | coursePackagePayment.setOrderNumber(tradeNo); |
| | | couPayClient.updatePaymentCoursePackage(coursePackagePayment); |
| | | break; |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module version="4"> |
| | | <component name="FacetManager"> |
| | | <facet type="Spring" name="Spring"> |
| | | <configuration /> |
| | | </facet> |
| | | </component> |
| | | </module> |
| | | <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> |
| | |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | @ResponseBody |
| | | @PostMapping("/base/benefitsVideo/queryClassificationBenefitsVideosListOne") |
| | | @ApiOperation(value = "获取视频列表", tags = {"APP-线上课得积分", "APP-看视频得奖励"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(value = "位置(1=线上课得积分,2=看视频得奖励)", name = "position", dataType = "int", required = true), |
| | | @ApiImplicitParam(value = "搜索内容", name = "search", dataType = "string", required = false), |
| | | @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") |
| | | }) |
| | | public ResultUtil<List<BenefitsVideoClassificationListVo>> queryClassificationBenefitsVideosListOne(Integer position, String search){ |
| | | try { |
| | | Integer uid = -1; |
| | | List<BenefitsVideoClassificationListVo> listVos = bfvService.queryClassificationBenefitsVideosListOne(uid, position, search); |
| | | return ResultUtil.success(listVos); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | |
| | | package com.dsh.activity.controller; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.dsh.activity.entity.IntroduceRewards; |
| | | import com.dsh.activity.feignclient.model.IntrduceOfUserRequest; |
| | |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Api |
| | | @CrossOrigin |
| | |
| | | return recordVos; |
| | | } |
| | | |
| | | @PostMapping("/base/introduce/getGiftList") |
| | | public Integer getGiftList(@RequestBody String cityCode){ |
| | | List<IntroduceRewards> list = idrService.list(new LambdaQueryWrapper<IntroduceRewards>().eq(IntroduceRewards::getCityCode,cityCode).ge(IntroduceRewards::getStartTime,new Date()).le(IntroduceRewards::getEndTime,new Date())); |
| | | int sum = list.stream().mapToInt(IntroduceRewards::getGiveClass).sum(); |
| | | return sum; |
| | | } |
| | | |
| | | } |
| | |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); |
| | | ProductDetailsVo detailsVo = new ProductDetailsVo(); |
| | | PointsMerchandise merchandise = pmdsService.getById(detailRequest.getGoodId()); |
| | | detailsVo.setCardType(merchandise.getCardTye()); |
| | | switch (detailRequest.getGoodsType()){ |
| | | case 2: |
| | | // 课包 |
| | |
| | | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); |
| | | PointDetailsVo detailsVo = new PointDetailsVo(); |
| | | UserPointsMerchandise byId = upmseService.getById(speMercharsId); |
| | | |
| | | if (ToolUtil.isNotEmpty(byId)){ |
| | | PointsMerchandise pmdsServiceById = pmdsService.getById(byId.getPointsMerchandiseId()); |
| | | // 2.0 |
| | | detailsVo.setCardType(pmdsServiceById.getCardTye()); |
| | | detailsVo.setExchangeType(pmdsServiceById.getRedemptionMethod()); |
| | | detailsVo.setGoodType(pmdsServiceById.getType()); |
| | | if (pmdsServiceById.getRedemptionMethod() == 1){ |
| | |
| | | } |
| | | |
| | | detailsVo.setGoodName(pmdsServiceById.getName()); |
| | | detailsVo.setStartTime(simpleDateFormat.format(pmdsServiceById.getStartTime())); |
| | | // 2.0 |
| | | detailsVo.setStartTime(simpleDateFormat.format(byId.getInsertTime())); |
| | | detailsVo.setEndTime(simpleDateFormat.format(pmdsServiceById.getEndTime())); |
| | | detailsVo.setOrderTime(simpleDateFormat.format(byId.getInsertTime())); |
| | | if (byId.getStatus() == 1){ |
| | |
| | | import com.dsh.activity.feignclient.model.CouponStuAvailableVo; |
| | | import com.dsh.activity.feignclient.model.QueryUserCouponByIdAndUserId; |
| | | import com.dsh.activity.model.CouponListVo; |
| | | import com.dsh.activity.model.SendCouponReq; |
| | | import com.dsh.activity.service.CouponStoreService; |
| | | import com.dsh.activity.service.ICouponService; |
| | | import com.dsh.activity.service.UserCouponService; |
| | |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | |
| | | return cService.queryConponRuleOfJson(couponId); |
| | | } |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/base/userConpon/getCoupons") |
| | | public List<Coupon> getCoupons(@RequestBody String couponIds){ |
| | | ArrayList<Integer> integers = new ArrayList<>(); |
| | | for (String s : couponIds.split(",")) { |
| | | Integer integer = Integer.valueOf(s); |
| | | integers.add(integer); |
| | | } |
| | | return cService.list(new LambdaQueryWrapper<Coupon>().in(Coupon::getId,integers)); |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | |
| | | } |
| | | } |
| | | |
| | | @PostMapping("/userCoupon/sendUserCoupon") |
| | | public void sendUserCoupon(@RequestBody SendCouponReq sendCouponReq){ |
| | | try { |
| | | String couponIds = sendCouponReq.getCouponIds(); |
| | | for (String s : couponIds.split(",")) { |
| | | UserCoupon userCoupon = new UserCoupon(); |
| | | userCoupon.setCouponId(Integer.valueOf(s)); |
| | | userCoupon.setUserId(sendCouponReq.getUserId()); |
| | | userCoupon.setStatus(1); |
| | | userCoupon.setInsertTime(new Date()); |
| | | userCouponService.save(userCoupon); |
| | | } |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 修改优惠券数据 |
| | |
| | | */ |
| | | @TableField("shelves") |
| | | private Integer shelves; |
| | | @TableField("cardTye") |
| | | private Integer cardTye; |
| | | |
| | | @Override |
| | | protected Serializable pkVal() { |
| | |
| | | @ApiModelProperty(value = "兑换方式(1=积分,2=积分+现金)") |
| | | private Integer exchangeType; |
| | | |
| | | private Integer cardType; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "商品类型 1实物 2课包 3门票 4优惠券") |
| | | private Integer goodType; |
| | | |
| | | @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") |
| | | private Integer cardType; |
| | | |
| | | } |
| | |
| | | * @throws Exception |
| | | */ |
| | | List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosList(Integer uid, Integer position, String search) throws Exception; |
| | | List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosListOne(Integer uid, Integer position, String search) throws Exception; |
| | | |
| | | |
| | | /** |
| | |
| | | } |
| | | return listVos; |
| | | } |
| | | @Override |
| | | public List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosListOne(Integer uid, Integer position, String search) throws Exception { |
| | | QueryWrapper<BenefitsVideoClassification> wrapper = new QueryWrapper<BenefitsVideoClassification>().eq("position", position); |
| | | if(ToolUtil.isNotEmpty(search)){ |
| | | wrapper.like("name", search); |
| | | } |
| | | List<BenefitsVideoClassification> list = benefitsVideoClassificationService.list(wrapper.orderByAsc("sort")); |
| | | List<UserBenefitsVideos> userBenefitsVideos = userBenefitsVideosService.list(new QueryWrapper<UserBenefitsVideos>().eq("appUserId", -1)); |
| | | List<Integer> collect = userBenefitsVideos.stream().map(UserBenefitsVideos::getBenefitsVideosId).collect(Collectors.toList()); |
| | | |
| | | List<BenefitsVideoClassificationListVo> listVos = new ArrayList<>(); |
| | | for (BenefitsVideoClassification benefitsVideoClassification : list) { |
| | | BenefitsVideoClassificationListVo benefitsVideoClassificationListVo = new BenefitsVideoClassificationListVo(); |
| | | benefitsVideoClassificationListVo.setId(benefitsVideoClassification.getId()); |
| | | benefitsVideoClassificationListVo.setName(benefitsVideoClassification.getName()); |
| | | QueryWrapper<BenefitsVideos> benefitsVideosQueryWrapper = new QueryWrapper<BenefitsVideos>().eq("state", 1); |
| | | if(collect.size() > 0){ |
| | | benefitsVideosQueryWrapper.notIn("id", collect); |
| | | } |
| | | List<BenefitsVideos> list1 = this.list(benefitsVideosQueryWrapper.orderByDesc("insertTime").last(" limit 0, 4")); |
| | | List<BenefitsVideosListVo> lists = new ArrayList<>(); |
| | | for (BenefitsVideos benefitsVideos : list1) { |
| | | Integer courseId = benefitsVideos.getCourseId(); |
| | | Course course = courseClient.queryCourseById(courseId); |
| | | BenefitsVideosListVo benefitsVideosListVo = new BenefitsVideosListVo(); |
| | | benefitsVideosListVo.setId(benefitsVideos.getId()); |
| | | benefitsVideosListVo.setName(course.getName()); |
| | | benefitsVideosListVo.setCover(course.getCoverDrawing()); |
| | | benefitsVideosListVo.setIntroduce(course.getIntroduce()); |
| | | lists.add(benefitsVideosListVo); |
| | | } |
| | | benefitsVideoClassificationListVo.setList(lists); |
| | | listVos.add(benefitsVideoClassificationListVo); |
| | | } |
| | | return listVos; |
| | | } |
| | | |
| | | |
| | | @Override |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module version="4"> |
| | | <component name="FacetManager"> |
| | | <facet type="Spring" name="Spring"> |
| | | <configuration /> |
| | | </facet> |
| | | </component> |
| | | </module> |
| | | <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module version="4"> |
| | | <component name="FacetManager"> |
| | | <facet type="Spring" name="Spring"> |
| | | <configuration /> |
| | | </facet> |
| | | </component> |
| | | </module> |
| | | <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> |
| | |
| | | @ApiOperation(value = "赛事报名", tags = {"APP-赛事活动列表"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") |
| | | |
| | | }) |
| | | public ResultUtil paymentCompetition(PaymentCompetitionVo paymentCompetitionVo){ |
| | | try { |
| | |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | @ResponseBody |
| | | @PostMapping("/api/competition/paymentCompetitionCourseList") |
| | | @ApiOperation(value = "赛事报名--支付可用课时列表", tags = {"APP-赛事活动列表"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | @ApiImplicitParam(value = "赛事id", name = "id", dataType = "int", required = true), |
| | | }) |
| | | public ResultUtil paymentCompetitionCourseList(Integer id){ |
| | | try { |
| | | Integer uid = tokenUtil.getUserIdFormRedis(); |
| | | if(null == uid){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | return cttService.paymentCompetitionCourseList(uid, id); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | |
| | | * 门店id |
| | | */ |
| | | @TableField("storeId") |
| | | private Integer storeId; |
| | | private String storeId; |
| | | /** |
| | | * 赛事名称 |
| | | */ |
| | |
| | | package com.dsh.competition.feignclient.course; |
| | | |
| | | import com.dsh.competition.feignclient.course.model.PaymentDeductionClassHour; |
| | | import com.dsh.competition.model.PayCourseRes; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | |
| | | Integer queryResidueClassHour(Integer id); |
| | | |
| | | |
| | | @PostMapping("/coursePackagePayment/queryResidueClassHourById") |
| | | Integer queryResidueClassHourById(Long id); |
| | | |
| | | |
| | | /** |
| | | * 支付扣减学员课时 |
| | | */ |
| | |
| | | */ |
| | | @PostMapping("/coursePackagePayment/rollbackPaymentDeductionClassHour") |
| | | void rollbackPaymentDeductionClassHour(PaymentDeductionClassHour paymentDeductionClassHour); |
| | | |
| | | @PostMapping("/coursePackagePayment/paymentCompetitionCourseList") |
| | | List<PayCourseRes> paymentCompetitionCourseList(String s); |
| | | |
| | | |
| | | } |
| | |
| | | * 支付编号 |
| | | */ |
| | | private String code; |
| | | /** |
| | | * 用于支付的课程 |
| | | */ |
| | | private Long courseId; |
| | | } |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | |
| | | private Double payMoney; |
| | | @ApiModelProperty("支付方式(1=微信,2=支付宝,3=玩湃币,4=课时)") |
| | | private Integer payType; |
| | | @ApiModelProperty("门店信息") |
| | | private List<Map<String,Object>> storeInfos; |
| | | } |
| | |
| | | private String ids; |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=余额,4=课时)", dataType = "int", required = true) |
| | | private Integer payType; |
| | | @ApiModelProperty(value = "我的购买课包id") |
| | | private Long coursePaymentId; |
| | | } |
| | |
| | | * 定时任务修改赛事状态 |
| | | */ |
| | | void taskSetStatus(); |
| | | |
| | | /** |
| | | * 赛事可用课包 |
| | | * @param uid |
| | | * @param id |
| | | * @return |
| | | */ |
| | | ResultUtil paymentCompetitionCourseList(Integer uid, Integer id); |
| | | |
| | | |
| | | } |
| | |
| | | import com.dsh.competition.feignclient.other.StoreClient; |
| | | import com.dsh.competition.feignclient.other.model.Store; |
| | | import com.dsh.competition.mapper.CompetitionMapper; |
| | | import com.dsh.competition.model.CompetitionInfo; |
| | | import com.dsh.competition.model.CompetitionListVo; |
| | | import com.dsh.competition.model.ParticipantVo; |
| | | import com.dsh.competition.model.PaymentCompetitionVo; |
| | | import com.dsh.competition.model.*; |
| | | import com.dsh.competition.service.CompetitionService; |
| | | import com.dsh.competition.service.IParticipantService; |
| | | import com.dsh.competition.service.IPaymentCompetitionService; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | competitionInfo.setImgs(competition.getImgs()); |
| | | competitionInfo.setName(competition.getName()); |
| | | competitionInfo.setRegisterCondition(competition.getRegisterCondition()); |
| | | |
| | | // 2.0 |
| | | ArrayList<Map<String,Object>> objects = new ArrayList<>(); |
| | | if(null != competition.getStoreId()){ |
| | | Store store = storeClient.queryStoreById(competition.getStoreId()); |
| | | competitionInfo.setStoreName(store.getName()); |
| | | competitionInfo.setStoreAddress(store.getAddress()); |
| | | competitionInfo.setStoreLon(store.getLon()); |
| | | competitionInfo.setStoreLat(store.getLat()); |
| | | competitionInfo.setStoreCoverDrawing(store.getCoverDrawing()); |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | String storeId = competition.getStoreId(); |
| | | for (String s : storeId.split(",")) { |
| | | Store store = storeClient.queryStoreById(Integer.valueOf(s)); |
| | | map.put("name",store.getName()); |
| | | map.put("address",store.getAddress()); |
| | | map.put("storeLon",store.getLon()); |
| | | map.put("storeLat",store.getLat()); |
| | | map.put("storeCoverDrawing",store.getCoverDrawing()); |
| | | if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); |
| | | double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); |
| | | competitionInfo.setDistance(wgs84); |
| | | map.put("distance",wgs84); |
| | | } |
| | | } |
| | | objects.add(map); |
| | | } |
| | | competitionInfo.setStoreInfos(objects); |
| | | |
| | | |
| | | competitionInfo.setRegisterEndTime(sdf.format(competition.getRegisterEndTime())); |
| | | competitionInfo.setStartTime(sdf.format(competition.getStartTime())); |
| | | competitionInfo.setEndTime(sdf.format(competition.getEndTime())); |
| | |
| | | if(null == student){ |
| | | return ResultUtil.error(participant.getName() + "不是学员,无法使用课时支付。"); |
| | | } |
| | | Integer integer = coursePackagePaymentClient.queryResidueClassHour(student.getId()); |
| | | // 2.0 |
| | | Integer integer = coursePackagePaymentClient.queryResidueClassHourById(paymentCompetitionVo.getCoursePaymentId()); |
| | | if(new BigDecimal(integer).compareTo(new BigDecimal(competition.getClassPrice())) < 0){ |
| | | return ResultUtil.error(participant.getName() + "剩余课时不足,无法完成支付。"); |
| | | } |
| | |
| | | paymentDeductionClassHour.setId(student.getId()); |
| | | paymentDeductionClassHour.setClassHour(competition.getClassPrice()); |
| | | paymentDeductionClassHour.setCode(code); |
| | | paymentDeductionClassHour.setCourseId(paymentCompetitionVo.getCoursePaymentId()); |
| | | coursePackagePaymentClient.paymentDeductionClassHour(paymentDeductionClassHour); |
| | | } |
| | | paymentCompetition = paymentCompetitionService.getById(paymentCompetition.getId()); |
| | |
| | | this.baseMapper.taskSetStatusStart(); |
| | | this.baseMapper.taskSetStatusEnd(); |
| | | } |
| | | |
| | | @Override |
| | | public ResultUtil paymentCompetitionCourseList(Integer uid, Integer id) { |
| | | Competition competition = this.baseMapper.selectById(id); |
| | | // 获取门店id 找出符合这些门店的课包 |
| | | String storeId = competition.getStoreId(); |
| | | |
| | | List<PayCourseRes> list = coursePackagePaymentClient.paymentCompetitionCourseList(uid+"_"+storeId); |
| | | return ResultUtil.success(list); |
| | | } |
| | | } |
| | |
| | | competitionInfo.setImgs(competition.getImgs()); |
| | | competitionInfo.setName(competition.getName()); |
| | | competitionInfo.setRegisterCondition(competition.getRegisterCondition()); |
| | | Store store = storeClient.queryStoreById(competition.getStoreId()); |
| | | Store store = storeClient.queryStoreById(Integer.valueOf(competition.getStoreId().split(",")[0])); |
| | | competitionInfo.setStoreName(store.getName()); |
| | | competitionInfo.setStoreAddress(store.getAddress()); |
| | | competitionInfo.setStoreLon(store.getLon()); |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module version="4"> |
| | | <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4"> |
| | | <component name="FacetManager"> |
| | | <facet type="Spring" name="Spring"> |
| | | <configuration /> |
| | | </facet> |
| | | <facet type="jpa" name="JPA"> |
| | | <configuration> |
| | | <setting name="validation-enabled" value="true" /> |
| | | <setting name="provider-name" value="Hibernate" /> |
| | | <datasource-mapping> |
| | | <factory-entry name="entityManagerFactory" /> |
| | | </datasource-mapping> |
| | | <naming-strategy-map /> |
| | | </configuration> |
| | | </facet> |
| | | </component> |
| | | </module> |
| | |
| | | |
| | | |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/course/queryCourseList") |
| | | @ApiOperation(value = "获取课程列表", tags = {"APP-课程列表"}) |
| | |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | List<CoursePackageListVo> coursePackageListVos = coursePackageService.queryCourseList(uid, coursePackageList); |
| | | return ResultUtil.success(coursePackageListVos); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/base/course/queryCourseListOne") |
| | | @ApiOperation(value = "获取课程列表", tags = {"APP-课程列表"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") |
| | | }) |
| | | public ResultUtil<List<CoursePackageListVo>> queryCourseListOne(CoursePackageList coursePackageList){ |
| | | try { |
| | | List<CoursePackageListVo> coursePackageListVos = coursePackageService.queryCourseListOne( coursePackageList); |
| | | return ResultUtil.success(coursePackageListVos); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | |
| | | } |
| | | } |
| | | |
| | | // 2.0 |
| | | @ResponseBody |
| | | @PostMapping("/api/course/paymentCourseCouponList") |
| | | @ApiOperation(value = "支付课程--完成后优惠券列表", tags = {"APP-课程列表"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") |
| | | }) |
| | | public ResultUtil paymentCourseCouponList(Integer coursePackagePaymentConfigId){ |
| | | try { |
| | | Integer uid = tokenUtil.getUserIdFormRedis(); |
| | | if(null == uid){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | return coursePackageService.paymentCourseCouponList(uid, coursePackagePaymentConfigId); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 购买课程微信支付回调 |
| | |
| | | package com.dsh.course.controller; |
| | | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | |
| | | import com.dsh.course.feignclient.account.StudentClient; |
| | | import com.dsh.course.feignclient.account.model.AppUser; |
| | | import com.dsh.course.feignclient.account.model.Student; |
| | | import com.dsh.course.feignclient.account.model.TCourseInfoRecord; |
| | | import com.dsh.course.feignclient.model.*; |
| | | import com.dsh.course.feignclient.other.StoreClient; |
| | | import com.dsh.course.feignclient.other.model.Store; |
| | |
| | | import com.dsh.course.model.vo.CourseDetailRequest; |
| | | import com.dsh.course.model.vo.RegisterCourseVo; |
| | | import com.dsh.course.model.vo.request.*; |
| | | import com.dsh.course.model.vo.response.AppUserVideoResponse; |
| | | import com.dsh.course.model.vo.response.CourseDetailsResponse; |
| | | import com.dsh.course.model.vo.response.CourseOfVideoResponse; |
| | | import com.dsh.course.model.vo.response.*; |
| | | import com.dsh.course.service.*; |
| | | import com.dsh.course.util.*; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | |
| | | |
| | | @Resource |
| | | private StoreClient sreClient; |
| | | |
| | | @Autowired |
| | | private AppUserClient appUserClient; |
| | | |
| | | @Autowired |
| | | private RestTemplate internalRestTemplate; |
| | | |
| | | |
| | | private final SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm"); |
| | | |
| | |
| | | storeVo.setLon(store.getLon()); |
| | | storeVo.setCoursePrice(ToolUtil.isEmpty(paymentConfig.getCashPayment()) ? (double) paymentConfig.getPlayPaiCoin():paymentConfig.getCashPayment()); |
| | | storeVo.setStatus(1); |
| | | // 2.0 |
| | | storeVo.setAllNum(tCoursePackagePayment.getTotalClassHours()); |
| | | storeVo.setLastNum(tCoursePackagePayment.getLaveClassHours()); |
| | | storeVo.setUseNum(tCoursePackagePayment.getTotalClassHours()-tCoursePackagePayment.getLaveClassHours()); |
| | | |
| | | course.add(storeVo); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/payCourseInfo") |
| | | @ApiOperation(value = "课后练习-购课详情(用于购课)", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | }) |
| | | public ResultUtil<PayCourseInfoReq> payCourseInfo(Integer courseId){ |
| | | try { |
| | | return ResultUtil.success(packagePaymentService.payCourseInfo(courseId)); |
| | | }catch (Exception e){ |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/getMyCourseList") |
| | | @ApiOperation(value = "课后练习-可支付课程列表(用于购课)", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | }) |
| | | public ResultUtil<List<PayCourseRes>> getMyCourseList(Integer storeId){ |
| | | try { |
| | | Integer appUserId = tokenUtil.getUserIdFormRedis(); |
| | | if(null == appUserId){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | return ResultUtil.success(packagePaymentService.getMyCourseList(storeId,appUserId)); |
| | | }catch (Exception e){ |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | // 2.0 |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/payCourse") |
| | | @ApiOperation(value = "课后练习-确认购课", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | }) |
| | | public ResultUtil<?> payCourse(@RequestBody PayCourseReq req){ |
| | | try { |
| | | Integer appUserId = tokenUtil.getUserIdFormRedis(); |
| | | if(null == appUserId){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | return packagePaymentService.payCourse(req,appUserId); |
| | | }catch (Exception e){ |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 更新课后视频学习状态 |
| | | */ |
| | |
| | | return 0; |
| | | } |
| | | } |
| | | /** |
| | | * 获取学员剩余课时 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | @ResponseBody |
| | | @PostMapping("/coursePackagePayment/queryResidueClassHourById") |
| | | public Integer queryResidueClassHourById(@RequestBody Long id){ |
| | | try { |
| | | TCoursePackagePayment list = packagePaymentService.getById(id); |
| | | return list.getLaveClassHours(); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | |
| | | @PostMapping("/coursePackagePayment/paymentDeductionClassHour") |
| | | public void paymentDeductionClassHour(@RequestBody PaymentDeductionClassHour paymentDeductionClassHour){ |
| | | try { |
| | | List<TCoursePackagePayment> list = packagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("studentId", paymentDeductionClassHour.getId()).eq("payStatus", 2) |
| | | // 2.0 用id进行查询 |
| | | List<TCoursePackagePayment> list = packagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("id", paymentDeductionClassHour.getCourseId()).eq("payStatus", 2) |
| | | .eq("status", 1).eq("state", 1).gt("laveClassHours", 0)); |
| | | Integer classHour = paymentDeductionClassHour.getClassHour(); |
| | | for (TCoursePackagePayment coursePackagePayment : list) { |
| | | if(coursePackagePayment.getLaveClassHours().compareTo(classHour) >= 0){ |
| | | coursePackagePayment.setLaveClassHours(coursePackagePayment.getLaveClassHours() - classHour); |
| | | packagePaymentService.updateById(coursePackagePayment); |
| | | |
| | | // 2.0 少于3课时 推送 |
| | | if(coursePackagePayment.getLaveClassHours()<=3){ |
| | | Integer appUserId = coursePackagePayment.getAppUserId(); |
| | | |
| | | //调用推送 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | // 以表单的方式提交 |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | String s1 = appUserId + "_" + "Three"; |
| | | //定时修改排课状态 |
| | | String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); |
| | | JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); |
| | | if(jsonObject1.getIntValue("code") != 200){ |
| | | System.err.println(jsonObject1.getString("msg")); |
| | | } |
| | | } |
| | | |
| | | CancelledClasses cancelledClasses = new CancelledClasses(); |
| | | cancelledClasses.setType(2); |
| | |
| | | |
| | | |
| | | /** |
| | | * 找出符合门店的课包 |
| | | * @param s |
| | | * @return |
| | | */ |
| | | @ResponseBody |
| | | @PostMapping("/coursePackagePayment/paymentCompetitionCourseList") |
| | | public List<PayCourseRes> paymentCompetitionCourseList(@RequestBody String s){ |
| | | ArrayList<PayCourseRes> objects = new ArrayList<>(); |
| | | |
| | | String[] split = s.split("_"); |
| | | // 用户id |
| | | Integer integer = Integer.valueOf(split[0]); |
| | | String s1 = split[1]; |
| | | // 门店id |
| | | String[] split1 = s1.split(","); |
| | | ArrayList<Integer> storeIds = new ArrayList<>(); |
| | | for (String s2 : split1) { |
| | | storeIds.add(Integer.valueOf(s2)); |
| | | } |
| | | List<TCoursePackagePayment> list = packagePaymentService.list(new LambdaQueryWrapper<TCoursePackagePayment>().eq(TCoursePackagePayment::getAppUserId, integer).ge(TCoursePackagePayment::getLaveClassHours, 0).eq(TCoursePackagePayment::getStatus, 1).eq(TCoursePackagePayment::getState, 1)); |
| | | for (TCoursePackagePayment tCoursePackagePayment : list) { |
| | | Integer coursePackageId = tCoursePackagePayment.getCoursePackageId(); |
| | | TCoursePackage byId = tcpService.getById(coursePackageId); |
| | | if(storeIds.contains(byId.getStoreId())){ |
| | | PayCourseRes payCourseRes = new PayCourseRes(); |
| | | payCourseRes.setCourseNum(tCoursePackagePayment.getLaveClassHours()); |
| | | payCourseRes.setId(tCoursePackagePayment.getId()); |
| | | payCourseRes.setName(byId.getName()); |
| | | objects.add(payCourseRes); |
| | | } |
| | | } |
| | | return objects; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 课包续费玩湃币支付 |
| | | * @param |
| | | */ |
| | |
| | | |
| | | appUser.setPlayPaiCoins(appUser.getPlayPaiCoins()-paymentConfig.getPlayPaiCoin()); |
| | | auClitn.updateAppUser(appUser); |
| | | |
| | | // 2.0 |
| | | TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); |
| | | tCourseInfoRecord.setUserId(userIdFormRedis); |
| | | tCourseInfoRecord.setCourseId(coursePackage.getCoursePackageId()); |
| | | tCourseInfoRecord.setName("续课"); |
| | | tCourseInfoRecord.setTime(new Date()); |
| | | tCourseInfoRecord.setType(1); |
| | | tCourseInfoRecord.setNum(paymentConfig.getClassHours()); |
| | | auClitn.addCourseInfoRecord(tCourseInfoRecord); |
| | | } catch (Exception e) { |
| | | return 4; |
| | | } |
| | |
| | | } |
| | | @PostMapping("/base/coursePack/updatePaymentCoursePackage") |
| | | public boolean updatePaymentCoursePackage(@RequestBody TCoursePackagePayment packagePayment){ |
| | | return packagePaymentService.update(packagePayment,new QueryWrapper<TCoursePackagePayment>() |
| | | boolean id = packagePaymentService.update(packagePayment, new QueryWrapper<TCoursePackagePayment>() |
| | | .eq("id",packagePayment.getId())); |
| | | if(id){ |
| | | // 2.0 |
| | | TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); |
| | | tCourseInfoRecord.setNum(packagePayment.getTotalClassHours()); |
| | | tCourseInfoRecord.setName("续课"); |
| | | tCourseInfoRecord.setCourseId(packagePayment.getCoursePackageId()); |
| | | tCourseInfoRecord.setUserId(packagePayment.getAppUserId()); |
| | | tCourseInfoRecord.setType(1); |
| | | tCourseInfoRecord.setTime(new Date()); |
| | | id = appUserClient.addCourseInfoRecord(tCourseInfoRecord); |
| | | } |
| | | return id; |
| | | } |
| | | |
| | | @PostMapping("/base/coursePack/savePaymentCoursePackage") |
| | |
| | | .eq("code",code)); |
| | | } |
| | | |
| | | |
| | | // 2.0 送课时 |
| | | @PostMapping("/base/coursePack/sendHours") |
| | | public Boolean sendHours(@RequestBody String s){ |
| | | String[] split = s.split("_"); |
| | | TCoursePackagePayment byId = packagePaymentService.getById(Integer.valueOf(split[0])); |
| | | byId.setTotalClassHours(byId.getTotalClassHours()+Integer.valueOf(split[2])); |
| | | return packagePaymentService.updateById(byId); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 查询课时 |
| | | * @param courseConfigId |
| | | * @return |
| | | */ |
| | | @PostMapping("/base/coursePack/getClassHour") |
| | | public Integer getClassHour(@RequestBody Integer courseConfigId){ |
| | | CoursePackagePaymentConfig byId = icppcService.getById(courseConfigId); |
| | | return byId.getClassHours(); |
| | | } |
| | | |
| | | /** |
| | | * 获取课包报名信息列表 |
| | |
| | | */ |
| | | @ResponseBody |
| | | @PostMapping("/api/startCource/reverse") |
| | | @ApiOperation(value = "上课主页-预约操作", tags = {"APP-开始上课"}) |
| | | @ApiOperation(value = "上课主页-预约操作--2.0改请假操作", tags = {"APP-开始上课"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), |
| | | @ApiImplicitParam(value = "课包id", name = "courseID", required = true, dataType = "String"), |
| | |
| | | ); |
| | | |
| | | if (ToolUtil.isNotEmpty(coursePackageStudent) && coursePackageStudent.getReservationStatus() == 0){ |
| | | coursePackageStudent.setReservationStatus(1); |
| | | coursePackageStudent.setSignInOrNot(2); |
| | | coursePackageStudent.setInsertTime(simpleDateFormat.parse(time)); |
| | | cspsService.updateById(coursePackageStudent); |
| | | }else { |
| | |
| | | coursePackageStudent.setStudentId(stuId); |
| | | coursePackageStudent.setCoursePackageId(packagePayment.getCoursePackageId()); |
| | | coursePackageStudent.setCoursePackagePaymentId(Long.parseLong(courseID)); |
| | | coursePackageStudent.setReservationStatus(1); |
| | | coursePackageStudent.setSignInOrNot(2); |
| | | coursePackageStudent.setInsertTime(simpleDateFormat.parse(time)); |
| | | cspsService.save(coursePackageStudent); |
| | | } |
| | |
| | | */ |
| | | @TableField("playPaiCoin") |
| | | private Integer playPaiCoin; |
| | | @TableField("couponIds") |
| | | private String couponIds; |
| | | } |
| | |
| | | @TableField("insertTime") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private Date insertTime; |
| | | @TableField("type") |
| | | private Integer type; |
| | | @TableField("needNum") |
| | | private Integer needNum; |
| | | |
| | | } |
| | |
| | | package com.dsh.course.feignclient.account; |
| | | |
| | | import com.dsh.course.feignclient.account.model.AppUser; |
| | | import com.dsh.course.feignclient.account.model.TCourseInfoRecord; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | |
| | |
| | | */ |
| | | @PostMapping("/appUser/queryAppUserListByName") |
| | | List<AppUser> queryAppUserListByName(String name); |
| | | |
| | | |
| | | @PostMapping("/appUser/addCourseInfoRecord") |
| | | Boolean addCourseInfoRecord(TCourseInfoRecord tCourseInfoRecord); |
| | | |
| | | |
| | | } |
| | |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | |
| | | |
| | | @PostMapping("/base/userConpon/queryCouponRules") |
| | | Map<String,Object> getCouponRules(@RequestBody Integer couponId); |
| | | |
| | | @PostMapping("/base/userConpon/getCoupons") |
| | | List<Coupon> getCoupons(String couponIds); |
| | | |
| | | |
| | | } |
| | |
| | | package com.dsh.course.feignclient.activity; |
| | | |
| | | import com.dsh.course.feignclient.activity.model.SendCouponReq; |
| | | import com.dsh.course.feignclient.activity.model.UserCoupon; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | |
| | | */ |
| | | @PostMapping("/userCoupon/queryUserCouponById") |
| | | UserCoupon queryUserCouponById(Long id); |
| | | |
| | | /** |
| | | * 送优惠券 |
| | | * @param sendCouponReq |
| | | */ |
| | | @PostMapping("/userCoupon/sendUserCoupon") |
| | | void sendUserCoupon(SendCouponReq sendCouponReq); |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "预约状态") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "总学时数") |
| | | Integer allNum; |
| | | @ApiModelProperty(value = "已扣学时数") |
| | | Integer useNum; |
| | | @ApiModelProperty(value = "剩余学时数") |
| | | Integer lastNum; |
| | | |
| | | } |
| | |
| | | * 支付编号 |
| | | */ |
| | | private String code; |
| | | /** |
| | | * 用于支付的课程 |
| | | */ |
| | | private Long courseId; |
| | | } |
| | |
| | | @ApiModelProperty(value = "门店名称+地址") |
| | | private String storeNameAddr; |
| | | |
| | | @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消)") |
| | | @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消 5已请假 6旷课)") |
| | | private Integer status; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty("上课周") |
| | | private List<String> weeks; |
| | | @ApiModelProperty("上课时间") |
| | | private String times; |
| | | private List<String> times; |
| | | @ApiModelProperty("详情图片") |
| | | private String detailDrawing; |
| | | @ApiModelProperty("介绍图") |
| | |
| | | private List<CoursePackagePaymentConfigVo> list; |
| | | @ApiModelProperty("学员") |
| | | private StudentVo student; |
| | | @ApiModelProperty("1常规 2假期 3体验") |
| | | private Integer type; |
| | | } |
| | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @date 2023/6/24 17:34 |
| | |
| | | @ApiModelProperty("封面图") |
| | | private String coverDrawing; |
| | | @ApiModelProperty("上课时间") |
| | | private String classStartTime; |
| | | private List<String> classStartTime; |
| | | @ApiModelProperty("已报名人数") |
| | | private Integer applicantsNumber; |
| | | @ApiModelProperty("支付方式(1=现金,2=玩湃币)") |
| | |
| | | private Integer playPaiCoin; |
| | | @ApiModelProperty("距离") |
| | | private Double distance; |
| | | @ApiModelProperty("1常规 2假期 3体验") |
| | | private Integer type; |
| | | } |
| | |
| | | @ApiModelProperty(value = "课包类型id") |
| | | private Integer coursePackTypeId; |
| | | |
| | | @ApiModelProperty(value = "1常规 2假期 3体验") |
| | | private Integer type; |
| | | |
| | | } |
| | |
| | | package com.dsh.course.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.api.R; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.dsh.course.entity.TCoursePackagePayment; |
| | |
| | | import com.dsh.course.model.QueryWalkInStudentList; |
| | | import com.dsh.course.model.BillingRequest; |
| | | import com.dsh.course.model.vo.RegisterCourseVo; |
| | | import com.dsh.course.model.vo.request.ClasspaymentRequest; |
| | | import com.dsh.course.model.vo.request.CourseOfAfterRequest; |
| | | import com.dsh.course.model.vo.request.CourseWithDetailsRequest; |
| | | import com.dsh.course.model.vo.request.UpdateCourseVideoStatusRequest; |
| | | import com.dsh.course.model.vo.response.AppUserVideoResponse; |
| | | import com.dsh.course.model.vo.response.CourseDetailsResponse; |
| | | import com.dsh.course.model.vo.response.CourseOfVideoResponse; |
| | | import com.dsh.course.model.vo.request.*; |
| | | import com.dsh.course.model.vo.response.*; |
| | | import com.dsh.course.util.ResultUtil; |
| | | |
| | | import java.util.List; |
| | |
| | | * @return |
| | | */ |
| | | List<Map<String, Object>> queryWalkInStudentList(Page<Map<String, Object>> page, QueryWalkInStudentList queryWalkInStudentList); |
| | | |
| | | List<PayCourseRes> getMyCourseList(Integer storeId, Integer appUserId); |
| | | |
| | | |
| | | PayCourseInfoReq payCourseInfo(Integer courseId); |
| | | |
| | | |
| | | ResultUtil payCourse(PayCourseReq req, Integer userId); |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | String getHours(Integer coursePackageId); |
| | | |
| | | ResultUtil paymentCourseCouponList(Integer uid, Integer coursePackagePaymentConfigId); |
| | | |
| | | |
| | | List<CoursePackageListVo> queryCourseListOne(CoursePackageList coursePackageList) throws Exception; |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.dsh.course.feignclient.account.model.AppUser; |
| | | import com.dsh.course.feignclient.account.model.Coach; |
| | | import com.dsh.course.feignclient.account.model.Student; |
| | | import com.dsh.course.feignclient.account.model.TCourseInfoRecord; |
| | | import com.dsh.course.feignclient.activity.BenefitVideoClient; |
| | | import com.dsh.course.feignclient.activity.CouponClient; |
| | | import com.dsh.course.feignclient.activity.model.BenefitsVideos; |
| | |
| | | import com.dsh.course.model.QueryWalkInStudentList; |
| | | import com.dsh.course.model.dto.DiscountJsonDto; |
| | | import com.dsh.course.model.vo.RegisterCourseVo; |
| | | import com.dsh.course.model.vo.request.ClasspaymentRequest; |
| | | import com.dsh.course.model.vo.request.CourseOfAfterRequest; |
| | | import com.dsh.course.model.vo.request.CourseWithDetailsRequest; |
| | | import com.dsh.course.model.vo.request.UpdateCourseVideoStatusRequest; |
| | | import com.dsh.course.model.vo.response.AppUserVideoResponse; |
| | | import com.dsh.course.model.vo.response.CourseDetailsResponse; |
| | | import com.dsh.course.model.vo.response.CourseOfVideoResponse; |
| | | import com.dsh.course.model.vo.request.*; |
| | | import com.dsh.course.model.vo.response.*; |
| | | import com.dsh.course.service.ICoursePackageSchedulingService; |
| | | import com.dsh.course.service.TCoursePackagePaymentService; |
| | | import com.dsh.course.util.*; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | |
| | | |
| | | @Autowired |
| | | private ICoursePackageSchedulingService coursePackageSchedulingService; |
| | | |
| | | |
| | | @Autowired |
| | | private RestTemplate internalRestTemplate; |
| | | |
| | | |
| | | |
| | |
| | | TCoursePackage coursePackage = tcpmapper.selectById(tCoursePackagePayment.getCoursePackageId()); |
| | | Store store = stoClient.queryStoreById(coursePackage.getStoreId()); |
| | | RegisterCourseVo registerCourseVo = new RegisterCourseVo(); |
| | | // 2.0 |
| | | registerCourseVo.setType(coursePackage.getType()); |
| | | |
| | | registerCourseVo.setCoursePayId(tCoursePackagePayment.getId()); |
| | | registerCourseVo.setCoursePackageId(tCoursePackagePayment.getCoursePackageId()); |
| | | registerCourseVo.setCoursePackTypeId(coursePackage.getCoursePackageTypeId()); |
| | | registerCourseVo.setPackageImg(coursePackage.getCoverDrawing()); |
| | | String storeAndCourse = coursePackage.getName()+"("+ store.getName() +")"; |
| | | registerCourseVo.setCourseNameStore(storeAndCourse); |
| | | registerCourseVo.setCourseTime(coursePackage.getClassStartTime()+"-"+coursePackage.getClassEndTime()); |
| | | // registerCourseVo.setCourseTime(coursePackage.getClassStartTime()+"-"+coursePackage.getClassEndTime()); |
| | | // 2.0 |
| | | registerCourseVo.setCourseTime(new SimpleDateFormat("yyyy-MM-dd").format(tCoursePackagePayment.getInsertTime())); |
| | | Coach coach = coachClient.queryCoachById(coursePackage.getCoachId()); |
| | | registerCourseVo.setCourseTeacher(ToolUtil.isEmpty(coach) ? "" : coach.getName()); |
| | | List<CoursePackageStudent> coursePackageStudents = cpsMapper.selectList(new QueryWrapper<CoursePackageStudent>() |
| | |
| | | String[] split = classWeeks.split(";"); |
| | | List<String> integerList = Arrays.asList(split); |
| | | String weekOfDate = DateTimeHelper.getWeekOfDate(new Date()); |
| | | |
| | | if (integerList.contains(weekOfDate)){ |
| | | String dat = simpleDateFormat.format(date) +" "+ classStartTime; |
| | | |
| | |
| | | } |
| | | if (start.after(new Date())){ |
| | | recordVo.setStatus(1); |
| | | }else if(coursePackageStudent.getSignInOrNot()==2){ |
| | | recordVo.setStatus(5); |
| | | }else { |
| | | CancelledClasses cancelledClasses = cacMapper.selectOne(new QueryWrapper<CancelledClasses>() |
| | | .eq("coursePackageId",tCoursePackagePayment.getCoursePackageId() )); |
| | | if (ToolUtil.isNotEmpty(cancelledClasses)){ |
| | | recordVo.setStatus(3); |
| | | // 消课 到课状态0 旷课 |
| | | if(coursePackageStudent.getSignInOrNot()==0){ |
| | | recordVo.setStatus(6); |
| | | } |
| | | |
| | | }else { |
| | | recordVo.setStatus(2); |
| | | } |
| | |
| | | }else { |
| | | recordVo.setStatus(1); |
| | | } |
| | | |
| | | }else { |
| | | recordVo.setStatus(4); |
| | | } |
| | | |
| | | recordVoList.add(recordVo); |
| | | } |
| | | } |
| | |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | @Override |
| | | public List<PayCourseRes> getMyCourseList(Integer storeId, Integer appUserId) { |
| | | // 找到购买的课包 |
| | | List<TCoursePackagePayment> tCoursePackagePayments = this.baseMapper.selectList(new LambdaQueryWrapper<TCoursePackagePayment>().eq(TCoursePackagePayment::getAppUserId, appUserId)); |
| | | ArrayList<PayCourseRes> payCourseRes = new ArrayList<>(); |
| | | for (TCoursePackagePayment tCoursePackagePayment : tCoursePackagePayments) { |
| | | TCoursePackage tCoursePackage = tcpmapper.selectById(tCoursePackagePayment.getCoursePackageId()); |
| | | if(tCoursePackage.getStoreId().equals(storeId)){ |
| | | PayCourseRes payCourseRes1 = new PayCourseRes(); |
| | | payCourseRes1.setId(tCoursePackagePayment.getId()); |
| | | payCourseRes1.setName(tCoursePackage.getName()); |
| | | payCourseRes1.setCourseNum(tCoursePackagePayment.getLaveClassHours()); |
| | | payCourseRes.add(payCourseRes1); |
| | | |
| | | } |
| | | } |
| | | return payCourseRes; |
| | | } |
| | | |
| | | @Override |
| | | public PayCourseInfoReq payCourseInfo(Integer courseId){ |
| | | PayCourseInfoReq payCourseInfoReq = new PayCourseInfoReq(); |
| | | TCoursePackage tCoursePackage = tcpmapper.selectById(courseId); |
| | | payCourseInfoReq.setId(courseId); |
| | | payCourseInfoReq.setName(tCoursePackage.getName()); |
| | | payCourseInfoReq.setNum(tCoursePackage.getNeedNum()); |
| | | payCourseInfoReq.setWeek(tCoursePackage.getClassWeeks()); |
| | | String classStartTime = tCoursePackage.getClassStartTime(); |
| | | String classEndTime = tCoursePackage.getClassEndTime(); |
| | | String[] split = classStartTime.split(","); |
| | | String[] split1 = classEndTime.split(","); |
| | | ArrayList<String> strings = new ArrayList<>(); |
| | | for (int i = 0; i < classStartTime.split(",").length; i++) { |
| | | String s = split[i] + "-" + split1[i]; |
| | | strings.add(s); |
| | | } |
| | | payCourseInfoReq.setTime(strings); |
| | | return payCourseInfoReq; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW) |
| | | public ResultUtil payCourse(PayCourseReq req,Integer userId){ |
| | | // 扣除 原来的课时数 |
| | | // 添加购买课时 paytyoe为7 |
| | | // 排课可期 判断课程时间段 添加排课表 添加上课记录表 |
| | | // 找到原来的课包 扣课时 |
| | | TCoursePackagePayment tCoursePackagePayment = this.baseMapper.selectById(req.getOldCourseId()); |
| | | if(req.getNum()>tCoursePackagePayment.getLaveClassHours()){ |
| | | return ResultUtil.error("当前课包课时数不足"); |
| | | } |
| | | tCoursePackagePayment.setLaveClassHours(tCoursePackagePayment.getLaveClassHours()-req.getNum()); |
| | | this.baseMapper.updateById(tCoursePackagePayment); |
| | | |
| | | |
| | | TCoursePackage tCoursePackage = tcpmapper.selectById(req.getCourseId()); |
| | | // 添加课包 |
| | | TCoursePackagePayment tCoursePackagePayment1 = new TCoursePackagePayment(); |
| | | tCoursePackagePayment1.setAppUserId(userId); |
| | | Student student = studentClient.queryDefaultStudent(userId); |
| | | // student ID |
| | | Integer sId=null; |
| | | if(student!=null){ |
| | | tCoursePackagePayment1.setStudentId(student.getId()); |
| | | sId=student.getId(); |
| | | } |
| | | tCoursePackagePayment1.setCoursePackageId(tCoursePackage.getId()); |
| | | tCoursePackagePayment1.setPayType(7); |
| | | tCoursePackagePayment1.setClassHours(req.getNum()); |
| | | tCoursePackagePayment1.setOriginalPrice(0.0); |
| | | tCoursePackagePayment1.setTotalClassHours(req.getNum()); |
| | | tCoursePackagePayment1.setLaveClassHours(req.getNum()); |
| | | tCoursePackagePayment1.setAbsencesNumber(0); |
| | | tCoursePackagePayment1.setPayUserType(1); |
| | | tCoursePackagePayment1.setPayStatus(2); |
| | | tCoursePackagePayment1.setPayUserId(userId); |
| | | tCoursePackagePayment1.setStatus(1); |
| | | tCoursePackagePayment1.setState(1); |
| | | tCoursePackagePayment1.setInsertTime(new Date()); |
| | | this.baseMapper.insert(tCoursePackagePayment1); |
| | | // 找出课包时间段 |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); |
| | | String classStartTime = tCoursePackage.getClassStartTime(); |
| | | String classEndTime = tCoursePackage.getClassEndTime(); |
| | | String[] split = classStartTime.split(","); |
| | | String[] split1 = classEndTime.split(","); |
| | | List<String> time = req.getTime(); |
| | | for (String s : time) { |
| | | for (int i = 0; i < split.length; i++) { |
| | | CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); |
| | | coursePackageScheduling.setCourseId(tCoursePackage.getId()); |
| | | try { |
| | | Date parse = format.parse(s + " " + split[i]); |
| | | Date parse1 = format.parse(s + " " + split1[i]); |
| | | coursePackageScheduling.setClassDate(parse); |
| | | coursePackageScheduling.setEndDate(parse1); |
| | | coursePackageScheduling.setStatus(1); |
| | | coursePackageSchedulingService.save(coursePackageScheduling); |
| | | |
| | | CoursePackageStudent student1 = new CoursePackageStudent(); |
| | | student1.setAppUserId(userId); |
| | | student1.setStudentId(sId); |
| | | student1.setCoursePackageId(tCoursePackage.getId()); |
| | | student1.setCoursePackagePaymentId(tCoursePackagePayment1.getId()); |
| | | student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); |
| | | student1.setSignInOrNot(0); |
| | | student1.setReservationStatus(1); |
| | | student1.setInsertTime(new Date()); |
| | | cpsMapper.insert(student1); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | // 2.0 |
| | | TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); |
| | | tCourseInfoRecord.setUserId(userId); |
| | | tCourseInfoRecord.setCourseId(req.getOldCourseId()); |
| | | tCourseInfoRecord.setName("体验购课"); |
| | | tCourseInfoRecord.setNum(req.getNum()); |
| | | tCourseInfoRecord.setTime(new Date()); |
| | | tCourseInfoRecord.setType(2); |
| | | appuClient.addCourseInfoRecord(tCourseInfoRecord); |
| | | |
| | | |
| | | if(tCoursePackagePayment.getLaveClassHours()<=3){ |
| | | Integer appUserId = userId; |
| | | |
| | | //调用推送 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | // 以表单的方式提交 |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | String s1 = appUserId + "_" + "Three"; |
| | | //定时修改排课状态 |
| | | String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); |
| | | JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); |
| | | if(jsonObject1.getIntValue("code") != 200){ |
| | | System.err.println(jsonObject1.getString("msg")); |
| | | } |
| | | } |
| | | |
| | | return ResultUtil.success(); |
| | | |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | package com.dsh.course.service.impl; |
| | | |
| | | import cn.hutool.core.date.DateUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | |
| | | import com.dsh.course.feignclient.account.StudentClient; |
| | | import com.dsh.course.feignclient.account.model.AppUser; |
| | | import com.dsh.course.feignclient.account.model.Student; |
| | | import com.dsh.course.feignclient.account.model.TCourseInfoRecord; |
| | | import com.dsh.course.feignclient.activity.CouponClient; |
| | | import com.dsh.course.feignclient.activity.UserCouponClient; |
| | | import com.dsh.course.feignclient.activity.model.Coupon; |
| | | import com.dsh.course.feignclient.activity.model.SendCouponReq; |
| | | import com.dsh.course.feignclient.activity.model.UserCoupon; |
| | | import com.dsh.course.feignclient.other.StoreClient; |
| | | import com.dsh.course.feignclient.other.model.Store; |
| | | import com.dsh.course.mapper.CoursePackageStudentMapper; |
| | | import com.dsh.course.mapper.TCoursePackageMapper; |
| | | import com.dsh.course.feignclient.model.CourseOfStoreVo; |
| | | import com.dsh.course.model.*; |
| | | import com.dsh.course.service.*; |
| | | import com.dsh.course.util.*; |
| | | import com.dsh.course.util.httpClinet.HttpResult; |
| | | import org.omg.CORBA.INTERNAL; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | |
| | | |
| | | @Autowired |
| | | private CoursePackageStudentService coursePackageStudentService; |
| | | |
| | | @Resource |
| | | private CoursePackageStudentMapper cpsMapper; |
| | | |
| | | |
| | | |
| | |
| | | coursePackageListVo.setName(coursePackage.getName()); |
| | | coursePackageListVo.setStoreName(null != store ? store.getName() : ""); |
| | | coursePackageListVo.setCoverDrawing(coursePackage.getCoverDrawing()); |
| | | coursePackageListVo.setClassStartTime(coursePackage.getClassStartTime() + "-" + coursePackage.getClassEndTime()); |
| | | |
| | | // 2.0修改 |
| | | String classStartTime = coursePackage.getClassStartTime(); |
| | | String classEndTime = coursePackage.getClassEndTime(); |
| | | ArrayList<String> classTime = new ArrayList<>(); |
| | | String[] split = classStartTime.split(","); |
| | | String[] split3 = classEndTime.split(","); |
| | | for (int i = 0; i < split.length; i++) { |
| | | String s = split[i] + "-" + split3[i]; |
| | | classTime.add(s); |
| | | } |
| | | coursePackageListVo.setClassStartTime(classTime); |
| | | coursePackageListVo.setType(coursePackage.getType()); |
| | | |
| | | |
| | | |
| | | coursePackageListVo.setApplicantsNumber(integer); |
| | | coursePackageListVo.setPayType(coursePackage.getPayType()); |
| | | coursePackageListVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); |
| | | |
| | | //会员显示原价和会员价(最低)。非会员显示会员价和支付价(最低) |
| | | if(appUser.getIsVip() == 0){//非会员 |
| | | List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) |
| | | .eq("type", 1).eq("auditStatus", 2)); |
| | | Double vipPrice = coursePackagePaymentConfig.getCashPayment(); |
| | | for (TCoursePackageDiscount coursePackageDiscount : list2) { |
| | | Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); |
| | | if(vipPrice.compareTo(num1) > 0){ |
| | | vipPrice = num1; |
| | | } |
| | | } |
| | | coursePackageListVo.setVipPrice(vipPrice); |
| | | |
| | | Double paymentPrice = coursePackagePaymentConfig.getCashPayment(); |
| | | List<TCoursePackageDiscount> list3 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) |
| | | .eq("type", 3).eq("auditStatus", 2)); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | for (TCoursePackageDiscount coursePackageDiscount : list3) { |
| | | /** |
| | | * [{ |
| | | * "startDate": "2023-01-01 00:00:00", |
| | | * "endDate": "2023-12-31 23:59:59", |
| | | * "startTime": "02:00:00", |
| | | * "endTime": "23:00:00", |
| | | * "weeks": [1, 2, 7], |
| | | * "cashPayment": 100 |
| | | * }] |
| | | */ |
| | | JSONArray jsonArray = JSON.parseArray(coursePackageDiscount.getContent()); |
| | | for (int i = 0; i < jsonArray.size(); i++) { |
| | | try { |
| | | JSONObject jsonObject = jsonArray.getJSONObject(i); |
| | | String startDate = jsonObject.getString("startDate"); |
| | | String endDate = jsonObject.getString("endDate"); |
| | | String startTime = jsonObject.getString("startTime"); |
| | | String endTime = jsonObject.getString("endTime"); |
| | | List<Integer> weeks = jsonObject.getJSONArray("weeks").toJavaList(Integer.class); |
| | | Double cashPayment = jsonObject.getDouble("cashPayment"); |
| | | Date startDate_date = sdf.parse(startDate); |
| | | Date endDate_date = sdf.parse(endDate); |
| | | long timeMillis = System.currentTimeMillis(); |
| | | if(timeMillis >= startDate_date.getTime() && timeMillis < endDate_date.getTime()){ |
| | | Date date = new Date(); |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(date); |
| | | int week = calendar.get(Calendar.DAY_OF_WEEK); |
| | | boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY); |
| | | if(isFirstSunday){ |
| | | week = week - 1; |
| | | if(week == 0){ |
| | | week = 7; |
| | | } |
| | | } |
| | | if(!weeks.contains(week)){ |
| | | continue; |
| | | } |
| | | |
| | | String[] split1 = startTime.split(":"); |
| | | Integer hour1 = Integer.valueOf(split1[0]); |
| | | Calendar s = Calendar.getInstance(); |
| | | s.setTime(date); |
| | | s.set(Calendar.HOUR_OF_DAY, hour1); |
| | | s.set(Calendar.MINUTE, Integer.valueOf(split1[1])); |
| | | s.set(Calendar.SECOND, Integer.valueOf(split1[2])); |
| | | |
| | | String[] split2 = endTime.split(":"); |
| | | Integer hour2 = Integer.valueOf(split2[0]); |
| | | Calendar e = Calendar.getInstance(); |
| | | e.setTime(date); |
| | | e.set(Calendar.HOUR_OF_DAY, hour2); |
| | | e.set(Calendar.MINUTE, Integer.valueOf(split2[1])); |
| | | e.set(Calendar.SECOND, Integer.valueOf(split2[2])); |
| | | |
| | | if(hour1 > hour2){ |
| | | if(s.getTimeInMillis() > date.getTime()){ |
| | | s.set(Calendar.DAY_OF_YEAR, s.get(Calendar.DAY_OF_YEAR) - 1); |
| | | }else{ |
| | | e.set(Calendar.DAY_OF_YEAR, e.get(Calendar.DAY_OF_YEAR) + 1); |
| | | } |
| | | } |
| | | if(timeMillis >= s.getTimeInMillis() && timeMillis < e.getTimeInMillis() && paymentPrice.compareTo(cashPayment) > 0){ |
| | | paymentPrice = cashPayment; |
| | | } |
| | | } |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | coursePackageListVo.setPaymentPrice(paymentPrice); |
| | | }else{ |
| | | List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) |
| | | .eq("type", 1).eq("auditStatus", 2)); |
| | | Double vipPrice = coursePackagePaymentConfig.getCashPayment(); |
| | | for (TCoursePackageDiscount coursePackageDiscount : list2) { |
| | | Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); |
| | | if(vipPrice.compareTo(num1) > 0){ |
| | | vipPrice = num1; |
| | | } |
| | | } |
| | | coursePackageListVo.setPaymentPrice(vipPrice); |
| | | coursePackageListVo.setOriginalPrice(coursePackagePaymentConfig.getCashPayment()); |
| | | } |
| | | |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(coursePackageList.getLon() + "," + coursePackageList.getLat(), store.getLon() + "," + store.getLat()); |
| | | coursePackageListVo.setDistance(distance.get("WGS84") / 1000); |
| | | listVos.add(coursePackageListVo); |
| | | } |
| | | |
| | | //销量排行 |
| | | if(ToolUtil.isNotEmpty(coursePackageList.getSalesRanking())){ |
| | | Collections.sort(listVos, new Comparator<CoursePackageListVo>() { |
| | | public int compare(CoursePackageListVo s1, CoursePackageListVo s2) { |
| | | return Integer.compare(s1.getApplicantsNumber(), s2.getApplicantsNumber()); |
| | | } |
| | | }); |
| | | } |
| | | //距离排行 |
| | | if(ToolUtil.isNotEmpty(coursePackageList.getDistanceSort())){ |
| | | Collections.sort(listVos, new Comparator<CoursePackageListVo>() { |
| | | public int compare(CoursePackageListVo s1, CoursePackageListVo s2) { |
| | | return Double.compare(s1.getDistance(), s2.getDistance()); |
| | | } |
| | | }); |
| | | } |
| | | return listVos; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public List<CoursePackageListVo> queryCourseListOne(CoursePackageList coursePackageList) throws Exception { |
| | | // AppUser appUser = appUserClient.queryAppUser(uid); |
| | | Map<String, String> geocode = gdMapGeocodingUtil.geocode(coursePackageList.getLon(), coursePackageList.getLat()); |
| | | String provinceCode = geocode.get("provinceCode"); |
| | | String cityCode = geocode.get("cityCode"); |
| | | QueryWrapper<TCoursePackage> wrapper = new QueryWrapper<TCoursePackage>().in("status", Arrays.asList(1, 2)) |
| | | .eq("auditStatus", 2).eq("state", 1).eq("provinceCode", provinceCode).eq("cityCode", cityCode); |
| | | if(null != coursePackageList.getCoursePackageTypeId()){ |
| | | wrapper.eq("coursePackageTypeId", coursePackageList.getCoursePackageTypeId()); |
| | | } |
| | | if(null != coursePackageList.getStoreId()){ |
| | | wrapper.eq("storeId", coursePackageList.getStoreId()); |
| | | } |
| | | if(null != coursePackageList.getStoreId()){ |
| | | wrapper.eq("storeId", coursePackageList.getStoreId()); |
| | | } |
| | | if(ToolUtil.isNotEmpty(coursePackageList.getSearch())){ |
| | | wrapper.like("name", coursePackageList.getSearch()); |
| | | List<Store> stores = storeClient.queryStoreListByName(coursePackageList.getSearch()); |
| | | List<Integer> collect = stores.stream().map(Store::getId).collect(Collectors.toList()); |
| | | if(collect.size() > 0){ |
| | | wrapper.or().in("storeId", collect); |
| | | } |
| | | } |
| | | List<TCoursePackage> list = this.list(wrapper.last(" order by sort, insertTime desc")); |
| | | List<CoursePackageListVo> listVos = new ArrayList<>(); |
| | | for (TCoursePackage coursePackage : list) { |
| | | Store store = storeClient.queryStoreById(coursePackage.getStoreId()); |
| | | Integer integer = coursePackagePaymentService.queryCountNumber(coursePackage.getId()); |
| | | CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getOne(new QueryWrapper<CoursePackagePaymentConfig>() |
| | | .eq("coursePackageId", coursePackage.getId()).orderByAsc("classHours").last(" limit 0, 1")); |
| | | CoursePackageListVo coursePackageListVo = new CoursePackageListVo(); |
| | | coursePackageListVo.setId(coursePackage.getId()); |
| | | coursePackageListVo.setName(coursePackage.getName()); |
| | | coursePackageListVo.setStoreName(null != store ? store.getName() : ""); |
| | | coursePackageListVo.setCoverDrawing(coursePackage.getCoverDrawing()); |
| | | |
| | | // 2.0修改 |
| | | String classStartTime = coursePackage.getClassStartTime(); |
| | | String classEndTime = coursePackage.getClassEndTime(); |
| | | ArrayList<String> classTime = new ArrayList<>(); |
| | | String[] split = classStartTime.split(","); |
| | | String[] split3 = classEndTime.split(","); |
| | | for (int i = 0; i < split.length; i++) { |
| | | String s = split[i] + "-" + split3[i]; |
| | | classTime.add(s); |
| | | } |
| | | coursePackageListVo.setClassStartTime(classTime); |
| | | coursePackageListVo.setType(coursePackage.getType()); |
| | | |
| | | |
| | | |
| | | coursePackageListVo.setApplicantsNumber(integer); |
| | | coursePackageListVo.setPayType(coursePackage.getPayType()); |
| | | coursePackageListVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); |
| | | |
| | | //会员显示原价和会员价(最低)。非会员显示会员价和支付价(最低) |
| | | if(false){//非会员 |
| | | List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) |
| | | .eq("type", 1).eq("auditStatus", 2)); |
| | | Double vipPrice = coursePackagePaymentConfig.getCashPayment(); |
| | |
| | | |
| | | String[] split = coursePackage.getClassWeeks().split(";"); |
| | | coursePackageInfo.setWeeks(Arrays.asList(split)); |
| | | coursePackageInfo.setTimes(coursePackage.getClassStartTime() + "-" + coursePackage.getClassEndTime()); |
| | | |
| | | // 2.0 |
| | | String classStartTime = coursePackage.getClassStartTime(); |
| | | String classEndTime = coursePackage.getClassEndTime(); |
| | | ArrayList<String> classTime = new ArrayList<>(); |
| | | String[] split4 = classStartTime.split(","); |
| | | String[] split3 = classEndTime.split(","); |
| | | for (int i = 0; i < split4.length; i++) { |
| | | String s = split4[i] + "-" + split3[i]; |
| | | classTime.add(s); |
| | | } |
| | | coursePackageInfo.setTimes(classTime); |
| | | coursePackageInfo.setType(coursePackage.getType()); |
| | | |
| | | coursePackageInfo.setDetailDrawing(coursePackage.getDetailDrawing()); |
| | | coursePackageInfo.setIntroduceDrawing(coursePackage.getIntroduceDrawing()); |
| | | List<CoursePackagePaymentConfigVo> list = new ArrayList<>(); |
| | |
| | | } |
| | | return playPaiCoinPaymentCourse(appUser, price, paymentCourseVo); |
| | | } |
| | | |
| | | |
| | | return ResultUtil.success(); |
| | | } |
| | | |
| | |
| | | coursePackagePaymentService.save(coursePackagePayment); |
| | | } |
| | | |
| | | Student student = studentClient.queryDefaultStudent(uid); |
| | | Integer sid=null; |
| | | if(student!=null){ |
| | | sid=student.getId(); |
| | | } |
| | | ResultUtil weixinpay = payMoneyUtil.weixinpay("购买课程", "", code, paymentPrice.toString(), "/base/course/weChatPaymentCourseCallback", "APP", ""); |
| | | if(weixinpay.getCode() == 200){ |
| | | Integer finalSid = sid; |
| | | new Thread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | |
| | | coursePackagePayment.setOrderNumber(transaction_id); |
| | | } |
| | | coursePackagePaymentService.updateBatchById(list); |
| | | // 2.0 |
| | | userCouponClient.sendUserCoupon(new SendCouponReq(uid,coursePackagePaymentConfig.getCouponIds())); |
| | | |
| | | addPackageStudent(paymentCourseVo.getId(),uid, finalSid,one.getId()); |
| | | break; |
| | | } |
| | | if("USERPAYING".equals(s)){ |
| | |
| | | coursePackagePaymentService.save(coursePackagePayment); |
| | | } |
| | | |
| | | Student student = studentClient.queryDefaultStudent(uid); |
| | | Integer sid=null; |
| | | if(student!=null){ |
| | | sid=student.getId(); |
| | | } |
| | | |
| | | ResultUtil alipay = payMoneyUtil.alipay("购买课程", "购买课程", "", code, paymentPrice.toString(), "/base/course/aliPaymentCourseCallback"); |
| | | if(alipay.getCode() == 200){ |
| | | Integer finalSid = sid; |
| | | new Thread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | |
| | | coursePackagePayment.setOrderNumber(tradeNo); |
| | | } |
| | | coursePackagePaymentService.updateBatchById(list); |
| | | |
| | | // 2.0 |
| | | userCouponClient.sendUserCoupon(new SendCouponReq(uid,coursePackagePaymentConfig.getCouponIds())); |
| | | |
| | | |
| | | |
| | | if(student!=null){ |
| | | |
| | | } |
| | | addPackageStudent(paymentCourseVo.getId(),uid, finalSid,one.getId()); |
| | | break; |
| | | } |
| | | if("WAIT_BUYER_PAY".equals(s)){ |
| | |
| | | coursePackagePayment.setState(1); |
| | | coursePackagePayment.setInsertTime(new Date()); |
| | | coursePackagePaymentService.save(coursePackagePayment); |
| | | Integer sId=null; |
| | | Student student = studentClient.queryDefaultStudent(appUser.getId()); |
| | | if(student!=null){ |
| | | sId=student.getId(); |
| | | } |
| | | addPackageStudent(paymentCourseVo.getId(),appUser.getId(),sId,coursePackagePayment.getId()); |
| | | } |
| | | |
| | | Integer playPaiCoins = appUser.getPlayPaiCoins(); |
| | | appUser.setPlayPaiCoins(playPaiCoins - paymentPrice.intValue()); |
| | | appUserClient.updateAppUser(appUser); |
| | | |
| | | // 2.0 |
| | | String couponIds = coursePackagePaymentConfig.getCouponIds(); |
| | | if(ToolUtil.isNotEmpty(couponIds)){ |
| | | // 赠送优惠券 |
| | | userCouponClient.sendUserCoupon(new SendCouponReq(appUser.getId(),couponIds)); |
| | | } |
| | | return ResultUtil.success(); |
| | | } |
| | | |
| | | |
| | | private void addPackageStudent(Integer courseId, Integer userId, Integer sId,Long paymentId){ |
| | | // 课包 |
| | | TCoursePackage tCoursePackage = this.baseMapper.selectById(courseId); |
| | | |
| | | |
| | | |
| | | String classWeeks = tCoursePackage.getClassWeeks(); |
| | | List<Integer> week = week(classWeeks); |
| | | |
| | | String[] split = tCoursePackage.getClassStartTime().split(","); |
| | | String[] split1 = tCoursePackage.getClassEndTime().split(","); |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); |
| | | SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm"); |
| | | // 本周周几 |
| | | int i = DateUtil.dayOfWeek(new Date())-1; |
| | | for (Integer integer : week) { |
| | | if(integer<i){ |
| | | // 找下一周的时间 |
| | | Calendar instance = Calendar.getInstance(); |
| | | instance.add(Calendar.DATE,7-(i-integer)); |
| | | Date time = instance.getTime(); |
| | | |
| | | for (int i1 = 0; i1 < split.length; i1++) { |
| | | |
| | | CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); |
| | | coursePackageScheduling.setCourseId(tCoursePackage.getId()); |
| | | try { |
| | | Date parse = format1.parse(format.format(time) + " " + split[i1]); |
| | | Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); |
| | | coursePackageScheduling.setClassDate(parse); |
| | | coursePackageScheduling.setEndDate(parse1); |
| | | coursePackageScheduling.setStatus(1); |
| | | coursePackageSchedulingService.save(coursePackageScheduling); |
| | | |
| | | CoursePackageStudent student1 = new CoursePackageStudent(); |
| | | student1.setAppUserId(userId); |
| | | student1.setStudentId(sId); |
| | | student1.setCoursePackageId(tCoursePackage.getId()); |
| | | student1.setCoursePackagePaymentId(paymentId); |
| | | student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); |
| | | student1.setSignInOrNot(0); |
| | | student1.setReservationStatus(1); |
| | | student1.setInsertTime(new Date()); |
| | | cpsMapper.insert(student1); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | }else if(integer>i) { |
| | | Calendar instance = Calendar.getInstance(); |
| | | instance.add(Calendar.DATE,integer-i); |
| | | Date time = instance.getTime(); |
| | | |
| | | for (int i1 = 0; i1 < split.length; i1++) { |
| | | CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); |
| | | coursePackageScheduling.setCourseId(tCoursePackage.getId()); |
| | | try { |
| | | Date parse = format1.parse(format.format(time) + " " + split[i1]); |
| | | Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); |
| | | coursePackageScheduling.setClassDate(parse); |
| | | coursePackageScheduling.setEndDate(parse1); |
| | | coursePackageScheduling.setStatus(1); |
| | | coursePackageSchedulingService.save(coursePackageScheduling); |
| | | |
| | | CoursePackageStudent student1 = new CoursePackageStudent(); |
| | | student1.setAppUserId(userId); |
| | | student1.setStudentId(sId); |
| | | student1.setCoursePackageId(tCoursePackage.getId()); |
| | | student1.setCoursePackagePaymentId(paymentId); |
| | | student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); |
| | | student1.setSignInOrNot(0); |
| | | student1.setReservationStatus(1); |
| | | student1.setInsertTime(new Date()); |
| | | cpsMapper.insert(student1); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }else { |
| | | Calendar instance = Calendar.getInstance(); |
| | | instance.add(Calendar.DATE,7); |
| | | Date time = instance.getTime(); |
| | | |
| | | for (int i1 = 0; i1 < split.length; i1++) { |
| | | CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); |
| | | coursePackageScheduling.setCourseId(tCoursePackage.getId()); |
| | | try { |
| | | Date parse = format1.parse(format.format(time) + " " + split[i1]); |
| | | Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); |
| | | coursePackageScheduling.setClassDate(parse); |
| | | coursePackageScheduling.setEndDate(parse1); |
| | | coursePackageScheduling.setStatus(1); |
| | | coursePackageSchedulingService.save(coursePackageScheduling); |
| | | |
| | | CoursePackageStudent student1 = new CoursePackageStudent(); |
| | | student1.setAppUserId(userId); |
| | | student1.setStudentId(sId); |
| | | student1.setCoursePackageId(tCoursePackage.getId()); |
| | | student1.setCoursePackagePaymentId(paymentId); |
| | | student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); |
| | | student1.setSignInOrNot(0); |
| | | student1.setReservationStatus(1); |
| | | student1.setInsertTime(new Date()); |
| | | cpsMapper.insert(student1); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 2.0 |
| | | TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); |
| | | tCourseInfoRecord.setUserId(userId); |
| | | tCourseInfoRecord.setCourseId(courseId); |
| | | tCourseInfoRecord.setName("报名假期班"); |
| | | tCourseInfoRecord.setNum(tCoursePackage.getNeedNum()); |
| | | tCourseInfoRecord.setTime(new Date()); |
| | | tCourseInfoRecord.setType(2); |
| | | appUserClient.addCourseInfoRecord(tCourseInfoRecord); |
| | | |
| | | |
| | | } |
| | | private List<Integer> week(String week){ |
| | | String[] split = week.split(";"); |
| | | ArrayList<Integer> integers = new ArrayList<>(); |
| | | for (String s : split) { |
| | | switch (s){ |
| | | case "周一": |
| | | integers.add(1); |
| | | break; |
| | | case "周二": |
| | | integers.add(2); |
| | | break; |
| | | case "周三": |
| | | integers.add(3); |
| | | break; |
| | | case "周四": |
| | | integers.add(4); |
| | | break; |
| | | case "周五": |
| | | integers.add(5); |
| | | break; |
| | | case "周六": |
| | | integers.add(6); |
| | | break; |
| | | case "周日": |
| | | integers.add(7); |
| | | break; |
| | | } |
| | | } |
| | | return integers; |
| | | } |
| | | |
| | | |
| | |
| | | public String getHours(Integer coursePackageId) { |
| | | return this.baseMapper.getHours(coursePackageId); |
| | | } |
| | | |
| | | @Override |
| | | public ResultUtil paymentCourseCouponList(Integer uid, Integer coursePackagePaymentConfigId) { |
| | | CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getById(coursePackagePaymentConfigId); |
| | | if(ToolUtil.isEmpty(coursePackagePaymentConfig.getCouponIds())){ |
| | | coursePackagePaymentConfig.setCouponIds("-1"); |
| | | } |
| | | List<Coupon> coupons = couponClient.getCoupons(coursePackagePaymentConfig.getCouponIds()); |
| | | return ResultUtil.success(coupons); |
| | | } |
| | | } |
| | |
| | | package com.dsh.course.util; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.dsh.course.entity.CoursePackageScheduling; |
| | | import com.dsh.course.entity.CoursePackageStudent; |
| | | import com.dsh.course.entity.TCoursePackagePayment; |
| | | import com.dsh.course.service.CoursePackageStudentService; |
| | | import com.dsh.course.service.ICoursePackageSchedulingService; |
| | | import com.dsh.course.service.TCoursePackagePaymentService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.LinkedMultiValueMap; |
| | | import org.springframework.util.MultiValueMap; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | |
| | | @Autowired |
| | | private ICoursePackageSchedulingService coursePackageSchedulingService; |
| | | |
| | | @Autowired |
| | | private CoursePackageStudentService coursePackageStudentService; |
| | | |
| | | |
| | | @Autowired |
| | | private RestTemplate internalRestTemplate; |
| | | |
| | | /** |
| | | * 每隔一分钟去处理的定时任务 |
| | | */ |
| | |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | /** |
| | | * 每隔一分钟去处理的定时任务 预约课时 |
| | | */ |
| | | @Scheduled(cron = "0 0 18 * * ?") |
| | | public void pushOne(){ |
| | | try { |
| | | Calendar instance = Calendar.getInstance(); |
| | | instance.add(Calendar.DATE,1); |
| | | Date time = instance.getTime(); |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); |
| | | String format1 = format.format(time); |
| | | // 获取明天排课 |
| | | List<CoursePackageScheduling> list = coursePackageSchedulingService.list(new LambdaQueryWrapper<CoursePackageScheduling>().like(CoursePackageScheduling::getClassDate, format1)); |
| | | for (CoursePackageScheduling coursePackageScheduling : list) { |
| | | CoursePackageStudent one = coursePackageStudentService.getOne(new LambdaQueryWrapper<CoursePackageStudent>().eq(CoursePackageStudent::getCoursePackageSchedulingId, coursePackageScheduling.getId())); |
| | | if(one!=null && one.getReservationStatus()==1){ |
| | | Integer appUserId = one.getAppUserId(); |
| | | |
| | | //调用推送 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | // 以表单的方式提交 |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | String s1 = appUserId + "_" + "Class"; |
| | | //定时修改排课状态 |
| | | String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); |
| | | JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); |
| | | if(jsonObject1.getIntValue("code") != 200){ |
| | | System.err.println(jsonObject1.getString("msg")); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | <dependencies> |
| | | |
| | | |
| | | |
| | | <dependency> |
| | | <groupId>io.netty</groupId> |
| | | <artifactId>netty-all</artifactId> |
| | | <version>4.1.27.Final</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.mb.cloud</groupId> |
| | | <artifactId>mb-cloud-common-gateway</artifactId> |
New file |
| | |
| | | package cn.mb.cloud.gateway.controller; |
| | | |
| | | |
| | | import cn.mb.cloud.gateway.auth.ResultUtil; |
| | | import cn.mb.cloud.gateway.util.applets.NettyWebSocketController; |
| | | import cn.mb.cloud.gateway.util.echo.NettyChannelMap; |
| | | import cn.mb.cloud.gateway.util.echo.NettyServerController; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | @RestController |
| | | @RequestMapping("/netty") |
| | | public class NettyController { |
| | | |
| | | |
| | | /** 3.4.5.6 |
| | | * 向客户端推送消息 |
| | | * @param id |
| | | * @param msg |
| | | */ |
| | | @ResponseBody |
| | | @GetMapping("/sendMsgToClient") |
| | | public String sendMsgToClient(String id, Integer type, String msg){ |
| | | System.out.println(id+"|"+type+"|"+msg+"!!!!!!!!"); |
| | | if(true){//用户端 |
| | | String[] split = id.split("_"); |
| | | ChannelHandlerContext channel = NettyChannelMap.getData("USER" + split[0]); |
| | | if(null != channel){ |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("code", 200); |
| | | jsonObject.put("msg", "SUCCESS"); |
| | | jsonObject.put("method", "CLASS"); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | jsonObject.put("data", map); |
| | | NettyServerController.sendMsgToClient(channel, jsonObject.toJSONString()); |
| | | return JSON.toJSONString(ResultUtil.success()); |
| | | } |
| | | return JSON.toJSONString(ResultUtil.error("推送失败-----用户id=" + id)); |
| | | |
| | | } |
| | | return JSON.toJSONString(ResultUtil.error("推送失败")); |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.text.DecimalFormat; |
| | | import java.text.NumberFormat; |
| | | import java.util.*; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * 基本数据处理工具类 |
| | | */ |
| | | public class SinataUtil { |
| | | /** |
| | | * List集合分页<br/> |
| | | * 创建人:Mryang<br/> |
| | | * 时间:2016年7月28日-下午2:58:14 <br/> |
| | | * @param <T> |
| | | * @param pageNo |
| | | * @param pageSize |
| | | * @param list |
| | | * @throws Exception List<UserOrderList> <br/> |
| | | */ |
| | | public static <T> List<T> listpage(int pageNo, int pageSize, List<T> list) throws Exception { |
| | | List<T> result = new ArrayList<T>(); |
| | | if (list != null && list.size() > 0) { |
| | | int allCount = list.size(); |
| | | if(pageNo > 1 && allCount < pageSize) { |
| | | return new ArrayList<>(); |
| | | } |
| | | int pageCount = (allCount + pageSize - 1) / pageSize; |
| | | if (pageNo >= pageCount) { |
| | | pageNo = pageCount; |
| | | } |
| | | int start = (pageNo - 1) * pageSize; |
| | | int end = pageNo * pageSize; |
| | | if (end >= allCount) { |
| | | end = allCount; |
| | | } |
| | | for (int i = start; i < end; i++) { |
| | | result.add(list.get(i)); |
| | | } |
| | | } |
| | | return (result != null && result.size() > 0) ? result : new ArrayList<T>(); |
| | | } |
| | | |
| | | /** |
| | | * Double类型取整 |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String doubleTrans(double num) { |
| | | return String.valueOf((long) num); |
| | | } |
| | | |
| | | /** |
| | | * Double类型保留1位小数 |
| | | * |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String doubleRetainOne(double num) { |
| | | DecimalFormat dfs = new DecimalFormat("0.0"); |
| | | return dfs.format(num); |
| | | } |
| | | |
| | | /** |
| | | * Double类型保留2位小数 |
| | | * |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String doubleRetainTwo(double num) { |
| | | DecimalFormat dfs = new DecimalFormat("0.00"); |
| | | String.format("%.2f", num); |
| | | return dfs.format(num); |
| | | } |
| | | |
| | | /** |
| | | * Double类型保留1位小数(四舍五入) |
| | | * |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String doubleForwardOne(double num) { |
| | | return String.format("%.1f", num); |
| | | } |
| | | |
| | | /** |
| | | * Double类型保留2位小数(四舍五入) |
| | | * |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String doubleForwardTwo(double num) { |
| | | return String.format("%.2f", num); |
| | | } |
| | | |
| | | /** |
| | | * 字符串转换成Ascii |
| | | * |
| | | * @param value |
| | | * @return |
| | | */ |
| | | public static String stringToAscii(String value) { |
| | | StringBuffer sbu = new StringBuffer(); |
| | | char[] chars = value.toCharArray(); |
| | | for (int i = 0; i < chars.length; i++) { |
| | | if (i != chars.length - 1) { |
| | | sbu.append((int) chars[i]); |
| | | } else { |
| | | sbu.append((int) chars[i]); |
| | | } |
| | | } |
| | | return sbu.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 小数转换为百分比 |
| | | * |
| | | * @param decimal |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String decTurnPercent(double decimal) { |
| | | NumberFormat num = NumberFormat.getPercentInstance(); |
| | | num.setMaximumIntegerDigits(3); |
| | | num.setMaximumFractionDigits(2); |
| | | return num.format(decimal); |
| | | } |
| | | |
| | | /** |
| | | * Ascii转换成字符串 |
| | | * |
| | | * @param value |
| | | * @return |
| | | */ |
| | | public static String asciiToString(String value) { |
| | | String[] chars = value.split(","); |
| | | StringBuffer sbu = new StringBuffer(); |
| | | for (int i = 0; i < chars.length; i++) { |
| | | sbu.append((char) Integer.parseInt(chars[i])); |
| | | } |
| | | return sbu.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 字符串转换unicode |
| | | * |
| | | * @param string |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String string2Unicode(String string) { |
| | | StringBuffer unicode = new StringBuffer(); |
| | | for (int i = 0; i < string.length(); i++) { |
| | | // 取出每一个字符 |
| | | char c = string.charAt(i); |
| | | // 转换为unicode |
| | | unicode.append("\\u" + Integer.toHexString(c)); |
| | | } |
| | | return unicode.toString(); |
| | | } |
| | | |
| | | /** |
| | | * unicode 转字符串 |
| | | * |
| | | * @param unicode |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String unicode2String(String unicode) { |
| | | StringBuffer string = new StringBuffer(); |
| | | String[] hex = unicode.split("\\\\u"); |
| | | for (int i = 1; i < hex.length; i++) { |
| | | // 转换出每一个代码点 |
| | | int data = Integer.parseInt(hex[i], 16); |
| | | // 追加成string |
| | | string.append((char) data); |
| | | } |
| | | return string.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 字符串编码转换的实现方法 |
| | | * |
| | | * @param str |
| | | * 待转换编码的字符串 |
| | | * @param newCharset |
| | | * 目标编码 |
| | | * @return |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | public static String changeCharset(String str, String newCharset) throws UnsupportedEncodingException { |
| | | if (str != null) { |
| | | // 用默认字符编码解码字符串。 |
| | | byte[] bs = str.getBytes(); |
| | | // 用新的字符编码生成字符串 |
| | | return new String(bs, newCharset); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 注: \n 回车( ) \t 水平制表符( ) \s 空格(\u0008) \r 换行( ) |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String replaceBlank(String str) { |
| | | String dest = ""; |
| | | if (str != null) { |
| | | Pattern p = Pattern.compile("\\s*|\t|\r|\n"); |
| | | Matcher m = p.matcher(str); |
| | | dest = m.replaceAll(""); |
| | | } |
| | | return dest; |
| | | } |
| | | |
| | | /** |
| | | * 判断该字符串不能为空 |
| | | * |
| | | * @param str |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static boolean isNotEmpty(Object str) { |
| | | return !isEmpty(str); |
| | | } |
| | | |
| | | |
| | | public static boolean isNotEmptyUndefined(Object str) { |
| | | return !isEmpty(str) && !str.toString().equals("undefined"); |
| | | } |
| | | |
| | | /** |
| | | * 字符串编码转换的实现方法 |
| | | * |
| | | * @param str |
| | | * 待转换编码的字符串 |
| | | * @param oldCharset |
| | | * 原编码 |
| | | * @param newCharset |
| | | * 目标编码 |
| | | * @return |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | public static String changeCharset(String str, String oldCharset, String newCharset) throws UnsupportedEncodingException { |
| | | if (str != null) { |
| | | // 用旧的字符编码解码字符串。解码可能会出现异常。 |
| | | byte[] bs = str.getBytes(oldCharset); |
| | | // 用新的字符编码生成字符串 |
| | | return new String(bs, newCharset); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 给手机号码加分割符 |
| | | * |
| | | * @param phone |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String splitPhone(String phone) { |
| | | if (isNotEmpty(phone)) { |
| | | String strone = phone.substring(0, 3); |
| | | String strtwo = phone.substring(strone.length(), 7); |
| | | String strthree = phone.substring(strtwo.length() + strone.length(), phone.length()); |
| | | return strone + "-" + strtwo + "-" + strthree; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 非空判断 |
| | | * |
| | | * @param str |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static boolean isEmpty(Object str) { |
| | | return str == null || str.toString().length() == 0 || str.equals("") || str.toString().matches("\\s*"); |
| | | } |
| | | |
| | | /** |
| | | * 把米转换成公里 |
| | | * |
| | | * @param km |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static Double kmTransKilo(Integer m) { |
| | | return Math.round(m / 100d) / 10d; |
| | | } |
| | | |
| | | /** |
| | | * 将List<{@link Object}>转换成List<{@link T}> |
| | | * |
| | | * @param list |
| | | * 将要转换的对象 |
| | | * @param clazs |
| | | * 需要转换的泛型对象 |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <T> List<T> fromToObject(List<?> list, Class<T> clazs) { |
| | | List<T> t = new ArrayList<T>(); |
| | | for (Object object : list) { |
| | | t.add((T) object); |
| | | } |
| | | return t; |
| | | } |
| | | |
| | | /** |
| | | * 生成 uuid, 即用来标识一笔单,也用做 nonce_str |
| | | * @return |
| | | */ |
| | | public static String generateUUID() { |
| | | return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); |
| | | } |
| | | |
| | | /** |
| | | * 将List<{@link Object}>转换成List<{@link Map<String, Object>}> |
| | | * |
| | | * @param list |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static List<Map<String, Object>> fromToObject_M(List<?> list) { |
| | | List<Map<String, Object>> t = new ArrayList<Map<String, Object>>(); |
| | | for (Object object : list) { |
| | | t.add((Map<String, Object>) object); |
| | | } |
| | | return t; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将对象中的null转换为空 |
| | | * @param obj |
| | | * @return |
| | | * @throws IllegalAccessException |
| | | */ |
| | | |
| | | public static Object checkObjFieldIsNull(Object obj) throws IllegalAccessException { |
| | | if(obj!=null){ |
| | | for(java.lang.reflect.Field f : obj.getClass().getDeclaredFields()){ |
| | | f.setAccessible(true); |
| | | if(f.get(obj) == null){ |
| | | if(f.getType()==String.class){ |
| | | f.set(obj, ""); |
| | | } |
| | | if(f.getType()==Double.class){ |
| | | f.set(obj, 0d); |
| | | } |
| | | if(f.getType()==Integer.class){ |
| | | f.set(obj, 0); |
| | | } |
| | | if(f.getType()==Date.class){ |
| | | f.set(obj, new Date()); |
| | | } |
| | | } |
| | | } |
| | | return obj; |
| | | } |
| | | return obj; |
| | | } |
| | | /** |
| | | * 获取六位标识码 |
| | | * @param length |
| | | * @return |
| | | */ |
| | | public static String createRandomCharData() |
| | | { |
| | | StringBuilder sb=new StringBuilder(); |
| | | Random rand=new Random();//随机用以下三个随机生成器 |
| | | Random randdata=new Random(); |
| | | int data=0; |
| | | for(int i=0;i<6;i++) |
| | | { |
| | | int index=rand.nextInt(3); |
| | | //目的是随机选择生成数字,大小写字母 |
| | | switch(index) |
| | | { |
| | | case 0: |
| | | data=randdata.nextInt(10);//仅仅会生成0~9 |
| | | sb.append(data); |
| | | break; |
| | | case 1: |
| | | data=randdata.nextInt(26)+65;//保证只会产生65~90之间的整数 |
| | | sb.append((char)data); |
| | | break; |
| | | case 2: |
| | | data=randdata.nextInt(26)+97;//保证只会产生97~122之间的整数 |
| | | sb.append((char)data); |
| | | break; |
| | | } |
| | | } |
| | | String result=sb.toString().toLowerCase(); |
| | | return result; |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util; |
| | | |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.context.ApplicationContextAware; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | public class SpringUtil implements ApplicationContextAware { |
| | | @Autowired |
| | | private static ApplicationContext applicationContext; |
| | | |
| | | @Override |
| | | public void setApplicationContext(ApplicationContext applicationContextParam) throws BeansException { |
| | | applicationContext = applicationContextParam; |
| | | } |
| | | public static Object getObject(String id) { |
| | | Object object = null; |
| | | object = applicationContext.getBean(id); |
| | | return object; |
| | | } |
| | | public static <T> T getObject(Class<T> tClass) { |
| | | return applicationContext.getBean(tClass); |
| | | } |
| | | |
| | | public static Object getBean(String tClass) { |
| | | return applicationContext.getBean(tClass); |
| | | } |
| | | |
| | | public <T> T getBean(Class<T> tClass) { |
| | | return applicationContext.getBean(tClass); |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util; |
| | | |
| | | import org.apache.commons.lang.StringUtils; |
| | | |
| | | public class StringUtil { |
| | | |
| | | /** |
| | | * 判断字符串中是否包含表情 |
| | | * @param source |
| | | * @return |
| | | */ |
| | | public static boolean containsEmoji(String source) { |
| | | int len = 0; |
| | | if(null != source){ |
| | | len = source.length(); |
| | | } |
| | | boolean isEmoji = false; |
| | | for (int i = 0; i < len; i++) { |
| | | char hs = source.charAt(i); |
| | | if (0xd800 <= hs && hs <= 0xdbff) { |
| | | if (source.length() > 1) { |
| | | char ls = source.charAt(i + 1); |
| | | int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000; |
| | | if (0x1d000 <= uc && uc <= 0x1f77f) { |
| | | return true; |
| | | } |
| | | } |
| | | } else { |
| | | // non surrogate |
| | | if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) { |
| | | return true; |
| | | } else if (0x2B05 <= hs && hs <= 0x2b07) { |
| | | return true; |
| | | } else if (0x2934 <= hs && hs <= 0x2935) { |
| | | return true; |
| | | } else if (0x3297 <= hs && hs <= 0x3299) { |
| | | return true; |
| | | } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d |
| | | || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c |
| | | || hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) { |
| | | return true; |
| | | } |
| | | if (!isEmoji && source.length() > 1 && i < source.length() - 1) { |
| | | char ls = source.charAt(i + 1); |
| | | if (ls == 0x20e3) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return isEmoji; |
| | | } |
| | | |
| | | /** |
| | | * 判断某个字符是不是表情 |
| | | * @param codePoint |
| | | * @return |
| | | */ |
| | | private static boolean isEmojiCharacter(char codePoint) { |
| | | return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) |
| | | || (codePoint == 0xD) |
| | | || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) |
| | | || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) |
| | | || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 过滤掉字符串中的表情 |
| | | * @param source |
| | | * @return |
| | | */ |
| | | public static String filterEmoji(String source) { |
| | | if (StringUtils.isBlank(source)) { |
| | | return source; |
| | | } |
| | | StringBuilder buf = null; |
| | | int len = source.length(); |
| | | for (int i = 0; i < len; i++) { |
| | | char codePoint = source.charAt(i); |
| | | if (isEmojiCharacter(codePoint)) { |
| | | if (buf == null) { |
| | | buf = new StringBuilder(source.length()); |
| | | } |
| | | buf.append(codePoint); |
| | | } |
| | | } |
| | | if (buf == null) { |
| | | return source; |
| | | } else { |
| | | if (buf.length() == len) { |
| | | buf = null; |
| | | return source; |
| | | } else { |
| | | return buf.toString(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断字符串为空 |
| | | * @param value |
| | | * @return |
| | | */ |
| | | public static boolean isEmpty(String value){ |
| | | if(null == value || value.trim().equals("")){ |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 判断字符串非空 |
| | | * @param value |
| | | * @return |
| | | */ |
| | | public static boolean isNotEmpty(String value){ |
| | | return !isEmpty(value); |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | /** |
| | | * 缓存消息类型 |
| | | * |
| | | * @author TaoNingBo |
| | | * @data 2016年9月21日 |
| | | * @version 1.0 |
| | | */ |
| | | public class CacheType { |
| | | |
| | | /** |
| | | * 用户通讯通道标识 |
| | | */ |
| | | public static final String userCtx = "USER_CTX_"; |
| | | |
| | | /** |
| | | * 司机通讯通道标识 |
| | | */ |
| | | public static final String driverCtx = "DRIVER_CTX_"; |
| | | |
| | | /** |
| | | * 出行-快车/专车/代驾-订单消息队列-自营车辆 |
| | | */ |
| | | public static final String travelOrder1 = "TRAVEL_ORDER1_"; |
| | | |
| | | /** |
| | | * 出行-快车/专车/代驾-订单消息队列-外来车辆 |
| | | */ |
| | | public static final String travelOrder2 = "TRAVEL_ORDER2_"; |
| | | |
| | | /** |
| | | * 快车-司机位置-自营车辆 |
| | | */ |
| | | public static final String location1 = "_LOCATION1"; |
| | | |
| | | /** |
| | | * 快车-司机位置-外来车辆 |
| | | */ |
| | | public static final String location2 = "_LOCATION2"; |
| | | |
| | | /** |
| | | * 快车-司机抢单成功后的消息 |
| | | */ |
| | | public static final String travelOrder = "TRAVEL_ORDER_"; |
| | | |
| | | /** |
| | | * 开始服务时间 |
| | | */ |
| | | public static final String startServerT = "START_SERVER_TIME_"; |
| | | |
| | | /** |
| | | * 司机上一次的位置(经纬度) |
| | | */ |
| | | public static final String location = "LAST_DRIVER_LOCATION_"; |
| | | |
| | | /** |
| | | * 司机上一次总共行驶距离 |
| | | */ |
| | | public static final String triverd = "LAST_TRIVER_Distance_"; |
| | | |
| | | /** |
| | | * 记录订单数据 司机 异常处理 |
| | | */ |
| | | public static final String dreco = "DRIVER_DATA_RECO"; |
| | | |
| | | /** |
| | | * 记录订单数据 用户 异常处理 |
| | | */ |
| | | public static final String ureco = "USER_DATA_RECO"; |
| | | |
| | | /** |
| | | * 记录司机跟用户的关系ID |
| | | */ |
| | | public final static String udID = "USER_DRIVER_ID_"; |
| | | |
| | | /** |
| | | * 记录下单乘客的出发点位置坐标 |
| | | */ |
| | | public final static String userLoc = "USER_LOCATION_"; |
| | | |
| | | /** |
| | | * 记录计费规则【用订单号获取】 |
| | | */ |
| | | public final static String rules = "RULES_ORDER_"; |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import io.netty.channel.ChannelInitializer; |
| | | import io.netty.channel.socket.SocketChannel; |
| | | import io.netty.handler.codec.http.HttpObjectAggregator; |
| | | import io.netty.handler.codec.http.HttpServerCodec; |
| | | import io.netty.handler.ssl.SslHandler; |
| | | import io.netty.handler.stream.ChunkedWriteHandler; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.SSLEngine; |
| | | |
| | | public class ChildChannelHandler extends ChannelInitializer<SocketChannel> { |
| | | @Override |
| | | protected void initChannel(SocketChannel socketChannel) throws Exception { |
| | | String path = "D:\\Program Files\\Apache Software Foundation\\Tomcat 8.5-80\\cert\\6855055_zhentonggongsi.com.pfx"; |
| | | // String path = "/usr/local/server/apache-tomcat-80/conf/cert/6064978_okyueche.com.pfx"; |
| | | SSLContext sslContext = createSSLContext.createSSLContext("PKCS12" |
| | | , path, "jBOjj2fR"); |
| | | //SSLEngine 此类允许使用ssl安全套接层协议进行安全通信 |
| | | SSLEngine engine = sslContext.createSSLEngine(); |
| | | engine.setUseClientMode(false); |
| | | socketChannel.pipeline().addLast("ssl", new SslHandler(engine)); |
| | | |
| | | // 设置30秒没有读到数据,则触发一个READER_IDLE事件。 |
| | | // pipeline.addLast(new IdleStateHandler(30, 0, 0)); |
| | | // HttpServerCodec:将请求和应答消息解码为HTTP消息 |
| | | socketChannel.pipeline().addLast("http-codec", new HttpServerCodec()); |
| | | // HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息 |
| | | socketChannel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536)); |
| | | // ChunkedWriteHandler:向客户端发送HTML5文件 |
| | | socketChannel.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); |
| | | // 在管道中添加我们自己的接收数据实现方法 |
| | | socketChannel.pipeline().addLast("handler", new WebSocketHandler()); |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * 客户端心跳消息处理 |
| | | * |
| | | * @author TaoNingBo |
| | | * @data 2016年7月26日 |
| | | * @version 1.0 |
| | | */ |
| | | public class ClientPingMessage implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -4953410803742767757L; |
| | | |
| | | /** |
| | | * 客户端标识ID |
| | | */ |
| | | private Integer id; |
| | | |
| | | /** |
| | | * 角色【0:用户,1:司机】 |
| | | */ |
| | | private Integer role; |
| | | |
| | | /** |
| | | * 客户端单点登录标识TOKEN |
| | | */ |
| | | private String token; |
| | | |
| | | public ClientPingMessage() { |
| | | |
| | | } |
| | | |
| | | public Integer getId() { |
| | | return id; |
| | | } |
| | | |
| | | public void setId(Integer id) { |
| | | this.id = id; |
| | | } |
| | | |
| | | public Integer getRole() { |
| | | return role; |
| | | } |
| | | |
| | | public void setRole(Integer role) { |
| | | this.role = role != null ? role : 0; |
| | | } |
| | | |
| | | public String getToken() { |
| | | return token; |
| | | } |
| | | |
| | | public void setToken(String token) { |
| | | this.token = token; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import io.netty.channel.group.ChannelGroup; |
| | | import io.netty.channel.group.DefaultChannelGroup; |
| | | import io.netty.util.concurrent.GlobalEventExecutor; |
| | | |
| | | public class Global { |
| | | public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import io.netty.bootstrap.ServerBootstrap; |
| | | import io.netty.channel.Channel; |
| | | import io.netty.channel.EventLoopGroup; |
| | | import io.netty.channel.nio.NioEventLoopGroup; |
| | | import io.netty.channel.socket.nio.NioServerSocketChannel; |
| | | |
| | | import java.util.Timer; |
| | | import java.util.TimerTask; |
| | | |
| | | |
| | | /** |
| | | * 即时通讯服务启动类 |
| | | * |
| | | * @date 2016年6月25日 |
| | | * @version 1.0 |
| | | */ |
| | | public class NettyServer0 { |
| | | |
| | | /** |
| | | * 延迟启动设置 |
| | | * |
| | | * NettyServer启动方法. |
| | | */ |
| | | public void bind() { |
| | | final Thread thread = new Thread(new NettyRunnable()); |
| | | Timer timer = new Timer(); |
| | | timer.schedule(new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | thread.start(); |
| | | } |
| | | }, 1000 * 2); |
| | | } |
| | | |
| | | /** |
| | | * 即时通讯服务启动 |
| | | * |
| | | * @date 2016年6月24日 |
| | | * @version 1.0 |
| | | */ |
| | | public class NettyRunnable implements Runnable { |
| | | |
| | | /** |
| | | * 获取即时通讯启动端口 |
| | | */ |
| | | @Override |
| | | public void run() { |
| | | System.out.println("===========================Netty端口启动========"); |
| | | // Boss线程:由这个线程池提供的线程是boss种类的,用于创建、连接、绑定socket, |
| | | // (有点像门卫)然后把这些socket传给worker线程池。 |
| | | // 在服务器端每个监听的socket都有一个boss线程来处理。在客户端,只有一个boss线程来处理所有的socket。 |
| | | EventLoopGroup bossGroup = new NioEventLoopGroup(); |
| | | // Worker线程:Worker线程执行所有的异步I/O,即处理操作 |
| | | EventLoopGroup workrGroup = new NioEventLoopGroup(); |
| | | try { |
| | | |
| | | // ServerBootstrap 启动NIO服务的辅助启动类,负责初始话netty服务器,并且开始监听端口的socket请求 |
| | | ServerBootstrap b = new ServerBootstrap(); |
| | | b.group(bossGroup, workrGroup); |
| | | // 设置非阻塞,用它来建立新accept的连接,用于构造serversocketchannel的工厂类 |
| | | b.channel(NioServerSocketChannel.class); |
| | | // ChildChannelHandler 对出入的数据进行的业务操作,其继承ChannelInitializer |
| | | b.childHandler(new ChildChannelHandler()); |
| | | System.out.println("服务端开启等待客户端连接 ... ..."); |
| | | Channel ch = b.bind(9090).sync().channel(); |
| | | ch.closeFuture().sync(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | bossGroup.shutdownGracefully(); |
| | | workrGroup.shutdownGracefully(); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | |
| | | import cn.mb.cloud.gateway.util.RedisUtil; |
| | | import cn.mb.cloud.gateway.util.SinataUtil; |
| | | import cn.mb.cloud.gateway.util.SpringUtil; |
| | | import cn.mb.cloud.gateway.util.StringUtil; |
| | | import cn.mb.cloud.gateway.util.echo.Method; |
| | | import cn.mb.cloud.gateway.util.echo.NettyChannelMap; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import io.netty.buffer.ByteBuf; |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.ChannelFuture; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; |
| | | |
| | | import java.util.Hashtable; |
| | | import java.util.Timer; |
| | | import java.util.TimerTask; |
| | | |
| | | public class NettyWebSocketController { |
| | | |
| | | public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext, String>>(); |
| | | |
| | | private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class); |
| | | |
| | | public static Hashtable<String, String> table; |
| | | |
| | | static { |
| | | if (table == null) { |
| | | table = new Hashtable<>(); |
| | | } |
| | | } |
| | | |
| | | public static boolean isdebug = false; |
| | | public static int i = 0; |
| | | |
| | | |
| | | /** |
| | | * 判断客户端要执行什么操作 |
| | | * |
| | | * @param ctx |
| | | * @param msg |
| | | * @author TaoNingBo |
| | | */ |
| | | public void JudgeOperation(ChannelHandlerContext ctx, String msg) { |
| | | try { |
| | | // 验证即时通讯命令是否正确有效 |
| | | if (SinataUtil.isEmpty(msg)) { |
| | | return; |
| | | } |
| | | String msgStr = msg.toString(); |
| | | if (msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) { |
| | | return; |
| | | } |
| | | if (isdebug) { |
| | | // System.out.println("<<<--receive-->>>111" + msg); |
| | | } |
| | | |
| | | // 获取socket信息,保存相应的socket |
| | | JSONObject jsonMsg = JSONObject.parseObject(msg.toString()); |
| | | int code = jsonMsg.getIntValue("code"); |
| | | String message = jsonMsg.getString("msg"); |
| | | String method = jsonMsg.getString("method"); |
| | | if (code != 200 || !message.equals("SUCCESS")) { |
| | | return; |
| | | } |
| | | JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString()); |
| | | |
| | | if (null != ctx && ctx.channel().isActive()) { |
| | | jsonMsg.put("method", Method.pong); |
| | | sendMsgToClient(ctx, jsonMsg.toJSONString()); |
| | | } |
| | | |
| | | |
| | | // ############################### 心跳 ############################ |
| | | // 心跳 |
| | | if (method.equals(Method.ping)) { |
| | | String token = jsonCon.getString("token"); |
| | | String userId1 = jsonCon.getString("userId"); |
| | | if (StringUtil.isNotEmpty(userId1)) { |
| | | //确保账号在单个设备上登录 |
| | | if (StringUtil.isNotEmpty(token)) { |
| | | NettyChannelMap.update_(token.substring(0, 23), ctx);//存储单点登录的通道 |
| | | String token_ = redisUtil.getValue("USER_Applets_" + userId1);//获取缓存中最新的数据 |
| | | if (StringUtil.isNotEmpty(token_) && !token.equals(token_)) {//不在同一设备上登录,向其他设备发送数据 |
| | | JSONObject msg_ = new JSONObject(); |
| | | msg_.put("code", 200); |
| | | msg_.put("msg", "SUCCESS"); |
| | | msg_.put("method", "OFFLINE"); |
| | | msg_.put("data", new Object()); |
| | | this.sendMsgToClient(ctx, msg_.toJSONString()); |
| | | TimerTask timerTask = new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | NettyChannelMap.remove_(ctx); |
| | | } |
| | | }; |
| | | Timer timer = new Timer(); |
| | | timer.schedule(timerTask, 3000); |
| | | timer.cancel(); |
| | | } |
| | | if (StringUtil.isEmpty(token_)) {//确保登录的时候存储token失败的情况 |
| | | redisUtil.setStrValue("USER_Applets_" + userId1, token); |
| | | } |
| | | } |
| | | |
| | | //存储业务使用的通道 |
| | | if (null != ctx && ctx.channel().isActive()) { |
| | | NettyChannelMap.update("Applets" + userId1, ctx); |
| | | // String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | // ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | } catch (Exception e) { |
| | | if (isdebug) { |
| | | NettyWebSocketController.sendMsgToClient(ctx, "__error__" + msg.toString()); |
| | | } |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 向客户端发送消息 |
| | | * |
| | | * @param ctx |
| | | * @param msg |
| | | * @author TaoNingBo |
| | | */ |
| | | public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) { |
| | | // System.out.println(ctx.channel().isActive()); |
| | | if (ctx != null && ctx.channel().isActive()) { |
| | | ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.channel().writeAndFlush(new TextWebSocketFrame(msg)).sync(); |
| | | if (!sync.isSuccess()) { |
| | | boolean b = true; |
| | | for (int i = 0; i < 10; i++) { |
| | | ctx.wait(3000); |
| | | sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); |
| | | if (sync.isSuccess()) { |
| | | b = false; |
| | | break; |
| | | } |
| | | System.err.println("小程序-》推送不成功,将继续推送" + msg); |
| | | } |
| | | if (b) { |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | System.err.println("小程序-》推送发生异常,记录:" + msg); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | if (isdebug) { |
| | | System.err.println("小程序-》 <<<--send-->>>" + msg); |
| | | } |
| | | } else { |
| | | System.err.println("小程序-》推送失败,长连接不存在"); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | } |
| | | |
| | | // **链接断开 将推送消息记录 |
| | | public static void sendMsgToClient(String cacheType, Integer id, String msg) { |
| | | ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id); |
| | | if (ctx != null) { |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); |
| | | if (!sync.isSuccess()) { |
| | | for (int i = 0; i < 10; i++) { |
| | | sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); |
| | | ; |
| | | if (!sync.isSuccess()) { |
| | | sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); |
| | | ; |
| | | System.err.println("推送不成功,将继续推送" + msg); |
| | | if (i == 9) { |
| | | table.put(cacheType + id, msg); |
| | | ctx.close(); |
| | | System.err.println("推送发生异常,记录:" + msg); |
| | | } |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | table.put(cacheType + id, msg); |
| | | System.err.println("推送发生异常,记录:" + msg); |
| | | } |
| | | if (isdebug) { |
| | | System.err.println("<<<--send-->>>" + msg); |
| | | } |
| | | } else { |
| | | table.put(cacheType + id, msg); |
| | | System.err.println("链接断开,记录:id=" + cacheType + id + ",消息:" + msg); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import cn.mb.cloud.gateway.util.echo.Method; |
| | | import cn.mb.cloud.gateway.util.echo.NettyChannelMap; |
| | | import cn.mb.cloud.gateway.util.echo.NettyMsg; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import io.netty.buffer.ByteBuf; |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.ChannelFuture; |
| | | import io.netty.channel.ChannelFutureListener; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | import io.netty.channel.SimpleChannelInboundHandler; |
| | | import io.netty.handler.codec.http.*; |
| | | import io.netty.handler.codec.http.websocketx.*; |
| | | import io.netty.handler.timeout.IdleState; |
| | | import io.netty.handler.timeout.IdleStateEvent; |
| | | import io.netty.util.CharsetUtil; |
| | | |
| | | import java.util.HashMap; |
| | | |
| | | |
| | | public class WebSocketHandler extends SimpleChannelInboundHandler<Object> { |
| | | //用于websocket握手的处理类 |
| | | private WebSocketServerHandshaker handshaker; |
| | | |
| | | private static final String WEB_SOCKET_URL = "wss://localhost:9090/websocket"; |
| | | |
| | | |
| | | |
| | | // @Override |
| | | // protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { |
| | | // if (msg instanceof FullHttpRequest) { |
| | | // // websocket连接请求 |
| | | // handleHttpRequest(ctx, (FullHttpRequest)msg); |
| | | // } else if (msg instanceof WebSocketFrame) { |
| | | // // websocket业务处理 |
| | | // handleWebSocketRequest(ctx, (WebSocketFrame)msg); |
| | | // } |
| | | // } |
| | | |
| | | @Override |
| | | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { |
| | | ctx.flush(); |
| | | } |
| | | |
| | | /** 心跳 */ |
| | | @Override |
| | | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { |
| | | if (evt instanceof IdleStateEvent) { |
| | | IdleStateEvent event = (IdleStateEvent) evt; |
| | | if (event.state().equals(IdleState.READER_IDLE)) |
| | | { |
| | | // |
| | | } |
| | | else if (event.state().equals(IdleState.WRITER_IDLE)) |
| | | { |
| | | // |
| | | } |
| | | else if (event.state().equals(IdleState.ALL_IDLE)) |
| | | { |
| | | String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | if(ctx != null && ctx.channel().isActive()) { |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes())); |
| | | } |
| | | } |
| | | } |
| | | // super.userEventTriggered(ctx, evt); |
| | | } |
| | | |
| | | @Override |
| | | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { |
| | | ctx.close(); |
| | | } |
| | | |
| | | private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { |
| | | // Http解码失败,向服务器指定传输的协议为Upgrade:websocket |
| | | if(!req.getDecoderResult().isSuccess() || !("websocket").equals(req.headers().get("Upgrade"))){ |
| | | sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); |
| | | return; |
| | | } |
| | | // 握手相应处理,创建websocket握手的工厂类, |
| | | WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(WEB_SOCKET_URL, null, false); |
| | | // 根据工厂类和HTTP请求创建握手类 |
| | | handshaker = wsFactory.newHandshaker(req); |
| | | if (handshaker == null) { |
| | | // 不支持websocket |
| | | WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); |
| | | } else { |
| | | // 通过它构造握手响应消息返回给客户端 |
| | | handshaker.handshake(ctx.channel(), req); |
| | | } |
| | | } |
| | | |
| | | private void handleWebSocketRequest(ChannelHandlerContext ctx, WebSocketFrame req) throws Exception { |
| | | if (req instanceof CloseWebSocketFrame) { |
| | | // 关闭websocket连接 |
| | | handshaker.close(ctx.channel(), (CloseWebSocketFrame)req.retain()); |
| | | return; |
| | | } |
| | | if (req instanceof PingWebSocketFrame) { |
| | | ctx.channel().write(new PongWebSocketFrame(req.content().retain())); |
| | | return; |
| | | } |
| | | if (!(req instanceof TextWebSocketFrame)) { |
| | | throw new UnsupportedOperationException("当前只支持文本消息,不支持二进制消息"); |
| | | } |
| | | if (ctx == null || this.handshaker == null || ctx.isRemoved()) { |
| | | throw new Exception("尚未握手成功,无法向客户端发送WebSocket消息"); |
| | | } |
| | | String requestmsg = ((TextWebSocketFrame) req).text(); |
| | | |
| | | |
| | | //给连接的客户端返回数据 |
| | | //返回心跳 |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("code", 200); |
| | | jsonObject.put("method", Method.ok); |
| | | jsonObject.put("msg", "SUCCESS"); |
| | | jsonObject.put("data", new JSONObject()); |
| | | TextWebSocketFrame tws = new TextWebSocketFrame(jsonObject.toJSONString()); |
| | | // ctx.channel().writeAndFlush(tws); |
| | | |
| | | new NettyWebSocketController().JudgeOperation(ctx,requestmsg);//小程序心跳处理 |
| | | |
| | | // 群发服务端心跳响应 |
| | | Global.group.writeAndFlush(new TextWebSocketFrame((tws).text())); |
| | | } |
| | | |
| | | private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) { |
| | | // BAD_REQUEST(400) 客户端请求错误返回的应答消息 |
| | | if(res.getStatus().code() != 200){ |
| | | ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8); |
| | | res.content().writeBytes(buf); |
| | | buf.release(); |
| | | } |
| | | //服务端向客户端发送数据 |
| | | ChannelFuture f = ctx.channel().writeAndFlush(res); |
| | | // 非法连接直接关闭连接 |
| | | if(res.getStatus().code() != 200){ |
| | | f.addListener(ChannelFutureListener.CLOSE); |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void channelActive(ChannelHandlerContext ctx) throws Exception { |
| | | Global.group.add(ctx.channel()); |
| | | System.err.println("客户端与服务器端开启"); |
| | | } |
| | | |
| | | @Override |
| | | public void channelInactive(ChannelHandlerContext ctx) throws Exception { |
| | | Global.group.remove(ctx.channel()); |
| | | NettyChannelMap.remove(ctx); |
| | | System.err.println("客户端与服务器链接关闭"); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { |
| | | if (msg instanceof FullHttpRequest) { |
| | | // websocket连接请求 |
| | | handleHttpRequest(ctx, (FullHttpRequest)msg); |
| | | } else if (msg instanceof WebSocketFrame) { |
| | | // websocket业务处理 |
| | | handleWebSocketRequest(ctx, (WebSocketFrame)msg); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { |
| | | if (msg instanceof FullHttpRequest) { |
| | | // websocket连接请求 |
| | | handleHttpRequest(ctx, (FullHttpRequest)msg); |
| | | } else if (msg instanceof WebSocketFrame) { |
| | | // websocket业务处理 |
| | | handleWebSocketRequest(ctx, (WebSocketFrame)msg); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.applets; |
| | | |
| | | import javax.net.ssl.KeyManagerFactory; |
| | | import javax.net.ssl.SSLContext; |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.security.KeyStore; |
| | | |
| | | public class createSSLContext { |
| | | |
| | | /** |
| | | * 获取SSLContext |
| | | * @param type |
| | | * @param path |
| | | * @param password |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public static SSLContext createSSLContext(String type , String path , String password) throws Exception { |
| | | KeyStore ks = KeyStore.getInstance(type); /// "JKS" |
| | | InputStream ksInputStream = new FileInputStream(path); /// 证书存放地址 |
| | | ks.load(ksInputStream, password.toCharArray()); |
| | | //KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。 |
| | | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。 |
| | | kmf.init(ks, password.toCharArray()); |
| | | //SSLContext的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。 |
| | | SSLContext sslContext = SSLContext.getInstance("TLS"); |
| | | sslContext.init(kmf.getKeyManagers(), null, null); |
| | | return sslContext; |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | import io.netty.channel.ChannelPromise; |
| | | import io.netty.channel.SimpleChannelInboundHandler; |
| | | import io.netty.handler.timeout.IdleState; |
| | | import io.netty.handler.timeout.IdleStateEvent; |
| | | import io.netty.util.ReferenceCountUtil; |
| | | |
| | | import java.net.InetSocketAddress; |
| | | import java.util.HashMap; |
| | | |
| | | public class DiscardServerHandler extends SimpleChannelInboundHandler<String> { |
| | | |
| | | private NettyServerController nettyServerController = new NettyServerController(); |
| | | |
| | | public static boolean isdebug = true; |
| | | |
| | | @Override |
| | | public void channelRead(ChannelHandlerContext ctx, Object msg) { |
| | | InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | if(isdebug) { |
| | | // System.err.println(insocket.getAddress() + ": 收到客户端数据......."); |
| | | } |
| | | try { |
| | | // 调用service |
| | | nettyServerController.JudgeOperation(ctx, msg); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | ReferenceCountUtil.release(msg); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { |
| | | InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | if(isdebug) { |
| | | // System.err.println(insocket.getAddress() + ": 收到客户端数据......."); |
| | | } |
| | | try { |
| | | // 调用service |
| | | nettyServerController.JudgeOperation(ctx, msg); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | ReferenceCountUtil.release(msg); |
| | | } |
| | | } |
| | | |
| | | // @Override |
| | | // protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception { |
| | | // |
| | | // } |
| | | |
| | | // @Override |
| | | // protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception { |
| | | // |
| | | // } |
| | | |
| | | // @Override |
| | | // protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception { |
| | | // |
| | | // } |
| | | |
| | | /** 在连接被建立并且准备进行通信时被调用 */ |
| | | public void channelActive(final ChannelHandlerContext ctx) throws Exception { |
| | | InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | if(isdebug) { |
| | | // System.err.println(insocket.getAddress() + ": Connect successful......"); |
| | | } |
| | | } |
| | | |
| | | /** 心跳 */ |
| | | @Override |
| | | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { |
| | | if (evt instanceof IdleStateEvent) { |
| | | IdleStateEvent event = (IdleStateEvent) evt; |
| | | if (event.state().equals(IdleState.READER_IDLE)) |
| | | { |
| | | // |
| | | } |
| | | else if (event.state().equals(IdleState.WRITER_IDLE)) |
| | | { |
| | | // |
| | | } |
| | | else if (event.state().equals(IdleState.ALL_IDLE)) |
| | | { |
| | | String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | if(ctx != null && ctx.channel().isActive()) { |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes())); |
| | | // System.err.println(msg); |
| | | } |
| | | } |
| | | } |
| | | //super.userEventTriggered(ctx, evt); |
| | | } |
| | | |
| | | /** 连接处于不活跃时调用(连接关闭) **/ |
| | | public void channelInactive(ChannelHandlerContext ctx) throws Exception { |
| | | if(isdebug) { |
| | | InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | // System.err.println(insocket.getAddress() + ": Disconnect connection......"); |
| | | } |
| | | NettyChannelMap.remove(ctx); |
| | | // System.err.println("清除通道" + ctx); |
| | | // super.channelInactive(ctx); |
| | | } |
| | | |
| | | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { |
| | | ctx.flush(); |
| | | } |
| | | |
| | | /** 处理方法是当出现Throwable对象才会被调用 **/ |
| | | public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception { |
| | | ctx.close(); |
| | | } |
| | | |
| | | public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { |
| | | if(isdebug) { |
| | | InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | // System.err.println("close......." + insocket.getAddress()); |
| | | } |
| | | ctx.close(promise); |
| | | } |
| | | |
| | | public void read(ChannelHandlerContext ctx) throws Exception { |
| | | ctx.read(); |
| | | } |
| | | |
| | | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { |
| | | ctx.write(msg, promise); |
| | | } |
| | | |
| | | // @Override |
| | | // protected void channelRead(ChannelHandlerContext ctx, String msg) throws Exception { |
| | | // // TODO Auto-generated method stub |
| | | // InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | // if(isdebug) { |
| | | // System.out.println(insocket.getAddress() + ": 收到客户端数据......."); |
| | | // } |
| | | // try { |
| | | // // 调用service |
| | | // nettyServerController.JudgeOperation(ctx, msg); |
| | | // } catch (Exception e) { |
| | | // e.printStackTrace(); |
| | | // } finally { |
| | | // ReferenceCountUtil.release(msg); |
| | | // } |
| | | // } |
| | | |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | /** |
| | | * 即时通讯【通讯类型类】 |
| | | * |
| | | * @author TaoNingBo |
| | | * @createDate 2016年6月14日 |
| | | * @version 1.0 |
| | | */ |
| | | public class Method { |
| | | |
| | | /** 心跳【推送】 */ |
| | | public static final String ok = "OK"; |
| | | |
| | | /** 心跳【接收】 */ |
| | | public final static String ping = "PING"; |
| | | |
| | | /** 心跳【响应】 */ |
| | | public final static String pong = "PONG"; |
| | | |
| | | /** 司机上传位置 */ |
| | | public static final String location = "LOCATION"; |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | public class NettyChannelMap { |
| | | |
| | | protected static Map<String, ChannelHandlerContext> map = new ConcurrentHashMap<>(); |
| | | |
| | | public static Map<String, ChannelHandlerContext> ctxMap = new HashMap<>();//单点登录存储的通道 |
| | | |
| | | |
| | | private NettyChannelMap() { |
| | | // 放置外部实例化 |
| | | } |
| | | |
| | | /** |
| | | * Get data from source. |
| | | * |
| | | * @param key |
| | | * @return |
| | | */ |
| | | public static ChannelHandlerContext getData(String key) { |
| | | if(map==null){ |
| | | map = new HashMap<String, ChannelHandlerContext>(); |
| | | } |
| | | return map.get(key); |
| | | } |
| | | |
| | | |
| | | public static ChannelHandlerContext getData_(String key) { |
| | | if(ctxMap==null){ |
| | | ctxMap = new HashMap<String, ChannelHandlerContext>(); |
| | | } |
| | | return ctxMap.get(key); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Save data from source. |
| | | * |
| | | * @param key |
| | | * @param val |
| | | */ |
| | | public static synchronized void saveData(String key, ChannelHandlerContext val) { |
| | | map.put(key, val); |
| | | } |
| | | |
| | | /** |
| | | * Determine whether the cache key contains the key. |
| | | * |
| | | * @param key |
| | | * @return true|false |
| | | * @author TaoNingBo |
| | | */ |
| | | public static synchronized boolean containsKey(String key) { |
| | | return map.containsKey(key); |
| | | } |
| | | |
| | | /** |
| | | * Determine whether the cache value contains the value. |
| | | * |
| | | * @param val |
| | | * @return |
| | | */ |
| | | public static synchronized boolean containsVal(ChannelHandlerContext val) { |
| | | return map.containsValue(val); |
| | | } |
| | | |
| | | /** |
| | | * Remove the data resources. |
| | | * |
| | | * @param value |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | public static synchronized void remove(ChannelHandlerContext value) { |
| | | Set<String> strings = map.keySet(); |
| | | for(String key : strings){ |
| | | ChannelHandlerContext channelHandlerContext = map.get(key); |
| | | String s = channelHandlerContext.channel().remoteAddress().toString(); |
| | | String s1 = value.channel().remoteAddress().toString(); |
| | | if(s.equals(s1)){ |
| | | channelHandlerContext.close();//关闭通道 |
| | | map.remove(key); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | public static synchronized void remove_(ChannelHandlerContext value) { |
| | | Set<String> strings = ctxMap.keySet(); |
| | | for(String key : strings){ |
| | | ChannelHandlerContext channelHandlerContext = ctxMap.get(key); |
| | | String s = channelHandlerContext.channel().remoteAddress().toString(); |
| | | String s1 = value.channel().remoteAddress().toString(); |
| | | if(s.equals(s1)){ |
| | | channelHandlerContext.close();//关闭通道 |
| | | ctxMap.remove(key); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Remove the data resources. |
| | | * |
| | | * @param key |
| | | * @author TaoNingBo |
| | | */ |
| | | public static synchronized void remove(String key) { |
| | | map.remove(key); |
| | | } |
| | | |
| | | /** |
| | | * Update the data resources. |
| | | * |
| | | * @param key |
| | | * @param value |
| | | */ |
| | | public static synchronized void update(String key, ChannelHandlerContext value) { |
| | | map.put(key, value); |
| | | } |
| | | |
| | | |
| | | |
| | | public static synchronized void update_(String key, ChannelHandlerContext value) { |
| | | ctxMap.put(key, value); |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import io.netty.buffer.ByteBuf; |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.ChannelFuture; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | |
| | | public class NettyMsg { |
| | | public static void main(String[] args) { |
| | | Map<String,Object> map = new HashMap<String, Object>(); |
| | | //用户信息 |
| | | map.put("imgUrl","1"); |
| | | map.put("nickName","1"); |
| | | map.put("licensePlate","1"); |
| | | map.put("phone",1); |
| | | map.put("driverId",1); |
| | | map.put("carColor","1"); |
| | | map.put("modelName","1"); |
| | | map.put("brandName","1"); |
| | | map.put("driverOrderNums",1); |
| | | map.put("score",1); |
| | | |
| | | |
| | | map.put("id",1); |
| | | map.put("orderNum", "123456"); |
| | | map.put("startAddress", "测试"); |
| | | map.put("endAddress", "测试1"); |
| | | map.put("departureTime", 1533608196000L); |
| | | map.put("type",1); |
| | | map.put("mileage",1); |
| | | map.put("mileageMoney",10); |
| | | map.put("duration",10); |
| | | map.put("durationMoney",10); |
| | | map.put("nightMoney",1); |
| | | map.put("serverMoney",1); |
| | | map.put("nightMileage",10); |
| | | map.put("longMileage",10); |
| | | map.put("longDurationMoney",10); |
| | | map.put("orderMoney",10); |
| | | map.put("payMoney",10); |
| | | map.put("couponsMoney",10); |
| | | System.out.println(setMsg(Method.ping, new HashMap<String, Object>())); |
| | | } |
| | | |
| | | /** |
| | | * 返回一个正确数据 |
| | | * |
| | | * @param method |
| | | * @param data |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String setMsg(String method, Map<String, Object> data) { |
| | | StringBuffer json = new StringBuffer(); |
| | | json.append(getHeader(200, "SUCCESS", method)); |
| | | json.append(JSON.toJSONString(data)); |
| | | json.append("}"); |
| | | //return JSON.toJSONString(json); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 返回一个正确数据 |
| | | * |
| | | * @param method |
| | | * @param data |
| | | * @return |
| | | */ |
| | | public static String setMsg(String method, List<Map<String, Object>> data) { |
| | | StringBuffer json = new StringBuffer(); |
| | | json.append(getHeader(200, "SUCCESS", method)); |
| | | List<JSONObject> jsonList = new ArrayList<JSONObject>(); |
| | | for(Map<String, Object> map : data) { |
| | | JSONObject dataJson = new JSONObject(map); |
| | | jsonList.add(dataJson); |
| | | } |
| | | json.append(jsonList); |
| | | json.append("}"); |
| | | |
| | | // return JSON.toJSONString(json); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 返回一个错误数据 |
| | | * |
| | | * @param method |
| | | * @param data |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | public static String setErrMsg(String method, String data) { |
| | | StringBuffer json = new StringBuffer(); |
| | | json.append(getHeader(-1, "FAILURE", method)); |
| | | json.append("\"" + data + "\""); |
| | | json.append("}"); |
| | | // return JSON.toJSONString(json); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 生成一个返回JSON的头 |
| | | * |
| | | * @param code |
| | | * @param msg |
| | | * @param method |
| | | * @return |
| | | * @author TaoNingBo |
| | | */ |
| | | private static String getHeader(int code, String msg, String method) { |
| | | StringBuffer header = new StringBuffer(); |
| | | header.append("{"); |
| | | header.append("\"code\":\"" + code); |
| | | header.append("\",\"msg\":\"" + msg); |
| | | header.append("\",\"method\":\"" + method); |
| | | header.append("\",\"data\":"); |
| | | return header.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 发送消息给客户端 |
| | | * |
| | | * @param cacheType |
| | | * @param id |
| | | * @param method |
| | | * @param data |
| | | * @author TaoNingBo |
| | | */ |
| | | public static void sendMsg(String cacheType, Integer id, String method, Map<String, Object> data) { |
| | | //NettyServerController.sendMsgToClient(NettyChannelMap.getData(cacheType + id), setMsg(method, data)); |
| | | NettyServerController.sendMsgToClient(cacheType,id, setMsg(method, data)); |
| | | } |
| | | |
| | | |
| | | public static void resendMsg(String token){ |
| | | String msg = NettyServerController.table.get(token); |
| | | ChannelHandlerContext ctx = NettyChannelMap.getData(token); |
| | | if(null != msg && !"".equals(msg) && ctx != null && ctx.channel().isActive()){ |
| | | ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg); |
| | | if(!sync.isSuccess()){ |
| | | resendMsg(token); |
| | | System.err.println("重发异常推送不成功,将继续推送"+msg); |
| | | } |
| | | NettyServerController.table.remove(token); |
| | | } catch (Exception e) { |
| | | resendMsg(token); |
| | | System.err.println("重发推送发生异常,记录:"+msg); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import io.netty.bootstrap.ServerBootstrap; |
| | | import io.netty.channel.ChannelFuture; |
| | | import io.netty.channel.ChannelOption; |
| | | import io.netty.channel.ChannelPipeline; |
| | | import io.netty.channel.EventLoopGroup; |
| | | import io.netty.channel.nio.NioEventLoopGroup; |
| | | import io.netty.channel.socket.SocketChannel; |
| | | import io.netty.channel.socket.nio.NioServerSocketChannel; |
| | | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; |
| | | import io.netty.handler.codec.LengthFieldPrepender; |
| | | import io.netty.handler.timeout.IdleStateHandler; |
| | | |
| | | import java.util.Timer; |
| | | import java.util.TimerTask; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * 即时通讯服务启动类 |
| | | * |
| | | * @date 2016年6月25日 |
| | | * @version 1.0 |
| | | */ |
| | | public class NettyServer { |
| | | |
| | | |
| | | /** |
| | | * NettyServer启动方法. |
| | | */ |
| | | public void bind() { |
| | | final Thread thread = new Thread(new NettyRunnable()); |
| | | Timer timer = new Timer(); |
| | | timer.schedule(new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | thread.start(); |
| | | } |
| | | }, 10000); |
| | | } |
| | | |
| | | /** |
| | | * 即时通讯服务启动 |
| | | * |
| | | * @date 2016年6月24日 |
| | | * @version 1.0 |
| | | */ |
| | | public class NettyRunnable implements Runnable { |
| | | |
| | | /** |
| | | * 获取即时通讯启动端口 |
| | | */ |
| | | private Integer nettyPort = 8888; |
| | | @Override |
| | | public void run() { |
| | | EventLoopGroup bossGroup = new NioEventLoopGroup(); |
| | | EventLoopGroup workerGroup = new NioEventLoopGroup(); |
| | | try { |
| | | ServerBootstrap bootstrap = new ServerBootstrap(); |
| | | bootstrap.group(bossGroup, workerGroup); |
| | | bootstrap.channel(NioServerSocketChannel.class); |
| | | bootstrap.option(ChannelOption.SO_BACKLOG, 1024); |
| | | // 通过TCP_NODELAY禁用NAGLE,使消息立即发出去,不用等待到一定的数据量才发出去 |
| | | bootstrap.option(ChannelOption.TCP_NODELAY, true); |
| | | // 保持长连接状态 |
| | | bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); |
| | | bootstrap.childHandler(new ServerInit() { |
| | | @Override |
| | | protected void initChannel(SocketChannel socketChannel) throws Exception { |
| | | ChannelPipeline pipeline = socketChannel.pipeline(); |
| | | pipeline.addLast("ping", new IdleStateHandler(120, 60, 5, TimeUnit.SECONDS)); |
| | | pipeline.addLast("decoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); |
| | | pipeline.addLast("encoder", new LengthFieldPrepender(4)); |
| | | //pipeline.addLast(new LineBasedFrameDecoder(1048576 * 10)); |
| | | //pipeline.addLast(new StringDecoder(Charset.forName("UTF-8"))); |
| | | //pipeline.addLast(new StringEncoder(Charset.forName("UTF-8"))); |
| | | pipeline.addLast(new DiscardServerHandler()); |
| | | } |
| | | }); |
| | | // 服务器绑定端口监听 |
| | | ChannelFuture f = bootstrap.bind(nettyPort).sync(); |
| | | if(f.isSuccess()) { |
| | | System.out.println("******************************Netty启动成功******************************"); |
| | | } |
| | | // 监听服务器关闭监听 |
| | | f.channel().closeFuture().sync(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | bossGroup.shutdownGracefully(); |
| | | workerGroup.shutdownGracefully(); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import cn.mb.cloud.gateway.util.RedisUtil; |
| | | import cn.mb.cloud.gateway.util.SinataUtil; |
| | | import cn.mb.cloud.gateway.util.SpringUtil; |
| | | import com.alibaba.csp.sentinel.util.StringUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import io.netty.buffer.ByteBuf; |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.ChannelFuture; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.util.LinkedMultiValueMap; |
| | | import org.springframework.util.MultiValueMap; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Hashtable; |
| | | import java.util.Timer; |
| | | import java.util.TimerTask; |
| | | |
| | | |
| | | /** |
| | | * Netty业务逻辑层 |
| | | * @author sinata |
| | | * @createDate 2016年6月3日 |
| | | * @version 1.0 |
| | | */ |
| | | public class NettyServerController { |
| | | |
| | | public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext,String>>(); |
| | | |
| | | public static Hashtable<String,String> table; |
| | | |
| | | private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class); |
| | | |
| | | |
| | | private RestTemplate internalRestTemplate = SpringUtil.getObject(RestTemplate.class); |
| | | |
| | | |
| | | |
| | | |
| | | static{ |
| | | if(table == null){ |
| | | table = new Hashtable<>(); |
| | | } |
| | | } |
| | | |
| | | public static boolean isdebug = false; |
| | | public static int i = 0; |
| | | |
| | | |
| | | /** |
| | | * 判断客户端要执行什么操作 |
| | | * |
| | | * @param ctx |
| | | * @param msg |
| | | * @author TaoNingBo |
| | | */ |
| | | public void JudgeOperation(ChannelHandlerContext ctx, Object msg) { |
| | | try { |
| | | // ByteBuf转String |
| | | ByteBuf byteBuf = (ByteBuf) msg; |
| | | |
| | | byte[] req = new byte[byteBuf.readableBytes()]; |
| | | byteBuf.readBytes(req); |
| | | msg = new String(req, "UTF-8"); |
| | | // 验证即时通讯命令是否正确有效 |
| | | if(SinataUtil.isEmpty(msg)) { |
| | | return; |
| | | } |
| | | String msgStr = msg.toString(); |
| | | if(msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) { |
| | | return; |
| | | } |
| | | if(isdebug) { |
| | | // System.out.println("<<<--receive-->>>" + msg); |
| | | } |
| | | |
| | | // 获取socket信息,保存相应的socket |
| | | JSONObject jsonMsg = JSONObject.parseObject(msg.toString()); |
| | | int code = jsonMsg.getInteger("code"); |
| | | String message = jsonMsg.getString("msg"); |
| | | String method = jsonMsg.getString("method"); |
| | | if(code != 200 || !message.equals("SUCCESS")) { |
| | | return; |
| | | } |
| | | JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString()); |
| | | |
| | | if(null != ctx && ctx.channel().isActive()){ |
| | | jsonMsg.put("method", Method.pong); |
| | | sendMsgToClient(ctx, jsonMsg.toJSONString()); |
| | | } |
| | | |
| | | //心跳 |
| | | if(method.equals(Method.ping)) { |
| | | Integer type = jsonCon.getInteger("type"); |
| | | String token = jsonCon.getString("token"); |
| | | String userId1 = jsonCon.getString("userId"); |
| | | String device = jsonCon.getString("device"); |
| | | String version = jsonCon.getString("version"); |
| | | if(StringUtil.isNotEmpty(userId1)){ |
| | | |
| | | //判断用户或者司机长连接 |
| | | if(type==1){ |
| | | //确保账号在单个设备上登录 |
| | | if(StringUtil.isNotEmpty(token)){ |
| | | String token_ = redisUtil.getValue("USER_APP_"+ userId1);//获取缓存中最新的数据 |
| | | if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向其他设备发送数据 |
| | | JSONObject msg_ = new JSONObject(); |
| | | msg_.put("code", 200); |
| | | msg_.put("msg", "SUCCESS"); |
| | | msg_.put("method", "OFFLINE"); |
| | | msg_.put("data", new Object()); |
| | | this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 |
| | | TimerTask timerTask = new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | NettyChannelMap.remove_(ctx); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | }; |
| | | Timer timer = new Timer(); |
| | | timer.schedule(timerTask, 3000); |
| | | timer.cancel(); |
| | | }else{ |
| | | NettyChannelMap.update_(token.substring(0, 23), ctx); |
| | | NettyChannelMap.update("USER" + userId1, ctx); |
| | | String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); |
| | | } |
| | | if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 |
| | | redisUtil.setStrValue("USER_APP_" + userId1, token); |
| | | } |
| | | } |
| | | |
| | | }else{ |
| | | //添加司机在线 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | // 以表单的方式提交 |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | //将请求头部和参数合成一个请求 |
| | | MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); |
| | | params.add("driverId", userId1); |
| | | params.add("device", (null != device && device.equals("carDevice")) ? "2" : "1"); |
| | | params.add("version", version); |
| | | HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers); |
| | | String w = internalRestTemplate.postForObject("http://driver-server/base/driverOnline/addDriverOnline",requestEntity , String.class); |
| | | JSONObject jsonObject = JSON.parseObject(w, JSONObject.class); |
| | | if(jsonObject.getIntValue("code") != 200){ |
| | | System.err.println("调用driver-server添加司机在线数据出错了"); |
| | | } |
| | | |
| | | //TODO 存储最后一次上传的时间(用于保证车载端断电后1小时自动下班) |
| | | if(StringUtil.isNotEmpty(device) && device.equals("carDevice")){ |
| | | redisUtil.setStrValue("DEVICE_" + userId1, String.valueOf(System.currentTimeMillis())); |
| | | |
| | | String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据 |
| | | if(StringUtil.isNotEmpty(token_) && !token_.equals(token)){ |
| | | //如果是车载端登录,则将其它端都强迫下线 |
| | | JSONObject msg_ = new JSONObject(); |
| | | msg_.put("code", 200); |
| | | msg_.put("msg", "SUCCESS"); |
| | | msg_.put("method", "OFFLINE"); |
| | | msg_.put("data", new Object()); |
| | | this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 |
| | | TimerTask timerTask = new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | NettyChannelMap.remove_(ctx); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | }; |
| | | Timer timer = new Timer(); |
| | | timer.schedule(timerTask, 3000); |
| | | timer.cancel(); |
| | | }else{ |
| | | // System.err.println("开始存储司机通道" + userId1); |
| | | NettyChannelMap.update("DRIVER" + userId1, ctx); |
| | | NettyChannelMap.update_(token.substring(0, 23), ctx); |
| | | String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); |
| | | } |
| | | if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 |
| | | redisUtil.setStrValue("DRIVER_" + userId1, token); |
| | | } |
| | | } |
| | | |
| | | |
| | | //确保账号在单个设备上登录 |
| | | String value = redisUtil.getValue("DEVICE_" + userId1); |
| | | if(StringUtil.isNotEmpty(token) && StringUtil.isEmpty(device) && StringUtil.isEmpty(value)){//APP端登录的操作 |
| | | String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据 |
| | | if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向当前设备发送数据 |
| | | JSONObject msg_ = new JSONObject(); |
| | | msg_.put("code", 200); |
| | | msg_.put("msg", "SUCCESS"); |
| | | msg_.put("method", "OFFLINE"); |
| | | msg_.put("data", new Object()); |
| | | this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 |
| | | TimerTask timerTask = new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | NettyChannelMap.remove_(ctx); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | }; |
| | | Timer timer = new Timer(); |
| | | timer.schedule(timerTask, 3000); |
| | | timer.cancel(); |
| | | }else{ |
| | | // System.err.println("开始存储司机通道" + userId1); |
| | | NettyChannelMap.update("DRIVER" + userId1, ctx); |
| | | NettyChannelMap.update_(token.substring(0, 23), ctx); |
| | | String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); |
| | | } |
| | | if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 |
| | | redisUtil.setStrValue("DRIVER_" + userId1, token); |
| | | } |
| | | } |
| | | |
| | | |
| | | //存储通讯通道 |
| | | if(null != ctx && ctx.channel().isActive()){ |
| | | // System.err.println("开始存储司机通道" + userId1); |
| | | NettyChannelMap.update("DRIVER" + userId1, ctx); |
| | | String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); |
| | | ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | //司机上传位置 |
| | | if(method.equals(Method.location)){ |
| | | Integer driverId = jsonCon.getInteger("driverId"); |
| | | Integer orderId = jsonCon.getInteger("orderId"); |
| | | Integer orderType = jsonCon.getInteger("orderType"); |
| | | Double lon = jsonCon.getDouble("lon"); |
| | | Double lat = jsonCon.getDouble("lat"); |
| | | Double computeAzimuth = jsonCon.getDouble("computeAzimuth"); |
| | | Double altitude = jsonCon.getDouble("altitude"); |
| | | if(SinataUtil.isNotEmpty(driverId)){ |
| | | if(null != lon && 0 != lon && null != lat && 0 != lat){ |
| | | if(null != orderId && 0 != driverId && null != orderType && 0 != orderType){//开始存入数据库 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | // 以表单的方式提交 |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | //将请求头部和参数合成一个请求 |
| | | MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); |
| | | params.add("orderType", String.valueOf(orderType)); |
| | | params.add("orderId", String.valueOf(orderId)); |
| | | params.add("driverId", String.valueOf(driverId)); |
| | | params.add("lon", String.valueOf(lon)); |
| | | params.add("lat", String.valueOf(lat)); |
| | | params.add("directionAngle", String.valueOf(computeAzimuth)); |
| | | params.add("altitude", String.valueOf(altitude)); |
| | | HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers); |
| | | String s = internalRestTemplate.postForObject("http://driver-server/base/savePosition",requestEntity , String.class); |
| | | JSONObject jsonObject = JSON.parseObject(s, JSONObject.class); |
| | | if(jsonObject.getIntValue("code") != 200){ |
| | | System.err.println("调用driver-server存储位置数据出错了"); |
| | | } |
| | | } |
| | | redisUtil.setStrValue("DRIVER" + driverId, lon + "," + lat, 300);//实时位置存入redis中 |
| | | }else{ |
| | | NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); |
| | | } |
| | | }else{ |
| | | NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | if(isdebug) { |
| | | NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); |
| | | } |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 向客户端发送消息 |
| | | * |
| | | * @param ctx |
| | | * @param msg |
| | | * @author TaoNingBo |
| | | */ |
| | | public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) { |
| | | if (ctx != null && ctx.channel().isActive()) { |
| | | ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | if(!sync.isSuccess()){//如果推送失败则继续推送10次 |
| | | boolean b = true; |
| | | for (int i = 0; i < 10; i++) { |
| | | ctx.wait(3000); |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | if(sync.isSuccess()){ |
| | | b = false; |
| | | break; |
| | | } |
| | | System.err.println("推送不成功,将继续推送"+msg); |
| | | } |
| | | if(b){ |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | System.err.println("推送发生异常,记录:"+msg); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | if(isdebug) { |
| | | System.err.println("<<<--send-->>>" + msg) ; |
| | | } |
| | | }else{ |
| | | System.err.println("推送失败,长连接不存在"); |
| | | NettyChannelMap.remove(ctx); |
| | | } |
| | | } |
| | | |
| | | // **链接断开 将推送消息记录 |
| | | public static void sendMsgToClient(String cacheType, Integer id,String msg) { |
| | | ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id); |
| | | if (ctx != null) { |
| | | ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | // System.out.println("推送状态"+sync.isSuccess()); |
| | | if(!sync.isSuccess()){ |
| | | for (int i = 0; i < 10; i++) { |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | if(!sync.isSuccess()){ |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | System.err.println("推送不成功,将继续推送"+msg); |
| | | if(i == 9){ |
| | | table.put(cacheType+id, msg); |
| | | |
| | | ctx.close(); |
| | | System.err.println("推送发生异常,记录:"+msg); |
| | | } |
| | | }else{ |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | table.put(cacheType+id, msg); |
| | | System.err.println("推送发生异常,记录:"+msg); |
| | | } |
| | | if(isdebug) { |
| | | // System.out.println("<<<--send-->>>" + msg); |
| | | } |
| | | }else{ |
| | | table.put(cacheType+id, msg); |
| | | System.err.println("链接断开,记录:id="+cacheType+id+",消息:"+msg); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 记录推送不成功消息,并在心跳连接续推 |
| | | * @param token |
| | | */ |
| | | public static void resendMsg(String token){ |
| | | String msg = table.get(token); |
| | | ChannelHandlerContext ctx = NettyChannelMap.getData(token); |
| | | if(SinataUtil.isNotEmpty(msg) && ctx != null && ctx.channel().isActive()){ |
| | | ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); |
| | | ChannelFuture sync; |
| | | try { |
| | | sync = ctx.writeAndFlush(buffer).sync(); |
| | | System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg); |
| | | if(!sync.isSuccess()){ |
| | | i++; |
| | | if(i == 10){ |
| | | i =0; |
| | | ctx.close(); |
| | | return; |
| | | } |
| | | System.err.println("重发异常推送不成功,将继续推送"+msg); |
| | | resendMsg(token); |
| | | }else{ |
| | | i=0; |
| | | } |
| | | table.remove(token); |
| | | } catch (Exception e) { |
| | | resendMsg(token); |
| | | System.err.println("重发推送发生异常,记录:"+msg); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cn.mb.cloud.gateway.util.echo; |
| | | |
| | | import io.netty.channel.ChannelInitializer; |
| | | import io.netty.channel.ChannelPipeline; |
| | | import io.netty.channel.socket.SocketChannel; |
| | | import io.netty.handler.codec.string.StringDecoder; |
| | | import io.netty.handler.codec.string.StringEncoder; |
| | | |
| | | import java.nio.charset.Charset; |
| | | |
| | | public class ServerInit extends ChannelInitializer<SocketChannel> { |
| | | |
| | | private DiscardServerHandler discardServerHandler = new DiscardServerHandler(); |
| | | |
| | | @Override |
| | | protected void initChannel(SocketChannel ch) throws Exception { |
| | | ChannelPipeline pipeline = ch.pipeline(); |
| | | pipeline.addLast(new StringDecoder(Charset.forName("utf-8"))); |
| | | pipeline.addLast(new StringEncoder(Charset.forName("utf-8"))); |
| | | // 心跳监测机制 |
| | | // pipeline.addLast(new IdleStateHandler(5,7,10, TimeUnit.SECONDS)); |
| | | pipeline.addLast(discardServerHandler); |
| | | } |
| | | |
| | | } |
| | |
| | | <label class="col-sm-3 control-label">所属门店:</label> |
| | | <div class="col-sm-9"> |
| | | <select class="form-control" id="storeId" name="storeId"> |
| | | <option value="">${item.name}</option> |
| | | <option value="">${shopName}</option> |
| | | </select> |
| | | </div> |
| | | </div> |
| | |
| | | <label class="col-sm-3 control-label">课包类型:</label> |
| | | <div class="col-sm-9"> |
| | | <select class="form-control" id="coursePackageTypeId" name="pCode" onchange="TGoodsInfoDlg.packageChange(this)"> |
| | | <option value="">${shopName}</option> |
| | | <option value="">${typeName}</option> |
| | | </select> |
| | | </div> |
| | | </div> |
| | |
| | | package com.dsh.other.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.dsh.other.entity.Site; |
| | | import com.dsh.other.entity.SiteBooking; |
| | | import com.dsh.other.entity.SiteType; |
| | | import com.dsh.other.entity.TSite; |
| | | import com.dsh.other.feignclient.account.CityManagerClient; |
| | | import com.dsh.other.feignclient.account.model.CityManager; |
| | | import com.dsh.other.feignclient.activity.UserCouponClient; |
| | | import com.dsh.other.feignclient.activity.model.QueryUserCouponByIdAndUserId; |
| | | import com.dsh.other.feignclient.activity.model.UserCoupon; |
| | |
| | | import com.dsh.other.feignclient.model.SiteVo; |
| | | import com.dsh.other.model.*; |
| | | import com.dsh.other.model.dto.siteDto.TSiteDTO; |
| | | import com.dsh.other.model.vo.questionVo.QuestionChangeStateVO; |
| | | import com.dsh.other.model.vo.siteVo.ExpireSiteSearchVO; |
| | | import com.dsh.other.model.vo.siteVo.SiteSearchVO; |
| | | import com.dsh.other.service.ISiteBookingService; |
| | |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | |
| | | if(null == uid){ |
| | | return ResultUtil.tokenErr(); |
| | | } |
| | | |
| | | |
| | | return siteService.cancelMySite(uid, id); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | |
| | | */ |
| | | @ResponseBody |
| | | @PostMapping("/store/queryStoreListByName") |
| | | public List<Store> queryStoreListByName(@RequestParam("name") String name){ |
| | | public List<Store> queryStoreListByName(@RequestBody String name){ |
| | | try { |
| | | List<Store> stores = storeService.list(new QueryWrapper<Store>().eq("state", 1).like("name", name)); |
| | | return stores; |
| | |
| | | @TableField("insertTime") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private Date insertTime; |
| | | @TableField("imgs") |
| | | private String imgs; |
| | | @TableField("introduce") |
| | | private String introduce; |
| | | @TableField("是否半场 1是 2否") |
| | | private Integer ishalf; |
| | | @TableField("场地名称 多个逗号分割") |
| | | private String nextName; |
| | | @TableField("半场名称 多个逗号分割") |
| | | private String halfName; |
| | | |
| | | } |
| | |
| | | */ |
| | | @TableField("insertTime") |
| | | private Date insertTime; |
| | | @TableField("nextName") |
| | | private String nextName; |
| | | @TableField("isHalf") |
| | | private Integer isHalf; |
| | | @TableField("halfName") |
| | | private String halfName; |
| | | @TableField("goType") |
| | | private Integer goType; |
| | | } |
| | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @date 2023/7/17 11:49 |
| | |
| | | private Double cashPrice; |
| | | @ApiModelProperty("玩湃币价格(x/半小时)") |
| | | private Integer playPaiCoin; |
| | | @ApiModelProperty("图片 逗号拼接") |
| | | private String imgs; |
| | | @ApiModelProperty("多场地名称") |
| | | private List<String> nextName; |
| | | @ApiModelProperty("半场名称") |
| | | private List<String> halfName; |
| | | @ApiModelProperty("是否半场 1是 2否") |
| | | private Integer ishalf; |
| | | @ApiModelProperty("场地说明") |
| | | private String introduce; |
| | | |
| | | } |
| | |
| | | private String phone; |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=玩湃比)", dataType = "int", required = true) |
| | | private Integer payType; |
| | | @ApiModelProperty(value = "场地名称", dataType = "String", required = false) |
| | | private String nextName; |
| | | @ApiModelProperty(value = "是否半场 1是 2否",required = false) |
| | | private Integer isHalf; |
| | | @ApiModelProperty(value = "半场名称",required = false) |
| | | private String halfName; |
| | | } |
| | |
| | | package com.dsh.other.service.impl; |
| | | |
| | | import cn.hutool.core.date.DateUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | |
| | | querySiteInfoVo.setStoreLon(store.getLon()); |
| | | querySiteInfoVo.setStoreLat(store.getLat()); |
| | | querySiteInfoVo.setStorePhone(store.getPhone()); |
| | | querySiteInfoVo.setImgs(site.getImgs()); |
| | | querySiteInfoVo.setDistance(0D); |
| | | querySiteInfoVo.setIntroduce(site.getIntroduce()); |
| | | ArrayList<String> nextName = new ArrayList<>(); |
| | | ArrayList<String> halfName = new ArrayList<>(); |
| | | String nextName1 = site.getNextName(); |
| | | String halfName1 = site.getHalfName(); |
| | | |
| | | String[] split = nextName1.split(","); |
| | | for (String s : split) { |
| | | nextName.add(s); |
| | | } |
| | | String[] split1 = halfName1.split(","); |
| | | for (String s : split1) { |
| | | halfName.add(s); |
| | | } |
| | | querySiteInfoVo.setHalfName(halfName); |
| | | querySiteInfoVo.setNextName(nextName); |
| | | if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); |
| | | double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); |
| | |
| | | siteBooking.setStatus(0); |
| | | siteBooking.setState(1); |
| | | siteBooking.setInsertTime(new Date()); |
| | | |
| | | // 2.0 |
| | | siteBooking.setNextName(reservationSite.getNextName()); |
| | | siteBooking.setIsHalf(reservationSite.getIsHalf()); |
| | | siteBooking.setHalfName(reservationSite.getHalfName()); |
| | | siteBookingService.save(siteBooking); |
| | | |
| | | if(reservationSite.getPayType() == 1){//微信支付 |
| | |
| | | @Override |
| | | public ResultUtil cancelMySite(Integer uid, Integer id) throws Exception { |
| | | SiteBooking siteBooking = siteBookingService.getById(id); |
| | | |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); |
| | | Date startTime = siteBooking.getStartTime(); |
| | | if(format.format(new Date()).equals(format.format(startTime))){ |
| | | return ResultUtil.error("预约当天,不能取消"); |
| | | } |
| | | if(siteBooking.getStatus() == 0){ |
| | | return ResultUtil.error("请先进行支付"); |
| | | } |