java 调用微信JsApi支付

1、首先查看微信支付官方文档了解支付流程

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3

2、编写统一下单接口

public class WxPayUtil  {
   public static final String PAY_URL="https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * 统一下单
     * @param body
     * @param out_trade_no
     * @param total_fee
     * @param IP
     * @param notify_url
     * @param openid
     * @return
     * @throws IOException
     */
    public static Map<String,Object> unifiedOrder(String body,String out_trade_no,Double third_fee,String openid,HttpServletRequest request)throws IOException {
        //设置访问路径
        HttpPost httppost = new HttpPost(PAY_URL);
        String IP = getIpAddr(request),prePath = SystemPath.getRequestProjectUrl(request);
        String nonce_str = getNonceStr().toUpperCase();//随机
        String notify_url = String.format(WeixinUtil.NOTIFY_URL, prePath);
        Long total_fee = Double.valueOf(DoubleUtil.mul(third_fee, 100)+"").longValue();
        //组装请求参数,按照ASCII排序
        String sign = "appid=" + WeixinUtil.APPID +
                        "&body=" + body +
                        "&mch_id=" + WeixinUtil.MCH_ID +
                        "&nonce_str=" + nonce_str +
                        "&notify_url="  +notify_url+
                        "&openid=" + openid +
                        "&out_trade_no=" + out_trade_no +
                        "&spbill_create_ip=" + IP +
                        "&total_fee=" + total_fee.toString() +
                        "&trade_type=" + WeixinUtil.TRADE_TYPE_JS + 
                        "&key=" + WeixinUtil.KEY;//这个字段是用于之后MD5加密的,字段要按照ascii码顺序排序
        sign = MD5Util.MD5Encode(sign.toString(), "UTF-8").toUpperCase();

        //组装包含openid用于请求统一下单返回结果的XML
        StringBuilder sb = new StringBuilder("");
        sb.append("<xml>");
        setXmlKV(sb,"appid",WeixinUtil.APPID);
        setXmlKV(sb,"body",body);
        setXmlKV(sb,"mch_id",WeixinUtil.MCH_ID);
        setXmlKV(sb,"nonce_str",nonce_str);
        setXmlKV(sb,"notify_url",notify_url);
        setXmlKV(sb,"openid",openid);
        setXmlKV(sb,"out_trade_no",out_trade_no);
        setXmlKV(sb,"spbill_create_ip",IP);
        setXmlKV(sb,"total_fee",total_fee.toString());
        setXmlKV(sb,"trade_type",WeixinUtil.TRADE_TYPE_JS);
        setXmlKV(sb,"sign",sign);
        sb.append("</xml>");
        System.out.println("统一下单请求:" + sb);

        StringEntity reqEntity = new StringEntity(new String (sb.toString().getBytes("UTF-8"),"ISO8859-1"));//这个处理是为了防止传中文的时候出现签名错误
        httppost.setEntity(reqEntity);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = httpclient.execute(httppost);
        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
        System.out.println("统一下单返回xml:" + strResult);

        return WxPayUtil.getPayMap(strResult);
    }
    /**
     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map(调用微信支付)
     * @param prePayInfoXml
     * @return
     */
    public static Map<String,Object> getPayMap(String prePayInfoXml){
        Map<String,Object> map = new HashMap<String,Object>();

        String prepay_id = getXmlPara(prePayInfoXml,"prepay_id");//统一下单返回xml中prepay_id
        String timeStamp = String.valueOf((System.currentTimeMillis()/1000));//1970年到现在的秒数
        String nonceStr = getNonceStr().toUpperCase();//随机数据字符串
        String packageStr = "prepay_id=" + prepay_id;
        String signType = WeixinUtil.SIGN_TYPE;
        String paySign =
                "appId=" + WeixinUtil.APPID +
                "&nonceStr=" + nonceStr +
                "&package=prepay_id=" + prepay_id +
                "&signType=" + signType +
                "&timeStamp=" + timeStamp +
                "&key="+ WeixinUtil.KEY;//注意这里的参数要根据ASCII码 排序
        paySign =  MD5Util.MD5Encode(paySign, "UTF-8").toLowerCase();//将数据MD5加密

        map.put("appId",WeixinUtil.APPID);
        map.put("timeStamp",timeStamp);
        map.put("nonceStr",nonceStr);
        map.put("packageStr",packageStr);
        map.put("signType",signType);
        map.put("paySign",paySign);
        map.put("prepay_id",prepay_id);
        return map;
    }
    /**
     * 获取32位随机字符串
     * @return
     */
    public static String getNonceStr(){
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        Random rd = new Random();
        for(int i = 0 ; i < 32 ; i ++ ){
            sb.append(str.charAt(rd.nextInt(str.length())));
        }
        return sb.toString();
    }
    /**
     * 插入XML标签
     * @param sb
     * @param Key
     * @param value
     * @return
     */
    public static StringBuilder setXmlKV(StringBuilder sb,String Key,String value){
        sb.append("<");
        sb.append(Key);
        sb.append(">");

        sb.append(value);

        sb.append("</");
        sb.append(Key);
        sb.append(">");

        return sb;
    }

