LeYunFuController.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. package com.izouma.weixin.web;
  2. import com.github.kevinsawicki.http.HttpRequest;
  3. import com.izouma.awesomeadmin.constant.AppConstant;
  4. import com.izouma.awesomeadmin.dto.Result;
  5. import com.izouma.awesomeadmin.model.MemberTicket;
  6. import com.izouma.awesomeadmin.model.ProductInfo;
  7. import com.izouma.awesomeadmin.service.MemberTicketService;
  8. import com.izouma.awesomeadmin.service.ProductInfoService;
  9. import com.izouma.awesomeadmin.util.MbappUtil;
  10. import com.izouma.awesomeadmin.util.PropertiesFileLoader;
  11. import com.izouma.weixin.dao.WxpayTempMapper;
  12. import com.izouma.weixin.model.WxpayTemp;
  13. import com.izouma.weixin.util.WeixinUtil;
  14. import org.apache.commons.codec.digest.DigestUtils;
  15. import org.apache.commons.lang3.StringUtils;
  16. import org.apache.log4j.Logger;
  17. import org.json.JSONObject;
  18. import org.springframework.beans.factory.annotation.Autowired;
  19. import org.springframework.stereotype.Controller;
  20. import org.springframework.web.bind.annotation.RequestMapping;
  21. import org.springframework.web.bind.annotation.RequestMethod;
  22. import org.springframework.web.bind.annotation.RequestParam;
  23. import org.springframework.web.bind.annotation.ResponseBody;
  24. import org.springframework.web.context.request.RequestContextHolder;
  25. import org.springframework.web.context.request.ServletRequestAttributes;
  26. import javax.servlet.http.HttpServletRequest;
  27. import javax.servlet.http.HttpServletResponse;
  28. import javax.servlet.http.HttpSession;
  29. import java.io.BufferedOutputStream;
  30. import java.io.IOException;
  31. import java.math.BigDecimal;
  32. import java.util.*;
  33. @Controller
  34. @RequestMapping("/lyf")
  35. public class LeYunFuController {
  36. private static Logger logger = Logger.getLogger(LeYunFuController.class);
  37. @Autowired
  38. private MemberTicketService memberTicketService;
  39. @Autowired
  40. private WxpayTempMapper wxpayTempMapper;
  41. @Autowired
  42. private ProductInfoService productInfoService;
  43. @RequestMapping(value = "/notify", method = RequestMethod.POST)
  44. @ResponseBody
  45. public String notify(HttpServletRequest request, HttpServletResponse response) {
  46. logger.error("lyf:notify");
  47. try {
  48. Map<String, String> m = notifyMap(request, response);
  49. payResultChange(m);
  50. } catch (Exception e) {
  51. logger.error("微信支付回调异常", e);
  52. }
  53. return "SUCCESS";
  54. }
  55. /**
  56. * 支付结果
  57. *
  58. * @param m
  59. */
  60. public void payResultChange(Map<String, String> m) {
  61. try {
  62. if (m != null && "SUCCESS".equals(m.get("return_code"))) {//支付成功
  63. String attach = m.get("attach");
  64. JSONObject attachJson = new JSONObject(attach);
  65. WxpayTemp checkTemp = new WxpayTemp();
  66. checkTemp.setOutTradeNo(m.get("out_trade_no"));
  67. checkTemp = wxpayTempMapper.queryWxpayTemp(checkTemp);
  68. if (checkTemp != null && "WAIT_BUYER_PAY".equals(checkTemp.getResultCode())) {
  69. WxpayTemp wxpayTemp = new WxpayTemp();
  70. wxpayTemp.setOutTradeNo(m.get("out_trade_no"));
  71. wxpayTemp.setUserId(attachJson.getString("userId"));
  72. wxpayTemp.setOrderId(attachJson.getString("productId"));
  73. wxpayTemp.setCash(BigDecimal.valueOf(attachJson.getDouble("cash")));
  74. wxpayTemp.setTotalAmount(BigDecimal.valueOf(attachJson.getInt("total") / 100.0));
  75. wxpayTemp.setOutTradeNo(m.get("out_trade_no"));
  76. wxpayTemp.setTransactionId(m.get("transaction_id"));
  77. wxpayTemp.setResultCode(m.get("payment_status"));
  78. wxpayTempMapper.updateByOutTradeNo(wxpayTemp);
  79. if ("SUCCESS".equals(m.get("payment_status"))) {
  80. logger.info("buyProductInfo");
  81. try {
  82. ProductInfo productInfo = productInfoService.getProductInfoById(attachJson.getString("productId"));
  83. if (productInfo != null) {
  84. if (AppConstant.ProductType.RECHARGE == productInfo.getTypeFlag()) {//如果是充值类型
  85. MemberTicket memberTicket = new MemberTicket();
  86. memberTicket.setMoney(productInfo.getCoin());
  87. memberTicket.setUserId(Integer.valueOf(attachJson.getString("userId")));
  88. memberTicket.setRemark("购买" + productInfo.getProductName() + "套餐,充值");
  89. memberTicket.setRechargeType(AppConstant.RechargeType.WEI_XIN);
  90. memberTicketService.recharge(memberTicket);
  91. } else {
  92. //TODO 购买VIP
  93. }
  94. }
  95. } catch (Exception e) {
  96. logger.error("buyProductInfo", e);
  97. }
  98. }
  99. }
  100. }
  101. } catch (Exception e) {
  102. logger.error("支付结果转换异常", e);
  103. }
  104. }
  105. @RequestMapping(value = "/unifiedOrder", method = RequestMethod.GET)
  106. @ResponseBody
  107. public String unifiedOrder(@RequestParam(required = true, value = "userId") String userId,
  108. @RequestParam(required = true, value = "productId") String productId) {
  109. try {
  110. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  111. String ip = WeixinUtil.getIpAdderss(request);
  112. double cash = 1;
  113. ProductInfo productInfo = productInfoService.getProductInfoById(productId);
  114. cash = productInfo.getMoney().doubleValue();
  115. int total = 0;
  116. total = (int) (cash * 100);
  117. //测试为一分
  118. total = 1;
  119. JSONObject attach = new JSONObject();
  120. attach.put("productId", productId);
  121. attach.put("userId", userId);
  122. attach.put("cash", cash);
  123. attach.put("total", total);
  124. String out_trade_no = MbappUtil.create_out_trade_no();
  125. String nonceStr = MbappUtil.create_nonce_str();
  126. Map<String, String> params = new TreeMap<>();
  127. params.put("mch_id", PropertiesFileLoader.getProperties("leyunfu_mch_id")); //商户号
  128. params.put("nonce_str", nonceStr); //随机串
  129. params.put("amount", String.valueOf(total)); //金额 单位分
  130. params.put("body", productInfo.getProductName()); //商品或支付单简要描述
  131. params.put("out_trade_no", out_trade_no); //商户系统内部的订单号
  132. params.put("notify_url", PropertiesFileLoader.getProperties("leyunfu_return_url")); //接收支付结果异步通知回调地址
  133. params.put("spbill_create_ip", ip); //客户端IP
  134. params.put("return_url", PropertiesFileLoader.getProperties("leyunfu_notify_url")); //页面回调地址
  135. params.put("payment_type", "trade.weixin.native"); //支付类型
  136. params.put("attach", attach.toString()); //附加数据
  137. String signSrc = getSignSrc(params);
  138. String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("leyunfu_mch_secret"));
  139. params.put("sign_type", "MD5"); //签名方式
  140. params.put("sign", sign); //签名
  141. String response = HttpRequest.post(PropertiesFileLoader.getProperties("leyunfu_pay_url"))
  142. .form(params).body();
  143. /**
  144. * 返回示例:
  145. {"return_code":"SUCCESS",
  146. "return_msg":"成功",
  147. "mch_id":"100000007927",
  148. "payment_type":"trade.qqpay.native",x
  149. "code_img_url":"http://xxx"}
  150. */
  151. WxpayTemp wxpayTemp = new WxpayTemp();
  152. wxpayTemp.setOrderId(productId);
  153. wxpayTemp.setUserId(userId);
  154. wxpayTemp.setCash(BigDecimal.valueOf(cash));
  155. wxpayTemp.setTotalAmount(BigDecimal.valueOf(total / 100.0));
  156. wxpayTemp.setOutTradeNo(out_trade_no);
  157. wxpayTemp.setTypeFlag(AppConstant.Aliapi.BUY);
  158. wxpayTemp.setResultCode("WAIT_BUYER_PAY");
  159. wxpayTemp.setCreateUser("lyf");
  160. wxpayTempMapper.insertSelective(wxpayTemp);
  161. return response;
  162. } catch (Exception e) {
  163. logger.error("leyunfu下单失败", e);
  164. }
  165. return null;
  166. }
  167. @RequestMapping(value = "/orderquery", method = RequestMethod.GET)
  168. @ResponseBody
  169. public String orderquery(@RequestParam(required = true, value = "out_trade_no") String out_trade_no) {
  170. try {
  171. String nonceStr = MbappUtil.create_nonce_str();
  172. Map<String, String> params = new TreeMap<>();
  173. params.put("mch_id", PropertiesFileLoader.getProperties("leyunfu_mch_id")); //商户号
  174. params.put("nonce_str", nonceStr); //随机串
  175. params.put("out_trade_no", out_trade_no); //商户系统内部的订单号
  176. String signSrc = getSignSrc(params);
  177. String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("leyunfu_mch_secret"));
  178. params.put("sign_type", "MD5"); //签名方式
  179. params.put("sign", sign); //签名
  180. String response = HttpRequest.post(PropertiesFileLoader.getProperties("leyunfu_query_url"))
  181. .form(params).body();
  182. return response;
  183. } catch (Exception e) {
  184. logger.error("leyunfu查询订单失败", e);
  185. }
  186. return null;
  187. }
  188. @RequestMapping(value = "/autoCheckPayResult", method = RequestMethod.GET)
  189. @ResponseBody
  190. public Result autoCheckPayResult() {
  191. try {
  192. WxpayTemp param = new WxpayTemp();
  193. param.setCreateUser("lyf");
  194. param.setResultCode("WAIT_BUYER_PAY");
  195. List<WxpayTemp> wxpayTempList = wxpayTempMapper.queryAllWxpayTemp(param);
  196. for (WxpayTemp wxpayTemp : wxpayTempList) {
  197. try {
  198. String nonceStr = MbappUtil.create_nonce_str();
  199. Map<String, String> params = new TreeMap<>();
  200. params.put("mch_id", PropertiesFileLoader.getProperties("leyunfu_mch_id")); //商户号
  201. params.put("nonce_str", nonceStr); //随机串
  202. params.put("out_trade_no", wxpayTemp.getOutTradeNo()); //商户系统内部的订单号
  203. String signSrc = getSignSrc(params);
  204. String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("leyunfu_mch_secret"));
  205. params.put("sign_type", "MD5"); //签名方式
  206. params.put("sign", sign); //签名
  207. String response = HttpRequest.post(PropertiesFileLoader.getProperties("leyunfu_query_url"))
  208. .form(params).body();
  209. JSONObject responseJson = new JSONObject(response);
  210. Map<String, String> notifyMap = new HashMap<>();
  211. notifyMap.put("return_code", responseJson.getString("return_code"));
  212. notifyMap.put("return_msg", responseJson.getString("return_msg"));
  213. notifyMap.put("mch_id", responseJson.getString("mch_id"));
  214. notifyMap.put("payment_status", responseJson.getString("payment_status"));
  215. notifyMap.put("transaction_id", responseJson.getString("transaction_id"));
  216. notifyMap.put("out_trade_no", responseJson.getString("out_trade_no"));
  217. notifyMap.put("payment_type", responseJson.getString("payment_type"));
  218. notifyMap.put("attach", responseJson.getString("attach"));
  219. notifyMap.put("fee_type", responseJson.getString("fee_type"));
  220. notifyMap.put("nonce_str", responseJson.getString("nonce_str"));
  221. notifyMap.put("amount", String.valueOf(responseJson.getInt("amount")));
  222. notifyMap.put("sign", responseJson.getString("sign"));
  223. payResultChange(notifyMap);
  224. } catch (Exception e) {
  225. logger.error("查询支付结果异常", e);
  226. }
  227. }
  228. return new Result(true, "自动检测支付结果成功");
  229. } catch (Exception e) {
  230. logger.error("leyunfu查询订单失败", e);
  231. }
  232. return null;
  233. }
  234. /**
  235. * 解析微信支付回调结果
  236. *
  237. * @param request
  238. * @param response
  239. * @return
  240. */
  241. public Map<String, String> notifyMap(HttpServletRequest request, HttpServletResponse response) {
  242. logger.info("payOrder:支付订单");
  243. Map<String, String> notifyMap = new HashMap<>();
  244. String resXml = "SUCCESS";
  245. try {
  246. notifyMap.put("return_code", request.getParameter("return_code"));
  247. notifyMap.put("return_msg", request.getParameter("return_msg"));
  248. notifyMap.put("mch_id", request.getParameter("mch_id"));
  249. notifyMap.put("payment_status", request.getParameter("payment_status"));
  250. notifyMap.put("transaction_id", request.getParameter("transaction_id"));
  251. notifyMap.put("out_trade_no", request.getParameter("out_trade_no"));
  252. notifyMap.put("payment_type", request.getParameter("payment_type"));
  253. notifyMap.put("attach", request.getParameter("attach"));
  254. notifyMap.put("fee_type", request.getParameter("fee_type"));
  255. notifyMap.put("nonce_str", request.getParameter("nonce_str"));
  256. notifyMap.put("amount", request.getParameter("amount"));
  257. notifyMap.put("sign", request.getParameter("sign"));
  258. System.out.println("notifyMap:" + notifyMap.toString());
  259. // 签名正确
  260. // 进行处理。
  261. // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
  262. if ("SUCCESS".equals(notifyMap.get("result_code"))) {
  263. //支付成功
  264. resXml = "SUCCESS";
  265. } else {
  266. resXml = "SUCCESS";
  267. }
  268. System.out.println("支付回调数据结束");
  269. HttpSession seesion = request.getSession();
  270. seesion.setAttribute("notify", "支付回调");
  271. try {
  272. BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
  273. out.write(resXml.getBytes());
  274. out.flush();
  275. out.close();
  276. } catch (IOException e) {
  277. // TODO Auto-generated catch block
  278. e.printStackTrace();
  279. }
  280. } catch (Exception e) {
  281. logger.error("payOrder:支付订单异常", e);
  282. }
  283. return notifyMap;
  284. }
  285. private String getSignSrc(Map<String, ?> paramMap) {
  286. StringJoiner signSrc = new StringJoiner("&");
  287. paramMap.forEach((key, value) -> {
  288. if (!"sign".equals(key) && value != null && StringUtils.isNotBlank(value.toString())) {
  289. signSrc.add(key + "=" + value);
  290. }
  291. });
  292. return signSrc.toString();
  293. }
  294. }