微信扫码支付---模式二(Native)

来源:互联网 发布:手机淘宝店标怎么设置 编辑:程序博客网 时间:2024/06/04 23:20
/**
 * 微信支付的类
 * @author zp
 */
public class Zhifu {
    public static String weixin_pay() throws Exception {
        
        //账号信息
        //公众账号ID
        String appid = "xxxxxxxxxxxxxxxx";
        //商业号
        String mch_id = "xxxxxxxxxxx";
        //key
        String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        
        //生成随机字符串
        String currTime = PayCommonUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayCommonUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;
        
        //商品的总价格,必须以分为单位
        String order_price = "1";
        String body = "**商城-充值";
        //商户订单号,每次不能够重复
        String out_trade_no = "11345";
        //终端ip
        String spbill_create_ip = PayCommonUtil.localIp();
        //微信的回调地址
        String notify_url = "****************";
        //交易类型
        String trade_type = "NATIVE";
        
        //将相应的信息放到map中去
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("total_fee", order_price);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        //生成签名
        String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);
        packageParams.put("sign", sign);
        
        //将请求参数转换为xml格式的string
        String requestXML = PayCommonUtil.getRequestXml(packageParams);
 
        //调微信的接口
        String resXml = HttpUtil.postData("https://api.mch.weixin.qq.com/pay/unifiedorder", requestXML);

        //解析xml
        Map map = XMLUtil.doXMLParse(resXml);
        
        //获取微信返回的二维码信息,并且返回
        String urlCode = (String) map.get("code_url");
        return urlCode;
}
    
    
        /**
         * 特殊字符处理
         */
        public static String UrlEncode(String src)  throws Exception {
            return URLEncoder.encode(src, "UTF-8").replace("+", "%20");
        }
        
      /**
       * 微信扫码支付成功之后,回调
       * @throws Exception
       */
      public static void weixin_notify() throws Exception{  
          
            //读取参数  
            InputStream inputStream ;  
            StringBuffer sb = new StringBuffer();  
            //inputStream = request.getInputStream();
            
            URL localURL = new URL("http://www.gpmart.cn/");
            URLConnection connection = localURL.openConnection();
            HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
            //httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            
            inputStream = httpURLConnection.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());  
              
            //过滤空 设置 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 key = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"; // key  
      
            System.out.println(packageParams);
            //判断签名是否正确  
            if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {  
                //------------------------------  
                //处理业务开始  
                //------------------------------  
                String resXml = "";  
                if("SUCCESS".equals((String)packageParams.get("result_code"))){  
                    // 这里是支付成功  
                    //////////执行自己的业务逻辑////////////////  
                    String mch_id = (String)packageParams.get("mch_id");  
                    String openid = (String)packageParams.get("openid");  
                    String is_subscribe = (String)packageParams.get("is_subscribe");  
                    String out_trade_no = (String)packageParams.get("out_trade_no");  
                    String total_fee = (String)packageParams.get("total_fee");  
                      
                    System.out.println("mch_id:"+mch_id);  
                    System.out.println("openid:"+openid);  
                    System.out.println("is_subscribe:"+is_subscribe);  
                    System.out.println("out_trade_no:"+out_trade_no);  
                    System.out.println("total_fee:"+total_fee);  
                      
                    //////////执行自己的业务逻辑////////////////  
                      
                    System.out.println("支付成功");  
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.  
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
                      
                } else {  
                    System.out.println("支付失败,错误信息:" + packageParams.get("err_code"));  
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
                }  
                //------------------------------  
                //处理业务完毕  
                //------------------------------  
                BufferedOutputStream out = new BufferedOutputStream(  
                        httpURLConnection.getOutputStream());  
                out.write(resXml.getBytes());  
                out.flush();  
                out.close();  
            } else{  
                System.out.println("通知签名验证失败");  
            }  
              
        }

}


public class XMLUtil {
    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     */
    public static Map doXMLParse(String strxml) throws Exception {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if(null == strxml || "".equals(strxml)) {
            return null;
        }
        
        Map m = new HashMap();
        
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = XMLUtil.getChildrenText(children);
            }
            
