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

 

看完还做不出来你找我

看文档是件烦人的事,你现在做支付,我就假设你肯定已经尝试过了微信公众号的基本接口,例如:获取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>\r\n"
                + "<FromUserName><![CDATA[FromUser]]></FromUserName>\r\n" + "<CreateTime>123456789</CreateTime>\r\n"
                + "<MsgType><![CDATA[event]]></MsgType>\r\n" + "<Event><![CDATA[subscribe]]></Event>\r\n"
                + "<EventKey><![CDATA[qrscene_123123]]></EventKey>\r\n" + "<Ticket><![CDATA[TICKET]]></Ticket>\r\n"
                + "</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() + "\t值:" + 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>

 

转载于:https://www.cnblogs.com/cnsdhzzl/p/8970641.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值