zoukankan      html  css  js  c++  java
  • 微信公众号支付,为什么你找了那么多关于微信支付博客案例依然跑不通......两步带你完成支付,看完还做不出来你找我

    看完还做不出来你找我

    看文档是件烦人的事,你现在做支付,我就假设你肯定已经尝试过了微信公众号的基本接口,例如:获取token,获取用户信息,......那你就会明白,公众号的文档是需要逐字的去看,一扫而过,只会让你坠入深坑

    很多博客甚至视频,讲解支付的时候,都是一律跟着文档走,和看文档的区别不大,我个人犯错一般比较低级,另类,奇葩.....下面内容我会提出一些不常见的问题

    正题

    前置条件

    1.商户平台==>产品中心==>开发者配置==>公众号支付,设置支付授权目录,有说明注意看.(tomcat配置了访问域名直接访问项目.例:域名/控制器/方法名.action(http://xxx.xxx.com/index/pay.action),应该配成:域名/控制器/(http://xxx.xxx.com/index/))

    2.都做支付了,其余的就不废话了,该配的自己都配了就行

    3.明确商户key,公众号的配置比较多,这个商户key是指在商户平台安装证书时设置的api秘钥.记住这个key才是你后面两次签名用到的key,明确这个key你才算真正的做了支付的第一步(帐户中心——API安全——设置API密钥——提示会影响——确认——新密钥——手机验证码——登录密码)

    大概流程

    很多人不愿意看文档,没关系,我明确的告诉你,只需要看这两个地方就足够了,第一步:统一下单.第二步微信H5调起支付

    第一步:统一下单

    这个是啥意思就不过多解释了,结果就是做完这步,你能获取到一个prepay_id(预支付交易会话标识),公众号赋予的含义我们不去管它,只要知道做完这两步你就能支付成功了就可以

    首先我们都知道我们需要传一个xml字符串给微信,什么参数要传,什么参数不传文档都有讲,但是其中openid在做公众号支付的时候是必须要传的

    完成统一下单的决定性技巧

    照做文档!!!!:

    下图是文档中关于签名的说明.很多人第一步就卡在了签名处,这个时候,你只要完完全全照着文档做一遍就可以避免第一步统一下单99%的问题

    这是文档中对于签名的说明或者说是帮助,强烈建议,把他这三步复制照做,对比结果(签名)是否和文档一致跟着做一遍,统一下单你就完成了99%了

     上面这步做完,其实应该算已经成功了,剩下的就是注意事项了(坑)

    统一下单注意事项

    1.参数尽量使用<![CDATA[]]>包裹,下面提供的代码已经实现,直接使用就行

    2.body(商品描述),当你在本地一切代码就绪,放上服务器支付却失败了,提示参数校验失败,很有可能是你在body中传入了中文(当然,还有个detail应该也能传中文,只不过我没有尝试传这个参数),而你的服务环境导致中文乱码了,在控制台打印发送的字符串可以看到是否乱码.(微信验证你传过去的参数是乱码后的中文内容),解决方法当然是修改服务器环境了

    3.签名类型

    生成签名重要的就是明确最后传入的key,根据之前调用接口的经验.开始我以为是开发者秘钥或者api秘钥(没有仔细看文档,大概意思是误以为key是使用在某个设置时我选择了采用SHA-512生成的秘钥),那么就得采用SHA-512方式去做这个签名,其实人家写的很清楚,只支持MD5和HMAC-SHA256方式.

    最重要的是,我在做的过程中,使用SHA-512生成签名,竟然成功了!,成功的获取到了prepay_id,继而导致后续唤起支付一错再错.在后续唤起支付时提示请求参数校验错误,个人感觉,这也说明了第二步唤起支付,会去找到第一步统一下单时的参数,并且再次对参数校验.所以,当第二步没问题了以后,提示什么参数问题,应该都是指第一步统一下单时传入参数的问题

    所以,一定要对照文档,按他的提示去做,很多人都对微信文档不满,但就这次支付经历来说,个人感觉人家文档说的很精准,并没有不对的地方,包括上面说的openid不能为空的事,人家说明也很对啊,只有在trade_type=JSAPI时(即公众号支付),此参数必传,所以分情况的话当然不能说openid是必填项

    4.必填参数中,不必非要传真实值的参数有(随便填):

    4.1  spbill_create_ip   终端IP

    4.2  notify_url     通知地址

    第二步:微信H5调起支付

    这步没啥好说的,文档有,复制粘贴,然后ok

    微信H5调起支付注意事项

    还是那句注意看文档

    1.参与签名参数为:appId、timeStamp、nonceStr、package、signType,请注意参数大小写。

    只要照着文档做这步出错的几率还是很小的,只有一小部分的朋友不知道怎么从哪写的这几个参数,没有注意大小写

    2.有些朋友说前台获取支付参数时,必须要写在onBridgeReady()方法里面,不然获取不到,应该是不正确的,所有的js像普通项目一样正常写,没有啥可特别注意的(我的就写在外面了,专门放到方法里测试过,也可以,没区别)

    此时一切完毕效果图

    代码一步到位

    这个是主类

    package cn.cnsdhzzl.controller.pay;
    
    import java.security.MessageDigest;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.SortedMap;
    import java.util.TreeMap;
    import java.util.UUID;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import cn.cnsdhzzl.wechat.utils.AnalysisXml;
    import cn.cnsdhzzl.wechat.utils.VisitUrl;
    
    /**
     * 
     * @author zl 2018年5月1日 下午2:56:53 WeChatPay
     *
     */
    @Controller
    @Scope("prototype")
    @RequestMapping({ "/pay" })
    public class WeChatPay {
        @ResponseBody
        @SuppressWarnings("unchecked")
        @RequestMapping({ "/jsapi" })
        public Map<String, String> cs(Model model, HttpSession session, HttpServletRequest request) throws Exception {
            String out_trade_no = UUID.randomUUID().toString().replaceAll("-", "");
            System.out.println("商户订单号:" + out_trade_no);
    
            SortedMap signMap = new TreeMap();// 统一下单生成签名的参数
            signMap.put("appid", "你的APPID");
            signMap.put("body", "xk-money");
            signMap.put("mch_id", "你的商户ID");
            signMap.put("nonce_str", "随机字符串");
            signMap.put("notify_url", "http://xxx.xxxcom/wechat/receive.action");
            signMap.put("openid", "付款用户的openid");
            signMap.put("out_trade_no", out_trade_no);
            signMap.put("spbill_create_ip", getIpAddress(request));
            signMap.put("total_fee", "1");// 金额
            signMap.put("trade_type", "JSAPI");
            System.out.println(signMap.toString());
    
            String sign = generateSignature(signMap, "api秘钥", "MD5");
            System.out.println("统一下单签名:" + sign);
    
            SortedMap map = new TreeMap();// 统一下单发送的数据
            map.put("appid", "你的APPID");
            map.put("body", "xk-money");
            map.put("mch_id", "你的商户ID");
            map.put("nonce_str", "随机字符串");
            map.put("notify_url", "http://xxx.xxxcom/wechat/receive.action");
            map.put("openid", "付款用户的openid");
            map.put("out_trade_no", out_trade_no);
            map.put("spbill_create_ip", getIpAddress(request));
            map.put("total_fee", "1");
            map.put("trade_type", "JSAPI");
            map.put("sign", sign);
    
            String dataStr = new String(AnalysisXml.MapToXMLNoHead(map));
            System.out.println("最终发送的xml:" + dataStr);
            String sendResult = VisitUrl.sendHttps("https://api.mch.weixin.qq.com/pay/unifiedorder", dataStr);// 统一下单,并返回结果
            System.out.println("统一下单返回结果:" + sendResult);
    
            Map xmlToMap = AnalysisXml.xmlToMap(sendResult);
    
            if (xmlToMap.get("prepay_id") != null) {// 获取到prepay_id
                String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
                System.out.println("h5支付时间戳:" + timestamp);
    
                SortedMap signMap2 = new TreeMap();// h5支付中的签名生成时用到的参数
                signMap2.put("appId", "你的APPID");
                signMap2.put("nonceStr", "随机字符串");
                signMap2.put("package", "prepay_id=" + (String) xmlToMap.get("prepay_id"));
    
                System.out.println("map中预支付id:" + (String) xmlToMap.get("prepay_id"));
    
                signMap2.put("signType", "MD5");
                signMap2.put("timeStamp", timestamp);
    
                String str = generateSignature(signMap2, "api秘钥", "MD5");
                System.out.println("h5支付签名:" + str);
    
                Map result = new HashMap();// 组装前台h5支付用到的参数
                result.put("appId", "你的APPID");
                result.put("nonceStr", "随机字符串");
                result.put("pack", "prepay_id=" + (String) xmlToMap.get("prepay_id"));
                result.put("paySign", str);
                result.put("signType", "MD5");
                result.put("timeStamp", timestamp);
    
                System.out.println("返回给前台的最终结果:" + result.toString());
                return result;
            }
    
            return null;
        }
    
        /**
         * 生成签名
         * 
         * @param data
         * @param key
         * @param signType
         * @return
         * @throws Exception
         */
        public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
            Set keySet = data.keySet();
            String[] keyArray = (String[]) keySet.toArray(new String[keySet.size()]);
            Arrays.sort(keyArray);
            StringBuilder sb = new StringBuilder();
            for (String k : keyArray) {
                if (k.equals("sign")) {
                    continue;
                }
                if (((String) data.get(k)).trim().length() > 0)// 参数值为空,则不参与签名
                    sb.append(k).append("=").append(((String) data.get(k)).trim()).append("&");
            }
            sb.append("key=").append(key);
            if ("MD5".equals(signType)) {
                return MD5(sb.toString()).toUpperCase();
            }
            if ("HMACSHA256".equals(signType)) {
                return HMACSHA256(sb.toString(), key);
            }
    
            throw new Exception(String.format("Invalid sign_type: %s", new Object[] { signType }));
        }
    
        /**
         * 生成 MD5
         *
         * @param data
         *            待处理数据
         * @return MD5结果
         */
        public static String MD5(String data) throws Exception {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString(item & 0xFF | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    
        /**
         * 生成 HMACSHA256
         * 
         * @param data
         *            待处理数据
         * @param key
         *            密钥
         * @return 加密结果
         * @throws Exception
         */
        public static String HMACSHA256(String data, String key) throws Exception {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString(item & 0xFF | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    
        /**
         * 获取远程主机ip
         * 
         * @param request
         * @return
         */
        public static String getIpAddress(HttpServletRequest request) {
            String ip = request.getHeader("x-forwarded-for");
            if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
                ip = request.getRemoteAddr();
            }
            return ip;
        }
    }

    这两个是上面用到的工具类

    package cn.cnsdhzzl.wechat.utils;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    
    /**
     * 解析xml并转存至map 解析map并转存至xml
     * 
     * @author zl 2017年9月9日上午11:52:01
     */
    public class AnalysisXml {
    
        public static void main(String[] args) {
            String xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName>
    "
                    + "<FromUserName><![CDATA[FromUser]]></FromUserName>
    " + "<CreateTime>123456789</CreateTime>
    "
                    + "<MsgType><![CDATA[event]]></MsgType>
    " + "<Event><![CDATA[subscribe]]></Event>
    "
                    + "<EventKey><![CDATA[qrscene_123123]]></EventKey>
    " + "<Ticket><![CDATA[TICKET]]></Ticket>
    "
                    + "</xml>";
    
            String temp = "<xml>    <ToUserName><![CDATA[gh_1643056df06d]]></ToUserName>    <Encrypt><![CDATA[1p0AdRxH3ohITPxDuUGniR3B9imeHJ/R4ASmA9+clxStNYYmIfLdy4aX1d/fYFduTjadMfXYmb0hoVra6YhSp3ssEPK1CWOGmecV65ETgwzAIFf1R+rtaPecTqQrbTvvFOAoKzgybM1RTSRqCr42wW/X12fQVquSomLnfrGlSyBit8wC/AetdZmOQ0QxgilsLgDGtAeEQgUveJA+9wrGFaXVZJxJpvjFk5TzXjGwjHKuRWxu4buetMweOFA/gvgnSex9Kioi2lQxuYZQo9k66Kc+6aF4EGIn4pxGLZcZKUbslbt0iZSQ77lLL7udzZ1PBMvT36sg+0ZrfcBA6egl5Wd3ulnEOYmVOZsCLLJpnDxx2UkIIksi3ggRk0EbvuiDQvRJQJGtRrsIAM4S1lWKxq6IRzP04pAinNN9zMrrWn0=]]></Encrypt></xml>";
    
            Map<String, String> map = xmlToMap(temp);
            for (Entry<String, String> string : map.entrySet()) {
                System.out.println("key:" + string.getKey() + "	值:" + string.getValue());
            }
        }
    
        /**
         * xml 转 Map
         * 
         * @param xml
         * @return
         */
        public static Map<String, String> xmlToMap(String xml) {
    
            Map<String, String> map = new HashMap<String, String>();
            Document doc = null;
            try {
                doc = DocumentHelper.parseText(xml);
            } catch (DocumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (doc == null)
                return map;
            Element root = doc.getRootElement();
            for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {
                Element e = (Element) iterator.next();
                map.put(e.getName(), e.getText());
            }
    
            return map;
        }
    
        /**
         * Map 转 XML 无xml头
         * 
         * @param map
         * @return
         */
        public static byte[] MapToXMLNoHead(Map map) {
    
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            mapToXMLTest2(map, sb);
            sb.append("</xml>");
    
            try {
                return sb.toString().getBytes("UTF-8");
            } catch (Exception e) {
            }
    
            return null;
        }
        
        /**
         * Map 转 XML 有xml头
         * 
         * @param map
         * @return
         */
        public static byte[] MapToXMLHaveHead(Map map) {
    
            StringBuffer sb = new StringBuffer();
            sb.append("<?xml version="1.0" encoding="UTF-8"?><xml>");
            mapToXMLTest2(map, sb);
            sb.append("</xml>");
    
            try {
                return sb.toString().getBytes("UTF-8");
            } catch (Exception e) {
            }
    
            return null;
        }
    
        private static void mapToXMLTest2(Map map, StringBuffer sb) {
    
            Set set = map.keySet();
            for (Iterator it = set.iterator(); it.hasNext();) {
                String key = (String) it.next();
                Object value = map.get(key);
                if (null == value)
                    value = "";
                if (value.getClass().getName().equals("java.util.ArrayList")) {
                    ArrayList list = (ArrayList) map.get(key);
                    sb.append("<" + key + "><![CDATA[");
                    for (int i = 0; i < list.size(); i++) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXMLTest2(hm, sb);
                    }
                    sb.append("]]></" + key + ">");
    
                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + "><![CDATA[");
                        mapToXMLTest2((HashMap) value, sb);
                        sb.append("]]></" + key + ">");
                    } else {
                        sb.append("<" + key + "><![CDATA[" + value + "]]></" + key + ">");
                    }
    
                }
            }
        }
    }
    package cn.cnsdhzzl.wechat.utils;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.KeyManager;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    /**
     * http访问url
     * 
     * @author zl 2017年9月1日上午9:27:33
     */
    public class VisitUrl {
        public static void main(String[] args) {
            // 发送 GET 请求
            // String s=VisitUrl.sendGet("http://...com"+"p1=1&p2=2");
            // System.out.println(s);
    
            // 发送 POST 请求
            String sr = VisitUrl.sendPost(
                    "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx126aa425932c5906&redirect_uri=https://www.baidu.com&response_type=code&scope=snsapi_base&state=1#wechat_redirect",
                    "");
            System.out.println(sr);
        }
    
        /**
         * 简单访问url获取结果 http
         * 
         * @author zl 20172017年9月1日上午10:52:18
         * @param url
         * @return String
         */
        public static String visitUrl(String url) {
            // 访问url
            String jsonResulet = "";
            try {
                String str;
                URL u = new URL(url);
                InputStream is = u.openStream();
                InputStreamReader isr = new InputStreamReader(is, "UTF-8");
                BufferedReader br = new BufferedReader(isr);
                if (br.ready()) {
                    while ((str = br.readLine()) != null) {
                        jsonResulet += str;
                    }
                }
                br.close();
                isr.close();
                is.close();
            } catch (MalformedURLException e) {
                // url地址错误
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return jsonResulet;
        }
    
        /**
         * 向指定URL发送GET方法的请求 http
         * 
         * @param url
         *            发送请求的URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return URL 所代表远程资源的响应结果
         */
        public static String sendGet(String url, String param) {
            String result = "";
            String urlNameString = null;
            BufferedReader in = null;
            try {
                if (null == param) {
                    urlNameString = url;
                } else {
                    urlNameString = url + "?" + param;
                }
                URL realUrl = new URL(urlNameString);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("Accept-Charset", "utf-8");
                connection.setRequestProperty("contentType", "utf-8");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                // Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                // for (String key : map.keySet()) {
                // System.out.println(key + "--->" + map.get(key));
                // }
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                // System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输入流
            finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * 向指定 URL 发送POST方法的请求 http
         * 
         * @param url
         *            发送请求的 URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return 所代表远程资源的响应结果
         */
        public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("Accept-Charset", "utf-8");
                conn.setRequestProperty("contentType", "utf-8");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                // System.out.println("发送 POST 请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输出流、输入流
            finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * https POST 访问
         */
        public static String sendHttps(String url, String param) throws IOException {
    
            SSLContext ctx = null;
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                ctx = SSLContext.getInstance("TLS");
                ctx.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() }, new SecureRandom());
            } catch (KeyManagementException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            SSLSocketFactory ssf = ctx.getSocketFactory();
    
            URL u = new URL(url);
            HttpsURLConnection httpsConn = (HttpsURLConnection) u.openConnection();
            httpsConn.setSSLSocketFactory(ssf);
            httpsConn.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });
            // 设置通用的请求属性
            httpsConn.setRequestProperty("accept", "*/*");
            httpsConn.setRequestProperty("Accept-Charset", "utf-8");
            httpsConn.setRequestProperty("contentType", "utf-8");
            httpsConn.setRequestProperty("connection", "Keep-Alive");
            httpsConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
    
            // 发送POST请求必须设置如下两行
            httpsConn.setDoInput(true);
            httpsConn.setDoOutput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(new OutputStreamWriter(httpsConn.getOutputStream(), "utf-8"));
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            if (out != null) {
                out.close();
            }
    
            return result;
        }
    
        private static class DefaultTrustManager implements X509TrustManager {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
    
        /**
         * 从url下载图片并返回其byte[]
         * 
         * @author zl 2018年1月16日 上午11:24:53
         * @param urlPath
         * @return byte[]
         */
        public static byte[] getImageFromURL(String urlPath) {
            byte[] data = null;
            InputStream is = null;
            HttpURLConnection conn = null;
            try {
                URL url = new URL(urlPath);
                conn = (HttpURLConnection) url.openConnection();
                conn.setDoInput(true);
                // conn.setDoOutput(true);
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(6000);
                is = conn.getInputStream();
                // conn.getContentType();
                if (conn.getResponseCode() == 200) {
                    data = readInputStream(is);
                } else {
                    data = null;
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                conn.disconnect();
            }
            return data;
        }
    
        /**
         * 读取InputStream数据,转为byte[]数据类型
         * 
         * @param is
         *            InputStream数据
         * @return 返回byte[]数据
         */
        public static byte[] readInputStream(InputStream is) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length = -1;
            try {
                while ((length = is.read(buffer)) != -1) {
                    baos.write(buffer, 0, length);
                }
                baos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] data = baos.toByteArray();
            try {
                is.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return data;
        }
    
        /**
         * 根据url下载文件,参数(文件网址,存文件的本地地址)
         * 
         * @author zl 2018年1月16日 上午11:11:59
         * @param urlString
         * @param filePath
         * @return
         */
        public static Boolean downloadFile(String urlString, String filePath) {
            // 构造URL
            URL url;
            try {
                url = new URL(urlString);
                // 打开连接
                URLConnection con;
                try {
                    con = url.openConnection();
                    // 输入流
                    InputStream is = con.getInputStream();
                    // 1K的数据缓冲
                    byte[] bs = new byte[1024];
                    // 读取到的数据长度
                    int len;
                    // 输出的文件流
                    OutputStream os = new FileOutputStream(filePath);
                    // 开始读取
                    while ((len = is.read(bs)) != -1) {
                        os.write(bs, 0, len);
                    }
                    // 完毕,关闭所有链接
                    os.close();
                    is.close();
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将输入流转换为字符串
         * 
         * @param input
         *            输入流
         * @return 转换后的字符串
         */
        public static String inputToStr(InputStream input) {
            String result = "";
            if (input != null) {
                byte[] array = new byte[1024];
                StringBuffer buffer = new StringBuffer();
                try {
                    for (int index; (index = (input.read(array))) > -1;) {
                        buffer.append(new String(array, 0, index, "UTF-8"));
                    }
                    result = buffer.toString();
                } catch (IOException e) {
                    e.printStackTrace();
                    result = "";
                }
            }
            return result;
        }
    
    }

    页面调起支付(不需要引入什么微信的js,在微信客户端浏览器打开方法已经内置了)

    html

    <div class="doctorList">
      <ul>
        <li>
          <div class="col-xs-12">
            <div class="smallAbout" style="text-align: center;" id="chushihua">
            访问后台初始化参数
            </div>
          </div>
        </li>
        <li><div>===========================</div></li>
        <li>
          <div class="col-xs-12">
            <div class="smallAbout" style="text-align: center;" id="annu">
            发起支付
            </div>
          </div>
        </li>
      </ul>
    </div>

    js

    <script type="text/javascript">
            var appId = ''
            var nonceStr = ''
            var pack = ''
            var paySign = ''
            var signType = ''
            var timeStamp = ''
            /* 1获取参数 */
            $('#chushihua').click(
                            function() {
                                alert('开始请求后台参数')
                                $
                                        .ajax({
                                            url : '${pageContext.request.contextPath }/pay/jsapi.action',
                                            type : 'POST',
                                            dataType : 'json',
                                            async : false,
                                            //data:{},
                                            success : function(jsonob) {
                                                alert('后台返回json数据:' + JSON.stringify(jsonob))
                                                if (null != jsonob) {
                                                    appId = jsonob.appId;
                                                    nonceStr = jsonob.nonceStr;
                                                    pack = jsonob.pack;
                                                    paySign = jsonob.paySign;
                                                    signType = jsonob.signType;
                                                    timeStamp = jsonob.timeStamp;
                                                } else {
                                                    alert('后台返回空数据')
                                                }
                                            },
                                            error : function() {
    
                                            }
                                        })
                            })
    
            /* 2支付 */
            $('#annu').click(function() {
                pay();
            })
    
            function pay() {
                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();
                }
            }
    
            function onBridgeReady() {
                alert('支付前打印package:' + pack)
                WeixinJSBridge.invoke('getBrandWCPayRequest', {
                    "appId" : "你的APPID",
                    "timeStamp" : timeStamp,
                    "nonceStr" : "随机字符串",
                    "package" : pack,<!-- 注意这里的完整值是:prepay_id=预支付ID,我是在后台传过来的时候就加上了 -->
                    "signType" : "MD5",
                    "paySign" : paySign
                }, function(res) {
                    alert(JSON.stringify(res))
                    if (res.err_msg == "get_brand_wcpay_request:ok") {
                        alert("微信支付成功!");
                    } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
                        alert("用户取消支付!");
                    } else if (res.err_msg == "get_brand_wcpay_request:fail") {
                        alert("支付失败!");
                    } else {
                        alert("支付失败!");
                    }
                });
            }
        </script>
  • 相关阅读:
    Oracle RAC的五大优势及其劣势
    Lucene全文检索基础
    oracle手工生成AWR报告方法记录
    log file sync 等侍值高的一般通用解决办法
    log file sync 因为数据线有问题而造成高等侍的表现
    MongoDB实用教程
    1小时学会JQuery
    Ajax+Struts2实现验证码验证功能
    硬件01:门
    关于软件工程的思考15:人和绩效
  • 原文地址:https://www.cnblogs.com/cnsdhzzl/p/8970641.html
Copyright © 2011-2022 走看看