From c0f6294b0be6789fddd652f89f820fcf6d5526cf Mon Sep 17 00:00:00 2001 From: puzhibing <393733352@qq.com> Date: 星期四, 06 七月 2023 17:32:39 +0800 Subject: [PATCH] 合并代码 --- cloud-server-competition/src/main/java/com/dsh/competition/service/IPaymentCompetitionService.java | 11 cloud-server-course/pom.xml | 10 cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java | 8 cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java | 112 ++ cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionListVo.java | 32 cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml | 4 cloud-server-course/src/main/java/com/dsh/course/util/PayMoneyUtil.java | 806 +++++++++++++++++++ cloud-server-competition/src/main/java/com/dsh/competition/service/impl/ParticipantServiceImpl.java | 15 cloud-server-competition/src/main/java/com/dsh/competition/model/ParticipantVo.java | 22 cloud-server-competition/src/main/java/com/dsh/competition/service/IParticipantService.java | 11 cloud-server-competition/src/main/java/com/dsh/competition/mapper/PaymentCompetitionMapper.java | 11 cloud-server-activity/src/main/resources/mapper/UserCouponMapper.xml | 4 cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java | 58 + cloud-server-competition/src/main/java/com/dsh/competition/mapper/ParticipantMapper.java | 11 cloud-server-competition/src/main/java/com/dsh/competition/controller/UserCompetitionController.java | 8 cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java | 15 cloud-server-competition/src/main/java/com/dsh/competition/entity/PaymentCompetition.java | 78 + cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java | 40 cloud-server-competition/src/main/java/com/dsh/competition/entity/UserCompetition.java | 14 cloud-server-competition/src/main/resources/sharding-jdbc.properties | 25 cloud-server-competition/pom.xml | 5 cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java | 253 +++++ cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java | 22 cloud-server-competition/src/main/resources/mapper/PaymentCompetitionMapper.xml | 4 cloud-server-activity/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java | 4 cloud-server-competition/src/main/resources/mapper/CompetitionMapper.xml | 32 cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackagePayment.java | 8 cloud-server-course/src/main/java/com/dsh/course/util/UUIDUtil.java | 101 ++ cloud-server-competition/src/main/java/com/dsh/competition/entity/Participant.java | 73 + cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java | 84 ++ cloud-server-course/src/main/java/com/dsh/course/model/PaymentCourseVo.java | 2 cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/StoreClient.java | 33 cloud-server-course/src/main/java/com/dsh/course/util/MD5AndKL.java | 112 ++ /dev/null | 17 cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/model/Store.java | 94 ++ cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java | 4 cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java | 88 ++ cloud-server-competition/src/main/java/com/dsh/competition/mapper/CompetitionMapper.java | 16 cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java | 15 cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/Master0DataSource.java | 18 cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/DatasourceModel.java | 86 ++ cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java | 51 + 42 files changed, 2,374 insertions(+), 43 deletions(-) diff --git a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java index 7f75133..9ab2b8a 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java +++ b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java @@ -325,4 +325,19 @@ return null; } } + + + /** + * 修改用户信息 + * @param appUser + */ + @ResponseBody + @PostMapping("/base/appUser/updateAppUser") + public void updateAppUser(@RequestBody TAppUser appUser){ + try { + appUserService.updateById(appUser); + }catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/cloud-server-activity/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java b/cloud-server-activity/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java index 75f7e69..2c53536 100644 --- a/cloud-server-activity/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java +++ b/cloud-server-activity/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java @@ -91,7 +91,7 @@ * @return */ private ShardingTableRuleConfiguration getUserCouponTableRuleConfiguration() { - ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_user_coupon", "m$->{0}.t_user_coupon->{1..5}");//50 + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_user_coupon", "m_$->{0}.t_user_coupon->{1..5}");//50 result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("userId", "t_user_coupon-inline")); result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_user_coupon-snowflake")); return result; @@ -104,7 +104,7 @@ * @return */ private ShardingTableRuleConfiguration getUserPointsMerchandiseTableRuleConfiguration() { - ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_user_points_merchandise", "m$->{0}.t_user_points_merchandise$->{1..5}");//30 + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_user_points_merchandise", "m_$->{0}.t_user_points_merchandise$->{1..5}");//30 result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("userId", "t_user_points_merchandise-inline")); result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_user_points_merchandise-snowflake")); return result; diff --git a/cloud-server-activity/src/main/resources/mapper/UserCouponMapper.xml b/cloud-server-activity/src/main/resources/mapper/UserCouponMapper.xml index 4cd1ab4..2c04ccd 100644 --- a/cloud-server-activity/src/main/resources/mapper/UserCouponMapper.xml +++ b/cloud-server-activity/src/main/resources/mapper/UserCouponMapper.xml @@ -9,8 +9,8 @@ b.`name`, b.type, b.content, - DATE_FORMAT('%y-%M-%d', b.startTime) as startTime, - DATE_FORMAT('%y-%M-%d', b.endTime) as endTime + DATE_FORMAT(b.startTime, '%Y-%m-%d') as startTime, + DATE_FORMAT(b.endTime, '%Y-%m-%d') as endTime from t_user_coupon a left join t_coupon b on (a.couponId = b.id) where a.`status` = 1 and b.type != 3 and a.userId = #{uid} and ( diff --git a/cloud-server-competition/pom.xml b/cloud-server-competition/pom.xml index 2ed3f7a..0b3b92c 100644 --- a/cloud-server-competition/pom.xml +++ b/cloud-server-competition/pom.xml @@ -75,6 +75,11 @@ <artifactId>swagger-models</artifactId> <version>1.5.22</version> </dependency> + <dependency> + <groupId>org.apache.shardingsphere</groupId> + <artifactId>shardingsphere-jdbc-core</artifactId> + <version>5.2.0</version> + </dependency> </dependencies> <build> diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java index 8a43523..6d6a418 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java @@ -5,8 +5,15 @@ import com.dsh.competition.entity.Competition; import com.dsh.competition.entity.UserCompetition; import com.dsh.competition.feignclient.model.PurchaseRecordVo; +import com.dsh.competition.model.CompetitionInfo; +import com.dsh.competition.model.CompetitionListVo; import com.dsh.competition.service.CompetitionService; import com.dsh.competition.service.UserCompetitionService; +import com.dsh.competition.util.ResultUtil; +import com.dsh.competition.util.TokenUtil; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -37,6 +44,12 @@ private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm"); + @Autowired + private TokenUtil tokenUtil; + + + + @PostMapping("/base/competition/getCompetitionsDetails") public List<PurchaseRecordVo> getStuSourseList(@RequestParam("startTime") Date startTime, @RequestParam("endTime") Date endTime, @RequestParam("appUserId") Integer appUserId){ @@ -61,5 +74,43 @@ } + + + + @ResponseBody + @PostMapping("/base/competition/queryCompetitionList") + @ApiOperation(value = "获取赛事列表", tags = {"APP-赛事活动列表"}) + @ApiImplicitParams({ + @ApiImplicitParam(value = "城市code", name = "cityCode", dataType = "string", required = false), + @ApiImplicitParam(value = "搜索内容", name = "content", dataType = "string", required = false), + @ApiImplicitParam(value = "报名条件(1=全部用户,2=仅限年度会员参与,3=仅限学员参与)", name = "registerCondition", dataType = "int", required = false), + @ApiImplicitParam(value = "排序(1=正序,2=倒序)", name = "heat", dataType = "int", required = false), + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) + public ResultUtil<List<CompetitionListVo>> queryCompetitionList(String cityCode, String content, Integer registerCondition, Integer heat){ + try { + List<CompetitionListVo> competitionListVos = cttService.queryCompetitionList(cityCode, content, registerCondition, heat); + return ResultUtil.success(competitionListVos); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } + + + + + public ResultUtil<CompetitionInfo> queryCompetitionInfo(Integer id){ + try { + Integer uid = tokenUtil.getUserIdFormRedis(); + if(null == uid){ + return ResultUtil.tokenErr(); + } + return null; + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/controller/UserCompetitionController.java b/cloud-server-competition/src/main/java/com/dsh/competition/controller/UserCompetitionController.java index 7039dd2..b20a3a3 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/controller/UserCompetitionController.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/controller/UserCompetitionController.java @@ -1,8 +1,12 @@ package com.dsh.competition.controller; +import com.dsh.competition.util.ResultUtil; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; + +import javax.xml.transform.Result; +import java.util.List; /** * <p> @@ -16,5 +20,9 @@ @RequestMapping("/user_competition") public class UserCompetitionController { + + + + } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java index 1fc29a0..b140bd5 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java @@ -114,10 +114,50 @@ */ private Integer realName; /** + * 赛事封面图 + */ + private String coverDrawing; + /** * 赛事简介 */ private String introduction; /** + * 赛事图片 + */ + private String imgs; + /** + * 报名须知 + */ + private String registrationNotes; + /** + * 参赛省 + */ + private String entryProvince; + /** + * 参赛省编号 + */ + private String entryProvinceCode; + /** + * 参赛市 + */ + private String entryCity; + /** + * 参赛市编号 + */ + private String entryCityCode; + /** + * 参赛地址 + */ + private String entryAddress; + /** + * 参赛经度 + */ + private String entryLon; + /** + * 参赛纬度 + */ + private String entryLat; + /** * 审核状态(1=待审核,2=已通过,3=已拒绝) */ private Integer auditStatus; diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/entity/Participant.java b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Participant.java new file mode 100644 index 0000000..d9146e3 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Participant.java @@ -0,0 +1,73 @@ +package com.dsh.competition.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:46 + */ +@Data +@TableName("t_participant") +public class Participant { + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + /** + * 用户id + */ + @TableField("appUserId") + private Integer appUserId; + /** + * 姓名 + */ + @TableField("name") + private String name; + /** + * 生日 + */ + @TableField("birthday") + private Date birthday; + /** + * 性别(1=男,2=女) + */ + @TableField("gender") + private Integer gender; + /** + * 身高(CM) + */ + @TableField("height") + private Integer height; + /** + * 体重(KG) + */ + @TableField("weight") + private Double weight; + /** + * 联系电话 + */ + @TableField("phone") + private String phone; + /** + * 身份证号码 + */ + @TableField("idcard") + private String idcard; + /** + * 状态(1=正常,2=冻结,3=删除) + */ + @TableField("state") + private Integer state; + /** + * 添加时间 + */ + @TableField("insertTime") + private Date insertTime; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/entity/PaymentCompetition.java b/cloud-server-competition/src/main/java/com/dsh/competition/entity/PaymentCompetition.java new file mode 100644 index 0000000..2473805 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/entity/PaymentCompetition.java @@ -0,0 +1,78 @@ +package com.dsh.competition.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:30 + */ +@Data +@TableName("t_payment_competition") +public class PaymentCompetition { + /** + * 主键 + */ + @TableId(value = "id", type = IdType.INPUT) + private Long id; + /** + * 业务流水号 + */ + @TableField("code") + private String code; + /** + * 赛事id + */ + @TableField("competitionId") + private Integer competitionId; + /** + * 用户id + */ + @TableField("appUserId") + private Integer appUserId; + /** + * 支付方式(1=微信,2=支付宝,3=玩湃币,4=课时) + */ + @TableField("payType") + private Integer payType; + /** + * 支付金额 + */ + @TableField("amount") + private Double amount; + /** + * 支付状态(1=待支付,2=已支付,3=已退款) + */ + @TableField("payStatus") + private Integer payStatus; + /** + * 支付时间 + */ + @TableField("payTime") + private Date payTime; + /** + * 第三方支付流水号 + */ + @TableField("payOrderNo") + private String payOrderNo; + /** + * 退款时间 + */ + @TableField("refundTime") + private Date refundTime; + /** + * 第三方退款流水 + */ + @TableField("refundOrderNo") + private String refundOrderNo; + /** + * 添加时间 + */ + @TableField("insertTime") + private Date insertTime; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/entity/UserCompetition.java b/cloud-server-competition/src/main/java/com/dsh/competition/entity/UserCompetition.java index c80a11a..215d797 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/entity/UserCompetition.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/entity/UserCompetition.java @@ -30,8 +30,8 @@ /** * 主键 */ - @TableId(value = "id", type = IdType.AUTO) - private Integer id; + @TableId(value = "id", type = IdType.INPUT) + private Long id; /** * 赛事id */ @@ -39,11 +39,15 @@ /** * 用户id */ - private Integer userId; + private Integer appUserId; /** - * 状态(1=正常,2=取消) + * 用户类型(1=学员,2=参赛人员) */ - private Integer status; + private Integer userType; + /** + * 参与者id + */ + private Integer userId; /** * 参加时间 */ diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/DeductionCompetitionsClient.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/DeductionCompetitionsClient.java deleted file mode 100644 index 98d9b2a..0000000 --- a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/DeductionCompetitionsClient.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dsh.competition.feignclient; - - -import com.dsh.competition.feignclient.model.PurchaseRecordVo; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.Date; -import java.util.List; - -@FeignClient(value = "mb-cloud-competition") -public interface DeductionCompetitionsClient { - - @PostMapping("/base/competition/getCompetitionsDetails") - public List<PurchaseRecordVo> getStuSourseList(@RequestParam("startTime") Date startTime, - @RequestParam("endTime") Date endTime, - @RequestParam("appUserId") Integer appUserId); - -} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/model/ClassDataDetails.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/model/ClassDataDetails.java deleted file mode 100644 index dc6e069..0000000 --- a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/model/ClassDataDetails.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dsh.competition.feignclient.model; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.List; - - -@Data -public class ClassDataDetails { - - @ApiModelProperty(value = "已扣课时数") - private Integer deductionClassHours; - - @ApiModelProperty(value = "类型变动记录") - private List<PurchaseRecordVo> recordVos; -} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/StoreClient.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/StoreClient.java new file mode 100644 index 0000000..9c4fa3d --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/StoreClient.java @@ -0,0 +1,33 @@ +package com.dsh.competition.feignclient.other; + +import com.dsh.competition.feignclient.other.model.Store; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.List; + +/** + * @author zhibing.pu + * @date 2023/6/29 10:09 + */ +@FeignClient("mb-cloud-other") +public interface StoreClient { + + + /** + * 根据名称模糊搜索门店 + * @param name + * @return + */ + @PostMapping("/store/queryStoreListByName") + List<Store> queryStoreListByName(String name); + + + /** + * 根据门店id获取门店信息 + * @param id + * @return + */ + @PostMapping("/store/queryStoreById") + Store queryStoreById(Integer id); +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/model/Store.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/model/Store.java new file mode 100644 index 0000000..2469c28 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/other/model/Store.java @@ -0,0 +1,94 @@ +package com.dsh.competition.feignclient.other.model; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @date 2023/6/29 10:09 + */ +@Data +public class Store { + private Integer id; + /** + * 门店名称 + */ + private String name; + /** + * 门店店长id + */ + private Integer storeStaffId; + /** + * 城市管理员id + */ + private Integer cityManagerId; + /** + * 省 + */ + private String province; + /** + * 省编号 + */ + private String provinceCode; + /** + * 市 + */ + private String city; + /** + * 市编号 + */ + private String cityCode; + /** + * 联系电话 + */ + private String phone; + /** + * 详细地址 + */ + private String address; + /** + * 纬度 + */ + private String lat; + /** + * 经度 + */ + private String lon; + /** + * 营业开始时间 + */ + private String startTime; + /** + * 营业结束时间 + */ + private String endTime; + /** + * 封面图 + */ + private String coverDrawing; + /** + * 实景图 + */ + private String realPicture; + /** + * 门店介绍 + */ + private String introduce; + /** + * 福利图片 + */ + private String welfarePicture; + /** + * 开始上课图片 + */ + private String classPicture; + /** + * 评分 + */ + private BigDecimal score; + /** + * 状态(1=正常,2=冻结,3=删除) + */ + private Integer state; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/mapper/CompetitionMapper.java b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/CompetitionMapper.java index 851cb69..69a7c85 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/mapper/CompetitionMapper.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/CompetitionMapper.java @@ -2,6 +2,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dsh.competition.entity.Competition; +import com.dsh.competition.model.CompetitionListVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** * <p> @@ -13,4 +17,16 @@ */ public interface CompetitionMapper extends BaseMapper<Competition> { + + /** + * 获取赛事列表 + * @param cityCode + * @param content + * @param registerCondition + * @param heat + * @return + */ + List<CompetitionListVo> queryCompetitionList(@Param("cityCode") String cityCode, @Param("content") String content, + @Param("registerCondition") Integer registerCondition, @Param("heat") Integer heat); + } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/mapper/ParticipantMapper.java b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/ParticipantMapper.java new file mode 100644 index 0000000..36db0a7 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/ParticipantMapper.java @@ -0,0 +1,11 @@ +package com.dsh.competition.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dsh.competition.entity.Participant; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:51 + */ +public interface ParticipantMapper extends BaseMapper<Participant> { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/mapper/PaymentCompetitionMapper.java b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/PaymentCompetitionMapper.java new file mode 100644 index 0000000..12010e5 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/mapper/PaymentCompetitionMapper.java @@ -0,0 +1,11 @@ +package com.dsh.competition.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dsh.competition.entity.PaymentCompetition; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:36 + */ +public interface PaymentCompetitionMapper extends BaseMapper<PaymentCompetition> { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java new file mode 100644 index 0000000..8452551 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java @@ -0,0 +1,58 @@ +package com.dsh.competition.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author zhibing.pu + * @date 2023/7/6 15:21 + */ +@Data +@ApiModel +public class CompetitionInfo { + @ApiModelProperty("赛事id") + private Integer id; + @ApiModelProperty("赛事图片") + private String imgs; + @ApiModelProperty("赛事名称") + private String name; + @ApiModelProperty("报名条件(1=全部用户,2=仅限年度会员参与,3=仅限学员参与)") + private Integer registerCondition; + @ApiModelProperty("门店名称") + private String storeName; + @ApiModelProperty("门店地址") + private String storeAddress; + @ApiModelProperty("门店经度") + private String storeLon; + @ApiModelProperty("门店纬度") + private String storeLat; + @ApiModelProperty("报名结束时间") + private String registerEndTime; + @ApiModelProperty("开始时间") + private String startTime; + @ApiModelProperty("结束时间") + private String endTime; + @ApiModelProperty("报名年龄") + private String age; + @ApiModelProperty("省名称") + private String province; + @ApiModelProperty("市名称") + private String city; + @ApiModelProperty("参赛地址") + private String address; + @ApiModelProperty("支付方式(1=现金,2=玩湃币支付,3=课时支付)") + private Integer payType; + @ApiModelProperty("支付价格") + private Double price; + @ApiModelProperty("赛事简介") + private String introduction; + @ApiModelProperty("报名须知") + private String registrationNotes; + @ApiModelProperty("是否已报名(0=否,1=是)") + private Integer apply; + @ApiModelProperty("报名参赛人员") + private List<ParticipantVo> participant; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionListVo.java b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionListVo.java new file mode 100644 index 0000000..3e6c6e5 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionListVo.java @@ -0,0 +1,32 @@ +package com.dsh.competition.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @date 2023/7/6 14:21 + */ +@Data +@ApiModel +public class CompetitionListVo { + @ApiModelProperty("赛事id") + private Integer id; + @ApiModelProperty("赛事名称") + private String name; + @ApiModelProperty("赛事封面") + private String coverDrawing; + @ApiModelProperty("城市名称") + private String cityName; + @ApiModelProperty("报名条件(1=全部用户,2=仅限年度会员参与,3=仅限学员参与)") + private Integer registerCondition; + @ApiModelProperty("赛事简介") + private String introduction; + @ApiModelProperty("报名结束时间") + private String registerEndTime; + @ApiModelProperty("报名年龄") + private String age; + @ApiModelProperty("热度") + private Integer heat; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/model/ParticipantVo.java b/cloud-server-competition/src/main/java/com/dsh/competition/model/ParticipantVo.java new file mode 100644 index 0000000..559edce --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/model/ParticipantVo.java @@ -0,0 +1,22 @@ +package com.dsh.competition.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:52 + */ +@Data +@ApiModel +public class ParticipantVo { + @ApiModelProperty("人员id") + private Integer id; + @ApiModelProperty("姓名") + private String name; + @ApiModelProperty("年龄") + private Integer age; + @ApiModelProperty("身份证号码") + private String idcard; +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java index 5f12a48..a91abda 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java @@ -2,6 +2,10 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.dsh.competition.entity.Competition; +import com.dsh.competition.model.CompetitionInfo; +import com.dsh.competition.model.CompetitionListVo; + +import java.util.List; /** * <p> @@ -13,4 +17,22 @@ */ public interface CompetitionService extends IService<Competition> { + + /** + * 获取赛事列表 + * @param content + * @param registerCondition + * @param heat + * @return + */ + List<CompetitionListVo> queryCompetitionList(String cityCode, String content, Integer registerCondition, Integer heat) throws Exception; + + + /** + * 获取赛事详情 + * @param uid + * @param id + * @return + */ + CompetitionInfo queryCompetitionInfo(Integer uid, Integer id) throws Exception; } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/IParticipantService.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/IParticipantService.java new file mode 100644 index 0000000..f7d48f3 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/IParticipantService.java @@ -0,0 +1,11 @@ +package com.dsh.competition.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dsh.competition.entity.Participant; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:50 + */ +public interface IParticipantService extends IService<Participant> { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/IPaymentCompetitionService.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/IPaymentCompetitionService.java new file mode 100644 index 0000000..9bc0060 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/IPaymentCompetitionService.java @@ -0,0 +1,11 @@ +package com.dsh.competition.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dsh.competition.entity.PaymentCompetition; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:37 + */ +public interface IPaymentCompetitionService extends IService<PaymentCompetition> { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java index a7ccc96..9966528 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java @@ -1,10 +1,26 @@ package com.dsh.competition.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dsh.competition.entity.Competition; +import com.dsh.competition.entity.PaymentCompetition; +import com.dsh.competition.entity.UserCompetition; +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.service.CompetitionService; +import com.dsh.competition.service.IPaymentCompetitionService; +import com.dsh.competition.service.UserCompetitionService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; /** * <p> @@ -17,4 +33,72 @@ @Service public class CompetitionServiceImpl extends ServiceImpl<CompetitionMapper, Competition> implements CompetitionService { + @Resource + private StoreClient storeClient; + + @Autowired + private IPaymentCompetitionService paymentCompetitionService; + + @Autowired + private UserCompetitionService userCompetitionService; + + + + /** + * 获取赛事列表 + * @param content + * @param registerCondition + * @param heat + * @return + */ + @Override + public List<CompetitionListVo> queryCompetitionList(String cityCode, String content, Integer registerCondition, Integer heat) throws Exception { + return this.baseMapper.queryCompetitionList(cityCode, content, registerCondition, heat); + } + + + /** + * 获取赛事详情 + * @param uid + * @param id + * @return + * @throws Exception + */ + @Override + public CompetitionInfo queryCompetitionInfo(Integer uid, Integer id) throws Exception { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Competition competition = this.getById(id); + CompetitionInfo competitionInfo = new CompetitionInfo(); + competitionInfo.setId(competition.getId()); + competitionInfo.setImgs(competition.getImgs()); + competitionInfo.setName(competition.getName()); + competitionInfo.setRegisterCondition(competition.getRegisterCondition()); + Store store = storeClient.queryStoreById(competition.getStoreId()); + competitionInfo.setStoreName(store.getName()); + competitionInfo.setStoreAddress(store.getAddress()); + competitionInfo.setStoreLon(store.getLon()); + competitionInfo.setStoreLat(store.getLat()); + competitionInfo.setRegisterEndTime(sdf.format(competition.getRegisterEndTime())); + competitionInfo.setStartTime(sdf.format(competition.getStartTime())); + competitionInfo.setEndTime(sdf.format(competition.getEndTime())); + competitionInfo.setAge(competition.getStartAge() + "-" + competition.getEndAge()); + competitionInfo.setProvince(competition.getEntryProvince()); + competitionInfo.setCity(competition.getEntryCity()); + competitionInfo.setAddress(competition.getEntryAddress()); + competitionInfo.setPayType(competition.getPayType()); + competitionInfo.setPrice(competition.getPrice().doubleValue()); + competitionInfo.setIntroduction(competition.getIntroduction()); + competitionInfo.setRegistrationNotes(competition.getRegistrationNotes()); + competitionInfo.setApply(0); + PaymentCompetition one = paymentCompetitionService.getOne(new QueryWrapper<PaymentCompetition>().eq("competitionId", id).eq("appUserId", uid).eq("payStatus", 2)); + if(null != one){ + competitionInfo.setApply(1); + List<ParticipantVo> participant = new ArrayList<>(); +// userCompetitionService.list(new QueryWrapper<UserCompetition>().eq("competitionId", id).eq("")) + } + + + + return null; + } } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/ParticipantServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/ParticipantServiceImpl.java new file mode 100644 index 0000000..d33d306 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/ParticipantServiceImpl.java @@ -0,0 +1,15 @@ +package com.dsh.competition.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dsh.competition.entity.Participant; +import com.dsh.competition.mapper.ParticipantMapper; +import com.dsh.competition.service.IParticipantService; +import org.springframework.stereotype.Service; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:51 + */ +@Service +public class ParticipantServiceImpl extends ServiceImpl<ParticipantMapper, Participant> implements IParticipantService { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java new file mode 100644 index 0000000..ec3eed7 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java @@ -0,0 +1,15 @@ +package com.dsh.competition.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dsh.competition.entity.PaymentCompetition; +import com.dsh.competition.mapper.PaymentCompetitionMapper; +import com.dsh.competition.service.IPaymentCompetitionService; +import org.springframework.stereotype.Service; + +/** + * @author zhibing.pu + * @date 2023/7/6 16:37 + */ +@Service +public class PaymentCompetitionServiceImpl extends ServiceImpl<PaymentCompetitionMapper, PaymentCompetition> implements IPaymentCompetitionService { +} diff --git a/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/DatasourceModel.java b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/DatasourceModel.java new file mode 100644 index 0000000..ea4cd0f --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/DatasourceModel.java @@ -0,0 +1,86 @@ +package com.dsh.config.Sharding_jdbc; + + +/** +* 数据源 +* @author pzb +* @Date 2022/11/21 21:13 +*/ +public class DatasourceModel { + private String url; + private String username; + private String password; + private String driverClassName; + private Integer maxActive; + private Long maxWait; + private Integer minIdle; + private Integer initialSize; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getDriverClassName() { + return driverClassName; + } + + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + + public DatasourceModel getDatasourceModel(){ + return this; + } + + public Integer getMaxActive() { + return maxActive; + } + + public void setMaxActive(Integer maxActive) { + this.maxActive = maxActive; + } + + public Long getMaxWait() { + return maxWait; + } + + public void setMaxWait(Long maxWait) { + this.maxWait = maxWait; + } + + public Integer getMinIdle() { + return minIdle; + } + + public void setMinIdle(Integer minIdle) { + this.minIdle = minIdle; + } + + public Integer getInitialSize() { + return initialSize; + } + + public void setInitialSize(Integer initialSize) { + this.initialSize = initialSize; + } +} diff --git a/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/Master0DataSource.java b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/Master0DataSource.java new file mode 100644 index 0000000..e1bbbaa --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/Master0DataSource.java @@ -0,0 +1,18 @@ +package com.dsh.config.Sharding_jdbc; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + + +/** +* 数据源配置 +* @author pzb +* @Date 2022/11/21 20:32 +*/ +@Component +@PropertySource(value = "classpath:sharding-jdbc.properties") +@ConfigurationProperties(prefix = "datasource.master0") +public class Master0DataSource extends DatasourceModel { + +} diff --git a/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java new file mode 100644 index 0000000..b53d988 --- /dev/null +++ b/cloud-server-competition/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java @@ -0,0 +1,112 @@ +package com.dsh.config.Sharding_jdbc; + +import com.alibaba.druid.pool.DruidDataSource; +import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory; +import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration; +import org.apache.shardingsphere.infra.config.rule.RuleConfiguration; +import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration; +import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration; +import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration; +import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; +import java.sql.SQLException; +import java.util.*; + +@Configuration +public class ShardingConfig { + + @Autowired + private Master0DataSource master0DataSource; + + + @Bean + public DataSource getDataSource(){ + DataSource dataSource = null; + try { + Properties properties = new Properties(); + properties.setProperty("sql-show", "true"); + String databaseName = "m_0";//真实数据源名称,多个数据源用逗号区分 + dataSource = ShardingSphereDataSourceFactory.createDataSource(databaseName, createDataSourceMap(), createShardingRuleConfiguration(), properties); + } catch (SQLException e) { + e.printStackTrace(); + } + return dataSource; + } + + + /** + * 配置多数据源 + * @return + */ + private Map<String, DataSource> createDataSourceMap() { + Map<String, DataSource> dataSourceMap = new HashMap<>(); + // 配置第 1 个数据源 + DruidDataSource dataSource1 = new DruidDataSource(); + dataSource1.setDriverClassName(master0DataSource.getDriverClassName()); + dataSource1.setUrl(master0DataSource.getUrl()); + dataSource1.setUsername(master0DataSource.getUsername()); + dataSource1.setPassword(master0DataSource.getPassword()); + dataSource1.setMaxActive(master0DataSource.getMaxActive()); + dataSource1.setMaxWait(master0DataSource.getMaxWait()); + dataSource1.setMinIdle(master0DataSource.getMinIdle()); + dataSource1.setInitialSize(master0DataSource.getInitialSize()); + dataSourceMap.put("m_0", dataSource1); + return dataSourceMap; + } + + + /** + * 分片配置 + * @return + */ + private Collection<RuleConfiguration> createShardingRuleConfiguration() { + LinkedList<RuleConfiguration> linkedList = new LinkedList(); + + //分片规则配置 + ShardingRuleConfiguration result1 = new ShardingRuleConfiguration(); + result1.getTables().add(getUserCompetitionTableRuleConfiguration()); + Properties props1 = new Properties(); + props1.setProperty("algorithm-expression", "t_user_competition$->{appUserId % 5 + 1}"); + result1.getShardingAlgorithms().put("t_user_competition-inline", new AlgorithmConfiguration("INLINE", props1)); + result1.getKeyGenerators().put("t_user_competition-snowflake", new AlgorithmConfiguration("SNOWFLAKE", new Properties())); + linkedList.add(result1); + + //分片规则配置 + ShardingRuleConfiguration result2 = new ShardingRuleConfiguration(); + result2.getTables().add(getPaymentCompetitionTableRuleConfiguration()); + Properties props2 = new Properties(); + props2.setProperty("algorithm-expression", "t_payment_competition$->{appUserId % 5 + 1}"); + result2.getShardingAlgorithms().put("t_payment_competition-inline", new AlgorithmConfiguration("INLINE", props2)); + result2.getKeyGenerators().put("t_payment_competition-snowflake", new AlgorithmConfiguration("SNOWFLAKE", new Properties())); + linkedList.add(result2); + + return linkedList; + } + + /** + * 分片算法配置 + * @return + */ + private ShardingTableRuleConfiguration getUserCompetitionTableRuleConfiguration() { + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_user_competition", "m_$->{0}.t_user_competition$->{1..5}");//50 + result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("appUserId", "t_user_competition-inline")); + result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_user_competition-snowflake")); + return result; + } + + + /** + * 分片算法配置 + * @return + */ + private ShardingTableRuleConfiguration getPaymentCompetitionTableRuleConfiguration() { + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_payment_competition", "m_$->{0}.t_payment_competition$->{1..5}");//50 + result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("appUserId", "t_payment_competition-inline")); + result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_payment_competition-snowflake")); + return result; + } +} diff --git a/cloud-server-competition/src/main/resources/mapper/CompetitionMapper.xml b/cloud-server-competition/src/main/resources/mapper/CompetitionMapper.xml index 0a11da1..df40070 100644 --- a/cloud-server-competition/src/main/resources/mapper/CompetitionMapper.xml +++ b/cloud-server-competition/src/main/resources/mapper/CompetitionMapper.xml @@ -3,4 +3,36 @@ <mapper namespace="com.dsh.competition.mapper.CompetitionMapper"> + <select id="queryCompetitionList" resultType="com.dsh.competition.model.CompetitionListVo"> + select * from ( + select + a.id, + a.`name`, + a.coverDrawing, + a.city as cityName, + a.registerCondition, + a.introduction, + DATE_FORMAT(a.registerEndTime, '%Y-%m-%d %H:%i') as registerEndTime, + CONCAT(a.startAge, '-', a.endAge) as age, + a.baseNumber + a.applicantsNumber as heat + from t_competition a + where a.auditStatus = 2 and a.`status` = 2 and a.state = 1 + <if test="null != cityCode and '' != cityCode"> + and a.cityCode = #{cityCode} + </if> + <if test="null != content and '' != content"> + and a.name like CONCAT('%', #{content}, '%') + </if> + <if test="null != registerCondition"> + and a.registerCondition = #{registerCondition} + </if> + order by a.insertTime desc + ) as aa + <if test="null != heat 1 == heat"> + order by aa.heat + </if> + <if test="null != heat 2 == heat"> + order by aa.heat desc + </if> + </select> </mapper> diff --git a/cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml b/cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml new file mode 100644 index 0000000..7a8fcc2 --- /dev/null +++ b/cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.dsh.competition.mapper.ParticipantMapper"> +</mapper> \ No newline at end of file diff --git a/cloud-server-competition/src/main/resources/mapper/PaymentCompetitionMapper.xml b/cloud-server-competition/src/main/resources/mapper/PaymentCompetitionMapper.xml new file mode 100644 index 0000000..fdabd07 --- /dev/null +++ b/cloud-server-competition/src/main/resources/mapper/PaymentCompetitionMapper.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.dsh.competition.mapper.PaymentCompetitionMapper"> +</mapper> \ No newline at end of file diff --git a/cloud-server-competition/src/main/resources/sharding-jdbc.properties b/cloud-server-competition/src/main/resources/sharding-jdbc.properties new file mode 100644 index 0000000..ffe6f6b --- /dev/null +++ b/cloud-server-competition/src/main/resources/sharding-jdbc.properties @@ -0,0 +1,25 @@ +datasource.names=master0 + +#�������� +datasource.master0.type=com.alibaba.druid.pool.DruidDataSource +datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver +datasource.master0.url=jdbc:mysql://192.168.110.80:3306/playpai_competition?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai +datasource.master0.username=root +datasource.master0.password=123456 +datasource.master0.maxActive=20 +datasource.master0.maxWait=60000 +datasource.master0.minIdle=5 +datasource.master0.initialSize=2 + +#�������� +#datasource.master0.type=com.alibaba.druid.pool.DruidDataSource +#datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver +#datasource.master0.url=jdbc:mysql://110.239.68.140:3306/playpai_competition?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B7 +#datasource.master0.username=root +#datasource.master0.password=G4LLlNouAGH1dijbyU&xDo$X +#datasource.master0.maxActive=200 +#datasource.master0.maxWait=60000 +#datasource.master0.minIdle=100 +#datasource.master0.initialSize=100 + + diff --git a/cloud-server-course/pom.xml b/cloud-server-course/pom.xml index 191c909..f14146a 100644 --- a/cloud-server-course/pom.xml +++ b/cloud-server-course/pom.xml @@ -119,6 +119,16 @@ <artifactId>shardingsphere-jdbc-core</artifactId> <version>5.2.0</version> </dependency> + <dependency> + <groupId>dom4j</groupId> + <artifactId>dom4j</artifactId> + <version>1.6.1</version> + </dependency> + <dependency> + <groupId>com.alipay.sdk</groupId> + <artifactId>alipay-sdk-java</artifactId> + <version>4.8.10.ALL</version> + </dependency> </dependencies> <build> diff --git a/cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java b/cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java index 179ef3d..1dc9751 100644 --- a/cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java +++ b/cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java @@ -91,7 +91,7 @@ * @return */ private ShardingTableRuleConfiguration getCoursePackagePaymentTableRuleConfiguration() { - ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_payment", "m$->{0}.t_course_package_payment$->{1..5}");//50 + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_payment", "m_$->{0}.t_course_package_payment$->{1..5}");//50 result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("appUserId", "t_course_package_payment-inline")); result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_course_package_payment-snowflake")); return result; @@ -104,7 +104,7 @@ * @return */ private ShardingTableRuleConfiguration getCoursePackageStudentTableRuleConfiguration() { - ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_student", "m$->{0}.t_course_package_student$->{1..5}");//30 + ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_student", "m_$->{0}.t_course_package_student$->{1..5}");//30 result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("appUserId", "t_course_package_student-inline")); result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_course_package_student-snowflake")); return result; diff --git a/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java b/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java index 0400ac4..ab2011c 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java +++ b/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java @@ -3,12 +3,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dsh.course.entity.TCourse; +import com.dsh.course.entity.TCoursePackagePayment; import com.dsh.course.entity.TCoursePackageType; import com.dsh.course.feignclient.model.ExerciseVideo; import com.dsh.course.model.*; +import com.dsh.course.service.TCoursePackagePaymentService; import com.dsh.course.service.TCoursePackageService; import com.dsh.course.service.TCoursePackageTypeService; import com.dsh.course.service.TCourseService; +import com.dsh.course.util.PayMoneyUtil; import com.dsh.course.util.ResultUtil; import com.dsh.course.util.TokenUtil; import io.swagger.annotations.Api; @@ -21,8 +24,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Map; @Api @CrossOrigin @@ -43,6 +50,12 @@ @Autowired private TCoursePackageTypeService coursePackageTypeService; + + @Autowired + private PayMoneyUtil payMoneyUtil; + + @Autowired + private TCoursePackagePaymentService coursePackagePaymentService; @@ -142,7 +155,12 @@ - + @ResponseBody + @PostMapping("/api/course/paymentCourse") + @ApiOperation(value = "支付课程", tags = {"APP-课程列表"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) public ResultUtil paymentCourse(@RequestBody PaymentCourseVo paymentCourseVo){ try { Integer uid = tokenUtil.getUserIdFormRedis(); @@ -156,4 +174,72 @@ } } + + /** + * 购买课程微信支付回调 + * @param request + * @param response + */ + @ResponseBody + @PostMapping("/base/course/weChatPaymentCourseCallback") + public void weChatPaymentCourseCallback(HttpServletRequest request, HttpServletResponse response){ + try { + Map<String, String> map = payMoneyUtil.weixinpayCallback(request); + if(null != map){ + String code = map.get("out_trade_no"); + String transaction_id = map.get("transaction_id"); + String result = map.get("result"); + + List<TCoursePackagePayment> list = coursePackagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("state", 1).eq("code", code).eq("payType", 1)); + TCoursePackagePayment one = list.get(0); + if(one.getPayStatus() == 1){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setPayStatus(2); + coursePackagePayment.setOrderNumber(transaction_id); + } + coursePackagePaymentService.updateBatchById(list); + } + PrintWriter out = response.getWriter(); + out.write(result); + out.flush(); + out.close(); + } + }catch (Exception e){ + e.printStackTrace(); + } + } + + + /** + * 购买课程支付宝回调 + * @param request + * @param response + */ + @ResponseBody + @PostMapping("/base/course/aliPaymentCourseCallback") + public void aliPaymentCourseCallback(HttpServletRequest request, HttpServletResponse response){ + try { + Map<String, String> map = payMoneyUtil.alipayCallback(request); + if(null != map){ + String code = map.get("out_trade_no"); + String trade_no = map.get("trade_no"); + + List<TCoursePackagePayment> list = coursePackagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("state", 1).eq("code", code).eq("payType", 2)); + TCoursePackagePayment one = list.get(0); + if(one.getPayStatus() == 1){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setPayStatus(2); + coursePackagePayment.setOrderNumber(trade_no); + } + coursePackagePaymentService.updateBatchById(list); + } + PrintWriter out = response.getWriter(); + out.write("success"); + out.flush(); + out.close(); + } + }catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackagePayment.java b/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackagePayment.java index 2869623..743d2de 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackagePayment.java +++ b/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackagePayment.java @@ -31,6 +31,10 @@ @TableId(value = "id", type = IdType.INPUT) private Long id; /** + * 业务编号 + */ + private String code; + /** * 用户id */ private Integer appUserId; @@ -43,9 +47,9 @@ */ private Integer coursePackageId; /** - * 支付方式(1=现金,2=玩湃币) + * 支付方式(1=微信,2=支付宝,3=玩湃币) */ - private String payType; + private Integer payType; /** * 课时数 */ diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java index 9b037e6..884dc02 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java @@ -18,4 +18,12 @@ */ @PostMapping("/base/appUser/queryAppUser") AppUser queryAppUser(Integer appUserId); + + + /** + * 修改用户信息 + * @param appUser + */ + @PostMapping("/base/appUser/updateAppUser") + void updateAppUser(AppUser appUser); } diff --git a/cloud-server-course/src/main/java/com/dsh/course/model/PaymentCourseVo.java b/cloud-server-course/src/main/java/com/dsh/course/model/PaymentCourseVo.java index 3d8757d..0a310c3 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/model/PaymentCourseVo.java +++ b/cloud-server-course/src/main/java/com/dsh/course/model/PaymentCourseVo.java @@ -15,7 +15,7 @@ private Integer id; @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=玩湃币)", dataType = "int", required = true) private Integer payType; - @ApiModelProperty(value = "支付金额", dataType = "double", required = true) + @ApiModelProperty(value = "支付金额(不使用优惠券的价格)", dataType = "double", required = true) private Double price; @ApiModelProperty(value = "课时id", dataType = "int", required = true) private Integer coursePackagePaymentConfigId; diff --git a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java index 356f640..2dbce49 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java +++ b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.alibaba.nacos.common.utils.UuidUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dsh.course.entity.CoursePackagePaymentConfig; @@ -26,10 +27,8 @@ import com.dsh.course.service.TCoursePackageDiscountService; import com.dsh.course.service.TCoursePackagePaymentService; import com.dsh.course.service.TCoursePackageService; -import com.dsh.course.util.GDMapGeocodingUtil; -import com.dsh.course.util.GeodesyUtil; -import com.dsh.course.util.ResultUtil; -import com.dsh.course.util.ToolUtil; +import com.dsh.course.util.*; +import com.dsh.course.util.httpClinet.HttpResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -77,6 +76,9 @@ @Resource private CouponClient couponClient; + + @Autowired + private PayMoneyUtil payMoneyUtil; @@ -493,21 +495,250 @@ } if(paymentCourseVo.getPayType() == 1){//微信支付 - + return weChatPaymentCourse(uid, price, paymentCourseVo); } if(paymentCourseVo.getPayType() == 2){//支付宝支付 - + return aliPaymentCourse(uid, price, paymentCourseVo); } if(paymentCourseVo.getPayType() == 3){//玩湃币支付 - + if(appUser.getPlayPaiCoins() < price.intValue()){ + return ResultUtil.error("报名失败,玩湃币不足,请充值!"); + } + return playPaiCoinPaymentCourse(appUser, price, paymentCourseVo); } - return null; + return ResultUtil.success(); } - public ResultUtil weChatPaymentCourse(Integer uid, PaymentCourseVo paymentCourseVo){ - TCoursePackagePayment coursePackagePayment = new TCoursePackagePayment(); -// coursePackagePayment + /** + * 课程微信支付 + * @param uid + * @param paymentPrice + * @param paymentCourseVo + * @return + * @throws Exception + */ + public ResultUtil weChatPaymentCourse(Integer uid, Double paymentPrice, PaymentCourseVo paymentCourseVo) throws Exception{ + CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getById(paymentCourseVo.getCoursePackagePaymentConfigId()); + String[] split = paymentCourseVo.getStudentIds().split(";"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); + for (String s : split) { + TCoursePackagePayment coursePackagePayment = new TCoursePackagePayment(); + coursePackagePayment.setCode(code); + coursePackagePayment.setAppUserId(uid); + coursePackagePayment.setStudentId(Integer.valueOf(s)); + coursePackagePayment.setCoursePackageId(paymentCourseVo.getId()); + coursePackagePayment.setPayType(paymentCourseVo.getPayType()); + coursePackagePayment.setClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setOriginalPrice(paymentCourseVo.getPrice()); + coursePackagePayment.setUserCouponId(paymentCourseVo.getCouponId()); + coursePackagePayment.setCashPayment(new BigDecimal(paymentPrice)); + coursePackagePayment.setTotalClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setLaveClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setAbsencesNumber(0); + coursePackagePayment.setPayUserType(1); + coursePackagePayment.setPayStatus(1); + coursePackagePayment.setPayUserId(uid); + coursePackagePayment.setStatus(1); + coursePackagePayment.setState(1); + coursePackagePayment.setInsertTime(new Date()); + coursePackagePaymentService.save(coursePackagePayment); + } + + ResultUtil weixinpay = payMoneyUtil.weixinpay("购买课程", "", code, paymentPrice.toString(), "/base/course/weChatPaymentCourseCallback", "APP"); + if(weixinpay.getCode() == 200){ + new Thread(new Runnable() { + @Override + public void run() { + try { + int num = 1; + int wait = 0; + while (num <= 10){ + int min = 5000; + wait += (min * num); + Thread.sleep(wait); + List<TCoursePackagePayment> list = coursePackagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("state", 1).eq("code", code).eq("payType", 1)); + TCoursePackagePayment one = list.get(0); + if(one.getPayStatus() == 2){ + break; + } + ResultUtil<Map<String, String>> resultUtil = payMoneyUtil.queryWXOrder(code, ""); + if(resultUtil.getCode() == 200 && one.getPayStatus() == 1){ + /** + * SUCCESS—支付成功, + * REFUND—转入退款, + * NOTPAY—未支付, + * CLOSED—已关闭, + * REVOKED—已撤销(刷卡支付), + * USERPAYING--用户支付中, + * PAYERROR--支付失败(其他原因,如银行返回失败) + */ + Map<String, String> data1 = resultUtil.getData(); + String s = data1.get("trade_state"); + String transaction_id = data1.get("transaction_id"); + if("REFUND".equals(s) || "NOTPAY".equals(s) || "CLOSED".equals(s) || "REVOKED".equals(s) || "PAYERROR".equals(s) || num == 10){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setStatus(3); + } + coursePackagePaymentService.updateBatchById(list); + break; + } + if("SUCCESS".equals(s)){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setPayStatus(2); + coursePackagePayment.setOrderNumber(transaction_id); + } + coursePackagePaymentService.updateBatchById(list); + break; + } + if("USERPAYING".equals(s)){ + num++; + } + } + } + }catch (Exception e){ + e.printStackTrace(); + } + } + }).start(); + } + return weixinpay; + } + + + /** + * 课程支付宝支付 + * @param uid + * @param paymentPrice + * @param paymentCourseVo + * @return + * @throws Exception + */ + public ResultUtil aliPaymentCourse(Integer uid, Double paymentPrice, PaymentCourseVo paymentCourseVo) throws Exception{ + CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getById(paymentCourseVo.getCoursePackagePaymentConfigId()); + String[] split = paymentCourseVo.getStudentIds().split(";"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); + for (String s : split) { + TCoursePackagePayment coursePackagePayment = new TCoursePackagePayment(); + coursePackagePayment.setCode(code); + coursePackagePayment.setAppUserId(uid); + coursePackagePayment.setStudentId(Integer.valueOf(s)); + coursePackagePayment.setCoursePackageId(paymentCourseVo.getId()); + coursePackagePayment.setPayType(paymentCourseVo.getPayType()); + coursePackagePayment.setClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setOriginalPrice(paymentCourseVo.getPrice()); + coursePackagePayment.setUserCouponId(paymentCourseVo.getCouponId()); + coursePackagePayment.setCashPayment(new BigDecimal(paymentPrice)); + coursePackagePayment.setTotalClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setLaveClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setAbsencesNumber(0); + coursePackagePayment.setPayUserType(1); + coursePackagePayment.setPayStatus(1); + coursePackagePayment.setPayUserId(uid); + coursePackagePayment.setStatus(1); + coursePackagePayment.setState(1); + coursePackagePayment.setInsertTime(new Date()); + coursePackagePaymentService.save(coursePackagePayment); + } + + ResultUtil alipay = payMoneyUtil.alipay("购买课程", "", code, paymentPrice.toString(), "/base/course/aliPaymentCourseCallback"); + if(alipay.getCode() == 200){ + new Thread(new Runnable() { + @Override + public void run() { + try { + int num = 1; + int wait = 0; + while (num <= 10){ + int min = 5000; + wait += (min * num); + Thread.sleep(wait); + List<TCoursePackagePayment> list = coursePackagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("state", 1).eq("code", code).eq("payType", 2)); + TCoursePackagePayment one = list.get(0); + if(one.getPayStatus() == 2){ + break; + } + ResultUtil<Map<String, String>> resultUtil = payMoneyUtil.queryALIOrder(code); + if(resultUtil.getCode() == 200 && one.getPayStatus() == 1){ + /** + * WAIT_BUYER_PAY(交易创建,等待买家付款)、 + * TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、 + * TRADE_SUCCESS(交易支付成功)、 + * TRADE_FINISHED(交易结束,不可退款) + */ + Map<String, String> data1 = resultUtil.getData(); + String s = data1.get("tradeStatus"); + String tradeNo = data1.get("tradeNo"); + if("TRADE_CLOSED".equals(s) || "TRADE_FINISHED".equals(s) || num == 10){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setStatus(3); + } + coursePackagePaymentService.updateBatchById(list); + break; + } + if("TRADE_SUCCESS".equals(s)){ + for (TCoursePackagePayment coursePackagePayment : list) { + coursePackagePayment.setPayStatus(2); + coursePackagePayment.setOrderNumber(tradeNo); + } + coursePackagePaymentService.updateBatchById(list); + break; + } + if("WAIT_BUYER_PAY".equals(s)){ + num++; + } + } + } + }catch (Exception e){ + e.printStackTrace(); + } + } + }).start(); + } + return alipay; + } + + + /** + * 玩湃币支付课程 + * @param appUser + * @param paymentPrice + * @param paymentCourseVo + * @return + * @throws Exception + */ + public ResultUtil playPaiCoinPaymentCourse(AppUser appUser, Double paymentPrice, PaymentCourseVo paymentCourseVo) throws Exception{ + CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getById(paymentCourseVo.getCoursePackagePaymentConfigId()); + String[] split = paymentCourseVo.getStudentIds().split(";"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); + for (String s : split) { + TCoursePackagePayment coursePackagePayment = new TCoursePackagePayment(); + coursePackagePayment.setCode(code); + coursePackagePayment.setAppUserId(appUser.getId()); + coursePackagePayment.setStudentId(Integer.valueOf(s)); + coursePackagePayment.setCoursePackageId(paymentCourseVo.getId()); + coursePackagePayment.setPayType(paymentCourseVo.getPayType()); + coursePackagePayment.setClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setOriginalPrice(paymentCourseVo.getPrice()); + coursePackagePayment.setPlayPaiCoin(paymentPrice.intValue()); + coursePackagePayment.setTotalClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setLaveClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePayment.setAbsencesNumber(0); + coursePackagePayment.setPayUserType(1); + coursePackagePayment.setPayStatus(2); + coursePackagePayment.setPayUserId(appUser.getId()); + coursePackagePayment.setStatus(1); + coursePackagePayment.setState(1); + coursePackagePayment.setInsertTime(new Date()); + coursePackagePaymentService.save(coursePackagePayment); + } + + Integer playPaiCoins = appUser.getPlayPaiCoins(); + appUser.setPlayPaiCoins(playPaiCoins - paymentPrice.intValue()); + appUserClient.updateAppUser(appUser); return ResultUtil.success(); } } diff --git a/cloud-server-course/src/main/java/com/dsh/course/util/MD5AndKL.java b/cloud-server-course/src/main/java/com/dsh/course/util/MD5AndKL.java new file mode 100644 index 0000000..f50f364 --- /dev/null +++ b/cloud-server-course/src/main/java/com/dsh/course/util/MD5AndKL.java @@ -0,0 +1,112 @@ +package com.dsh.course.util; + +import java.security.MessageDigest; + +public class MD5AndKL { + + /** + * MD5加码。32位 + * + * @param inStr + * @return + */ + public static String MD5(String inStr) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + byte[] md5Bytes = md5.digest(inStr.getBytes()); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++) { + int val = ((int) md5Bytes[i]) & 0xff; + if (val < 16) { + hexValue.append("0"); + } + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } + + /** + * 可逆的加密算法 + * + * @param inStr + * @return + */ + public static String KL(String inStr) { + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++) { + a[i] = (char) (a[i] ^ 't'); + } + String s = new String(a); + return s; + } + + /** + * 加密后解密 + * + * @param inStr + * @return + */ + public static String JM(String inStr) { + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++) { + a[i] = (char) (a[i] ^ 't'); + } + String k = new String(a); + return k; + } + + + + private static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) + resultSb.append(byteToHexString(b[i])); + + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n += 256; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)){ + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + }else{ + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return resultString; + } + + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; + + public static void main(String args[]) { + + System.out.println("MD5后再加密:" + KL(MD5("123456"))); + System.out.println(MD5("123456")); + // System.out.println("加密:" + KL(MD5("123456"))); + // s = KL(s); + // System.out.println("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055")); + // System.out.println("解密:" + JM(KL(s))); + // System.out.println("解密为MD5后的:" + KL(KL(MD5(s)))); + // System.out.println(JM("5d62957bb57d3e49dcf48a0df064be4c")); + // System.out.println(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321"))); + } +} diff --git a/cloud-server-course/src/main/java/com/dsh/course/util/PayMoneyUtil.java b/cloud-server-course/src/main/java/com/dsh/course/util/PayMoneyUtil.java new file mode 100644 index 0000000..759c28d --- /dev/null +++ b/cloud-server-course/src/main/java/com/dsh/course/util/PayMoneyUtil.java @@ -0,0 +1,806 @@ +package com.dsh.course.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.domain.AlipayTradeAppPayModel; +import com.alipay.api.request.AlipayTradeAppPayRequest; +import com.alipay.api.request.AlipayTradePrecreateRequest; +import com.alipay.api.request.AlipayTradeQueryRequest; +import com.alipay.api.request.AlipayTradeRefundRequest; +import com.alipay.api.response.AlipayTradeAppPayResponse; +import com.alipay.api.response.AlipayTradePrecreateResponse; +import com.alipay.api.response.AlipayTradeQueryResponse; +import com.alipay.api.response.AlipayTradeRefundResponse; +import com.dsh.course.util.httpClinet.HttpClientUtil; +import org.apache.commons.collections.map.HashedMap; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.math.BigDecimal; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.util.*; + +/** + * 第三方支付工具类 + */ +@Component +public class PayMoneyUtil { + //支付宝appid + private String aliAppid = ""; + //支付宝开发者应用私钥 + private String appPrivateKey = ""; + //支付宝应用公钥 + private String alipayPublicKey = ""; + //支付宝支付公钥 + private String alipay_public_key = ""; + //微信appid + private String appid = ""; + //微信商户号 + private String mchId = ""; + //微信商户号 + private String key = ""; + //支付回调网关地址 + @Value("${callbackPath}") + private String callbackPath; + //微信支付证书地址 + private String wechatPayCertificatesFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.p12"; + //微信私钥证书地址 + private String privateKeyFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.pem"; + + + + + /** + * 支付宝支付 + */ + public ResultUtil<String> alipay(String body, String subject, String outTradeNo, String amount, String notifyUrl){ + //实例化客户端 + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipayPublicKey, "RSA2"); + //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay + AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); + //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 + AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); + model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 + model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。 + model.setOutTradeNo(outTradeNo);//商户网站唯一订单号 + model.setTimeoutExpress("30m"); + model.setTotalAmount(amount);//付款金额 + model.setProductCode("QUICK_MSECURITY_PAY"); + request.setBizModel(model); + request.setNotifyUrl(callbackPath + notifyUrl); + try { + //这里和普通的接口调用不同,使用的是sdkExecute + AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); + System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。 + return ResultUtil.success(response.getBody()); + } catch (AlipayApiException e) { + e.printStackTrace(); + return ResultUtil.error("调起支付异常", ""); + } + } + + + /** + * 支付宝扫码支付下单 + * @param body + * @param subject + * @param outTradeNo + * @param amount + * @param notifyUrl + * @return + */ + public ResultUtil aliScanCodePay(String body, String subject, String outTradeNo, String amount, String notifyUrl){ + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); //获得初始化的AlipayClient + AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类 + request.setBizContent("{" + + " \"out_trade_no\":\"" + outTradeNo + "\"," +//商户订单号 + " \"total_amount\":\"" + 1 + "\"," + + " \"subject\":\"" + subject + "\"," + + " \"notify_url\":\"" + callbackPath + notifyUrl + "\"," + + " \"body\":\"" + body + "\"," + + " \"store_id\":\"NJ_001\"," + + " \"timeout_express\":\"90m\"}");//订单允许的最晚付款时间 + AlipayTradePrecreateResponse response = null; + try { + response = alipayClient.execute(request); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + JSONObject alipay_trade_precreate_response = JSON.parseObject(response.getBody()).getJSONObject("alipay_trade_precreate_response"); + + System.err.print(alipay_trade_precreate_response.getString("qr_code")); + return ResultUtil.success(alipay_trade_precreate_response.getString("qr_code")); + } + + + /** + * 支付成功后的回调处理逻辑 + * @param request + */ + public Map<String, String> alipayCallback(HttpServletRequest request){ + //获取支付宝POST过来反馈信息 + Map<String,String> params = new HashMap<String,String>(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { + String name = (String) iter.next(); + String[] values = (String[]) requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] + : valueStr + values[i] + ","; + } + //乱码解决,这段代码在出现乱码时使用。 + //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); + params.put(name, valueStr); + } + //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。 + //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type) +// try { +// boolean flag = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8","RSA2"); +// if(flag){ + Map<String, String> map = new HashMap<>(); + String out_trade_no = params.get("out_trade_no"); + String subject = params.get("subject"); + String total_amount = params.get("total_amount"); + String trade_no = params.get("trade_no"); + map.put("out_trade_no", out_trade_no);//商家订单号 + map.put("subject", subject); + map.put("total_amount", total_amount); + map.put("trade_no", trade_no);//支付宝交易号 + return map; +// } + +// } catch (AlipayApiException e) { +// e.printStackTrace(); +// } +// return null; + } + + + /** + * 支付宝查询订单支付状态 + * @param out_trade_no + * @return + * @throws Exception + */ + public ResultUtil<Map<String, String>> queryALIOrder(String out_trade_no) throws Exception{ + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2"); + AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); + request.setBizContent("{" + + "\"out_trade_no\":\"" + out_trade_no + + "\"}"); + AlipayTradeQueryResponse response = alipayClient.execute(request); + if(response.isSuccess()){ + String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款) + String tradeNo = response.getTradeNo(); + Map<String, String> map = new HashMap<>(); + map.put("tradeStatus", tradeStatus); + map.put("tradeNo", tradeNo); + return ResultUtil.success(map); + } else { + return ResultUtil.error(response.getMsg()); + } + } + + + + /** + * 微信统一下单 + * @param body 商品描述 + * @param attach 附加数据 + * @param out_trade_no 商户订单号 + * @param total_fee 标价金额 + * @param notify_url 通知地址 + * @param tradeType 交易类型 + * @return + */ + public ResultUtil weixinpay(String body, String attach, String out_trade_no, String total_fee, String notify_url, String tradeType) throws Exception{ + int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); + String hostAddress = null; + try { + hostAddress = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + String nonce_str = UUIDUtil.getRandomCode(16); + Map<String, Object> map = new HashMap<>(); + map.put("appid", appid); + map.put("mch_id", mchId); + map.put("nonce_str", nonce_str); + map.put("body", body); + map.put("attach", attach);//存储订单id + map.put("out_trade_no", out_trade_no);//存储的订单code + map.put("total_fee", i); + map.put("spbill_create_ip", hostAddress); + map.put("notify_url", callbackPath + notify_url); + map.put("trade_type", tradeType); + String s = this.weixinSignature(map); + map.put("sign", s); + + String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; + //设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + StringBuffer xmlString = new StringBuffer(); + Set<String> strings = map.keySet(); + String[] keys = {}; + keys = strings.toArray(keys); + Arrays.sort(keys); + xmlString.append("<xml>"); + for(int l = 0; l < keys.length; l++){ + xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); + } + xmlString.append("</xml>"); + + Map<String, String> map1 = null; + String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData(); + //将结果xml解析成map + body1 = body1.replaceAll("<!\\[CDATA\\[",""); + body1 = body1.replaceAll("]]>", ""); + try { + map1 = this.xmlToMap(body1, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + String return_code = map1.get("return_code"); + if("SUCCESS".equals(return_code)){ + String result_code = map1.get("result_code"); + if("SUCCESS".equals(result_code)){ + String type = map1.get("trade_type"); + switch (type){ + case "JSAPI": + break; + case "NATIVE": + String code_url = map1.get("code_url"); + return ResultUtil.success(code_url); + case "APP": + String prepay_id = map1.get("prepay_id"); + //重新进行签名后返回给前端 + Map<String, Object> map2 = new HashMap<>(); + map2.put("appid", appid); + map2.put("noncestr", nonce_str); + map2.put("package", "Sign=WXPay"); + map2.put("partnerid", mchId); + map2.put("prepayid", prepay_id); + map2.put("timestamp", new Date().getTime() / 1000); + String s1 = this.weixinSignature(map2); + map2.put("sign", s1); + System.err.println(map2); + return ResultUtil.success(map2); + } + return null; + }else{ + System.err.println(map1.get("err_code_des")); + return ResultUtil.error(map1.get("err_code_des")); + } + }else{ + System.err.println(map1.get("return_msg") + appid + "----" + mchId); + return ResultUtil.error(map1.get("return_msg"), new JSONObject()); + } + } + + + + + + /** + * 微信支付成功后的回调处理 + * @param request + */ + public Map<String, String> weixinpayCallback(HttpServletRequest request){ + try { + String param = this.getParam(request); + param = param.replaceAll("<!\\[CDATA\\[",""); + param = param.replaceAll("]]>", ""); + Map<String, String> map = this.xmlToMap(param, "UTF-8"); + String return_code = map.get("return_code"); + if("SUCCESS".equals(return_code)){ + String result_code = map.get("result_code"); + if("SUCCESS".equals(result_code)){ + Map<String, String> map1 = new HashedMap(); + map1.put("nonce_str", map.get("nonce_str")); + map1.put("out_trade_no", map.get("out_trade_no")); + map1.put("attach", map.get("attach")); + map1.put("total_fee", map.get("total_fee")); + map1.put("transaction_id", map.get("transaction_id"));//微信支付订单号 + String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; + map1.put("result", result); + return map1; + }else{ + System.err.println(map.get("err_code_des")); + } + }else{ + System.err.println(map.get("return_msg")); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 微信扫码收款 + * @param body 商品描述 + * @param attach 附加数据 + * @param nonce_str 随机字符串 + * @param out_trade_no 商户订单号 + * @param total_fee 订单金额 + * @param auth_code 授权码 扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头) + * @return + */ + public ResultUtil wxScanQRCodePay(String body, String attach, String nonce_str, String out_trade_no, String total_fee, String auth_code){ + int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); + String hostAddress = null; + try { + InetAddress address = InetAddress.getLocalHost(); + hostAddress = address.getHostAddress(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + String randomCode = null; + try { + randomCode = UUIDUtil.getRandomCode(10); + } catch (Exception e) { + e.printStackTrace(); + } + Map<String, Object> map = new HashMap<>(); + map.put("appid", appid); + map.put("mch_id", mchId); + map.put("nonce_str", nonce_str);//存储的支付人员id,员工扫描二维码支付的时候存储的是收款员工id + map.put("body", body); + map.put("attach", attach);//存储的费用月份数据,员工扫描二维码支付的时候存储的是收费项id + map.put("out_trade_no", randomCode + "_" + out_trade_no);//存储的房间id + map.put("total_fee", i); + map.put("spbill_create_ip", hostAddress); + map.put("auth_code", auth_code); + String s = this.weixinSignature(map); + map.put("sign", s); + + String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; + //设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + StringBuffer xmlString = new StringBuffer(); + Set<String> strings = map.keySet(); + String[] keys = {}; + keys = strings.toArray(keys); + Arrays.sort(keys); + xmlString.append("<xml>"); + for(int l = 0; l < keys.length; l++){ + xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); + } + xmlString.append("</xml>"); + + Map<String, String> map1 = null; + String body1 = null; + try { + body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData(); + } catch (Exception e) { + e.printStackTrace(); + } + //将结果xml解析成map + body1 = body1.replaceAll("<!\\[CDATA\\[",""); + body1 = body1.replaceAll("]]>", ""); + try { + map1 = this.xmlToMap(body1, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + String return_code = map1.get("return_code"); + if("SUCCESS".equals(return_code)){ + String result_code = map1.get("result_code"); + if("SUCCESS".equals(result_code)){ + String type = map1.get("trade_type"); + switch (type){ + case "JSAPI": + break; + case "NATIVE": + String code_url = map1.get("code_url"); + return ResultUtil.success(code_url); + case "APP": + String prepay_id = map1.get("prepay_id"); + //重新进行签名后返回给前端 + Map<String, Object> map2 = new HashMap<>(); + map2.put("appid", appid); + map2.put("noncestr", nonce_str); + map2.put("package", "Sign=WXPay"); + map2.put("partnerid", mchId); + map2.put("prepayid", prepay_id); + map2.put("timestamp", new Date().getTime() + ""); + String s1 = this.weixinSignature(map2); + + map2.put("pac", "Sign=WXPay"); + map2.put("sign", s1); +// System.err.println(map2); + return ResultUtil.success(map2); + } + return null; + }else{ +// System.err.println(map1.get("err_code_des")); + return ResultUtil.error(map1.get("err_code_des")); + } + }else{ +// System.err.println(map1.get("return_msg") + appid + "----" + mchId); + return ResultUtil.error(map1.get("return_msg"), new JSONObject()); + } + } + + + /** + * 支付宝扫码收款 + * @param data + * @return + */ + public Object aliScanQRCodePay(String data){ + return null; + } + + + /** + * 微信退款申请 + * @param transaction_id 微信订单号。微信生成的订单号,在支付通知中有返回 + * @param out_refund_no 商户退款单号。商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 + * @param total_fee 订单金额。订单总金额,单位为分,只能为整数 + * @param refund_fee 退款金额。退款总金额,订单总金额,单位为分,只能为整数 + * @param notify_url 退款结果通知url。异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。 + * @return + */ + public Map<String, String> wxRefund(String transaction_id, String out_refund_no, String total_fee, String refund_fee, String notify_url){ + int tf = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); + int rf = new BigDecimal(refund_fee).multiply(new BigDecimal("100")).intValue(); + String nonce_str = UUIDUtil.getRandomCode(); + Map<String, Object> map = new HashMap<>(); + map.put("appid", appid); + map.put("mch_id", mchId); + map.put("nonce_str", nonce_str); + map.put("transaction_id", transaction_id); + map.put("out_refund_no", out_refund_no); + map.put("total_fee", tf); + map.put("refund_fee", rf); + map.put("notify_url", callbackPath + notify_url); + String s = this.weixinSignature(map); + map.put("sign", s); + + String url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; + //设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + StringBuffer xmlString = new StringBuffer(); + Set<String> strings = map.keySet(); + String[] keys = {}; + keys = strings.toArray(keys); + Arrays.sort(keys); + xmlString.append("<xml>"); + for(int l = 0; l < keys.length; l++){ + xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); + } + xmlString.append("</xml>"); + + Map<String, String> map1 = null; + String body1 = null; + try { + body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData(); + } catch (Exception e) { + e.printStackTrace(); + } + //将结果xml解析成map + body1 = body1.replaceAll("<!\\[CDATA\\[",""); + body1 = body1.replaceAll("]]>", ""); + try { + map1 = this.xmlToMap(body1, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + String return_code = map1.get("return_code"); + Map<String, String> map2 = new HashMap<>(); + if("SUCCESS".equals(return_code)){ + String result_code = map1.get("result_code"); + if("SUCCESS".equals(result_code)){ + map2.put("return_code", result_code); + map2.put("refund_id", String.valueOf(map1.get("refund_id")));//微信退款订单号 + map2.put("refund_fee", String.valueOf(map1.get("refund_fee")));//退款金额 + return map2; + }else{ + map2.put("return_code", result_code); + map2.put("return_msg", map1.get("err_code_des")); + return map2; + } + }else{ + map2.put("return_code", return_code); + map2.put("return_msg", map1.get("return_msg")); + return map2; + } + } + + + /** + * 微信退款成功后的回调处理 + * @param request + * @return + */ + public Map<String, String> wxRefundCallback(HttpServletRequest request){ + try { + String param = this.getParam(request); + param = param.replaceAll("<!\\[CDATA\\[",""); + param = param.replaceAll("]]>", ""); + Map<String, String> map = this.xmlToMap(param, "UTF-8"); + String return_code = map.get("return_code"); + if("SUCCESS".equals(return_code)){ + String req_info = map.get("req_info");//加密信息请用商户秘钥进行解密 + String s = this.wxDecrypt(req_info); + s = s.replaceAll("<!\\[CDATA\\[",""); + s = s.replaceAll("]]>", ""); + map = this.xmlToMap(s, "UTF-8"); + Map<String, String> map1 = new HashMap<>(); + map1.put("refund_id", map.get("refund_id")); + map1.put("out_refund_no", map.get("out_refund_no")); + return map1; + }else{ +// System.err.println(map.get("return_msg")); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 支付宝退款 + * @param trade_no 支付宝交易号 + * @param refund_amount 退款金额 + * @return + * @throws AlipayApiException + */ + public Map<String, String> aliRefund(String trade_no, String refund_amount) throws AlipayApiException { + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2"); + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("trade_no", trade_no); + jsonObject.put("refund_amount", refund_amount); + request.setBizContent(jsonObject.toJSONString()); + AlipayTradeRefundResponse response = alipayClient.execute(request); + Map<String, String> map = new HashMap<>(); + if(response.isSuccess()){ + System.out.println("调用成功"); + String outTradeNo = response.getOutTradeNo(); + map.put("code", response.getCode());//10000 + map.put("trade_no", response.getTradeNo());//支付宝交易号 + map.put("out_trade_no", outTradeNo);//商户订单号 + } else { + System.out.println("调用失败"); + map.put("code", response.getCode()); + map.put("msg", response.getSubMsg()); + } + return map; + } + + + /** + * 查询微信支付订单 + * @return + * @throws Exception + */ + public ResultUtil<Map<String, String>> queryWXOrder(String out_trade_no, String transaction_id) throws Exception{ + String url = "https://api.mch.weixin.qq.com/pay/orderquery"; + String nonce_str = UUIDUtil.getRandomCode(16); + Map<String, Object> map = new HashMap<>(); + map.put("appid", appid); + map.put("mch_id", mchId); + map.put("out_trade_no", out_trade_no);//商户订单号 + map.put("transaction_id", transaction_id);//微信订单号 + map.put("nonce_str", nonce_str);//随机字符串 + String s = this.weixinSignature(map); + map.put("sign", s); + + //设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + StringBuffer xmlString = new StringBuffer(); + Set<String> strings = map.keySet(); + String[] keys = {}; + keys = strings.toArray(keys); + Arrays.sort(keys); + xmlString.append("<xml>"); + for(int l = 0; l < keys.length; l++){ + xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); + } + xmlString.append("</xml>"); + + Map<String, String> map1 = null; + String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData(); + //将结果xml解析成map + body1 = body1.replaceAll("<!\\[CDATA\\[",""); + body1 = body1.replaceAll("]]>", ""); + try { + map1 = this.xmlToMap(body1, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + String return_code = map1.get("return_code"); + if("SUCCESS".equals(return_code)){ + String result_code = map1.get("result_code"); + if("SUCCESS".equals(result_code)){ + Map<String, String> map2 = new HashMap<>(); + map2.put("trade_type", map1.get("trade_type")); + map2.put("trade_state", map1.get("trade_state"));//订单状态SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败) + map2.put("transaction_id", map1.get("transaction_id")); + return ResultUtil.success(map2); + }else{ + System.err.println(map1.get("err_code_des")); + return ResultUtil.error(map1.get("err_code_des")); + } + }else{ + System.err.println(map1.get("return_msg") + appid + "----" + mchId); + return ResultUtil.error(map1.get("return_msg")); + } + } + + + + + /** + * 获取请求内容 + * @param request + * @return + * @throws IOException + */ + private String getParam(HttpServletRequest request) throws IOException { + // 读取参数 + InputStream inputStream; + StringBuilder sb = new StringBuilder(); + inputStream = request.getInputStream(); + String s; + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + while ((s = in.readLine()) != null) { + sb.append(s); + } + in.close(); + inputStream.close(); + return sb.toString(); + } + + + /** + * 微信下单的签名算法 + * @param map + * @return + */ + private String weixinSignature(Map<String, Object> map){ + try { + Set<Map.Entry<String, Object>> entries = map.entrySet(); + List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries); + // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) + Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() { + public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) { + return (o1.getKey()).toString().compareTo(o2.getKey()); + } + }); + // 构造签名键值对的格式 + StringBuilder sb = new StringBuilder(); + for (Map.Entry<String, Object> item : infoIds) { + if (item.getKey() != null || item.getKey() != "") { + String key = item.getKey(); + Object val = item.getValue(); + if (!(val == "" || val == null)) { + sb.append(key + "=" + val + "&"); + } + } + } + sb.append("key=" + key); + String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 + return sign; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + + /** + * 微信退款成功后的解密 + * @param req_info + * @return + */ + private String wxDecrypt(String req_info) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + byte[] decode = Base64.getDecoder().decode(req_info); + String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase(); + if (Security.getProvider("BC") == null){ + Security.addProvider(new BouncyCastleProvider()); + } + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); + SecretKeySpec secretKeySpec = new SecretKeySpec(sign.getBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + return new String(cipher.doFinal(decode)); + } + + + public static void main(String[] ages){ +// PayMoneyUtil payMoneyUtil = new PayMoneyUtil(); +// payMoneyUtil.weixinpay("测试", "123", "12.5", ""); + } + + + /** + * xml转map + * @param xml + * @param charset + * @return + * @throws UnsupportedEncodingException + * @throws DocumentException + */ + public static Map<String, String> xmlToMap(String xml, String charset) throws UnsupportedEncodingException, DocumentException { + + Map<String, String> respMap = new HashMap<String, String>(); + + SAXReader reader = new SAXReader(); + Document doc = reader.read(new ByteArrayInputStream(xml.getBytes(charset))); + Element root = doc.getRootElement(); + xmlToMap(root, respMap); + return respMap; + } + + public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap){ + if (tmpElement.isTextOnly()) { + respMap.put(tmpElement.getName(), tmpElement.getText()); + return respMap; + } + + @SuppressWarnings("unchecked") + Iterator<Element> eItor = tmpElement.elementIterator(); + while (eItor.hasNext()) { + Element element = eItor.next(); + xmlToMap(element, respMap); + } + return respMap; + } +} diff --git a/cloud-server-course/src/main/java/com/dsh/course/util/UUIDUtil.java b/cloud-server-course/src/main/java/com/dsh/course/util/UUIDUtil.java new file mode 100644 index 0000000..702dc76 --- /dev/null +++ b/cloud-server-course/src/main/java/com/dsh/course/util/UUIDUtil.java @@ -0,0 +1,101 @@ +package com.dsh.course.util; + + + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +/** + * 定义生成随机码的工具类 + */ +public class UUIDUtil { + + private int i = 1; + + + /** + * 定义生成原生的UUID随机码 + * @return + */ + public static String getNativeUUID(){ + return UUID.randomUUID().toString(); + } + + + /** + * 生成32位随机码 + * @return + */ + public static String getRandomCode(){ + return UUIDUtil.getNativeUUID().replaceAll("-", ""); + } + + + /** + * 获取给定长度的随机码 + * @param num + * @return + * @throws Exception + */ + public static String getRandomCode(Integer num) throws Exception{ + String str = null; + if(0 < num){ + if(num % 32 > 0){ + Integer s = num / 32; + Integer l = num % 32; + StringBuffer sb = new StringBuffer(); + for(int i = 0; i < s; i++){ + sb.append(UUIDUtil.getRandomCode()); + } + sb.append(UUIDUtil.getRandomCode().substring(0, l)); + str = sb.toString(); + }else if(num % 32 == 0){ + Integer s = num / 32; + StringBuffer sb = new StringBuffer(); + for(int i = 0; i < s; i++){ + sb.append(UUIDUtil.getRandomCode()); + } + str = sb.toString(); + }else{ + str = UUIDUtil.getRandomCode().substring(0, num); + } + }else{ + throw new Exception("参数只能大于0"); + } + return str; + } + + + /** + * 获取根据当前时间的字符串数据 + * @return + */ + public synchronized static String getTimeStr(){ + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmssS"); + return simpleDateFormat.format(new Date()); + } + + + /** + * @Description: 获取数字随机码 + * @Author pzb + * @Date 2021/8/11 16:52 + * @Param + * @Return + * @Exception + */ + public static String getNumberRandom(Integer num){ + if(null == num){ + num = 32; + } + StringBuffer sb = new StringBuffer(); + for(int i = 0; i < num; i++){ + sb.append(Double.valueOf(Math.random() * 10).intValue()); + } + return sb.toString(); + } + + + +} -- Gitblit v1.7.1