            m.put(k, v);
        }
        
        //关闭流
        in.close();
        
        return m;
    }
    
    /**
     * 获取子结点的xml
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if(!children.isEmpty()) {
            Iterator it = children.iterator();
            while(it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if(!list.isEmpty()) {
                    sb.append(XMLUtil.getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        
        return sb.toString();
    }
    
}

public class PayCommonUtil {
    
    /**
     * @author zp
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     * @return boolean
     */
    public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        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=" + API_KEY);
        
        //算出摘要
        String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();
        return tenpaySign.equals(mysign);
    }

    /**
     * @author zp
     * @Description:sign签名
     * @param characterEncoding 编码格式
     * @param parameters 请求参数
     */
    public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        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 (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    /**
     * @author zp
     * @Description:将请求参数转换为xml格式的string
     * @throws Exception
     */
    public static String getRequestXml(SortedMap<Object, Object> parameters) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.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 ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
            } else {
                sb.append("<" + k + ">" + v + "</" + k + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
        //return new String(sb.toString().getBytes(), "ISO8859-1");
    }

    /**
     * @author zp
     * 取出一个指定长度大小的随机正整数.
     * @param length int 设定所取出随机数的长度。length小于11
     * @return int 返回生成的随机数。
     */
    public static int buildRandom(int length) {
        int num = 1;
        double random = Math.random();
        if (random < 0.1) {
            random = random + 0.1;
        }
        for (int i = 0; i < length; i++) {
            num = num * 10;
        }
        return (int) ((random * num));
    }

    /**
     * @author zp
     * 获取当前时间 yyyyMMddHHmmss
     * @return String
     */
    public static String getCurrTime() {
        Date now = new Date();
        SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String s = outFormat.format(now);
        return s;
    }
    
    /**
     *  获取本机Ip
     *  通过 获取系统所有的networkInterface网络接口 然后遍历 每个网络下的InterfaceAddress组。
     *  获得符合 <code>InetAddress instanceof Inet4Address</code> 条件的一个IpV4地址
     */
    @SuppressWarnings("rawtypes")
    public static String localIp(){
        String ip = null;
        Enumeration allNetInterfaces;
        try {
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();            
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                List<InterfaceAddress> InterfaceAddress = netInterface.getInterfaceAddresses();
                for (InterfaceAddress add : InterfaceAddress) {
                    InetAddress Ip = add.getAddress();
                    if (Ip != null && Ip instanceof Inet4Address) {
                        ip = Ip.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return ip;
    }
}

public class MD5Util {

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

}

public class HttpUtil {

    private final static int CONNECT_TIMEOUT = 5000;//毫秒
    private final static String DEFAULT_ENCODING = "UTF-8";
    
    public static String postData(String urlStr, String data){
        return postData(urlStr, data, null);
    }
    
    public static String postData(String urlStr, String data, String contentType){
        BufferedReader reader = null;
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            if(contentType != null)
                conn.setRequestProperty("content-type", contentType);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
            if(data == null)
                data = "";
            writer.write(data);
            writer.flush();
            writer.close();  

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }
        return null;
    }
}

public class JavaQRCode {
      /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param imgPath 图片路径
     */
    public void encoderQRCode(String content, String imgPath) {  
        this.encoderQRCode(content, imgPath, "png", 7);  
    }  
       
    /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param output 输出流
     */
    public void encoderQRCode(String content, OutputStream output) {  
        this.encoderQRCode(content, output, "png", 7);  
    }  
       
    /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     */
    public void encoderQRCode(String content, String imgPath, String imgType) {  
        this.encoderQRCode(content, imgPath, imgType, 7);  
    }  
       
    /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param output 输出流
     * @param imgType 图片类型
     */
    public void encoderQRCode(String content, OutputStream output, String imgType) {  
        this.encoderQRCode(content, output, imgType, 7);  
    }  
   
    /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     * @param size 二维码尺寸
     */
    public void encoderQRCode(String content, String imgPath, String imgType, int size) {  
        try {  
            BufferedImage bufImg = this.qRCodeCommon(content, imgType, size);  
               
            File imgFile = new File(imgPath);  
            // 生成二维码QRCode图片  
            ImageIO.write(bufImg, imgType, imgFile);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
   
    /**
     * 生成二维码(QRCode)图片
     * @param content 存储内容
     * @param output 输出流
     * @param imgType 图片类型
     * @param size 二维码尺寸
     */
    public void encoderQRCode(String content, OutputStream output, String imgType, int size) {  
        try {  
            BufferedImage bufImg = this.qRCodeCommon(content, imgType, size);  
            // 生成二维码QRCode图片  
            ImageIO.write(bufImg, imgType, output);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
       
    /**
     * 生成二维码(QRCode)图片的公共方法
     * @param content 存储内容
     * @param imgType 图片类型
     * @param size 二维码尺寸
     * @return
     */
    private BufferedImage qRCodeCommon(String content, String imgType, int size) {  
        BufferedImage bufImg = null;  
        try {  
            Qrcode qrcodeHandler = new Qrcode();  
            // 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小  
            qrcodeHandler.setQrcodeErrorCorrect('M');  
            qrcodeHandler.setQrcodeEncodeMode('B');  
            // 设置设置二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大  
            qrcodeHandler.setQrcodeVersion(size);  
            // 获得内容的字节数组,设置编码格式  
            byte[] contentBytes = content.getBytes("utf-8");  
            // 图片尺寸  
            int imgSize = 67 + 12 * (size - 1);  
            bufImg = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);  
            Graphics2D gs = bufImg.createGraphics();  
            // 设置背景颜色  
            gs.setBackground(Color.WHITE);  
            gs.clearRect(0, 0, imgSize, imgSize);  
   
            // 设定图像颜色> BLACK  
            gs.setColor(Color.BLACK);  
            // 设置偏移量,不设置可能导致解析出错  
            int pixoff = 2;  
            // 输出内容> 二维码  
            if (contentBytes.length > 0 && contentBytes.length < 800) {  
                boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);  
                for (int i = 0; i < codeOut.length; i++) {  
                    for (int j = 0; j < codeOut.length; j++) {  
                        if (codeOut[j][i]) {  
                            gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);  
                        }  
                    }  
                }  
            } else {  
                throw new Exception("QRCode content bytes length = " + contentBytes.length + " not in [0, 800].");  
            }  
            gs.dispose();  
            bufImg.flush();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return bufImg;  
    }  
       
    /**
     * 解析二维码(QRCode)
     * @param imgPath 图片路径
     * @return
     */
    public String decoderQRCode(String imgPath) {  
        // QRCode 二维码图片的文件  
        File imageFile = new File(imgPath);  
        BufferedImage bufImg = null;  
        String content = null;  
        try {  
            bufImg = ImageIO.read(imageFile);  
            QRCodeDecoder decoder = new QRCodeDecoder();  
            content = new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "utf-8");   
        } catch (IOException e) {  
            System.out.println("Error: " + e.getMessage());  
            e.printStackTrace();  
        } catch (DecodingFailedException dfe) {  
            System.out.println("Error: " + dfe.getMessage());  
            dfe.printStackTrace();  
        }  
        return content;  
    }  
       
    /**
     * 解析二维码(QRCode)
     * @param input 输入流
     * @return
     */
    public String decoderQRCode(InputStream input) {  
        BufferedImage bufImg = null;  
        String content = null;  
        try {  
            bufImg = ImageIO.read(input);  
            QRCodeDecoder decoder = new QRCodeDecoder();  
            content = new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "utf-8");   
        } catch (IOException e) {  
            System.out.println("Error: " + e.getMessage());  
            e.printStackTrace();  
        } catch (DecodingFailedException dfe) {  
            System.out.println("Error: " + dfe.getMessage());  
            dfe.printStackTrace();  
        }  
        return content;  
    }  
   
}

public class TwoDimensionCodeImage implements QRCodeImage  {
     BufferedImage bufImg;  
      
        public TwoDimensionCodeImage(BufferedImage bufImg) {  
            this.bufImg = bufImg;  
        }  
           
        @Override
        public int getHeight() {  
            return bufImg.getHeight();  
        }  
       
        @Override
        public int getPixel(int x, int y) {  
            return bufImg.getRGB(x, y);  
        }  
       
        @Override
        public int getWidth() {  
            return bufImg.getWidth();  
        }  
}

/**
 * @author zp
 * 用单元测试的方法测试生成二维码,并进行回调
 */
public class TestWeixin {
    
    @Test
    public void shengchengerweima() throws Exception{
        
        //调微信的接口生成二维码的内容
        String weixin_pay = Zhifu.weixin_pay();
        
        //调用方法生成二维码图片
        //设置生成二维码存储的路径
        String imgPath = "D:/Michael_QRCode.png";  
        String encoderContent=weixin_pay;  
        JavaQRCode handler = new JavaQRCode();  
        handler.encoderQRCode(encoderContent, imgPath, "png");
        
        /*  try {  
              OutputStream output = new FileOutputStream(imgPath);  
              handler.encoderQRCode(content, output);  
          } catch (Exception e) {  
              e.printStackTrace();  
          }*/  
            
            System.out.println("二维码生成成功!!!!!!");  
        }
    
    /**
     * 支付成功后,进行回调
     */
    @Test
    public void testhuidiao(){
        
        try {
            Zhifu.weixin_notify();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        
        
    }




1 0
原创粉丝点击