Commit 2c39527e authored by shangtx's avatar shangtx

feat: 订单支付

parent b0949b6e
...@@ -2,12 +2,13 @@ package com.onsiteservice.common.order.vo; ...@@ -2,12 +2,13 @@ package com.onsiteservice.common.order.vo;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Getter; import lombok.*;
import lombok.Setter;
import lombok.ToString;
import java.util.Map; import java.util.Map;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter @Getter
@Setter @Setter
@ToString @ToString
......
...@@ -2,9 +2,11 @@ package com.onsiteservice.miniapp.controller.order; ...@@ -2,9 +2,11 @@ package com.onsiteservice.miniapp.controller.order;
import com.onsiteservice.common.annotation.dict.Dict; import com.onsiteservice.common.annotation.dict.Dict;
import com.onsiteservice.common.annotation.user.CurrentUserId; import com.onsiteservice.common.annotation.user.CurrentUserId;
import com.onsiteservice.common.order.dto.*; import com.onsiteservice.common.order.dto.DispatchServiceOrderDTO;
import com.onsiteservice.common.order.dto.FinishServiceOrderDTO;
import com.onsiteservice.common.order.dto.SendServiceOrderDTO;
import com.onsiteservice.common.order.dto.ValuationServiceOrderDTO;
import com.onsiteservice.common.order.vo.OrderPayVO; import com.onsiteservice.common.order.vo.OrderPayVO;
import com.onsiteservice.common.order.vo.ServiceOrderLogVO;
import com.onsiteservice.common.order.vo.ServiceOrderVO; import com.onsiteservice.common.order.vo.ServiceOrderVO;
import com.onsiteservice.constant.constant.DictConstants; import com.onsiteservice.constant.constant.DictConstants;
import com.onsiteservice.constant.enums.ServiceOrderOpSourceEnum; import com.onsiteservice.constant.enums.ServiceOrderOpSourceEnum;
...@@ -12,7 +14,6 @@ import com.onsiteservice.core.result.Result; ...@@ -12,7 +14,6 @@ import com.onsiteservice.core.result.Result;
import com.onsiteservice.dao.common.page.PageInfoVO; import com.onsiteservice.dao.common.page.PageInfoVO;
import com.onsiteservice.miniapp.controller.order.dto.CancelServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.CancelServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.PageServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.PageServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.PayServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.ReserveServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.ReserveServiceOrderDTO;
import com.onsiteservice.miniapp.service.order.ServiceOrderBizService; import com.onsiteservice.miniapp.service.order.ServiceOrderBizService;
import com.onsiteservice.service.order.ServiceOrderService; import com.onsiteservice.service.order.ServiceOrderService;
...@@ -26,7 +27,6 @@ import org.springframework.web.bind.annotation.*; ...@@ -26,7 +27,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Positive; import javax.validation.constraints.Positive;
import java.util.List;
import static com.onsiteservice.core.result.ResultGenerator.fail; import static com.onsiteservice.core.result.ResultGenerator.fail;
import static com.onsiteservice.core.result.ResultGenerator.success; import static com.onsiteservice.core.result.ResultGenerator.success;
...@@ -92,11 +92,6 @@ public class ServiceOrderController { ...@@ -92,11 +92,6 @@ public class ServiceOrderController {
return serviceOrderService.sendOrder(dto, userId, ServiceOrderOpSourceEnum.MINI_APP) == 1 ? success() : fail("发送失败"); return serviceOrderService.sendOrder(dto, userId, ServiceOrderOpSourceEnum.MINI_APP) == 1 ? success() : fail("发送失败");
} }
@ApiOperation(value = "支付订单")
@PostMapping("pay")
public Result pay(@RequestBody @NonNull @Validated PayServiceOrderDTO dto, @CurrentUserId Long userId) {
return serviceOrderBizService.pay(dto, userId, ServiceOrderOpSourceEnum.MINI_APP) == 1 ? success() : fail("支付失败");
}
@ApiOperation(value = "派单") @ApiOperation(value = "派单")
@PostMapping("dispatch") @PostMapping("dispatch")
...@@ -141,14 +136,10 @@ public class ServiceOrderController { ...@@ -141,14 +136,10 @@ public class ServiceOrderController {
/** /**
* 支付订单 * 支付订单
*/ */
/* @PutMapping("/pay/{orderId}") @GetMapping("/pay/{orderId}")
@ApiOperation(value = "发起支付") @ApiOperation(value = "发起支付")
public Result<OrderPayVO> pay(@ApiParam(value = "订单id", required = true) @PathVariable Long orderId, @CurrentUserId Long userId, HttpServletRequest request) { public Result<OrderPayVO> pay(@ApiParam(value = "订单id", required = true) @PathVariable Long orderId, @CurrentUserId Long userId, HttpServletRequest request) {
HotelOrderPayVO result = hotelOrderService.pay(orderId, currentUserInfo, request); return success(serviceOrderBizService.pay(orderId, userId, request));
if (null == result) { }
fail("支付已超时");
}
return success(hotelOrderService.pay(orderId, currentUserInfo, request));
}*/
} }
package com.onsiteservice.miniapp.controller.weixn;
import com.onsiteservice.core.exception.ServiceException;
import com.onsiteservice.dao.mapper.pay.PayChannelWechatMapper;
import com.onsiteservice.miniapp.service.order.ServiceOrderBizService;
import com.onsiteservice.miniapp.service.weixin.pay.util.MD5Util;
import com.onsiteservice.miniapp.service.weixin.pay.util.MapUtil;
import com.onsiteservice.miniapp.service.weixin.pay.util.ParseXmlUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Map;
/**
* @author: qiaobin
* @description:微信端支付回调
* @date: 2019/1/22
*/
@ApiIgnore
@Controller
@RequestMapping("/wechat")
@AllArgsConstructor(onConstructor_ = {@Autowired})
@Slf4j
public class WechatNotifyController {
private static final String RETURN_CODE_SUCCESS = "SUCCESS";
private ServiceOrderBizService orderBizService;
private PayChannelWechatMapper payChannelWechatMapper;
/**
* 服务器异步通知
*/
@RequestMapping(value = "/pay-notify")
public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
//WechatPayMyConfigMini config = new WechatPayMyConfigMini();
PrintWriter out = null;
try {
log.info("微信支付成功回调通知开始!");
StringBuffer sb = new StringBuffer();
InputStream is = request.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String s = "";
while ((s = br.readLine()) != null) {
sb.append(s);
}
log.info("微信支付成功回调通知内容:" + sb.toString());
if (StringUtils.isNotEmpty(sb.toString())) {
// 解析xml
Map<String, String> paramMap = ParseXmlUtil.parseXml2Map(sb.toString());
String returnCode = paramMap.get("return_code").toString();
log.info("微信支付成功返回result_code:" + returnCode);
String outTradeNo = paramMap.get("out_trade_no").toString();
var payChannels = payChannelWechatMapper.selectAll();
if (payChannels.isEmpty()) {
throw new ServiceException("未配置商户信息");
}
var payChannel = payChannels.get(0);
String transactionId = paramMap.get("transaction_id").toString();
//支付响应记录日志
// savePayResponseLog(outTradeNo, transactionId, returnCode, sb.toString());
if (RETURN_CODE_SUCCESS.equals(returnCode)) {
if (validateSign(paramMap, payChannel.getWechatKey())) {
//更新支付凭证支付状态
orderBizService.paySuccess(outTradeNo, sb.toString());
out = response.getWriter();
// 通知微信,防止微信再通知
response.setContentType("application/xml");
out.write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
out.flush();
out.close();
} else {
log.warn("微信支付成功回调通知签名校验失败,请检查!");
}
} else {
log.warn("微信支付成功回调通知返回码不成功(RETURN_CODE),请检查!");
}
} else {
log.warn("微信支付成功回调通知内容为空,请检查!");
}
} catch (Exception e) {
log.error("notify() Exception exception:{}", e.getMessage());
e.printStackTrace();
}
}
/**
* 微信通知签名校验
*
* @param map
* @param appKey
* @return
* @throws Exception
*/
public boolean validateSign(Map<String, String> map, String appKey) throws Exception {
//除去sign的信息
String responseSign = map.get("sign").toString();//微信响应的sign
map.remove("sign");
String signStr = MapUtil.FormatBizQueryParaMap(map, false);
signStr = signStr + "&key=" + appKey;
String buildSign = MD5Util.MD5(signStr).toUpperCase();//根据key和报文生成的sign
if (StringUtils.isEmpty(responseSign) || !buildSign.equals(responseSign)) {
return false;
}
return true;
}
}
package com.onsiteservice.miniapp.service.order; package com.onsiteservice.miniapp.service.order;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.onsiteservice.common.order.vo.OrderPayVO;
import com.onsiteservice.common.order.vo.ServiceOrderLogVO; import com.onsiteservice.common.order.vo.ServiceOrderLogVO;
import com.onsiteservice.common.order.vo.ServiceOrderVO; import com.onsiteservice.common.order.vo.ServiceOrderVO;
import com.onsiteservice.constant.constant.BizConstants; import com.onsiteservice.constant.constant.BizConstants;
import com.onsiteservice.constant.constant.SysParamConstants;
import com.onsiteservice.constant.enums.BizCodeEnum; import com.onsiteservice.constant.enums.BizCodeEnum;
import com.onsiteservice.constant.enums.ServiceOrderOpSourceEnum; import com.onsiteservice.constant.enums.ServiceOrderOpSourceEnum;
import com.onsiteservice.constant.enums.ServiceOrderStatusEnum; import com.onsiteservice.constant.enums.ServiceOrderStatusEnum;
...@@ -14,7 +16,9 @@ import com.onsiteservice.core.result.ResultGenerator; ...@@ -14,7 +16,9 @@ import com.onsiteservice.core.result.ResultGenerator;
import com.onsiteservice.dao.common.AbstractMapper; import com.onsiteservice.dao.common.AbstractMapper;
import com.onsiteservice.dao.common.page.PageInfoVO; import com.onsiteservice.dao.common.page.PageInfoVO;
import com.onsiteservice.dao.component.RecordComponent; import com.onsiteservice.dao.component.RecordComponent;
import com.onsiteservice.dao.mapper.pay.PayChannelWechatMapper;
import com.onsiteservice.dao.mapper.service.*; import com.onsiteservice.dao.mapper.service.*;
import com.onsiteservice.dao.mapper.sys.SysParamMapper;
import com.onsiteservice.dao.mapper.user.UserMapper; import com.onsiteservice.dao.mapper.user.UserMapper;
import com.onsiteservice.entity.address.ServiceAddress; import com.onsiteservice.entity.address.ServiceAddress;
import com.onsiteservice.entity.category.ServiceCategory; import com.onsiteservice.entity.category.ServiceCategory;
...@@ -22,15 +26,18 @@ import com.onsiteservice.entity.category.ServiceSubclass; ...@@ -22,15 +26,18 @@ import com.onsiteservice.entity.category.ServiceSubclass;
import com.onsiteservice.entity.order.ServiceOrder; import com.onsiteservice.entity.order.ServiceOrder;
import com.onsiteservice.entity.service.ServiceOrderImg; import com.onsiteservice.entity.service.ServiceOrderImg;
import com.onsiteservice.entity.service.ServiceOrderLog; import com.onsiteservice.entity.service.ServiceOrderLog;
import com.onsiteservice.entity.sys.SysParam;
import com.onsiteservice.entity.user.User; import com.onsiteservice.entity.user.User;
import com.onsiteservice.miniapp.controller.order.dto.CancelServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.CancelServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.PageServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.PageServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.PayServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.PayServiceOrderDTO;
import com.onsiteservice.miniapp.controller.order.dto.ReserveServiceOrderDTO; import com.onsiteservice.miniapp.controller.order.dto.ReserveServiceOrderDTO;
import com.onsiteservice.miniapp.service.weixin.pay.WechatNativePay;
import com.onsiteservice.service.order.ServiceOrderService; import com.onsiteservice.service.order.ServiceOrderService;
import com.onsiteservice.util.AttrCopyUtils; import com.onsiteservice.util.AttrCopyUtils;
import com.onsiteservice.util.RandomUtils; import com.onsiteservice.util.RandomUtils;
import com.onsiteservice.util.aliyun.SmsUtils; import com.onsiteservice.util.aliyun.SmsUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
...@@ -40,10 +47,8 @@ import org.springframework.util.CollectionUtils; ...@@ -40,10 +47,8 @@ import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Condition; import tk.mybatis.mapper.entity.Condition;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Comparator; import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -84,6 +89,10 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> { ...@@ -84,6 +89,10 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> {
@Autowired @Autowired
private RecordComponent recordComponent; private RecordComponent recordComponent;
@Resource
private PayChannelWechatMapper payChannelWechatMapper;
@Resource
private SysParamMapper sysParamMapper;
public ServiceOrderVO selectById(Long id, Long userId) { public ServiceOrderVO selectById(Long id, Long userId) {
...@@ -194,27 +203,19 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> { ...@@ -194,27 +203,19 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> {
} }
public int pay(PayServiceOrderDTO dto, Long userId, ServiceOrderOpSourceEnum sourceEnum) { public void paySuccess(String outTradeNo, String orderNo) {
log.info("order pay dto: {}, userId: {}", dto, userId); log.info("支付成功 outTradeNo: {}, orderNo: {}", outTradeNo, orderNo);
// 判断能发送的状态
ServiceOrder serviceOrder = serviceOrderService.checkOrder(dto.getId(), userId);
if (!serviceOrder.getOrderStatus().equals(ServiceOrderStatusEnum.SEND.getStatus())) {
throw new ServiceException(BizCodeEnum.SERVICE_ORDER_CANNOT_PAY);
}
serviceOrder.setOrderStatus(ServiceOrderStatusEnum.PAY.getStatus()); var order = selectOneByProperty("orderNo", orderNo);
serviceOrder.setModifyBy(userId);
int result = serviceOrderMapper.updateByPrimaryKeySelective(serviceOrder); order.setOrderStatus(ServiceOrderStatusEnum.PAY.getStatus());
// TODO 调用微信支付接口 int result = serviceOrderMapper.updateByPrimaryKeySelective(order);
if (result == 1) { if (result == 1) {
recordComponent.recordProcess(serviceOrder.getId(), ServiceOrderStatusEnum.PAY.getStatus(), ServiceOrderStatusEnum.PAY.getMsg(), sourceEnum, null, null, null); recordComponent.recordProcess(order.getId(), ServiceOrderStatusEnum.PAY.getStatus(), ServiceOrderStatusEnum.PAY.getMsg(), ServiceOrderOpSourceEnum.MINI_APP, null, null, null);
} }
return result;
} }
...@@ -243,7 +244,34 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> { ...@@ -243,7 +244,34 @@ public class ServiceOrderBizService extends AbstractMapper<ServiceOrder> {
/** /**
* 生成支付参数 * 生成支付参数
*/ */
public OrderPayVO pay(Long orderId, Long userId, HttpServletRequest request) {
if(userId == null) {
throw new ServiceException("用户未登录");
}
var order = selectByPrimaryKey(orderId);
if(!order.getAccountNo().equals(userId)) {
throw new ServiceException("用户错误");
}
if(new Date().compareTo(order.getCancelTime()) > 0) {
throw new ServiceException("支付超时");
}
if(!order.getOrderStatus().equals(ServiceOrderStatusEnum.SEND.getStatus())) {
throw new ServiceException("不能支付的订单状态");
}
var payChannel = payChannelWechatMapper.selectAll().get(0);
WechatNativePay wechatNativePay = new WechatNativePay(payChannel.getAppid(), payChannel.getMchid(), payChannel.getWechatKey());
String notifyUrl = sysParamMapper.selectOne(SysParam.builder().code(SysParamConstants.MINI_WECHAT_PAY_NOTIFY_URL).build()).getValue();
var user = userMapper.selectByPrimaryKey(userId);
try {
var params = wechatNativePay.getPayParam("服务预约", order.getOrderNo(), order.getPrice(), notifyUrl,
user.getOpenId(), request);
return new OrderPayVO(params);
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(e.getMessage());
}
}
/** /**
......
...@@ -17,7 +17,7 @@ project: ...@@ -17,7 +17,7 @@ project:
# 安全路径白名单 无需token # 安全路径白名单 无需token
ant-paths: "/error,**.html**,**.js,**.css,/favicon.ico,/webjars/**,/swagger**, ant-paths: "/error,**.html**,**.js,**.css,/favicon.ico,/webjars/**,/swagger**,
/swagger-resources/configuration/ui,/**/v2/api-docs,/doc.html,/v2/api-docs-ext,/druid/**\ /swagger-resources/configuration/ui,/**/v2/api-docs,/doc.html,/v2/api-docs-ext,/druid/**\
/,/websocket/**,/category/page,/subclass/**,/token/base,/dict,/common/*" /,/websocket/**,/category/page,/subclass/**,/token/base,/dict,/common/*,/wechat/pay-notify"
# 基础token可以访问的路径白名单 # 基础token可以访问的路径白名单
base-token-ant-paths: "/login" base-token-ant-paths: "/login"
schedule: schedule:
......
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