微信-App支付 java服务器端

1.相关变量设置:

微信支付相关配置
应用appid(在开发者中心设置)
wx.appid=wxe754*****b7
商户号(在开发者中心设置)
wx.mchid=1488***152
支付密钥((在开发者中心设置)长度32)
wx.apikey=mCuqsC********susvLa
统一下单接口,这里不需要修改,由系统自动调用
wx.uniurl=https://api.mch.weixin.qq.com/pay/unifiedorder

2.统一下单部分代码:

    /***
     * 微信统一下单
     *
     *@param request
     *@param response
     *@throws IOException
     *@throws JDOMException
     *@date: 2017年9月1日
     *@author: smallz
     *
     */
    @RequestMapping("/prePay")
    public void wxPrePay(String data, HttpServletRequest request,
            HttpServletResponse response) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        StatusData statusObject = null;
        JsonModel jsonModel = new JsonModel();
        jsonModel.setHeaderValue("flag", "0");
        SortedMap<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
        // jsonModel.setHeaderValue("flag", "0");
        if (requestHandle(data, jsonModel) == true) {
            try {
                //支付类型
                Integer payType=Integer.valueOf(jsonModel.getBodyValue("payType"));
                Long memberId=Long.valueOf(jsonModel.getBodyValue("memberId"));
                String orderId="";
                String body="";
                String price="";
                String noncestr=WeChatUtils.CreateNoncestr();
                if(payType.equals(WeChatPayTypeEnum.serviceFee.getStatus())){//服务费
                    //计算服务费规则
                    orderId=jsonModel.getBodyValue("orderId");
                    body=WeChatPayTypeEnum.serviceFee.getName();
                    price=PropertiesUtil.getPropertiesValue("serviceFeeCost");
                }else if(payType.equals(WeChatPayTypeEnum.transaction.getStatus())///交易会员
                        ){
                    orderId=String.valueOf(System.currentTimeMillis());
                    price=PropertiesUtil.getPropertiesValue("trascationFeeCost");
                    body=WeChatPayTypeEnum.transaction.getName();
                }else if(payType.equals(WeChatPayTypeEnum.limitInFee.getStatus())){//准入金
                    orderId=jsonModel.getBodyValue("orderId");
                    body=WeChatPayTypeEnum.limitInFee.getName();
                    price=PropertiesUtil.getPropertiesValue("limitInFeeCost");
                }else if(payType.equals(WeChatPayTypeEnum.orderFee.getStatus())){//订单结算
                    orderId=jsonModel.getBodyValue("orderId");
                    body=/*"2401_"+*/WeChatPayTypeEnum.orderFee.getName();
                    //价格先写死
                    price=PropertiesUtil.getPropertiesValue("limitInFeeCost");
                }
                int price100 = new BigDecimal(price).multiply(
                        new BigDecimal(100)).intValue();
                if (price100 <= 0) {
                    statusObject = AppInteractiveState.MONEY_FMT_ERROR;
                    returnJson(response, statusObject, resultMap);
                    return;
                }
                LogUtils.info(getClass(), "===此次预支付的订单Id==="+orderId);
                LogUtils.info(getClass(), "===此次预支付的订单内容==="+body);
                LogUtils.info(getClass(), "===此次预支付的订单价格==="+price100);
                // 设置回调地址-获取当前的地址拼接回调地址
                String url = request.getRequestURL().toString();
                String domain = url.substring(0, url.length() - 9);
                System.out.println("====微信回调URL:"+domain+"wxNotify.do");
                // 测试、正式环境
                 String notify_url= domain+"wxNotify.do";


                SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
                //封装请求参数
                setSignParameters(request, jsonModel, price100, notify_url,
                        parameters,orderId,body,WeChatUtils.CreateNoncestr(),payType,memberId);
                // 封装请求参数结束
                String requestXML = WeChatUtils.getRequestXml(parameters);
                // 调用统一下单接口
                String result = WeChatUtils.httpsRequest(UNI_URL, "POST", requestXML);
                LogUtils.info(getClass(), "===请求微信统一支付返回结果===:");
                LogUtils.info(getClass(),result);
                //System.out.println("\n" + result);
                try {
                    /**
                     * 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。
                     * 参与签名的字段名为appId
                     * ,partnerId,prepayId,nonceStr,timeStamp,package
                     * 。注意:package的值格式为Sign=WXPay
                     **/
                    Map<String, String> map = XMLUtil.doXMLParse(result);
                    if (map.get("return_code").equals("SUCCESS")) {
                        statusObject = new StatusData(
                                Integer.valueOf(AppInteractiveState.SUCCESS),
                                "请求统一下单成功!");
                    } else {
                        statusObject = new StatusData(
                                Integer.valueOf(AppInteractiveState.ERROR_BUSINESS),
                                "请求统一下单失败!");
                        LogUtils.error(getClass(), "微信统一下单错误,return_msg:"+map.get("return_msg"));
                        returnJson(response, statusObject, resultMap);
                        return;
                    }
                    //System.out.println(map);
                    // parameterMap2 = new TreeMap<Object, Object>();
                    parameterMap2.put("appid", APPID);
                    //parameterMap2.put("attach", "*****");//这里二次签名无需对attach再签名(不然就是支付验证签名失败,本人已经填坑)
                    parameterMap2.put("partnerid", MCH_ID);
                    parameterMap2.put("prepayid", map.get("prepay_id"));
                    parameterMap2.put("package", "Sign=WXPay");//这个key(package),绝对不能改,为了图方便我以为能省去parameterMap2.put("packageValue", "Sign=WXPay");这一句代码,结果填了一坑,导致签名失败。
                    parameterMap2.put("noncestr", WeChatUtils.CreateNoncestr());
                    // 本来生成的时间戳是13位,但是ios必须是10位,所以截取了一下
                    parameterMap2.put(
                            "timestamp",
                            Long.parseLong(String
                                    .valueOf(System.currentTimeMillis())
                                    .toString().substring(0, 10)));
                    //这里是二次签名
                    String sign2 = WeChatUtils.createSign("UTF-8",parameterMap2);
                    parameterMap2.put("tradeNo", orderId);
                    //避免安卓package关键字字段
                    parameterMap2.put("packageValue", "Sign=WXPay");
                    parameterMap2.put("sign", sign2);
                    System.out.println("二次签名参数:———————"+parameterMap2);
                } catch (JDOMException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //将统一下单的map返回给客户端
        returnJson(response, statusObject, parameterMap2);

    }

    //生成签名
    private void setSignParameters(HttpServletRequest request,
            JsonModel jsonModel, int price100, String notify_url,
            SortedMap<Object, Object> parameters,String orderId,String body,String dateStr,Integer payType,Long memberId) {
        parameters.put("appid", APPID);
        parameters.put("attach", payType+"|"+memberId+"|"+orderId);
        parameters.put("mch_id", MCH_ID);
        parameters.put("nonce_str",dateStr);
        parameters.put("body", body);
        parameters.put("out_trade_no",orderId); // 订单id
        parameters.put("fee_type", "CNY");
        parameters.put("total_fee", String.valueOf(price100));
        //本机测试Ip
        //parameters.put("spbill_create_ip", "220.202.152.37");
        parameters.put("spbill_create_ip", getIpAddr(request));
        parameters.put("notify_url", notify_url);
        parameters.put("trade_type", "APP");
        // 设置签名
        String sign = WeChatUtils.createSign("UTF-8", parameters);
        parameters.put("sign", sign);
    }

    /***
     * 微信异步回调方法
     *
     *@param request
     *@param response
     *@throws IOException
     *@throws JDOMException
     *@date: 2017年9月1日
     *@author: smallz
     *
     */
    @SuppressWarnings("unchecked")
    @RequestMapping("/wxNotify")
    public void wxNotify(HttpServletRequest request,
            HttpServletResponse response/*,String data*//*调试用*/) throws IOException, JDOMException {
        try {
        // 读取参数
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(
                inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();



        // 解析xml成map
        Map<String, String> m = new HashMap<String, String>();
        m = XMLUtil.doXMLParse(sb.toString());
        System.out.println("微信服务器返回的xml:"+sb.toString());
        //m = XMLUtil.doXMLParse(data);
        for (Object keyValue : m.keySet()) {
            System.out.println(keyValue + "=" + m.get(keyValue));
        }
        // 过滤空 设置 TreeMap
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        Iterator it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = m.get(parameter);

            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        // 判断签名是否正确
        String resXml = "";
        if (WeChatUtils.isTenpaySign("UTF-8", packageParams)) {
            LogUtils.info(this.getClass(), "签名校验成功,信息合法,未被篡改过");
            if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                String mch_id = (String) packageParams.get("mch_id"); // 商户号
                String openid = (String) packageParams.get("openid"); // 用户标识
                String out_trade_no = (String) packageParams
                        .get("out_trade_no"); // 商户订单号
                String total_fee = (String) packageParams.get("total_fee");
                String transaction_id = (String) packageParams
                        .get("transaction_id"); // 微信支付订单号
                WxPayResult trade = null;
                //比对app端的数据(金额、商户号...)
                if (!MCH_ID.equals(mch_id)
                        || trade == null
                        || new BigDecimal(total_fee).compareTo(new BigDecimal(
                                trade.getTotal_fee()).multiply(new BigDecimal(
                                100))) != 0) {
                    LogUtils.error(this.getClass(), "支付失败,错误信息:"
                            + packageParams.get("err_code"));
                    resXml = "<xml>"
                            + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[通知支付失败]]></return_msg>"
                            + "</xml> ";
                } 
            } else {
                System.out.println("支付成功");
                LogUtils.info(getClass(), "支付成功");
                resXml = "<xml>"
                        + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>"
                        + "</xml> ";
            }
            // 保存微信支付信息
            try {
                wxPayResultService.savePayResult(packageParams);
            } catch (Exception e) {
                // TODO: handle exception
            }
            // ------------------------------
            // 处理业务完毕
            // ------------------------------
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        }else {
            resXml = "<xml>"
                    + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[通知签名验证失败]]></return_msg>"
                    + "</xml> ";
            LogUtils.error(this.getClass(), "通知签名验证失败");
        }

    } catch (Exception e) {
        e.printStackTrace();
        LogUtils.error(getClass(), "异步交互异常:"+e.getMessage());
    }
    }   

如有不妥之处 请指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值