Browse Source

微信扫码支付页面以及支付完成跳转实现,微信用户授权实现

huangct 8 years ago
parent
commit
b3f18925d5

+ 1 - 0
donate-service/src/main/MP_verify_BMkQAHplMGROBlAn.txt


+ 4 - 10
donate-service/src/main/java/com/uas/service/donate/api/WxPayApi.java

@@ -415,9 +415,7 @@ public class WxPayApi implements WxPayService{
         return this.wxPayService.queryCouponInfo(request);
     }
 
-    /**
-     * 请忽略之
-     */
+
     @Override
     public WxPayApiData getWxApiData() {
         return null;
@@ -428,17 +426,13 @@ public class WxPayApi implements WxPayService{
         return this.queryComment(beginDate, endDate, offset, limit);
     }
 
-    /**
-     * 请忽略之
-     */
+
     @Override
     public WxPayConfig getConfig() {
-        return null;
+        return wxPayService.getConfig();
     }
 
-    /**
-     * 请忽略之
-     */
+
     @Override
     public void setConfig(WxPayConfig config) {
 

+ 1 - 11
donate-service/src/main/java/com/uas/service/donate/config/WxConfig.java

@@ -4,21 +4,11 @@ package com.uas.service.donate.config;
  * Created by 黄诚天 on 2017-10-27.
  */
 public class WxConfig {
-    //沙盒参数
-    public static String do_main = "http://5087452.nat123.cc";
 
-    //自己个人 wxe73df80d5c7a6ee8   自己公众号 wx59ebbd454c239e2d
     public static String APPID = "wxbc1f8607137d3b8a";
 
-    //自己个人 6497c36255030cdfd5e0716928abda21   自己公众号 f76b0b47ba1190f75b1590f38d032a7b
-    public static String APPSECRET = "f76b0b47ba1190f75b1590f38d032a7b";
-
-    public static String notify_url = do_main + "/wxpay/notifyUrl";
-
-    public static String redirect_url = do_main + "/wxpay/redirectUrl";
+    public static String APPSECRET = "5788793a734881c3410be63224b75292";
 
     public static String Token = "huangchengtian";
 
-    public static String encoding_aes_key = "bmSUBuzyzvfUYTw4GMKTHQmnaxj6SNf1JJ3Q1joFnGP";
-    //public static String encoding_aes_key = "34222222222222222f324e324324324324321431243";
 }

+ 9 - 7
donate-service/src/main/java/com/uas/service/donate/controller/AlipayController.java

@@ -20,9 +20,7 @@ import com.uas.platform.core.util.serializer.FlexJsonUtils;
 import com.uas.service.donate.DruidDBConfiguration;
 import com.uas.service.donate.api.AlipayApi;
 import com.uas.service.donate.config.AlipayConfig;
-import com.uas.service.donate.model.AlipayOrder;
-import com.uas.service.donate.model.AlipayUserInfo;
-import com.uas.service.donate.model.ProjectRecode;
+import com.uas.service.donate.model.*;
 import com.uas.service.donate.service.AlipayOrderService;
 import com.uas.service.donate.service.AlipayUserService;
 import com.uas.service.donate.service.ProjectRecodeService;
@@ -283,8 +281,6 @@ public class AlipayController {
             String notifySellerId = params.get("seller_id") == null ? "" : params.get("seller_id");
             String notifySellerEmail = params.get("seller_email") == null ? "" : params.get("seller_id");
 
-            System.out.print("*************************异步通知********************************* 商户订单号:" + notifyOutTradeNo);
-
             //商户系统订单支付状态
             short projectRecodePayStatus = 1;
             if ("TRADE_SUCCESS".equals(notifyTradeStatus)) {
@@ -302,8 +298,9 @@ public class AlipayController {
             } else {
                 //判断该笔订单是否在商户网站中已经做过处理
                 AlipayOrder oldAlipayOrder = alipayOrderService.getByOutTradeNo(notifyOutTradeNo);
-                if (oldAlipayOrder != null && notifyTradeStatus.equals(oldAlipayOrder.getTrade_status()) && oldAlipayOrder.getStatus() == 1) {
+                if (oldAlipayOrder != null && notifyTradeStatus.equals(oldAlipayOrder.getTrade_status()) && oldAlipayOrder.getStatus() == 1 && projectRecode.getStatus() != 1) {
                     //有做过处理,不执行商户的业务程序
+                    logger.info("系统已对该笔交易进行处理,交易订单号" + oldAlipayOrder.getOut_trade_no() + "支付宝订单号号" + oldAlipayOrder.getTrade_no());
                     response.getWriter().write("success");
                 } else {
                     projectRecode.setStatus(projectRecodePayStatus);
@@ -384,7 +381,6 @@ public class AlipayController {
                 if ("10000".equals(tradeQueryResponse.getCode())) {
                     if ("TRADE_SUCCESS".equals(tradeQueryResponse.getTradeStatus())) {
                         String requestUrlMessage = request.getScheme() +"://" + request.getServerName() + ":" + request.getServerPort();
-                        logger.info("服务器路径:" + requestUrlMessage);
                         String url = requestUrlMessage + "/project#/donationsOver/" +  notifyOutTradeNo;
                         modelAndView.setViewName("redirect:" + url);
                     }
@@ -563,6 +559,12 @@ public class AlipayController {
 
     private ProjectRecode createProjectRecode(String jsonStr) throws Exception {
         ProjectRecode projectRecode= JSONObject.parseObject(jsonStr,ProjectRecode.class);
+        
+        User user = SystemSession.getUser();
+        if (user != null) {
+            projectRecode.setUuid(user.getUserUU());
+        }
+
         projectRecode.setTime(new Date());
         ProjectRecode newProjectRecode = projectRecodeService.join(projectRecode);
         return newProjectRecode;

+ 85 - 6
donate-service/src/main/java/com/uas/service/donate/controller/IndexController.java

@@ -1,15 +1,32 @@
 package com.uas.service.donate.controller;
 
 import com.alibaba.fastjson.JSONObject;
-import com.uas.service.donate.model.*;
-import com.uas.service.donate.service.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.uas.service.donate.api.WxPayApi;
+import com.uas.service.donate.config.WxConfig;
+import com.uas.service.donate.model.Project;
+import com.uas.service.donate.model.SystemSession;
+import com.uas.service.donate.model.User;
+import com.uas.service.donate.model.WechatUserInfo;
+import com.uas.service.donate.service.CarouselService;
+import com.uas.service.donate.service.ProjectRecodeService;
+import com.uas.service.donate.service.ProjectService;
+import com.uas.service.donate.util.WechatConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.*;
-
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
 import java.util.List;
 
 @Controller
@@ -24,9 +41,71 @@ public class IndexController {
     @Autowired
     private CarouselService carouselService;
 
+    @Autowired
+    protected WxPayApi wxPayApi;
+
+    private Logger logger = LoggerFactory.getLogger(IndexController.class);
+
+    private String oauthUserScope = "snsapi_userinfo";
+
+
+    @RequestMapping(value = "/", method = RequestMethod.GET)
+    public String returnaDefault(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String code = request.getParameter("code");
+        String state = request.getParameter("state");
+        User user = SystemSession.getUser();
+
+        String ua = request.getHeader("user-agent").toLowerCase();
+        if (ua.indexOf("micromessenger") >= 0) {// 是微信浏览器
+
+            if (user != null && user.getWxOpenId() != null) {
+                //有用户 有openid 已授权
+                logger.info("公众号获取:--有用户 有openid 已授权");
+                return "forward:/index";
+            } else if (user != null && user.getWxOpenId() == null && code == null) {
+                //有用户 无openid 需要授权
+                logger.info("公众号获取:--有用户 无openid 需要授权");
+                //String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxPayApi.getConfig().getAppId() + "&redirect_uri=" + URLEncoder.encode("http://lj.ubtob.com/", "UTF-8") + "&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
+                String url = WechatConnector.createAuthorizeUrl(oauthUserScope, wxPayApi.getConfig().getAppId(), URLEncoder.encode("http://lj.ubtob.com", "UTF-8"));
+                response.sendRedirect(url);
+            } else if (user == null && code == null) {
+                //需要授权
+                logger.info("公众号获取:--需要授权");
+                //String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxPayApi.getConfig().getAppId() + "&redirect_uri=" + URLEncoder.encode("http://lj.ubtob.com/", "UTF-8") + "&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
+                String url = WechatConnector.createAuthorizeUrl(oauthUserScope, wxPayApi.getConfig().getAppId(), URLEncoder.encode("http://lj.ubtob.com", "UTF-8"));
+                response.sendRedirect(url);
+            }
+        }
+
+        if (code != null) {
+            //授权回调
+            logger.info("公众号获取,授权回调:authCode=" + code + ",state=" + state);
+
+            if (user == null) {
+                user = new User();
+            }
+            String openId = null;
+            try {
+                if ("snsapi_userinfo".equals(oauthUserScope)) {
+                    WechatUserInfo wechatUserInfo= WechatConnector.getOauthUser(code, wxPayApi.getConfig().getAppId(), WxConfig.APPSECRET); //TODO APPSECRET
+                    logger.info("微信用户授权信息:" + wechatUserInfo.toString());
+                    openId = wechatUserInfo.getOpenId();
+                } else if ("snsapi_base".equals(oauthUserScope)) {
+                    JSONObject tokenJson = WechatConnector.getAccessToken(code, wxPayApi.getConfig().getAppId(), WxConfig.APPSECRET);//TODO APPSECRET
+                    openId = tokenJson.getString("openid");
+                }
+
+                //openId = wxPayApi.authcode2Openid(code);
+            } catch (WxPayException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            user.setWxOpenId(openId);
+            logger.info("当前用户信息:" + user.toString());
+            SystemSession.setUser(user);
+        }
 
-    @RequestMapping(value = "/",method = RequestMethod.GET)
-    public String returnaDefault(){
         return "forward:/index";
     }
 

+ 126 - 59
donate-service/src/main/java/com/uas/service/donate/controller/WxpayController.java

@@ -14,9 +14,12 @@ import com.uas.platform.core.util.HttpUtil;
 import com.uas.service.donate.api.WxPayApi;
 import com.uas.service.donate.config.WxConfig;
 import com.uas.service.donate.model.ProjectRecode;
+import com.uas.service.donate.model.SystemSession;
+import com.uas.service.donate.model.User;
 import com.uas.service.donate.model.WechatOrder;
 import com.uas.service.donate.service.ProjectRecodeService;
 import com.uas.service.donate.service.WechatOrderService;
+import com.uas.service.donate.util.IpUtils;
 import com.uas.service.donate.util.StringUtils;
 import com.uas.service.donate.util.WxCheckoutUtil;
 import org.apache.commons.io.IOUtils;
@@ -36,6 +39,8 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URLEncoder;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Created by 黄诚天 on 2017-10-27.
@@ -68,24 +73,35 @@ public class WxpayController {
 
     /**
      * 扫码支付 @RequestParam ProjectRecode projectRecode
+     * 使用模式一   模式一,先扫码,再生成订单。模式二,先生成订单,再扫码。
      * @param request
      * @param response
      * @throws Exception
      */
     @ResponseBody
     @RequestMapping(value = "/pcPay", method = RequestMethod.POST)
-    public String pcPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception {
+    public ModelMap pcPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        ModelMap modelMap = new ModelMap();
         ProjectRecode projectRecode= null;
         try {
             projectRecode = this.createProjectRecode(jsonStr);
         } catch (Exception e) {
-            response.getWriter().write(e.getMessage());
             logger.error("生成商户订单错误,原因:{}", e.getMessage());
-            return null;
+            modelMap.put("error", "参数错误");
+            return modelMap;
         }
 
         WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.NATIVE);
-        return unifiedOrder(wxPayUnifiedOrderRequest);
+        Map map = unifiedOrder(wxPayUnifiedOrderRequest);
+        if ("FAIL".equals(map.get("status"))) {
+            modelMap.put("error", map.get("message"));
+        } else {
+            modelMap.put("qrcodeUrl", map.get("qrcodeUrl"));
+            modelMap.put("outTradeNo", projectRecode.getId());
+        }
+
+
+        return modelMap;
     }
 
     /**
@@ -97,46 +113,52 @@ public class WxpayController {
      */
     @ResponseBody
     @RequestMapping(value = "/webPay", method = RequestMethod.POST)
-    public ModelMap appPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception {
-        ModelMap map = new ModelMap();
+    public ModelMap webPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        ModelMap modelMap = new ModelMap();
 
         ProjectRecode projectRecode= null;
         try {
             projectRecode = this.createProjectRecode(jsonStr);
         } catch (Exception e) {
-            response.getWriter().write(e.getMessage());
             logger.error("生成商户订单错误,原因:{}", e.getMessage());
-            map.put("error", "参数错误");
-            return map;
+            modelMap.put("error", "参数错误");
+            return modelMap;
         }
 
         WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.JSAPI);
+        User user =SystemSession.getUser();
+        String openId = null;
+        if (user != null) {
+            openId = user.getWxOpenId();
+        }
 
-        //配置网页授权url
-        String openId = getOpenId(request);
+        openId = "o8lZ9uPU0cQRhPIEejd8XIuD6Urc";
+
+        logger.info("公众号支付处理:openId=" + openId);
         if (StringUtils.isEmpty(wxPayApi.getConfig().getSubAppId())) {
             wxPayUnifiedOrderRequest.setOpenid(openId);//否是 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
         } else {
             wxPayUnifiedOrderRequest.setSubOpenid(openId);//否是 trade_type=JSAPI,此参数必传,用户在子商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
         }
 
-        String prepayId = unifiedOrder(wxPayUnifiedOrderRequest);
-        if (StringUtils.isEmpty(prepayId)) {
-            //TODO 预下单失败处理
-            map.put("error", "支付失败,请重试");
+        Map map = unifiedOrder(wxPayUnifiedOrderRequest);
+
+        if ("FAIL".equals(map.get("status"))) {
+            modelMap.put("error", map.get("message"));
         } else {
-            //TODO 将prepayId返回给js
-            map.put("appId", wxPayApi.getConfig().getAppId());
-            map.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
-            map.put("nonceStr", wxPayUnifiedOrderRequest.getNonceStr());//String.valueOf(System.currentTimeMillis()
-            map.put("package", "prepay_id=" + prepayId);
-            map.put("signType", "MD5");
+            //modelMap.put("outTradeNo", projectRecode.getId());
+            //将prepayId返回给js
+            modelMap.put("appId", wxPayApi.getConfig().getAppId());
+            modelMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
+            modelMap.put("nonceStr", wxPayUnifiedOrderRequest.getNonceStr());//String.valueOf(System.currentTimeMillis()
+            modelMap.put("package", "prepay_id=" + map.get("prepayId"));
+            modelMap.put("signType", "MD5");
             //预付订单再次签名
             String packageSign = SignUtils.createSign(map, WxPayConstants.SignType.MD5, wxPayApi.getConfig().getMchKey(), false);
-            map.put("paySign", packageSign);
+            modelMap.put("paySign", packageSign);
         }
 
-        return map;
+        return modelMap;
     }
 
     /**
@@ -149,71 +171,74 @@ public class WxpayController {
     @ResponseBody
     @RequestMapping(value = "/wapPay", method = RequestMethod.POST)
     public ModelMap wapPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception {
-        ModelMap map = new ModelMap();
-
+        ModelMap modelMap = new ModelMap();
         ProjectRecode projectRecode= null;
         try {
             projectRecode = this.createProjectRecode(jsonStr);
         } catch (Exception e) {
-            response.getWriter().write(e.getMessage());
             logger.error("生成商户订单错误,原因:{}", e.getMessage());
-            map.put("error", "参数错误");
-            return map;
+            modelMap.put("error", "参数错误");
+            return modelMap;
         }
 
         WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.MWEB);
-        String mwebUrl = unifiedOrder(wxPayUnifiedOrderRequest);
-        if (StringUtils.isEmpty(mwebUrl)) {
-            //TODO 预下单失败处理
-            map.put("error", "支付失败,请重试");
+        Map map = unifiedOrder(wxPayUnifiedOrderRequest);
+        if ("FAIL".equals(map.get("status"))) {
+            modelMap.put("error", map.get("message"));
         } else {
-            map.put("mwebUrl", mwebUrl); //通过mweb_url调起微信支付中间页  重定向mweb_url
+            modelMap.put("mwebUrl", map.get("mwebUrl"));
         }
 
-        return map;
+        return modelMap;
     }
 
 
     //通过统一下单接口发起请求,获得prepay_id(预支付交易会话标识),这个标示是微信提交支付的关键数据
-    public String unifiedOrder(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest) throws Exception {
+    public Map unifiedOrder(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest) throws Exception {
+        Map map = new HashMap();
         WxPayUnifiedOrderResult wxPayUnifiedOrderResult = null;
         try {
             wxPayUnifiedOrderResult = wxPayApi.unifiedOrder(wxPayUnifiedOrderRequest);
 
+            //map.put("status", "SUCCESS");
             if (WxPayConstants.TradeType.MWEB.equals(wxPayUnifiedOrderRequest.getTradeType())) {
                 /*H5支付开发步骤:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4*/
                 String mwebUrl = wxPayUnifiedOrderResult.getMwebUrl() + "&redirect_url=" + URLEncoder.encode(redirectUrl,"UTF-8");
-                return mwebUrl;
+                map.put("mwebUrl", mwebUrl);
             } else if (WxPayConstants.TradeType.NATIVE.equals(wxPayUnifiedOrderRequest.getTradeType())) {
                 //扫码支付
                 //QrcodeUtils.encode(wxPayUnifiedOrderResult.getCodeURL(),response.getOutputStream());
                 byte[] bytes = QrcodeUtils.createQrcode(wxPayUnifiedOrderResult.getCodeURL(), 400, null);
-                String path=fileClient.upload(bytes, bytes.length,"jpg",null);
-                return path;
+                String qrcodeUrl = fileClient.upload(bytes, bytes.length,"jpg",null);
+                map.put("qrcodeUrl", qrcodeUrl);
             } else if (WxPayConstants.TradeType.JSAPI.equals(wxPayUnifiedOrderRequest.getTradeType())) {
                 //公众号支付
-                return wxPayUnifiedOrderResult.getPrepayId();
+                String prepayId = wxPayUnifiedOrderResult.getPrepayId();
+                map.put("prepayId", prepayId);
             }
             //byte[] arr = wxPayApi.createScanPayQrcodeMode2(wxPayUnifiedOrderResult.getCodeURL(),null,null);
         } catch (WxPayException e) {
             logger.error("微信支付失败!订单号:{},原因:{}", wxPayUnifiedOrderRequest.getOutTradeNo(), e.getMessage());
             e.printStackTrace();
+            map.put("status", e.getReturnCode());
+            map.put("message", e.getReturnMsg());
         }
-        return null;
-
+        return map;
     }
 
     /**
-     * 查询
+     * 查询订单支付状态 参数二选一
      * @param transactionId
      * @param outTradeNo
      */
-    public void queryOrder(String transactionId, String outTradeNo){
+    @ResponseBody
+    @RequestMapping(value = "/queryTradeState", method = RequestMethod.POST)
+    public String queryTradeState(@RequestParam(required = false) String transactionId, @RequestParam(required = false) String outTradeNo){
         try {
             WxPayOrderQueryResult wxPayOrderQueryResult =wxPayApi.queryOrder(transactionId, outTradeNo);
-            wxPayOrderQueryResult.getTradeState();
+             return wxPayOrderQueryResult.getTradeState();
         } catch (WxPayException e) {
-            e.printStackTrace();
+            return "ERROR";
         }
     }
 
@@ -231,8 +256,10 @@ public class WxpayController {
      */
     @ResponseBody
     @RequestMapping("/notifyUrl")
-    public synchronized String payNotify(HttpServletRequest request, HttpServletResponse response) {
+    public synchronized void payNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
         ModelMap map = new ModelMap();
+        boolean isPaySuccess = false;
+        String outTradeNo = null;
         String returnResult = null;
         try {
             String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
@@ -245,16 +272,20 @@ public class WxpayController {
                 if ("SUCCESS".equals(result.getResultCode())) {
                     returnResult = setXml("SUCCESS", "OK");
                     WechatOrder wechatOrder = wechatOrderService.getByTransactionId(result.getTransactionId());
+                    WxPayOrderQueryResult OrderQueryResult = null;
+                    if (wechatOrder != null) {
+                        OrderQueryResult = wxPayApi.queryOrder(result.getTransactionId(),null);//二选一填
+                    }
+
+                    ProjectRecode projectRecode = projectRecodeService.findOne(Long.parseLong(result.getOutTradeNo()));
                     //微信在数据库中订单存在且状态已处理
-                    if (wechatOrder != null && wechatOrder.getStatus() == 1) {
+                    if (wechatOrder != null && wechatOrder.getStatus() == 1 && projectRecode != null && projectRecode.getStatus() != 1 && wechatOrder.getTradeState().equals(OrderQueryResult.getTradeState())) {
                         logger.info("系统已对该笔交易进行处理,交易订单号" + wechatOrder.getOutTradeNo() + "微信交易号" + wechatOrder.getTransactionId());
                         returnResult = setXml("SUCCESS", "OK");
                     } else {
                         // 自己处理订单的业务逻辑
 
                         //校验返回的订单金额是否与商户侧的订单金额一致
-                        //TODO 先注释这两句
-                        ProjectRecode projectRecode = projectRecodeService.findOne(Long.parseLong(result.getOutTradeNo()));
                         if (!(projectRecode != null && ((int) (projectRecode.getAmount()*100)) == result.getTotalFee().intValue())) {
                             logger.warn("防止数据泄漏导致出现“假通知”,以免造成资金损失");
                             map.put("warning", "防止数据泄漏导致出现“假通知”,以免造成资金损失");
@@ -274,6 +305,8 @@ public class WxpayController {
                             if ("SUCCESS".equals(wxPayOrderQueryResult.getTradeState())) {
                                 projectRecodePayStatus = 2;
                                 projectRecode.setStatus(projectRecodePayStatus);
+                                isPaySuccess = true;
+                                outTradeNo = result.getOutTradeNo();
                             }
 
                             wechatOrderService.save(WechatOrder.WxPayOrderNotifyResultToConvert(result, (short) 1, wxPayOrderQueryResult));
@@ -281,6 +314,8 @@ public class WxpayController {
                         }
                         //更新订单状态
                         projectRecodeService.update(projectRecode);
+
+
                     }
                     //String totalFee = WxPayBaseResult.feeToYuan(result.getTotalFee());
                 } else {
@@ -297,13 +332,19 @@ public class WxpayController {
             returnResult = setXml("FAIL", "签名失败");
         } finally {
             //TODO map
-            return returnResult;
+            response.getWriter().write(returnResult);
+
+//            if (isPaySuccess) {
+//                String requestUrlMessage = request.getScheme() +"://" + request.getServerName() + ":" + request.getServerPort();
+//                String url = requestUrlMessage + "/project#/donationsOver/" +  outTradeNo;
+//                response.sendRedirect(url);
+//            }
         }
     }
 
     @ResponseBody
     @RequestMapping("/redirectUrl")
-    public String redirectUrl() {
+    public String redirectUrl(HttpServletRequest request) {
     /*由于设置redirect_url后,回跳指定页面的操作可能发生在:1,微信支付中间页调起微信收银台后超过5秒
     2,用户点击“取消支付“或支付完成后点“完成”按钮。因此无法保证页面回跳时,支付流程已结束,
     所以商户设置的redirect_url地址不能自动执行查单操作,应让用户去点击按钮触发查单操作。*/
@@ -329,7 +370,7 @@ public class WxpayController {
 
 
     /**
-     * 获取token  公众号支付模式也不需要  先放着
+     * 获取token  这大概是基础支持token  一日上限2000次  用具体用户授权无关
      * @return
      * @throws Exception
      */
@@ -342,6 +383,14 @@ public class WxpayController {
         return null;
     }
 
+    @ResponseBody
+    @RequestMapping(value = "/userAdvanced", method = RequestMethod.GET)
+    public void userAdvanced(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //配置网页授权url
+        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxPayApi.getConfig().getAppId() + "&redirect_uri=" + URLEncoder.encode("http://lj.ubtob.com/wxpay/getOpenId", "UTF-8") + "&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
+        response.sendRedirect(url);
+    }
+
     /**
      * 获取用户基本信息  静默获取  无需用户同意 只有公众号模式需要
      * https://mp.weixin.qq.com/advanced/advanced?action=table&token=719542712&lang=zh_CN
@@ -350,17 +399,25 @@ public class WxpayController {
      * @return
      */
     @ResponseBody
-    @RequestMapping("/getUserInfo")
-    public String getOpenId(HttpServletRequest request){
+    @RequestMapping(value = "/getOpenId", method = RequestMethod.GET)
+    public void getOpenId(HttpServletRequest request) throws IOException {
         try {
             //TODO 授权方式  是否需要电话号码  名字等信息
             //TODO 获取code
             String code = request.getParameter("code");
+            String state = request.getParameter("state");
+
+            logger.info("公众号获取:authCode=" + code + ",state=" + state);
             //String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
-            return wxPayApi.authcode2Openid(code);
+            String openId = wxPayApi.authcode2Openid(code);
+            User user = SystemSession.getUser();
+            if (user == null) {
+                user = new User();
+            }
+            user.setWxOpenId(openId);
+            SystemSession.setUser(user);
         } catch (WxPayException e) {
             e.printStackTrace();
-            return null;
         }
     }
 
@@ -447,7 +504,7 @@ public class WxpayController {
             wxPayUnifiedOrderRequest.setBody("一元捐-" + projectRecode.getProjectName());
         } else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)) {
             if (StringUtils.isEmpty(wxPayApi.getConfig().getSubAppId())) {
-                wxPayUnifiedOrderRequest.setOpenid(null);//否是 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
+                wxPayUnifiedOrderRequest.setOpenid(null);//TODO  否是 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
             } else {
                 wxPayUnifiedOrderRequest.setSubOpenid(null);//否是 trade_type=JSAPI,此参数必传,用户在子商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
             }
@@ -469,8 +526,12 @@ public class WxpayController {
         //wxPayUnifiedOrderRequest.setFeeType("CNY");//否 符合ISO 4217标准的三位字母代码,默认人民币:CNY
         wxPayUnifiedOrderRequest.setTotalFee((int)(projectRecode.getAmount() * 100));//是 订单总金额,只能为整数
 
-        //wxPayUnifiedOrderRequest.setSpbillCreateIp(IpUtils.getIpFromRequest(request));//是 APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP
-        wxPayUnifiedOrderRequest.setSpbillCreateIp(getIp(request));
+        String spbillCreateIp = IpUtils.getIpFromRequest(request);
+        if ("0:0:0:0:0:0:0:1".equals(spbillCreateIp)) {
+            spbillCreateIp = "127.0.0.1";
+        }
+        wxPayUnifiedOrderRequest.setSpbillCreateIp(spbillCreateIp);//是 APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP
+        //wxPayUnifiedOrderRequest.setSpbillCreateIp(getIp(request));
         //wxPayUnifiedOrderRequest.setSpbillCreateIp("10.10.100.200");
 
         //wxPayUnifiedOrderRequest.setTimeStart(null);//否 订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。
@@ -495,6 +556,12 @@ public class WxpayController {
 
     private ProjectRecode createProjectRecode(String jsonStr) throws Exception {
         ProjectRecode projectRecode= JSONObject.parseObject(jsonStr,ProjectRecode.class);
+
+        User user = SystemSession.getUser();
+        if (user != null) {
+            Long uuid = user.getUserUU();
+            projectRecode.setUuid(uuid);
+        }
         projectRecode.setTime(new Date());
         ProjectRecode newProjectRecode = projectRecodeService.join(projectRecode);
         return newProjectRecode;

+ 25 - 0
donate-service/src/main/java/com/uas/service/donate/model/User.java

@@ -57,6 +57,8 @@ public class User implements Serializable{
     @Column(name = "user_type")
     private String type;
 
+    private String wxOpenId;
+
 
     public String getName() {
         return name;
@@ -121,4 +123,27 @@ public class User implements Serializable{
     public void setType(String type) {
         this.type = type;
     }
+
+    public String getWxOpenId() {
+        return wxOpenId;
+    }
+
+    public void setWxOpenId(String wxOpenId) {
+        this.wxOpenId = wxOpenId;
+    }
+
+    @Override
+    public String toString() {
+        return "User{" +
+                "userUU=" + userUU +
+                ", name='" + name + '\'' +
+                ", pwd='" + pwd + '\'' +
+                ", tel=" + tel +
+                ", identity=" + identity +
+                ", company='" + company + '\'' +
+                ", userIMId=" + userIMId +
+                ", type='" + type + '\'' +
+                ", wxOpenId='" + wxOpenId + '\'' +
+                '}';
+    }
 }

+ 107 - 0
donate-service/src/main/java/com/uas/service/donate/model/WechatUserInfo.java

@@ -0,0 +1,107 @@
+package com.uas.service.donate.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Created by 黄诚天 on 2017-11-25.
+ */
+@Entity
+@Table(name="wechat$userinfo")
+public class WechatUserInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "open_id")
+    private String openId;
+
+    @Column(name = "nick_name")
+    private String nickname;
+
+    @Column(name = "avatar")
+    private String avatar;
+
+    @Column(name = "gender")
+    private String gender;
+
+    @Column(name = "union_id")
+    private String unionid;
+
+    @Column(name = "access_token")
+    private String accessToken;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getGender() {
+        return gender;
+    }
+
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+
+
+    public String getUnionid() {
+        return unionid;
+    }
+
+    public void setUnionid(String unionid) {
+        this.unionid = unionid;
+    }
+
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    @Override
+    public String toString() {
+        return "WechatUserInfo{" +
+                "id=" + id +
+                ", openId='" + openId + '\'' +
+                ", nickname='" + nickname + '\'' +
+                ", avatar='" + avatar + '\'' +
+                ", gender='" + gender + '\'' +
+                ", unionid='" + unionid + '\'' +
+                ", accessToken='" + accessToken + '\'' +
+                '}';
+    }
+}

+ 65 - 0
donate-service/src/main/java/com/uas/service/donate/util/WechatConnector.java

@@ -0,0 +1,65 @@
+package com.uas.service.donate.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.uas.service.donate.model.WechatUserInfo;
+import com.uas.sso.common.util.HttpUtil;
+
+/**
+ * Created by 黄诚天 on 2017-11-25.
+ */
+public class WechatConnector {
+
+    public static String createAuthorizeUrl(String scope, String appid, String redirectUri) {
+
+        StringBuilder urlBuilder = new StringBuilder("https://open.weixin.qq.com/connect/oauth2/authorize?");
+        urlBuilder.append("appid=" + appid);
+        urlBuilder.append("&redirect_uri=" + redirectUri);
+        urlBuilder.append("&response_type=code");
+        urlBuilder.append("&scope=" + scope);
+        urlBuilder.append("&state=123");
+        urlBuilder.append("#wechat_redirect");
+        return urlBuilder.toString();
+    }
+
+    public static JSONObject getAccessToken(String code, String app_id, String app_secret) throws Exception {
+
+        StringBuilder urlBuilder = new StringBuilder("https://api.weixin.qq.com/sns/oauth2/access_token?");
+        urlBuilder.append("appid="+app_id);
+        urlBuilder.append("&secret="+app_secret);
+        urlBuilder.append("&code=" + code);
+        urlBuilder.append("&grant_type=authorization_code");
+        String url = urlBuilder.toString();
+        HttpUtil.ResponseWrap responseWrap = HttpUtil.doGet(url);
+        if (responseWrap.isSuccess()) {
+            return JSONObject.parseObject(responseWrap.getContent());
+        }
+
+        return null;
+
+    }
+    /**
+     *
+     * @author xiaoqiang1006
+     * @date 2016年9月29日 下午2:34:58
+     */
+    public static WechatUserInfo getOauthUser(String code, String app_id, String app_secret) throws Exception {
+
+        JSONObject tokenJson = getAccessToken(code,app_id,app_secret);
+        String accessToken = tokenJson.getString("access_token");
+        String openId = tokenJson.getString("openid");
+        String url = "https://api.weixin.qq.com/sns/userinfo?" + "access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
+        HttpUtil.ResponseWrap responseWrap = HttpUtil.doGet(url);
+        WechatUserInfo user = new WechatUserInfo();
+        if (responseWrap.isSuccess()) {
+            user.setUnionid(tokenJson.getString("unionid"));
+            JSONObject json = JSONObject.parseObject(responseWrap.getContent());
+            user.setAccessToken(accessToken);
+            user.setAvatar(json.getString("headimgurl"));
+            user.setNickname(json.getString("nickname"));
+            user.setOpenId(openId);
+            int sex = json.getIntValue("sex");
+            user.setGender(sex == 1 ? "male" : "female");
+        }
+        return user;
+    }
+}

+ 1 - 0
donate-service/src/main/resources/MP_verify_BMkQAHplMGROBlAn.txt


+ 1 - 0
donate-service/src/main/resources/templates/MP_verify_BMkQAHplMGROBlAn.txt


+ 1 - 0
donate-service/src/main/webapp/WEB-INF/MP_verify_BMkQAHplMGROBlAn.txt


+ 1 - 0
donate-service/src/main/webapp/resources/MP_verify_BMkQAHplMGROBlAn.txt


+ 86 - 57
donate-service/src/main/webapp/resources/js/pay.js

@@ -9,6 +9,7 @@
 
 const userAgent = navigator.userAgent;
 const isMobile = /(iPhone|iPad|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry|Windows Phone)/ig.test(userAgent);
+var orderInterval;
 
 var pay =function (proId, amount, payWay, uuid) {
      var customAmount = $("#custom-amount" + proId).val();
@@ -18,7 +19,12 @@ var pay =function (proId, amount, payWay, uuid) {
         var patt = new RegExp(reg);
         var r = patt.test(customAmount);
         if (r) {
-            amount = customAmount;
+            if (parseFloat(customAmount) < 10000000) {
+                amount = customAmount;
+            } else {
+                alert("您输入的金额过大,请不要超过一千万");
+                return;
+            }
         } else {
             alert('输入金额有误,请正确输入金额且最多保留两位小数!');
             return;
@@ -49,51 +55,18 @@ var wxPay = function (proId, amount, payWay, uuid) {
     //var userAgent = navigator.userAgent;
     if (userAgent.match(/MicroMessenger/i) == 'MicroMessenger') {
         //公众号支付逻辑(微信浏览器)
-        $.ajax({
-            url : "/wxpay/webPay",
-            type : "POST",
-            dataType : "json",
-            async: false,
-            data: {
-                jsonStr : jsonStr
-            },
-            success : function(data) {
-                WeixinJSBridge.invoke('getBrandWCPayRequest', {
-                    "appId" : data.appId, //公众号名称,由商户传入       
-                    "timeStamp" : data.timeStamp, //时间戳,自1970年以来的秒数       
-                    "nonceStr" : data.nonceStr, //随机串       
-                    "package" : data.package,
-                    "signType" : data.signType, //微信签名方式:       
-                    "paySign" : data.paySign
-                    //微信签名   
-                }, function(res) {
-                    if (res.err_msg == "get_brand_wcpay_request:ok") {
-                        alert("支付成功");
-                        // 使用以上方式判断前端返回:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
-                    }
-                    else{
-                        alert("支付失败");
-                        //res.err_msg;  
-                    }
-                });
-
-
-                //这个if判断后面加的  不知道作用
-                if (typeof WeixinJSBridge == "undefined") {
-                    if (document.addEventListener) {
-                        document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
-                    } else if (document.attachEvent) {
-                        document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
-                        document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
-                    }
-                } else {
-                    onBridgeReady();
-                }
-            },
-            error : function() {
-                alert('系统异常,请联系客服!');
-            }
-        });
+        webPay(jsonStr);
+        // $.ajax({
+        //     url : "/wxpay/userAdvanced",
+        //     type : "GET",
+        //     async: false,
+        //     success : function() {
+        //         webPay(jsonStr);
+        //     },
+        //     error : function() {
+        //         alert("请求openid失败");
+        //     }
+        // });
     }else{
         //H5支付逻辑
 
@@ -115,16 +88,17 @@ var wxPay = function (proId, amount, payWay, uuid) {
                 jsonStr : jsonStr
             },
             success : function(res){
-                if (res.error == null) {
-                    if (isMobile) {
-                        var mwebUrl = res;
-                        window.location.href = mwebUrl;
-                    } else {
-                        var qrcodeUrl = res;
-                        window.location.href = qrcodeUrl;
-                    }
+                var resJsonObj=JSON.parse(res);
+                if (resJsonObj.error != null) {
+                    alert(resJsonObj.error);
+                    return;
+                }
+
+                if (isMobile) {
+                    window.location.href = resJsonObj.mwebUrl;
                 } else {
-                    alert(res.error);
+                    document.cookie = 'qrcodeUrl='+encodeURIComponent(resJsonObj.qrcodeUrl);
+                    window.location.href = "http://lj.ubtob.com/project#/donateQrcode/" + resJsonObj.outTradeNo;
                 }
             },
             error : function() {
@@ -164,6 +138,40 @@ var unionPay  = function () {
 
 }
 
+/*公众号支付*/
+var webPay = function (jsonStr) {
+    $.ajax({
+        url : '/wxpay/webPay',
+        type : 'POST',
+        dataType : 'json',
+        async: false,
+        data: {
+            jsonStr : jsonStr
+        },
+        success : function(res) {
+            var resJsonObj=JSON.parse(res);
+            if (resJsonObj.error != null) {
+                alert(resJsonObj.error);
+                return;
+            }
+
+            if (typeof WeixinJSBridge == "undefined") {
+                if (document.addEventListener) {
+                    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
+                } else if (document.attachEvent) {
+                    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
+                    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
+                }
+            } else {
+                onBridgeReady(resJsonObj);
+            }
+        },
+        error : function() {
+            alert('系统异常,请联系客服!');
+        }
+    });
+}
+
 var getJson = function (proId, amount, payWay, uuid) {
     if (typeof uuid == 'undefined') {
         return jsonStr = "{proId:" + proId + "," +
@@ -173,14 +181,35 @@ var getJson = function (proId, amount, payWay, uuid) {
     } else {
         return jsonStr = "{proId:" + proId + "," +
             "amount:" + amount + "," +
-            "way:" + "\"" + payWay + "\"" +
-            ", uuid:" + uuid +
+            "way:" + "\"" + payWay + "\"" + "," +
+            "uuid:" + uuid +
             "}";
     }
 
 
 }
 
+function onBridgeReady(resJsonObj){
+    WeixinJSBridge.invoke('getBrandWCPayRequest', {
+        "appId" : resJsonObj.appId, //公众号名称,由商户传入       
+        "timeStamp" : resJsonObj.timeStamp, //时间戳,自1970年以来的秒数       
+        "nonceStr" : resJsonObj.nonceStr, //随机串       
+        "package" : resJsonObj.package,
+        "signType" : resJsonObj.signType, //微信签名方式:       
+        "paySign" : resJsonObj.paySign
+        //微信签名   
+    }, function(res) {
+        if (res.err_msg == "get_brand_wcpay_request:ok") {
+            alert("支付成功");
+            // 使用以上方式判断前端返回:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
+        }
+        else{
+            alert("支付失败");
+            //res.err_msg;  
+        }
+    });
+}
+
 
 
 

+ 56 - 3
donate-service/src/main/webapp/resources/js/project/app.js

@@ -50,10 +50,10 @@ define([ 'angularAMD', 'ui.router', 'ui-bootstrap', 'ngLocal', 'ngTable', 'commo
             templateUrl : 'static/view/project/donationsOver.html',
             controller : 'donationsOverCtrl'
         }).state("wxPayQrcode", {
-            url : '/donateQrcode',
+            url : '/donateQrcode/:tradeNo',
             title : '微信扫码',
-            templateUrl : 'static/view/project/donateQrcode.html'
-            // controller : 'donationsOverCtrl'
+            templateUrl : 'static/view/project/donateQrcode.html',
+            controller : 'donateQrcodeCtrl'
         });
 	}]);
 
@@ -80,5 +80,58 @@ define([ 'angularAMD', 'ui.router', 'ui-bootstrap', 'ngLocal', 'ngTable', 'commo
         loadData();
     }]);
 
+    app.controller('donateQrcodeCtrl', ['$scope', '$stateParams', '$http', function ($scope, $stateParams, $http) {
+        var tradeNo = $stateParams.tradeNo;
+        var loadData = function () {
+            $scope.qrcodeUrl = decodeURIComponent(getCookie("qrcodeUrl"));
+            $http.get('/projectrecode/detail/' + tradeNo, {
+            }).success(function (data) {
+                $scope.projectRecode = data;
+            }).error(function () {
+                alert("查询支付结果出错");
+            });
+
+        };
+        loadData();
+
+        var orderInterval = self.setInterval(function(){orderStatus(tradeNo)} ,5000);
+
+        /*ajax轮询请求微信订单支付状态,用于跳转回商户页面*/
+        var orderStatus =function (outTradeNo) {
+
+            $.ajax({
+                type : "POST",
+                url : "/wxpay/queryTradeState",
+                dataType : "json",
+                data: {
+                    outTradeNo : outTradeNo
+                },
+                success : function(res){
+                    if ("SUCCESS" == res) {
+                        self.clearInterval(orderInterval);
+                        window.location.href = "http://lj.ubtob.com/project#/donationsOver/" + outTradeNo;
+                    } else if ("ERROR" == res) {
+                        console.log("查询微信订单错误");
+                    }
+                },
+                error : function () {
+                    console.log("查询支付状态请求失败");
+                }
+            });
+        }
+
+
+        function getCookie(key){
+            var arr1 = document.cookie.split('; ');
+            for(var i=0;i<arr1.length;i++){
+                var arr2 = arr1[i].split('=');
+                if(arr2[0] == key){
+                    return decodeURI(arr2[1]);
+                }
+            }
+        }
+
+    }]);
+
 	return app;
 });

+ 3 - 3
donate-service/src/main/webapp/resources/view/project/donateQrcode.html

@@ -136,11 +136,11 @@
 <div class="main">
     <div class="container">
         <div class="section">
-            <p class="project-title">捐款金额<em>1.00</em>元,支持<span>寒门学子 阳光助学</span>公益项目</p>
+            <p class="project-title">捐款金额<em>{{projectRecode.amount}}</em>元,支持<span>{{projectRecode.projectName}}</span>公益项目</p>
             <div class="qrcode">
-                <img src="static/images/instruction.png" alt=""/>
+                <img src="{{qrcodeUrl}}" alt=""/>
             </div>
-            <p class="instruction">收款机构 : <span>中国少年儿童文化艺术基金会</span></p>
+            <p class="instruction">收款机构 : <span>{{projectRecode.orgName}}</span></p>
             <span class="pay">请使用微信扫一扫,使用微信支付完成捐款</span>
         </div>
     </div>