Commit cf824362 authored by liuyang's avatar liuyang

update

parent 2c10bbff
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<docker.plugin.version>1.1.1</docker.plugin.version> <docker.plugin.version>1.1.1</docker.plugin.version>
<baidu.aip.version>4.11.3</baidu.aip.version> <baidu.aip.version>4.11.3</baidu.aip.version>
<shiro.version>1.4.0</shiro.version> <shiro.version>1.4.0</shiro.version>
<weixin-java.version>3.6.0</weixin-java.version> <weixin-java.version>4.0.0</weixin-java.version>
<hutool.version>5.3.5</hutool.version> <hutool.version>5.3.5</hutool.version>
<docker.registry>fywlsoft.cn:57802</docker.registry> <docker.registry>fywlsoft.cn:57802</docker.registry>
<docker.image.prefix>argus</docker.image.prefix> <docker.image.prefix>argus</docker.image.prefix>
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId> <artifactId>weixin-java-miniapp</artifactId>
<version>3.7.0</version> <version>${weixin-java.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<artifactId>bcpkix-jdk15on</artifactId> <artifactId>bcpkix-jdk15on</artifactId>
...@@ -248,6 +248,11 @@ ...@@ -248,6 +248,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${weixin-java.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
......
package com.qkdata.biz.enums;
/**
* 支付类型
*/
public enum PayMethodEnum {
WeiXin,
AliPay;
}
package com.qkdata.biz.enums;
/**
* 支付来源
*/
public enum PaySourceEnum {
NATIVE,
APP,
MWEB,
JSAPI
}
package com.qkdata.biz.enums;
/**
* 订单状态
*/
public enum ProductOrderStatusEnum {
WAIT_PAY,
PAY_COMPLETE,
PAY_FAILD;
}
package com.qkdata.biz.enums;
/**
* 订单类型
*/
public enum ProductTypeEnum {
USER_VIP,
ENTERPRISE_VIP,
COURSE_BUY;
}
package com.qkdata.biz.management.entity; package com.qkdata.biz.management.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.qkdata.common.base.entity.BasePO; import com.qkdata.common.base.entity.BasePO;
import lombok.Data; import lombok.Data;
...@@ -14,12 +15,13 @@ import lombok.EqualsAndHashCode; ...@@ -14,12 +15,13 @@ import lombok.EqualsAndHashCode;
* @since 2021-05-20 * @since 2021-05-20
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
@TableName("course_attachment") @TableName("course_attachment")
public class CourseAttachmentPO extends BasePO { public class CourseAttachmentPO {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId
private Long id;
/** /**
* 课程ID * 课程ID
*/ */
......
package com.qkdata.biz.management.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.qkdata.biz.enums.PayMethodEnum;
import com.qkdata.biz.enums.ProductOrderStatusEnum;
import com.qkdata.biz.enums.ProductTypeEnum;
import com.qkdata.common.base.entity.BasePO;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 产品订单
* </p>
*
* @author liuyang
* @since 2021-06-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("product_order")
public class ProductOrderPO extends BasePO {
private static final long serialVersionUID = 1L;
/**
* 订单编号
*/
private String orderNo;
/**
* 订单名称
*/
private String orderName;
/**
* 用户ID
*/
private Long userId;
/**
* 产品类型(个人包月、企业包月、付费点播)
*/
private ProductTypeEnum productType;
/**
* 课程ID
*/
private Long courseId;
/**
* 产品单价
*/
private BigDecimal productPrice;
/**
* 产品购买数量
*/
private Integer productCount;
/**
* 订单金额
*/
private BigDecimal orderMoney;
/**
* 支付金额
*/
private BigDecimal paymentMoney;
/**
* 支付方式(微信、支付宝)
*/
private PayMethodEnum payMethod;
/**
* 订单状态
*/
private ProductOrderStatusEnum status;
}
package com.qkdata.biz.management.mapper;
import com.qkdata.biz.management.entity.ProductOrderPO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 产品订单 Mapper 接口
* </p>
*
* @author liuyang
* @since 2021-06-02
*/
@Mapper
public interface ProductOrderMapper extends BaseMapper<ProductOrderPO> {
}
package com.qkdata.biz.management.service;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.qkdata.biz.common.BizConstants;
import com.qkdata.biz.enums.*;
import com.qkdata.biz.management.entity.CoursePO;
import com.qkdata.biz.management.entity.ProductOrderPO;
import com.qkdata.biz.management.mapper.ProductOrderMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qkdata.biz.sys.entity.SysUserPO;
import com.qkdata.biz.sys.service.SysConfigService;
import com.qkdata.biz.sys.service.SysUserService;
import com.qkdata.biz.web.vo.CreateOrderResult;
import com.qkdata.biz.web.vo.FullUserInfo;
import com.qkdata.biz.web.vo.UserBuyVIPModel;
import com.qkdata.common.base.exception.BusinessException;
import com.qkdata.common.util.HttpContextUtils;
import com.qkdata.common.util.IPUtils;
import com.qkdata.common.util.UserContext;
import com.qkdata.wx.pay.config.WxPayProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.math.BigDecimal;
/**
* <p>
* 产品订单 服务类
* </p>
*
* @author liuyang
* @since 2021-06-02
*/
@Service
public class ProductOrderService extends ServiceImpl<ProductOrderMapper, ProductOrderPO> {
@Autowired
private WxPayService wxService;
@Autowired
private CourseService courseService;
@Autowired
private SysConfigService sysConfigService;
@Autowired
private SysUserService sysUserService;
@Value("${frontend.domain}")
private String frontendDomain;
public void createOrder(UserBuyVIPModel model) {
}
private String generateOrderNo() {
DateTime nowDateTime = DateUtil.date();
String dateStr = DateUtil.format(nowDateTime,"yyyyMMddHHmmssSSS");
return dateStr + RandomUtil.randomNumbers(4);
}
private <T> T wxCreateOrder(ProductOrderPO order, PaySourceEnum source) throws WxPayException {
WxPayUnifiedOrderRequest payRequest = new WxPayUnifiedOrderRequest();
if(wxService.getConfig().isUseSandboxEnv()){
String key = wxService.getSandboxSignKey();
wxService.getConfig().setMchKey(key);
}
payRequest.setNonceStr(RandomUtil.randomString(32));
payRequest.setBody(StrUtil.format("在线培训网站-{}",order.getOrderName()));
payRequest.setOutTradeNo(order.getOrderNo());
//金额元转为分
BigDecimal fee = order.getPaymentMoney().multiply(new BigDecimal(100));
if (wxService.getConfig().isUseSandboxEnv()){
// payRequest.setTotalFee(101);//成功用例
payRequest.setTotalFee(102);//失败用例
}else {
payRequest.setTotalFee(fee.intValue());
}
payRequest.setSpbillCreateIp(IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest()));
payRequest.setNotifyUrl(StrUtil.format("{}{}",frontendDomain,"/online-edu-backend/wx/pay/notify/order"));
payRequest.setTradeType(source.name());
return wxService.createOrder(payRequest);
}
public CreateOrderResult userBuyVIP(UserBuyVIPModel model) {
CreateOrderResult result = new CreateOrderResult();
ProductOrderPO orderPO = createPO(ProductTypeEnum.USER_VIP,model.getCount(),model.getPayMethod(),model.getCourseId());
result.setOrderNo(orderPO.getOrderNo());
if (orderPO.getPayMethod() == PayMethodEnum.WeiXin){
try {
Object rtObj = wxCreateOrder(orderPO,model.getSource());
result.setResult(rtObj);
save(orderPO);
return result;
} catch (WxPayException e) {
log.error(e.getMessage(),e);
throw new BusinessException("微信支付异常");
}
}else if (orderPO.getPayMethod() == PayMethodEnum.AliPay){
return result;
}
return result;
}
private ProductOrderPO createPO(ProductTypeEnum productType, int count, PayMethodEnum payMehtod,Long courseId){
ProductOrderPO po = new ProductOrderPO();
po.setOrderNo(generateOrderNo());
po.setProductType(productType);
switch (po.getProductType()){
case USER_VIP:
po.setOrderName("会员包月");
String vipPriceStr = sysConfigService.getValueByKey(BizConstants.CONFIG_KEY_VIP_PRICE);
if (StrUtil.isBlank(vipPriceStr)){
throw new BusinessException("处理错误,尚未配置会员价格");
}
po.setProductPrice(new BigDecimal(vipPriceStr));
break;
case ENTERPRISE_VIP:
po.setOrderName("企业会员");
String enterpriseVipPriceStr = sysConfigService.getValueByKey(BizConstants.CONFIG_KEY_ENTERPRICE_VIP_PRICE);
if (StrUtil.isBlank(enterpriseVipPriceStr)){
throw new BusinessException("处理错误,尚未配置企业会员价格");
}
po.setProductPrice(new BigDecimal(enterpriseVipPriceStr));
break;
case COURSE_BUY:
CoursePO coursePO = courseService.getById(courseId);
if (coursePO == null){
throw new BusinessException("请求错误,课程不存在");
}
String orderName = "付费点播:{}";
po.setOrderName(StrUtil.format(orderName,coursePO.getName()));
FullUserInfo userInfo = sysUserService.findFullUserInfo(UserContext.getUser().getUsername());
if (userInfo.getType() == AccountTypeEnum.USER){
po.setProductPrice(coursePO.getPrice());
}else {
po.setProductPrice(coursePO.getVipPrice());
}
break;
default:
throw new BusinessException("购买产品类型错误");
}
po.setProductCount(count);
po.setOrderMoney(po.getProductPrice().multiply(new BigDecimal(po.getProductCount())));
po.setPaymentMoney(po.getOrderMoney());
po.setCourseId(courseId);
po.setPayMethod(payMehtod);
po.setStatus(ProductOrderStatusEnum.WAIT_PAY);
po.setUserId(UserContext.getUserId());
return po;
}
public void updateStatus(String outTradeNo, ProductOrderStatusEnum status) {
ProductOrderPO po = new ProductOrderPO();
po.setStatus(status);
update(po, Wrappers.<ProductOrderPO>lambdaUpdate().eq(ProductOrderPO::getOrderNo,outTradeNo));
}
public ProductOrderStatusEnum queryStatus(String orderNo) {
ProductOrderPO orderPO = getByOrderNo(orderNo);
if (orderPO == null){
throw new BusinessException("订单号不存在");
}
if (orderPO.getStatus() == ProductOrderStatusEnum.PAY_COMPLETE){
return ProductOrderStatusEnum.PAY_COMPLETE;
}else {
try {
if (orderPO.getPayMethod() == PayMethodEnum.WeiXin) {
if(wxService.getConfig().isUseSandboxEnv()){
String key = wxService.getSandboxSignKey();
wxService.getConfig().setMchKey(key);
}
WxPayOrderQueryResult queryResult = wxService.queryOrder(null, orderNo);
if ("SUCCESS".equals(queryResult.getTradeState())){
return ProductOrderStatusEnum.PAY_COMPLETE;
}else {
return ProductOrderStatusEnum.PAY_FAILD;
}
}else if (orderPO.getPayMethod() == PayMethodEnum.AliPay){
return ProductOrderStatusEnum.PAY_FAILD;
}else {
throw new BusinessException("暂不支持的支付类型");
}
} catch (WxPayException e) {
log.error(e.getMessage(),e);
return ProductOrderStatusEnum.PAY_FAILD;
}
}
}
private ProductOrderPO getByOrderNo(String orderNo) {
return getOne(Wrappers.<ProductOrderPO>lambdaQuery().eq(ProductOrderPO::getOrderNo,orderNo));
}
}
\ No newline at end of file
...@@ -31,4 +31,12 @@ public class SysConfigService extends BaseServiceImpl<SysConfigMapper, SysConfig ...@@ -31,4 +31,12 @@ public class SysConfigService extends BaseServiceImpl<SysConfigMapper, SysConfig
throw new BusinessException("不存的key"); throw new BusinessException("不存的key");
} }
} }
public String getValueByKey(String key){
SysConfigPO sysConfigPO = baseMapper.selectOne(Wrappers.<SysConfigPO>lambdaQuery().eq(SysConfigPO::getKey,key));
if (sysConfigPO == null){
return "";
}else {
return sysConfigPO.getValue();
}
}
} }
package com.qkdata.biz.web.controller; package com.qkdata.biz.web.controller;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qkdata.biz.common.BizConstants;
import com.qkdata.biz.enums.SwiperStatusEnum; import com.qkdata.biz.enums.SwiperStatusEnum;
import com.qkdata.biz.management.entity.CourseTagPO; import com.qkdata.biz.management.entity.CourseTagPO;
import com.qkdata.biz.management.service.CourseService; import com.qkdata.biz.management.service.CourseService;
...@@ -13,7 +11,6 @@ import com.qkdata.biz.management.vo.CourseDetailModel; ...@@ -13,7 +11,6 @@ import com.qkdata.biz.management.vo.CourseDetailModel;
import com.qkdata.biz.management.vo.SwiperConfigModel; import com.qkdata.biz.management.vo.SwiperConfigModel;
import com.qkdata.biz.web.service.UserCenterService; import com.qkdata.biz.web.service.UserCenterService;
import com.qkdata.biz.web.vo.MainPageModel; import com.qkdata.biz.web.vo.MainPageModel;
import com.qkdata.biz.web.vo.SaveFavoriteCourseModel;
import com.qkdata.biz.web.vo.SearchCourseConditionModel; import com.qkdata.biz.web.vo.SearchCourseConditionModel;
import com.qkdata.biz.web.vo.SearchCourseResultModel; import com.qkdata.biz.web.vo.SearchCourseResultModel;
import com.qkdata.common.annotation.SysLog; import com.qkdata.common.annotation.SysLog;
...@@ -21,14 +18,12 @@ import com.qkdata.common.base.model.PageResult; ...@@ -21,14 +18,12 @@ import com.qkdata.common.base.model.PageResult;
import com.qkdata.common.base.model.Result; import com.qkdata.common.base.model.Result;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@Api(tags = "首页数据获取") @Api(tags = "首页数据获取-手机端")
@RestController @RestController
@RequestMapping("/api/web/mainPage") @RequestMapping("/api/web/mainPage")
public class MainPageController { public class MainPageController {
...@@ -91,33 +86,5 @@ public class MainPageController { ...@@ -91,33 +86,5 @@ public class MainPageController {
CourseDetailModel model = courseService.getCourseDetail(id); CourseDetailModel model = courseService.getCourseDetail(id);
return Result.succeed(model); return Result.succeed(model);
} }
@ApiOperation("收藏课程")
@PostMapping("/course/favorite")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("收藏课程")
public Result<String> favoriteCourse(@RequestBody SaveFavoriteCourseModel model){
userCenterService.favoriteCourse(model.getCourseId());
return Result.succeed("ok");
}
@ApiOperation("取消收藏")
@PostMapping("/course/removeFavorite")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("取消收藏")
public Result<String> removeFavoriteCourse(@RequestBody SaveFavoriteCourseModel model){
userCenterService.removeFavoriteCourse(model.getCourseId());
return Result.succeed("ok");
}
@ApiOperation("获取视频播放凭证")
@GetMapping("/course/playVideo")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("获取视频播放凭证")
public Result<GetVideoPlayAuthResponse> getCoursePlayVideoUrl(@RequestParam Long courseId,@RequestParam Long chaperId){
//验证权限
userCenterService.checkCoursePlayPerm(courseId,chaperId);
GetVideoPlayAuthResponse response = courseService.getVideoPlayAuth(courseId,chaperId);
return Result.succeed(response);
}
} }
package com.qkdata.biz.web.controller; package com.qkdata.biz.web.controller;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.qkdata.biz.common.BizConstants; import com.qkdata.biz.common.BizConstants;
import com.qkdata.biz.enums.ProductOrderStatusEnum;
import com.qkdata.biz.management.service.CourseService;
import com.qkdata.biz.management.service.ProductOrderService;
import com.qkdata.biz.sys.service.SysUserService; import com.qkdata.biz.sys.service.SysUserService;
import com.qkdata.biz.web.service.UserCenterService; import com.qkdata.biz.web.service.UserCenterService;
import com.qkdata.biz.web.vo.FullUserInfo; import com.qkdata.biz.web.vo.*;
import com.qkdata.biz.web.vo.SearchCourseResultModel;
import com.qkdata.common.annotation.SysLog; import com.qkdata.common.annotation.SysLog;
import com.qkdata.common.base.model.PageResult; import com.qkdata.common.base.model.PageResult;
import com.qkdata.common.base.model.Result; import com.qkdata.common.base.model.Result;
...@@ -18,7 +21,7 @@ import org.springframework.web.bind.annotation.*; ...@@ -18,7 +21,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@Api(tags = "我的相关数据接口") @Api(tags = "我的相关数据接口-手机端")
@RestController @RestController
@RequestMapping("/api/userCenter") @RequestMapping("/api/userCenter")
public class UserCenterController { public class UserCenterController {
...@@ -26,6 +29,10 @@ public class UserCenterController { ...@@ -26,6 +29,10 @@ public class UserCenterController {
private UserCenterService userCenterService; private UserCenterService userCenterService;
@Autowired @Autowired
private SysUserService sysUserService; private SysUserService sysUserService;
@Autowired
private CourseService courseService;
@Autowired
private ProductOrderService orderService;
@ApiOperation("获取个人信息") @ApiOperation("获取个人信息")
@GetMapping("/userInfo") @GetMapping("/userInfo")
...@@ -50,4 +57,49 @@ public class UserCenterController { ...@@ -50,4 +57,49 @@ public class UserCenterController {
return Result.succeed("ok"); return Result.succeed("ok");
} }
@ApiOperation("收藏课程")
@PostMapping("/course/favorite")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("收藏课程")
public Result<String> favoriteCourse(@RequestBody SaveFavoriteCourseModel model){
userCenterService.favoriteCourse(model.getCourseId());
return Result.succeed("ok");
}
@ApiOperation("取消收藏")
@PostMapping("/course/removeFavorite")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("取消收藏")
public Result<String> removeFavoriteCourse(@RequestBody SaveFavoriteCourseModel model){
userCenterService.removeFavoriteCourse(model.getCourseId());
return Result.succeed("ok");
}
@ApiOperation("获取视频播放凭证")
@GetMapping("/course/playVideo")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
@SysLog("获取视频播放凭证")
public Result<GetVideoPlayAuthResponse> getCoursePlayVideoUrl(@RequestParam Long courseId, @RequestParam Long chaperId){
//验证权限
userCenterService.checkCoursePlayPerm(courseId,chaperId);
GetVideoPlayAuthResponse response = courseService.getVideoPlayAuth(courseId,chaperId);
return Result.succeed(response);
}
@ApiOperation("个人购买创建订单")
@PostMapping("/user/createOrder")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
public Result<CreateOrderResult> createOrder(@RequestBody UserBuyVIPModel model){
CreateOrderResult result = orderService.userBuyVIP(model);
return Result.succeed(result);
}
@ApiOperation("查询订单状态")
@GetMapping("/user/queryOrderStatus")
@RequiresRoles(value = {BizConstants.ROLE_USER,BizConstants.ROLE_ENTERPRISE_ADMIN},logical = Logical.OR)
public Result<ProductOrderStatusEnum> queryOrderStatus(@RequestParam String orderNo){
ProductOrderStatusEnum status = orderService.queryStatus(orderNo);
return Result.succeed(status);
}
} }
package com.qkdata.biz.web.vo;
import lombok.Data;
@Data
public class CreateOrderResult {
/**
* 订单号
*/
private String orderNo;
private Object result;
}
package com.qkdata.biz.web.vo;
import com.qkdata.biz.enums.PayMethodEnum;
import com.qkdata.biz.enums.PaySourceEnum;
import lombok.Data;
/**
* 个人购买VIP请求参数
*/
@Data
public class UserBuyVIPModel {
private int count;
private Long courseId;
private PayMethodEnum payMethod;
private PaySourceEnum source;
}
...@@ -2,7 +2,9 @@ package com.qkdata.common.config; ...@@ -2,7 +2,9 @@ package com.qkdata.common.config;
import com.qkdata.common.base.exception.BusinessException; import com.qkdata.common.base.exception.BusinessException;
import com.qkdata.common.base.model.Result; import com.qkdata.common.base.model.Result;
import com.qkdata.common.oauth.AuthorizationResponseEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -97,6 +99,11 @@ public class GlobalExceptionHandle { ...@@ -97,6 +99,11 @@ public class GlobalExceptionHandle {
log.warn("no permission found: {}", e.getMessage()); log.warn("no permission found: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Result.failed("无权限")); return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Result.failed("无权限"));
} }
@ExceptionHandler(value = UnauthenticatedException.class)
public ResponseEntity<Result> unauthenticatedExceptionHandler(UnauthenticatedException e){
log.warn("no permission found: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.OK).body(Result.of("", AuthorizationResponseEnum.INVALID_TOKEN.code(),AuthorizationResponseEnum.INVALID_TOKEN.text()));
}
} }
...@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; ...@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData; import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler; import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
...@@ -86,7 +86,7 @@ public class WxMaConfiguration { ...@@ -86,7 +86,7 @@ public class WxMaConfiguration {
} }
private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) -> { private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) -> {
service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder() service.getMsgService().sendUniformMsg(WxMaUniformMessage.builder()
.templateId("此处更换为自己的模板id") .templateId("此处更换为自己的模板id")
.formId("自己替换可用的formid") .formId("自己替换可用的formid")
.data(Lists.newArrayList( .data(Lists.newArrayList(
......
package com.qkdata.wx.pay.config;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfiguration {
private WxPayProperties properties;
@Bean
@ConditionalOnMissingBean
public WxPayService wxService() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(true);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
package com.qkdata.wx.pay.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
/**
* 设置微信公众号或者小程序等的appid
*/
private String appId;
/**
* 微信支付商户号
*/
private String mchId;
/**
* 微信支付商户密钥
*/
private String mchKey;
/**
* 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
*/
private String subAppId;
/**
* 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
*/
private String subMchId;
/**
* apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
*/
private String keyPath;
}
package com.qkdata.wx.pay.controller;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.qkdata.biz.enums.ProductOrderStatusEnum;
import com.qkdata.biz.management.service.ProductOrderService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 微信支付回调
*/
@Slf4j
@RestController
@RequestMapping("/wx/pay")
public class WxPayNotifyController {
@Autowired
private WxPayService wxPayService;
@Autowired
private ProductOrderService orderService;
@ApiOperation(value = "支付回调通知处理")
@PostMapping("/notify/order")
public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
try {
final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
log.info(notifyResult.toString());
notifyResult.checkResult(wxPayService,notifyResult.getSignType(),true);
String outTradeNo = notifyResult.getOutTradeNo();
orderService.updateStatus(outTradeNo, ProductOrderStatusEnum.PAY_COMPLETE);
}catch (WxPayException e){
log.error(e.getMessage(),e);
}
return WxPayNotifyResponse.success("OK");
}
@ApiOperation(value = "退款回调通知处理")
@PostMapping("/notify/refund")
public String parseRefundNotifyResult(@RequestBody String xmlData) throws WxPayException {
final WxPayRefundNotifyResult result = this.wxPayService.parseRefundNotifyResult(xmlData);
log.info(result.toString());
// TODO 根据自己业务场景需要构造返回对象
return WxPayNotifyResponse.success("成功");
}
@ApiOperation(value = "扫码支付回调通知处理")
@PostMapping("/notify/scanpay")
public String parseScanPayNotifyResult(String xmlData) throws WxPayException {
final WxScanPayNotifyResult result = this.wxPayService.parseScanPayNotifyResult(xmlData);
log.info(result.toString());
// TODO 根据自己业务场景需要构造返回对象
return WxPayNotifyResponse.success("成功");
}
}
...@@ -12,7 +12,7 @@ spring: ...@@ -12,7 +12,7 @@ spring:
host: localhost host: localhost
port: 6379 port: 6379
frontend: frontend:
domain: http://test2.qiankundata.com:60081 domain: http://test1.qiankundata.com:50081
log: log:
path: /Users/liuyang/work/argus_work/online-edu/data/logs path: /Users/liuyang/work/argus_work/online-edu/data/logs
file: file:
......
...@@ -108,6 +108,11 @@ wx: ...@@ -108,6 +108,11 @@ wx:
token: #微信小程序消息服务器配置的token token: #微信小程序消息服务器配置的token
aesKey: #微信小程序消息服务器配置的EncodingAESKey aesKey: #微信小程序消息服务器配置的EncodingAESKey
msgDataFormat: JSON msgDataFormat: JSON
pay:
appId: wx9b423ad87c070728
mchId: 1610013675
mchKey: z33nsd1go35ynhjubi4gappp6g0fkzed
keyPath: classpath:apiclient_cert.p12
sms: sms:
api: api:
v3: http://sms-service/sms/api/v3 v3: http://sms-service/sms/api/v3
......
CREATE TABLE `product_order` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NULL COMMENT '订单编号',
`order_name` varchar(255) NULL COMMENT '订单名称',
`user_id` bigint(11) NULL COMMENT '用户ID',
`product_type` varchar(20) NULL COMMENT '产品类型(个人包月、企业包月、付费点播)',
`course_id` bigint(11) NULL COMMENT '课程ID',
`product_price` decimal(8, 2) NULL COMMENT '产品单价',
`product_count` int(11) NULL COMMENT '产品购买数量',
`order_money` decimal(8, 2) NULL COMMENT '订单金额',
`payment_money` decimal(8, 2) NULL COMMENT '支付金额',
`pay_method` varchar(20) NULL COMMENT '支付方式(微信、支付宝)',
`status` varchar(20) NULL COMMENT '订单状态',
`create_time` datetime(0) NULL COMMENT '创建时间',
`update_time` datetime(0) NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) COMMENT = '产品订单';
\ No newline at end of file
<?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.qkdata.biz.management.mapper.ProductOrderMapper">
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment