ClientPayController.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package com.fuint.module.clientApi.controller;
  2. import com.alipay.api.AlipayApiException;
  3. import com.fuint.common.dto.*;
  4. import com.fuint.common.enums.OrderStatusEnum;
  5. import com.fuint.common.enums.SettingTypeEnum;
  6. import com.fuint.common.enums.YesOrNoEnum;
  7. import com.fuint.common.service.*;
  8. import com.fuint.common.util.TokenUtil;
  9. import com.fuint.framework.exception.BusinessCheckException;
  10. import com.fuint.framework.web.BaseController;
  11. import com.fuint.framework.web.ResponseObject;
  12. import com.fuint.repository.model.*;
  13. import com.fuint.utils.StringUtil;
  14. import com.ijpay.alipay.AliPayApi;
  15. import com.ijpay.core.kit.HttpKit;
  16. import com.ijpay.core.kit.WxPayKit;
  17. import com.ijpay.wxpay.WxPayApiConfigKit;
  18. import io.swagger.annotations.Api;
  19. import io.swagger.annotations.ApiOperation;
  20. import lombok.AllArgsConstructor;
  21. import org.springframework.util.CollectionUtils;
  22. import org.springframework.web.bind.annotation.*;
  23. import javax.servlet.http.HttpServletRequest;
  24. import javax.servlet.http.HttpServletResponse;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27. import java.math.BigDecimal;
  28. import java.util.HashMap;
  29. import java.util.List;
  30. import java.util.Map;
  31. /**
  32. * 支付类controller
  33. *
  34. * Created by FSQ
  35. * CopyRight https://www.fuint.cn
  36. */
  37. @Api(tags="会员端-支付相关接口")
  38. @RestController
  39. @AllArgsConstructor
  40. @RequestMapping(value = "/clientApi/pay")
  41. public class ClientPayController extends BaseController {
  42. private static final Logger logger = LoggerFactory.getLogger(ClientPayController.class);
  43. /**
  44. * 微信服务接口
  45. * */
  46. private WeixinService weixinService;
  47. /**
  48. * 支付宝服务接口
  49. * */
  50. private AlipayService alipayService;
  51. /**
  52. * 支付服务接口
  53. * */
  54. private PaymentService paymentService;
  55. /**
  56. * 订单服务接口
  57. * */
  58. private OrderService orderService;
  59. /**
  60. * 会员服务接口
  61. * */
  62. private MemberService memberService;
  63. /**
  64. * 系统设置接口
  65. * */
  66. private SettingService settingService;
  67. /**
  68. * 会员卡券接口
  69. * */
  70. private UserCouponService userCouponService;
  71. /**
  72. * 会员等级接口
  73. * */
  74. private UserGradeService userGradeService;
  75. /**
  76. * 商户服务接口
  77. */
  78. private MerchantService merchantService;
  79. /**
  80. * 支付前查询
  81. * */
  82. @ApiOperation(value = "支付前查询")
  83. @RequestMapping(value = "/prePay", method = RequestMethod.GET)
  84. @CrossOrigin
  85. public ResponseObject prePay(HttpServletRequest request) throws BusinessCheckException {
  86. Integer storeId = StringUtil.isEmpty(request.getHeader("storeId")) ? 0 : Integer.parseInt(request.getHeader("storeId"));
  87. String useFor = request.getParameter("type") == null ? "" : request.getParameter("type");
  88. String merchantNo = request.getHeader("merchantNo");
  89. UserInfo userInfo = TokenUtil.getUserInfoByToken(request.getHeader("Access-Token"));
  90. MtUser mtUser = memberService.queryMemberById(userInfo.getId());
  91. Map<String, Object> outParams = new HashMap<>();
  92. List<MtSetting> settingList = settingService.getSettingList(mtUser.getMerchantId(), SettingTypeEnum.POINT.getKey());
  93. String canUsedAsMoney = YesOrNoEnum.FALSE.getKey();
  94. String exchangeNeedPoint = "0";
  95. for (MtSetting setting : settingList) {
  96. if (setting.getName().equals("canUsedAsMoney")) {
  97. canUsedAsMoney = setting.getValue();
  98. } else if (setting.getName().equals("exchangeNeedPoint")) {
  99. exchangeNeedPoint = setting.getValue();
  100. }
  101. }
  102. // 可用卡券
  103. CouponDto canUseCouponInfo = null;
  104. if (mtUser != null) {
  105. List<CouponDto> couponList = userCouponService.getPayAbleCouponList(mtUser.getId(), storeId, useFor);
  106. if (couponList.size() > 0) {
  107. canUseCouponInfo = couponList.get(0);
  108. }
  109. }
  110. // 会员折扣
  111. BigDecimal payDiscount = new BigDecimal("1");
  112. Integer merchantId = merchantService.getMerchantId(merchantNo);
  113. if (mtUser != null && !mtUser.getIsStaff().equals(YesOrNoEnum.YES.getKey())) {
  114. MtUserGrade userGrade = userGradeService.queryUserGradeById(merchantId, Integer.parseInt(mtUser.getGradeId()), mtUser.getId());
  115. if (userGrade != null) {
  116. if (userGrade.getDiscount() > 0) {
  117. payDiscount = new BigDecimal(userGrade.getDiscount()).divide(new BigDecimal("10"), BigDecimal.ROUND_CEILING, 4);
  118. if (payDiscount.compareTo(new BigDecimal("0")) <= 0) {
  119. payDiscount = new BigDecimal("1");
  120. }
  121. }
  122. }
  123. }
  124. // 可用积分
  125. Integer canUsePointAmount = 0;
  126. if (mtUser != null && canUsedAsMoney.equals(YesOrNoEnum.TRUE.getKey())) {
  127. canUsePointAmount = mtUser.getPoint();
  128. }
  129. outParams.put("canUsedAsMoney", canUsedAsMoney);
  130. outParams.put("exchangeNeedPoint", exchangeNeedPoint);
  131. outParams.put("canUsePointAmount", canUsePointAmount);
  132. outParams.put("canUseCouponInfo", canUseCouponInfo);
  133. outParams.put("canUseCouponInfo", canUseCouponInfo);
  134. outParams.put("payDiscount", payDiscount);
  135. return getSuccessResult(outParams);
  136. }
  137. /**
  138. * 发起支付
  139. * */
  140. @ApiOperation(value = "发起支付")
  141. @RequestMapping(value = "/doPay", method = RequestMethod.GET)
  142. @CrossOrigin
  143. public ResponseObject doPay(HttpServletRequest request) throws BusinessCheckException {
  144. return getSuccessResult(paymentService.doPay(request));
  145. }
  146. /**
  147. * 微信支付回调
  148. */
  149. @RequestMapping(value = "/weixinCallback", method = RequestMethod.POST)
  150. @CrossOrigin
  151. public void weixinCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
  152. logger.info("微信支付结果回调....");
  153. Map<String, String> resData = weixinService.processResXml(request);
  154. logger.info("微信返回Map:" + resData);
  155. if (!CollectionUtils.isEmpty(resData)) {
  156. String orderSn = resData.get("out_trade_no"); // 商户订单号
  157. String orderId = resData.get("transaction_id"); // 微信交易单号
  158. String tranAmt = resData.get("total_fee"); // 交易金额
  159. BigDecimal tranAmount = new BigDecimal(tranAmt).divide(new BigDecimal("100"), BigDecimal.ROUND_CEILING, 4);
  160. // 参数校验
  161. if (StringUtil.isNotEmpty(orderSn) && StringUtil.isNotEmpty(tranAmt) && StringUtil.isNotEmpty(orderId)) {
  162. UserOrderDto orderInfo = orderService.getOrderByOrderSn(orderSn);
  163. if (orderInfo != null) {
  164. String result = resData.get("return_code");
  165. if (!result.equals("SUCCESS")) {
  166. logger.error("微信支付回调接口验签失败");
  167. return;
  168. }
  169. // 订单金额
  170. BigDecimal payAmount = orderInfo.getPayAmount();
  171. int compareFlag = tranAmount.compareTo(payAmount);
  172. if (compareFlag == 0) { // 支付金额正确
  173. if (orderInfo.getStatus().equals(OrderStatusEnum.CREATED.getKey())) {
  174. boolean flag = paymentService.paymentCallback(orderInfo);
  175. logger.info("回调结果:" + flag);
  176. if (flag) {
  177. weixinService.processRespXml(response, true);
  178. } else {
  179. weixinService.processRespXml(response, false);
  180. }
  181. } else {
  182. logger.error("订单{}已经支付,orderInfo.getStatus() = {}, CREATED.getKey() = {}", orderSn, orderInfo.getStatus(), OrderStatusEnum.CREATED.getKey());
  183. }
  184. } else {
  185. logger.error("回调金额与支付金额不匹配 tranAmount = {}, payAmount = {}, compareFlag = {}", tranAmount, orderInfo.getPayAmount(), compareFlag);
  186. }
  187. } else {
  188. logger.error("支付订单{}对应的信息不存在", orderSn);
  189. }
  190. }
  191. }
  192. }
  193. /**
  194. * 微信退款通知
  195. */
  196. @RequestMapping(value = "/weixinRefundNotify", method = {RequestMethod.POST, RequestMethod.GET})
  197. @ResponseBody
  198. public String weixinRefundNotify(HttpServletRequest request) {
  199. String xmlMsg = HttpKit.readData(request);
  200. logger.info("退款通知 = " + xmlMsg);
  201. Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
  202. String returnCode = params.get("return_code");
  203. // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
  204. if (WxPayKit.codeIsOk(returnCode)) {
  205. String reqInfo = params.get("req_info");
  206. String decryptData = WxPayKit.decryptData(reqInfo, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey());
  207. logger.info("退款通知解密后的数据 = " + decryptData);
  208. // 发送通知等
  209. Map<String, String> xml = new HashMap<>(2);
  210. xml.put("return_code", "SUCCESS");
  211. xml.put("return_msg", "OK");
  212. return WxPayKit.toXml(xml);
  213. }
  214. return null;
  215. }
  216. /**
  217. * 支付宝支付回调
  218. */
  219. @RequestMapping(value = "/aliPayCallback", method = RequestMethod.POST)
  220. @CrossOrigin
  221. public String aliPayCallback(HttpServletRequest request) throws Exception {
  222. try {
  223. // 获取支付宝POST过来反馈信息
  224. Map<String, String> params = AliPayApi.toMap(request);
  225. for (Map.Entry<String, String> entry : params.entrySet()) {
  226. logger.info("{} = {}", entry.getKey(), entry.getValue());
  227. }
  228. String orderSn = params.get("out_trade_no") != null ? params.get("out_trade_no") : "";
  229. if (StringUtil.isEmpty(orderSn)) {
  230. logger.error("支付宝验证失败 订单号为空");
  231. }
  232. Boolean verifyResult = alipayService.checkCallBack(params);
  233. if (verifyResult) {
  234. logger.info("支付宝验证成功 success");
  235. UserOrderDto orderInfo = orderService.getOrderByOrderSn(orderSn);
  236. Boolean flag = paymentService.paymentCallback(orderInfo);
  237. if (flag) {
  238. return "success";
  239. } else {
  240. return "failure";
  241. }
  242. } else {
  243. logger.error("支付宝验证失败 orderSn={}", orderSn);
  244. return "failure";
  245. }
  246. } catch (AlipayApiException e) {
  247. e.printStackTrace();
  248. logger.error("支付宝回调出错啦...");
  249. return "failure";
  250. }
  251. }
  252. }