看完还做不出来你找我
看文档是件烦人的事,你现在做支付,我就假设你肯定已经尝试过了微信公众号的基本接口,例如:获取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在做公众号支付的时候是必须要传的
完成统一下单的决定性技巧
照做文档:
这是文档中对于签名的说明或者说是帮助,强烈建议,把他这三步复制照做,对比结果(签名)是否和文档一致跟着做一遍,统一下单你就完成了一半了
上面这步昨晚,其实应该已经成功了,剩下的就是注意事项了(坑)
统一下单注意事项
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.kdzy.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.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.kdzy.wechat.utils.AnalysisXml; import cn.kdzy.wechat.utils.VisitUrl;
/**
* @author zl 2018年4月29日上午9:27:33
*/
@Controller @Scope("prototype") @RequestMapping("/pay") public class PayZL { @ResponseBody @RequestMapping("/jsapi") public Map<String, String> jsapi(Model model, HttpSession session, HttpServletRequest request) throws Exception { String out_trade_no = UUID.randomUUID().toString().replaceAll("-", ""); System.out.println("商户订单号:" + out_trade_no); Map<String, String> signMap = new HashMap<>(); signMap.put("appid", "你的APPID"); signMap.put("mch_id", "你的商户id"); signMap.put("nonce_str", "FB3930C5C94002262724CFEEAB6335EE"); signMap.put("body", "xk-在线咨询费用"); signMap.put("out_trade_no", out_trade_no); signMap.put("total_fee", "1"); signMap.put("spbill_create_ip", getIpAddress(request)); signMap.put("notify_url", "http://vip.xxx.com/xxx/xxx.action"); signMap.put("trade_type", "JSAPI"); signMap.put("openid", "换成要支付的openid"); String sign = generateSignature(signMap, "你的商户key", "MD5"); System.out.println("签名:" + sign); Map<String, String> map = new HashMap<>(); map.put("appid", "你的APPID"); map.put("mch_id", "你的商户id"); map.put("nonce_str", "FB3930C5C94002262724CFEEAB6335EE"); map.put("sign", sign); map.put("body", "xk-在线咨询费用"); map.put("out_trade_no", out_trade_no); map.put("total_fee", "1"); map.put("spbill_create_ip", getIpAddress(request)); map.put("notify_url", "http://vip.xxx.com/xxx/xxx.action"); map.put("trade_type", "JSAPI"); map.put("openid", "换成要支付的openid"); String str = new String(AnalysisXml.MapToXMLNoHead(map)); System.out.println(str); String sendPost = VisitUrl.sendHttps("https://api.mch.weixin.qq.com/pay/unifiedorder",str); System.out.println("统一下单返回结果:" + sendPost); Map<String, String> xmlToMap = AnalysisXml.xmlToMap(sendPost); if (null != xmlToMap.get("prepay_id")) { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); System.out.println("h5支付时间戳:" + timestamp); Map<String, String> signMap2 = new HashMap<>(); signMap2.put("appId", "你的APPID"); signMap2.put("nonceStr", "FB3930C5C94002262724CFEEAB6335EE"); signMap2.put("package", "prepay_id=" + xmlToMap.get("prepay_id")); System.out.println("map中预支付id:" + xmlToMap.get("prepay_id")); signMap2.put("signType", "MD5"); signMap2.put("timeStamp", timestamp); String signxx = generateSignature(signMap2, "你的商户key", "MD5"); System.out.println("h5支付签名:" + signxx); Map<String, String> result = new HashMap<>(); result.put("appId", "你的APPID"); result.put("nonceStr", "FB3930C5C94002262724CFEEAB6335EE"); result.put("pack", "prepay_id=" + xmlToMap.get("prepay_id")); result.put("paySign", signxx); result.put("signType", "MD5"); result.put("timeStamp", timestamp); System.out.println("返回给前台的最终结果:" + result.toString()); return result; } return null; } public static String generateSignature(final Map<String, String> data, String key, String signType) throws Exception { Set<String> keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals("sign")) { continue; } if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } sb.append("key=").append(key); if ("MD5".equals(signType)) { return MD5(sb.toString()).toUpperCase(); } else if ("HMACSHA256".equals(signType)) { return HMACSHA256(sb.toString(), key); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } /** * 生成 MD5 * * @param data * 待处理数据 * @return MD5结果 */ public static String MD5(String data) throws Exception { java.security.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.kdzy.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.kdzy.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(){ $.ajax({ url:'${pageContext.request.contextPath }/pay/jsapi.action', type:'POST', dataType:'json', async:false, //data:{}, success : function(jsonobj) { alert('后台返回json数据:'+JSON.stringify(jsonobj)) if (null!=jsonobj) { appId=jsonobj.appId nonceStr=jsonobj.nonceStr pack=jsonobj.pack paySign=jsonobj.paySign signType=jsonobj.signType timeStamp=jsonobj.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":nonceStr, "package":pack, "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>