微信支付java 服务端实现

项目里要使用到微信收款和付款.

微信收款分二部分,一部分向微信发起支付申请获取支付参数让用户触发支付申请,另部分是获取用户支付成功后的结果做业务处理,第一部分是主动的,第二部分是微信调我们的接口的,第一部分的核心代码为:

  String path = request.getContextPath();
        String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
        log.info("basePath=" + basePath);


        /** 总金额(分为单位) */
        int total = (int) (totalPrice * 100);


        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        /** 公众号APPID */
        parameters.put("appid", APPID);
        /** 商户号 */
        parameters.put("mch_id", MCH_ID);
        /** 随机字符串 */
        parameters.put("nonce_str", WXUtil.getNonceStr());
        /** 商品名称 */
        parameters.put("body", commodityName);


        /** 当前时间 yyyyMMddHHmmss */
        String currTime = TenpayUtil.getCurrTime();
        /** 8位日期 */
        String strTime = currTime.substring(8, currTime.length());
        /** 四位随机数 */
        String strRandom = TenpayUtil.buildRandom(4) + "";
        /** 订单号 */
        parameters.put("out_trade_no", strTime + strRandom);
        
        /** 订单金额以分为单位,只能为整数 */
        parameters.put("total_fee", total);
        /** 客户端本地ip */
        parameters.put("spbill_create_ip", request.getRemoteAddr());
        /** 支付回调地址 */
        parameters.put("notify_url", basePath + NOTIFY_URL);
        /** 支付方式为JSAPI支付 */
        parameters.put("trade_type", "JSAPI");
        /** 用户微信的openid,当trade_type为JSAPI的时候,该属性字段必须设置 */
        parameters.put("openid", openId);
        
        /** MD5进行签名,必须为UTF-8编码,注意上面几个参数名称的大小写 */
        String sign = createSign("UTF-8", parameters);
        parameters.put("sign", sign);
        
        /** 生成xml结构的数据,用于统一下单接口的请求 */
        String requestXML = getRequestXml(parameters);
        log.info("requestXML:" + requestXML);
        /** 开始请求统一下单接口,获取预支付prepay_id */
        HttpClient client = new HttpClient();
        PostMethod myPost = new PostMethod(UNI_URL);
        client.getParams().setSoTimeout(300 * 1000);
        String result = null;
        try {
            myPost.setRequestEntity(new StringRequestEntity(requestXML, "text/xml", "utf-8"));
            int statusCode = client.executeMethod(myPost);
            if (statusCode == HttpStatus.SC_OK) {
                BufferedInputStream bis = new BufferedInputStream(myPost.getResponseBodyAsStream());
                byte[] bytes = new byte[1024];
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                int count = 0;
                while ((count = bis.read(bytes)) != -1) {
                    bos.write(bytes, 0, count);
                }
                byte[] strByte = bos.toByteArray();
                result = new String(strByte, 0, strByte.length, "utf-8");
                bos.close();
                bis.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        /** 需要释放掉、关闭连接 */
        myPost.releaseConnection();
        client.getHttpConnectionManager().closeIdleConnections(0);


        log.info("请求统一支付接口的返回结果:");
        log.info(result);
        try {
            /** 解析微信返回的信息,以Map形式存储便于取值 */
            Map<String, String> map = XMLUtil.doXMLParse(result);
            
            SortedMap<Object, Object> params = new TreeMap<Object, Object>();
            params.put("appId", APPID);
            params.put("timeStamp", "\"" + new Date().getTime() + "\"");
            params.put("nonceStr", WXUtil.getNonceStr());
            /** 
             * 获取预支付单号prepay_id后,需要将它参与签名。
             * 微信支付最新接口中,要求package的值的固定格式为prepay_id=... 
             */
            params.put("package", "prepay_id=" + map.get("prepay_id"));


            /** 微信支付新版本签名算法使用MD5,不是SHA1 */
            params.put("signType", "MD5");
            /**
             * 获取预支付prepay_id之后,需要再次进行签名,参与签名的参数有:appId、timeStamp、nonceStr、package、signType.
             * 主意上面参数名称的大小写.
             * 该签名用于前端js中WeixinJSBridge.invoke中的paySign的参数值
             */
            String paySign = createSign("UTF-8", params);
            params.put("paySign", paySign);
            
            /** 预支付单号,前端ajax回调获取。由于js中package为关键字,所以,这里使用packageValue作为key。 */
            params.put("packageValue", "prepay_id=" + map.get("prepay_id"));
            
            /** 付款成功后,微信会同步请求我们自定义的成功通知页面,通知用户支付成功 */
//            params.put("sendUrl", basePath + "pay/paysuccess?totalPrice=" + totalPrice);
            params.put("sendUrl",  "https://frontend2.csq.im/caishenquan/weigu/"+gohref+".html?success=1&"+param);
            /** 获取用户的微信客户端版本号,用于前端支付之前进行版本判断,微信版本低于5.0无法使用微信支付 */
            String userAgent = request.getHeader("user-agent");
            char agent = userAgent.charAt(userAgent.indexOf("MicroMessenger") + 15);
            params.put("agent", new String(new char[] { agent }));


            String json = JSONArray.fromObject(params).toString();
            return json;


        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";



-------------------------------------------------此为分界线----------------------------------------------------

第二部分的核心代码为:

 log.info("微信支付成功调用回调URL");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        log.info("~~~~~~~~~~~~~~~~付款成功~~~~~~~~~");
        outSteam.close();
        inStream.close();


        /** 支付成功后,微信回调返回的信息 */
        String result = new String(outSteam.toByteArray(), "utf-8");
        log.info("微信返回的订单支付信息:" + result);
        Map<Object, Object> map = XMLUtil.doXMLParse(result);

        // 用于验签
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        for (Object keyValue : map.keySet()) {
            /** 输出返回的订单支付信息 */
            log.info(keyValue + "=" + map.get(keyValue));
            if (!"sign".equals(keyValue)) {
                parameters.put(keyValue, map.get(keyValue));
            }
        }
        if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
            // 先进行校验,是否是微信服务器返回的信息
            String checkSign = createSign("UTF-8", parameters);
            log.info("对服务器返回的结果进行签名:" + checkSign);
            log.info("服务器返回的结果签名:" + map.get("sign"));
            if (checkSign.equals(map.get("sign"))) {// 如果签名和服务器返回的签名一致,说明数据没有被篡改过
                log.info("签名校验成功,信息合法,未被篡改过");
                
                /** 告诉微信服务器,我收到信息了,不要再调用回调方法了 */
                /**如果不返回SUCCESS的信息给微信服务器,则微信服务器会在一定时间内,多次调用该回调方法,如果最终还未收到回馈,微信默认该订单支付失败*/
                /** 微信默认会调用8次该回调地址 */
                response.getWriter().write(setXML("SUCCESS", ""));
                log.info("-------------" + setXML("SUCCESS", ""));
                //业务处理
                //log.info("我去掉了发送SUCCESS给微信服务器");
                
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值