WeixinMobilePayController.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package com.itstyle.modules.weixinpay.controller;
  2. import java.io.BufferedOutputStream;
  3. import java.util.Map;
  4. import java.util.SortedMap;
  5. import java.util.TreeMap;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import org.apache.commons.lang3.StringUtils;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.beans.factory.annotation.Value;
  13. import org.springframework.stereotype.Controller;
  14. import org.springframework.ui.ModelMap;
  15. import org.springframework.web.bind.annotation.RequestMapping;
  16. import com.itstyle.common.model.Product;
  17. import com.itstyle.common.utils.AddressUtils;
  18. import com.itstyle.common.utils.DateUtil;
  19. import com.itstyle.modules.weixinpay.service.IWeixinPayService;
  20. import com.itstyle.modules.weixinpay.util.ConfigUtil;
  21. import com.itstyle.modules.weixinpay.util.HttpUtil;
  22. import com.itstyle.modules.weixinpay.util.PayCommonUtil;
  23. import com.itstyle.modules.weixinpay.util.XMLUtil;
  24. import com.itstyle.modules.weixinpay.util.mobile.MobileUtil;
  25. /**
  26. * 微信公众号H5支付
  27. * 创建者 科帮网
  28. * 创建时间 2017年7月31日
  29. *
  30. */
  31. @Controller
  32. @RequestMapping(value = "weixinMobile")
  33. public class WeixinMobilePayController {
  34. private static final Logger logger = LoggerFactory.getLogger(WeixinMobilePayController.class);
  35. @Autowired
  36. private IWeixinPayService weixinPayService;
  37. @Value("${server.context.url}")
  38. private String server_url;
  39. @RequestMapping("/pay")
  40. public String pay(Product product,ModelMap map) {
  41. logger.info("H5支付(需要公众号内支付)");
  42. String url = weixinPayService.weixinPayMobile(product);
  43. return "redirect:"+url;
  44. }
  45. //公众号H5支付主页
  46. @RequestMapping(value = "payPage")
  47. public String pay(HttpServletRequest request, HttpServletResponse response) throws Exception {
  48. return "weixin/payPage";
  49. }
  50. @RequestMapping("/h5pay")
  51. public String h5pay(Product product,ModelMap map) {
  52. logger.info("纯H5支付(不建议在APP端使用)");
  53. //mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。
  54. String mweb_url = weixinPayService.weixinPayH5(product);
  55. if(StringUtils.isNotBlank(mweb_url)){
  56. return "redirect:"+mweb_url;
  57. }else{
  58. return "redirect:https://blog.52itstyle.com";//自定义错误页面
  59. }
  60. }
  61. @RequestMapping("/smallRoutine")
  62. public String smallRoutine(Product product,ModelMap map) {
  63. logger.info("小程序支付(需要HTTPS)、不需要支付目录和授权域名");
  64. String url = weixinPayService.weixinPayMobile(product);
  65. return "redirect:"+url;
  66. }
  67. /**
  68. * 预下单(对于已经产生的订单)
  69. * @Author 科帮网
  70. * @param request
  71. * @param response
  72. * @return
  73. * @throws Exception String
  74. * @Date 2017年7月31日
  75. * 更新日志
  76. * 2017年7月31日 科帮网 首次创建
  77. *
  78. */
  79. @SuppressWarnings("rawtypes")
  80. @RequestMapping(value = "dopay")
  81. public String dopay(HttpServletRequest request, HttpServletResponse response) throws Exception {
  82. String orderNo = request.getParameter("outTradeNo");
  83. String totalFee = request.getParameter("totalFee");
  84. //获取code 这个在微信支付调用时会自动加上这个参数 无须设置
  85. String code = request.getParameter("code");
  86. //获取用户openID(JSAPI支付必须传openid)
  87. String openId = MobileUtil.getOpenId(code);
  88. String notify_url =server_url+"/weixinMobile/WXPayBack";//回调接口
  89. String trade_type = "JSAPI";// 交易类型H5支付 也可以是小程序支付参数
  90. SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
  91. ConfigUtil.commonParams(packageParams);
  92. packageParams.put("body","报告");// 商品描述
  93. packageParams.put("out_trade_no", orderNo);// 商户订单号
  94. packageParams.put("total_fee", totalFee);// 总金额
  95. packageParams.put("spbill_create_ip", AddressUtils.getIpAddr(request));// 发起人IP地址
  96. packageParams.put("notify_url", notify_url);// 回调地址
  97. packageParams.put("trade_type", trade_type);// 交易类型
  98. packageParams.put("openid", openId);//用户openID
  99. String sign = PayCommonUtil.createSign("UTF-8", packageParams,ConfigUtil.API_KEY);
  100. packageParams.put("sign", sign);// 签名
  101. String requestXML = PayCommonUtil.getRequestXml(packageParams);
  102. String resXml = HttpUtil.postData(ConfigUtil.UNIFIED_ORDER_URL, requestXML);
  103. Map map = XMLUtil.doXMLParse(resXml);
  104. String returnCode = (String) map.get("return_code");
  105. String returnMsg = (String) map.get("return_msg");
  106. StringBuffer url = new StringBuffer();
  107. if("SUCCESS".equals(returnCode)){
  108. String resultCode = (String) map.get("result_code");
  109. String errCodeDes = (String) map.get("err_code_des");
  110. if("SUCCESS".equals(resultCode)){
  111. //获取预支付交易会话标识
  112. String prepay_id = (String) map.get("prepay_id");
  113. String prepay_id2 = "prepay_id=" + prepay_id;
  114. String packages = prepay_id2;
  115. SortedMap<Object, Object> finalpackage = new TreeMap<Object, Object>();
  116. String timestamp = DateUtil.getTimestamp();
  117. String nonceStr = packageParams.get("nonce_str").toString();
  118. finalpackage.put("appId", ConfigUtil.APP_ID);
  119. finalpackage.put("timeStamp", timestamp);
  120. finalpackage.put("nonceStr", nonceStr);
  121. finalpackage.put("package", packages);
  122. finalpackage.put("signType", "MD5");
  123. //这里很重要 参数一定要正确 狗日的腾讯 参数到这里就成大写了
  124. //可能报错信息(支付验证签名失败 get_brand_wcpay_request:fail)
  125. sign = PayCommonUtil.createSign("UTF-8", finalpackage,ConfigUtil.API_KEY);
  126. url.append("redirect:/weixinMobile/payPage?");
  127. url.append("timeStamp="+timestamp+"&nonceStr=" + nonceStr + "&package=" + packages);
  128. url.append("&signType=MD5" + "&paySign=" + sign+"&appid="+ ConfigUtil.APP_ID);
  129. url.append("&orderNo="+orderNo+"&totalFee="+totalFee);
  130. }else{
  131. logger.info("订单号:{}错误信息:{}",orderNo,errCodeDes);
  132. url.append("redirect:/weixinMobile/error?code=0&orderNo="+orderNo);//该订单已支付
  133. }
  134. }else{
  135. logger.info("订单号:{}错误信息:{}",orderNo,returnMsg);
  136. url.append("redirect:/weixinMobile/error?code=1&orderNo="+orderNo);//系统错误
  137. }
  138. return url.toString();
  139. }
  140. /**
  141. * 手机支付完成回调
  142. * @Author 科帮网
  143. * @param request
  144. * @param response
  145. * @param platForm void
  146. * @Date 2017年7月31日
  147. * 更新日志
  148. * 2017年7月31日 科帮网 首次创建
  149. *
  150. */
  151. @RequestMapping(value = "WXPayBack")
  152. public void WXPayBack(HttpServletRequest request, HttpServletResponse response){
  153. String resXml = "";
  154. try {
  155. //解析XML
  156. Map<String, String> map = MobileUtil.parseXml(request);
  157. String return_code = map.get("return_code");//状态
  158. String out_trade_no = map.get("out_trade_no");//订单号
  159. if (return_code.equals("SUCCESS")) {
  160. if (out_trade_no != null) {
  161. //处理订单逻辑
  162. logger.info("微信手机支付回调成功订单号:{}",out_trade_no);
  163. resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
  164. }
  165. }else{
  166. logger.info("微信手机支付回调失败订单号:{}",out_trade_no);
  167. resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
  168. }
  169. } catch (Exception e) {
  170. logger.error("手机支付回调通知失败",e);
  171. resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
  172. }
  173. try {
  174. // ------------------------------
  175. // 处理业务完毕
  176. // ------------------------------
  177. BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
  178. out.write(resXml.getBytes());
  179. out.flush();
  180. out.close();
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. }
  184. }
  185. }