OrderWechatPayController.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package com.fdkankan.ucenter.controller;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.fdkankan.common.constant.Constant;
  4. import com.fdkankan.common.constant.ConstantUrl;
  5. import com.fdkankan.common.constant.ErrorCode;
  6. import com.fdkankan.common.exception.BusinessException;
  7. import com.fdkankan.redis.util.RedisUtil;
  8. import com.fdkankan.ucenter.common.BaseController;
  9. import com.fdkankan.ucenter.common.Result;
  10. import com.fdkankan.ucenter.entity.*;
  11. import com.fdkankan.ucenter.pay.factory.PayFactory;
  12. import com.fdkankan.ucenter.pay.factory.impl.PayOrderService;
  13. import com.fdkankan.ucenter.pay.paypal.sdk.UrlUtils;
  14. import com.fdkankan.ucenter.pay.strategy.OrderStrategyFactory;
  15. import com.fdkankan.ucenter.pay.wx.WXPayConstants;
  16. import com.fdkankan.ucenter.pay.wx.WXPayDefaultConfig;
  17. import com.fdkankan.ucenter.pay.wx.WXPayUtil;
  18. import com.fdkankan.ucenter.service.*;
  19. import com.fdkankan.ucenter.vo.request.PlaceOrderParam;
  20. import lombok.extern.log4j.Log4j2;
  21. import org.springframework.beans.factory.annotation.Autowired;
  22. import org.springframework.beans.factory.annotation.Value;
  23. import org.springframework.stereotype.Controller;
  24. import org.springframework.web.bind.annotation.RequestBody;
  25. import org.springframework.web.bind.annotation.RequestMapping;
  26. import org.springframework.web.bind.annotation.RequestMethod;
  27. import org.springframework.web.bind.annotation.ResponseBody;
  28. import java.io.BufferedOutputStream;
  29. import java.io.InputStream;
  30. import java.math.BigDecimal;
  31. import java.net.HttpURLConnection;
  32. import java.net.URL;
  33. import java.util.List;
  34. import java.util.Map;
  35. @Log4j2
  36. /**支付中心-微信支付模块"*/
  37. @Controller
  38. @RequestMapping("/ucenter/order/pay")
  39. public class OrderWechatPayController extends BaseController {
  40. @Autowired
  41. private OrderStrategyFactory orderStrategyFactory;
  42. @Autowired
  43. private PayFactory payFactory;
  44. @Autowired
  45. private IOrderService orderService;
  46. @Autowired
  47. private IVirtualOrderService virtualOrderService;
  48. @Autowired
  49. private IExpansionOrderService expansionOrderService;
  50. @Autowired
  51. private IIncrementOrderService incrementOrderService;
  52. @Autowired
  53. IOrderItemService orderItemService;
  54. @Autowired
  55. RedisUtil redisUtil;
  56. @Autowired
  57. PayOrderService payOrderService;
  58. @Value("${main.url}")
  59. private String mainUrl;
  60. @ResponseBody
  61. @RequestMapping(value = "/wechatPay", method = RequestMethod.POST)
  62. public Result wechatPay(@RequestBody PlaceOrderParam order) throws Exception {
  63. return Result.success(payFactory.scanPay("wechat", order));
  64. }
  65. @ResponseBody
  66. @RequestMapping(value = "/wechatMobilePay", method = RequestMethod.POST)
  67. public Result wechatMobilePay(@RequestBody PlaceOrderParam order) throws Exception {
  68. return Result.success(payFactory.h5Pay("wechat", order, UrlUtils.getIpAddr(request)));
  69. }
  70. @RequestMapping(value = "/wechatPreJsPay")
  71. public String wechatPreJsPay(Long orderId, int orderType, String code, Long spaceId) throws Exception {
  72. InputStream is = null;
  73. WXPayDefaultConfig config = new WXPayDefaultConfig();
  74. // 这个url链接地址和参数皆不能变
  75. String url = ConstantUrl.WEIXIN_TOKEN_URL1 + config.getAppID() + "&secret=" + config.getSecret() + "&grant_type=authorization_code" + "&code=" + code;
  76. try {
  77. URL urlGet = new URL(url);
  78. HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
  79. http.setRequestMethod("GET"); // 必须是get方式请求
  80. http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  81. http.setDoOutput(true);
  82. http.setDoInput(true);
  83. System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
  84. System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
  85. http.connect();
  86. is = http.getInputStream();
  87. int size = is.available();
  88. byte[] jsonBytes = new byte[size];
  89. is.read(jsonBytes);
  90. String message = new String(jsonBytes, "UTF-8");
  91. log.debug("获取access_token返回的message:"+message);
  92. JSONObject oppidObj = JSONObject.parseObject(message);
  93. String access_token = (String) oppidObj.get("access_token");
  94. String openid = (String) oppidObj.get("openid");
  95. String orderSn = null;
  96. StringBuilder sb = new StringBuilder();
  97. BigDecimal totalFee = null;
  98. switch (orderType){
  99. case 0:
  100. Order responseOrder = orderService.getById(orderId);
  101. if (responseOrder.getId() == null) return "redirect:" + mainUrl + "mobile.html#/payresult/fail";
  102. List<OrderItem> items = orderItemService.getByOrderId(orderId);
  103. for (int i = 0; i < items.size(); i++){
  104. sb.append(items.get(i).getGoodsCount()).append("*").append(items.get(i).getGoodsName());
  105. if (i != items.size() - 1){
  106. sb.append(",");
  107. }
  108. }
  109. totalFee = responseOrder.getTotalAmount().multiply(new BigDecimal(100));
  110. orderSn = responseOrder.getOrderSn();
  111. orderSn += "_entity";
  112. break;
  113. case 1:
  114. VirtualOrder virtualOrderEntity = virtualOrderService.getById(orderId);
  115. if (virtualOrderEntity == null){
  116. return "redirect:" + mainUrl + "mobile.html#/payresult/fail";
  117. }
  118. sb.append(Constant.PAY_SUBJECT + ":" + virtualOrderEntity.getPoints());
  119. totalFee = new BigDecimal(virtualOrderEntity.getPoints()).multiply(new BigDecimal(100));
  120. orderSn = virtualOrderEntity.getOrderSn();
  121. orderSn += "_recharge";
  122. break;
  123. case 2:
  124. ExpansionOrder expansion = expansionOrderService.getById(orderId);
  125. if (expansion == null){
  126. return "redirect:" + mainUrl + "mobile.html#/payresult/fail";
  127. }
  128. //订单金额为国外金额就报错
  129. if(expansion.getAbroad() == 1){
  130. throw new BusinessException(ErrorCode.FAILURE_CODE_8004);
  131. }
  132. String date = "1年";
  133. if(expansion.getMonth() < 12){
  134. date = expansion.getMonth() + "个月";
  135. }
  136. String subject = Constant.EXPANSION_SUBJECT + ":" + expansion.getUnitSize() + expansion.getUnit() + "/" + date;
  137. sb.append(subject);
  138. totalFee = expansion.getAmount().multiply(new BigDecimal(100));
  139. orderSn = expansion.getOrderSn();
  140. orderSn += "_expansion";
  141. break;
  142. case 3:
  143. break;
  144. case 4:
  145. IncrementOrder incrementOrderEntity = incrementOrderService.getById(orderId);
  146. if (incrementOrderEntity == null){
  147. return "redirect:" + mainUrl + "mobile.html#/payresult/fail";
  148. }
  149. //订单金额为国外金额就报错
  150. if(incrementOrderEntity.getAbroad() == 1){
  151. throw new BusinessException(ErrorCode.FAILURE_CODE_8004);
  152. }
  153. sb.append(Constant.INCREMENT_SUBJECT + ":" + incrementOrderEntity.getCount() + "个/年");
  154. totalFee = incrementOrderEntity.getAmount().multiply(new BigDecimal(100));
  155. orderSn = incrementOrderEntity.getOrderSn();
  156. orderSn += "_increment";
  157. break;
  158. case 5:
  159. break;
  160. }
  161. String body = sb.toString();
  162. if(spaceId != null){
  163. orderSn = orderSn.replace("expansion", String.valueOf(spaceId));
  164. }
  165. Map<String, String> resp = payOrderService.wechatPay(orderSn, sb.toString(), body, totalFee, UrlUtils.getIpAddr(request), openid);
  166. String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
  167. return "redirect:" + mainUrl + ConstantUrl.WEIXIN_MOBILE_PAY_URL + timeStamp + "&signType=MD5&appId=" + resp.get("appid")
  168. + "&nonceStr=" + resp.get("nonce_str") + "&prepay_id=" + resp.get("prepay_id") + "&paySign=" + resp.get("paySign");
  169. }catch (Exception e){
  170. log.debug("获取access_token发生异常",e);
  171. }finally {
  172. if (is != null){
  173. is.close();
  174. }
  175. }
  176. return "redirect:" + mainUrl + "mobile.html#/payresult/fail";
  177. }
  178. @RequestMapping(value = {"/wechatPay/notify"}, method = RequestMethod.POST)
  179. public void callback() {
  180. log.warn("微信回调接口方法 start");
  181. String inputLine = "";
  182. String notifyXml = "";
  183. try {
  184. while((inputLine = request.getReader().readLine()) != null){
  185. notifyXml += inputLine;
  186. }
  187. //关闭流
  188. request.getReader().close();
  189. log.warn("微信回调内容信息:"+notifyXml);
  190. //解析成Map
  191. Map<String,String> map = WXPayUtil.xmlToMap(notifyXml);
  192. WXPayDefaultConfig config = new WXPayDefaultConfig();
  193. if (WXPayUtil.isSignatureValid(map, config.getKey(), WXPayConstants.SignType.MD5) || WXPayUtil.isSignatureValid(map, config.getKey(), WXPayConstants.SignType.HMACSHA256)) {
  194. //判断 支付是否成功
  195. if("SUCCESS".equals(map.get("result_code"))){
  196. log.warn("微信回调返回是否支付成功:是");
  197. //获得 返回的商户订单号
  198. String out_trade_no = map.get("out_trade_no");
  199. String trade_no = map.get("transaction_id");
  200. String openid = map.get("openid");
  201. log.warn("微信回调返回商户订单号:" + out_trade_no);
  202. //修改订单状态
  203. String orderSnE = out_trade_no.substring(0, out_trade_no.lastIndexOf("_"));
  204. String orderSn = out_trade_no.split("_")[0];
  205. if(!out_trade_no.contains("recharge") && !out_trade_no.contains("commerce") &&
  206. !out_trade_no.contains("entity") && !out_trade_no.contains("expansion") &&
  207. !out_trade_no.contains("increment") && !out_trade_no.contains("download")){
  208. // orderSn += "_" + out_trade_no.split("_")[1];
  209. log.warn("orderSnE:" + orderSn + "_expansion");
  210. if (redisUtil.hasKey(orderSn + "_expansion")){
  211. redisUtil.del(orderSn + "_expansion");
  212. }
  213. redisUtil.set(orderSn + "_expansion", out_trade_no,5*60);
  214. }else {
  215. log.warn("orderSnE:" + orderSnE);
  216. if (redisUtil.hasKey(orderSnE)){
  217. redisUtil.del(orderSnE);
  218. }
  219. redisUtil.set(orderSnE, out_trade_no,5*60);
  220. }
  221. orderStrategyFactory.doHandler(orderSn, trade_no, openid, out_trade_no.split("_")[1], 0);
  222. log.warn("微信支付成功,订单号:" + orderSn);
  223. //通知微信服务器已经支付成功
  224. notifyXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code>"
  225. + "<return_msg><![CDATA[OK]]></return_msg></xml> ";
  226. }else{
  227. notifyXml = "<xml><return_code><![CDATA[FAIL]]></return_code>"
  228. + "<return_msg><![CDATA[报文为空]]></return_msg></xml> ";
  229. }
  230. } else{
  231. log.error("签名验证错误");
  232. notifyXml = "<xml><return_code><![CDATA[FAIL]]></return_code>"
  233. + "<return_msg><![CDATA[签名验证错误]]></return_msg></xml>";
  234. }
  235. BufferedOutputStream out = new BufferedOutputStream(
  236. response.getOutputStream());
  237. out.write(notifyXml.getBytes());
  238. out.flush();
  239. out.close();
  240. } catch (Exception e) {
  241. log.error("微信支付回调数据异常, errorMsg:{}", e.getMessage());
  242. }
  243. }
  244. }