    /**
     * 解析XML 获得名称为para的参数值
     * @param xml
     * @param para
     * @return
     */
    public static String getXmlPara(String xml,String para){
        int start = xml.indexOf("<"+para+">");
        int end = xml.indexOf("</"+para+">");

        if(start < 0 && end < 0){
            return null;
        }
        return xml.substring(start + ("<"+para+">").length(),end).replace("<![CDATA[","").replace("]]>","");
    }

    /**
     * 获取ip地址
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {  
        InetAddress addr = null;  
        try {  
            addr = InetAddress.getLocalHost();  
        } catch (UnknownHostException e) {  
           System.out.println("ip地址2:"+request.getRemoteAddr());
            return request.getRemoteAddr();  
        }  
        byte[] ipAddr = addr.getAddress();  
        String ipAddrStr = "";  
        for (int i = 0; i < ipAddr.length; i++) {  
            if (i > 0) {  
                ipAddrStr += ".";  
            }  
            ipAddrStr += ipAddr[i] & 0xFF;  
        }  
        System.out.println("ip地址:"+ipAddrStr);
        return ipAddrStr;  
    }
    /** 
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 
     * @return boolean 
     */  
    public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams) {  
        StringBuffer sb = new StringBuffer();  
        Set es = packageParams.entrySet();  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            String v = (String)entry.getValue();  
            if(!"sign".equals(k) && null != v && !"".equals(v)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  

        sb.append("key=" + WeixinUtil.KEY);  

        //算出摘要  
        String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();  
        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();  

//        System.out.println(tenpaySign + "    " + mysign);  
        return tenpaySign.equals(mysign);  
    } 

}

3、微信支付回调接口

  /**
     * 微信异步通知---js
     */
   @Transactional
    @RequestMapping(value="/wxJSNotify.do",  produces = "text/html;charset=UTF-8",method={RequestMethod.POST})
    public String wxJSNotify(HttpServletRequest request,HttpServletResponse response) throws Exception{
       System.out.println("===============wxJSNotify================");
       logger.warn("===============wxJSNotify================");
       //读取参数  
       InputStream inputStream = request.getInputStream();  
       StringBuffer sb = new StringBuffer();  
       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());  
       /*for(Object keyValue : m.keySet()){
          System.out.println(keyValue+"="+m.get(keyValue));
       }*/
       //过滤空 设置 TreeMap  
       SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();        
       Iterator<String> it = m.keySet().iterator();  
       while (it.hasNext()) {  
          String parameter = it.next();  
          String parameterValue = m.get(parameter);  
          
          String v = "";  
          if(null != parameterValue) {  
             v = parameterValue.trim();  
          }  
          packageParams.put(parameter, v);  
       }
       System.out.println("===============微信js回调回来的参数================"+JSONObject.fromObject(packageParams).toString());
       logger.warn("===============微信js回调回来的参数================"+JSONObject.fromObject(packageParams).toString());
       //判断签名是否正确  
       if(WxPayUtil.isTenpaySign("UTF-8", packageParams)) {
          String out_trade_no = (String)packageParams.get("out_trade_no"); //商户订单号
          //String attach = (String)packageParams.get("attach"); //附加参数
          String trade_status = (String)packageParams.get("result_code");
          System.out.println("========微信js中trade_status========"+trade_status);
          logger.warn("========微信js中trade_status========"+trade_status);
          if("SUCCESS".equals(trade_status)){ 
             // 这里是支付成功  
             //执行自己的业务逻辑  
             String mch_id = (String)packageParams.get("mch_id"); //商户号 
//                 String openid = (String)packageParams.get("openid");  //用户标识
             String total_fee = (String)packageParams.get("total_fee");  
             String transaction_id = (String)packageParams.get("transaction_id"); //微信支付订单号
             
             if(!WeixinUtil.MCH_ID.equals(mch_id)){
                System.out.println("微信js中支付失败,错误信息:" + "参数错误");  
                logger.warn("微信js中支付失败,错误信息:" + "参数错误");
                return "FAIL"; 
             }else{
                System.out.println("微信js支付成功");  
                logger.warn("微信js支付成功");
                return successOrder(out_trade_no);
             }
             
          }else {  
             System.out.println("微信js支付失败");  
             logger.warn("微信js支付失败");
             return failOrder(out_trade_no);
          }  
          
          
       } else{  
          System.out.println("微信js中通知签名验证失败");  
          logger.warn("微信js中通知签名验证失败");
       }   
       
       return "FAIL";
    }

 

注意:微信支付回调接口需要返回"<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[参数错误]]></return_msg>" + "</xml> ";或"<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";这种格式,不然会一直触发回调接口

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值