java微信扫码支付(模式二)

微信扫码支付——模式二

  代码:

  PayCommonUtil.java  微信支付常用方法

  1 import java.text.SimpleDateFormat;
  2 import java.util.Date;
  3 import java.util.Iterator;
  4 import java.util.Map;
  5 import java.util.Set;
  6 import java.util.SortedMap;
  7
  8 public class PayCommonUtil
  9 {
 10     /**
 11      * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
 12      * @return boolean
 13      */
 14     public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
 15         StringBuffer sb = new StringBuffer();
 16         Set es = packageParams.entrySet();
 17         Iterator it = es.iterator();
 18         while(it.hasNext()) {
 19             Map.Entry entry = (Map.Entry)it.next();
 20             String k = (String)entry.getKey();
 21             String v = (String)entry.getValue();
 22             if(!"sign".equals(k) && null != v && !"".equals(v)) {
 23                 sb.append(k + "=" + v + "&");
 24             }
 25         }
 26
 27         sb.append("key=" + API_KEY);
 28
 29         //算出摘要
 30         String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
 31         String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();
 32
 33         //System.out.println(tenpaySign + "    " + mysign);
 34         return tenpaySign.equals(mysign);
 35     }
 36
 37     /**
 38      * @author
 39      * @date 2016-4-22
 40      * @Description:sign签名
 41      * @param characterEncoding
 42      *            编码格式
 43      * @param parameters
 44      *            请求参数
 45      * @return
 46      */
 47     public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
 48         StringBuffer sb = new StringBuffer();
 49         Set es = packageParams.entrySet();
 50         Iterator it = es.iterator();
 51         while (it.hasNext()) {
 52             Map.Entry entry = (Map.Entry) it.next();
 53             String k = (String) entry.getKey();
 54             String v = (String) entry.getValue();
 55             if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
 56                 sb.append(k + "=" + v + "&");
 57             }
 58         }
 59         sb.append("key=" + API_KEY);
 60         String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
 61         return sign;
 62     }
 63
 64     /**
 65      * @author
 66      * @date 2016-4-22
 67      * @Description:将请求参数转换为xml格式的string
 68      * @param parameters
 69      *            请求参数
 70      * @return
 71      */
 72     public static String getRequestXml(SortedMap<Object, Object> parameters) {
 73         StringBuffer sb = new StringBuffer();
 74         sb.append("<xml>");
 75         Set es = parameters.entrySet();
 76         Iterator it = es.iterator();
 77         while (it.hasNext()) {
 78             Map.Entry entry = (Map.Entry) it.next();
 79             String k = (String) entry.getKey();
 80             String v = (String) entry.getValue();
 81             if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
 82                 sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
 83             } else {
 84                 sb.append("<" + k + ">" + v + "</" + k + ">");
 85             }
 86         }
 87         sb.append("</xml>");
 88         return sb.toString();
 89     }
 90
 91     /**
 92      * 取出一个指定长度大小的随机正整数.
 93      *
 94      * @param length
 95      *            int 设定所取出随机数的长度。length小于11
 96      * @return int 返回生成的随机数。
 97      */
 98     public static int buildRandom(int length) {
 99         int num = 1;
100         double random = Math.random();
101         if (random < 0.1) {
102             random = random + 0.1;
103         }
104         for (int i = 0; i < length; i++) {
105             num = num * 10;
106         }
107         return (int) ((random * num));
108     }
109
110     /**
111      * 获取当前时间 yyyyMMddHHmmss
112      *
113      * @return String
114      */
115     public static String getCurrTime() {
116         Date now = new Date();
117         SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
118         String s = outFormat.format(now);
119         return s;
120     }
121 }

  XMLUtil.java   将支付参数转换为xml格式

 1 import java.io.ByteArrayInputStream;
 2 import java.io.IOException;
 3 import java.io.InputStream;
 4 import java.util.HashMap;
 5 import java.util.Iterator;
 6 import java.util.List;
 7 import java.util.Map;
 8
 9 import org.jdom.Document;
10 import org.jdom.Element;
11 import org.jdom.JDOMException;
12 import org.jdom.input.SAXBuilder;
13
14 public class XMLUtil
15 {
16     /**
17      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
18      * @param strxml
19      * @return
20      * @throws JDOMException
21      * @throws IOException
22      */
23     public static Map doXMLParse(String strxml) throws JDOMException, IOException {
24         strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
25
26         if(null == strxml || "".equals(strxml)) {
27             return null;
28         }
29
30         Map m = new HashMap();
31
32         InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
33         SAXBuilder builder = new SAXBuilder();
34         Document doc = builder.build(in);
35         Element root = doc.getRootElement();
36         List list = root.getChildren();
37         Iterator it = list.iterator();
38         while(it.hasNext()) {
39             Element e = (Element) it.next();
40             String k = e.getName();
41             String v = "";
42             List children = e.getChildren();
43             if(children.isEmpty()) {
44                 v = e.getTextNormalize();
45             } else {
46                 v = XMLUtil.getChildrenText(children);
47             }
48
49             m.put(k, v);
50         }
51
52         //关闭流
53         in.close();
54
55         return m;
56     }
57
58     /**
59      * 获取子结点的xml
60      * @param children
61      * @return String
62      */
63     public static String getChildrenText(List children) {
64         StringBuffer sb = new StringBuffer();
65         if(!children.isEmpty()) {
66             Iterator it = children.iterator();
67             while(it.hasNext()) {
68                 Element e = (Element) it.next();
69                 String name = e.getName();
70                 String value = e.getTextNormalize();
71                 List list = e.getChildren();
72                 sb.append("<" + name + ">");
73                 if(!list.isEmpty()) {
74                     sb.append(XMLUtil.getChildrenText(list));
75                 }
76                 sb.append(value);
77                 sb.append("</" + name + ">");
78             }
79         }
80
81         return sb.toString();
82     }
83 }

  HttpUtil.java  用http连接提交支付信息参数

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 import java.io.OutputStreamWriter;
 5 import java.net.URL;
 6 import java.net.URLConnection;
 7
 8 import org.apache.commons.logging.Log;
 9 import org.apache.commons.logging.LogFactory;
10
11
12 public class HttpUtil
13 {
14     private static final Log logger = LogFactory.getLog("org.apache.catalina.tribes.MESSAGES" );
15
16     private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
17
18     private final static String DEFAULT_ENCODING = "UTF-8";
19
20     public static String postData(String urlStr, String data){
21         return postData(urlStr, data, null);
22     }
23
24     public static String postData(String urlStr, String data, String contentType){
25         BufferedReader reader = null;
26         try {
27             URL url = new URL(urlStr);
28             URLConnection conn = url.openConnection();
29             conn.setDoOutput(true);
30             conn.setConnectTimeout(CONNECT_TIMEOUT);
31             conn.setReadTimeout(CONNECT_TIMEOUT);
32             if(contentType != null)
33                 conn.setRequestProperty("content-type", contentType);
34             OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
35             if(data == null)
36                 data = "";
37             writer.write(data);
38             writer.flush();
39             writer.close();
40
41             reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
42             System.out.println(reader.toString());
43             StringBuilder sb = new StringBuilder();
44             String line = null;
45             while ((line = reader.readLine()) != null) {
46                 sb.append(line);
47                 sb.append("\r\n");
48             }
49             return sb.toString();
50         } catch (IOException e) {
51             logger.error("Error connecting to " + urlStr + ": " + e.getMessage());
52         } finally {
53             try {
54                 if (reader != null)
55                     reader.close();
56             } catch (IOException e) {
57             }
58         }
59         return null;
60     }
61 }

  MD5Util.java   md5加密

 1     private static String byteToHexString(byte b) {
 2         int n = b;
 3         if (n < 0)
 4             n += 256;
 5         int d1 = n / 16;
 6         int d2 = n % 16;
 7         return hexDigits[d1] + hexDigits[d2];
 8     }
 9
10     public static String MD5Encode(String origin, String charsetname) {
11         String resultString = null;
12         try {
13             resultString = new String(origin);
14             MessageDigest md = MessageDigest.getInstance("MD5");
15             if (charsetname == null || "".equals(charsetname))
16                 resultString = byteArrayToHexString(md.digest(resultString
17                         .getBytes()));
18             else
19                 resultString = byteArrayToHexString(md.digest(resultString
20                         .getBytes(charsetname)));
21         } catch (Exception exception) {
22         }
23         return resultString;
24     }
25
26     private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
27             "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
28 } 
  GetWeixinUrlUtil.java   获取订单生成的二维码URL
 1 import java.io.UnsupportedEncodingException;
 2 import java.net.URLEncoder;
 3 import java.util.Map;
 4 import java.util.SortedMap;
 5 import java.util.TreeMap;
 6
 7 public class GetWeixinUrlUtil
 8 {
 9     //获取二维码url
10     public static String weixin_pay(String ip, VcWeixinPay vcWeixinPay) throws Exception {
11     // 账号信息
12         String appid = PayConfigUtil.APP_ID;  // appid
13         String mch_id = PayConfigUtil.MCH_ID; // 商户号
14         String key = PayConfigUtil.API_KEY; // key
15         String currTime = PayCommonUtil.getCurrTime();
16         String strTime = currTime.substring(8, currTime.length());
17         String strRandom = PayCommonUtil.buildRandom(4) + "";
18         String nonce_str = strTime + strRandom;
19         int order_price = 1; // 商品价格   注意:价格的单位是分
20         String body = "商品名称";   // 商品名称
21         String out_trade_no = PayCommonUtil.getCurrTime() + PayCommonUtil.buildRandom(4); // 商户订单号
22         // 获取发起电脑 ip
23         String spbill_create_ip = ip;
24         // 回调接口
25         String notify_url = PayConfigUtil.NOTIFY_URL;
26         String trade_type = "NATIVE";  //交易类型
27         SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
28         packageParams.put("appid", appid);
29         packageParams.put("mch_id", mch_id);
30         packageParams.put("nonce_str", nonce_str);
31         packageParams.put("body", body);
32         packageParams.put("out_trade_no", out_trade_no);
33         packageParams.put("total_fee", String.valueOf(order_price));
34         packageParams.put("spbill_create_ip", spbill_create_ip);
35         packageParams.put("notify_url", notify_url);
36         packageParams.put("trade_type", trade_type);
37         //生成签名
38         String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);
39         packageParams.put("sign", sign);
40
41         String requestXML = PayCommonUtil.getRequestXml(packageParams);
42         System.out.println(requestXML);
43
44         String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);
45         Map map = XMLUtil.doXMLParse(resXml);
48         String urlCode = (String) map.get("code_url");
49
50         return urlCode;
51     }
52
53     // 特殊字符处理
54     public static String UrlEncode(String src)  throws UnsupportedEncodingException {
55         return URLEncoder.encode(src, "UTF-8").replace("+", "%20");
56     }
57 }    

  PayConfigUtil.java  微信支付参数

 1 import javax.servlet.http.HttpServletRequest;
 2
 3 public class PayConfigUtil
 4 {
 5     public static final String APP_ID = "";//微信开发平台应用ID(公众号ID)
 6     public static final String MCH_ID = "";//商户号(商户号ID)
 7     public static final String API_KEY = "";//API key(商户号里面的)
 8     public static final String CREATE_IP = "";//发起支付的ip
 9     public static final String NOTIFY_URL = "";//回调地址
10     public static final String UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单接口
11     public static final String APP_SECRET = "";//应用对应的凭证(在公众号里面)
12
13     //获取ip
14     public static String getIP(HttpServletRequest request)
15     {
16         String ip = request.getRemoteAddr();
17         return ip;
18     }
19     
  支付回调方法
  1 public void weixin_notify(HttpServletRequest request,HttpServletResponse response) throws Exception
  2     {
  3         System.out.println("调用回调方法");
  4         //读取参数
  5         InputStream inputStream ;
  6         StringBuffer sb = new StringBuffer();
  7         inputStream = request.getInputStream();
  8         String s ;
  9         BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
 10         while ((s = in.readLine()) != null){
 11             sb.append(s);
 12         }
 13         in.close();
 14         inputStream.close();
 15
 16         //解析xml成map
 17         Map<String, String> m = new HashMap<String, String>();
 18         m = XMLUtil.doXMLParse(sb.toString());
 19
 20         //过滤空 设置 TreeMap
 21         SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
 22         Iterator it = m.keySet().iterator();
 23         while (it.hasNext()) {
 24             String parameter = (String) it.next();
 25             String parameterValue = m.get(parameter);
 26
 27             String v = "";
 28             if(null != parameterValue) {
 29                 v = parameterValue.trim();
 30             }
 31             packageParams.put(parameter, v);
 32         }
 33
 34         // 账号信息
 35         String key = PayConfigUtil.API_KEY; // key
 36
 37         logger.info(packageParams);
 38         //判断签名是否正确
 39         if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {
 40             //------------------------------
 41             //处理业务开始
 42             //------------------------------
 44             String resXml = "";
 45             if("SUCCESS".equals((String) packageParams.get("result_code"))){
 46                 // 这里是支付成功
 47                 //////////执行自己的业务逻辑////////////////
 48                 String mch_id = (String) packageParams.get("mch_id");
 49                 String openid = (String) packageParams.get("openid");
 50                 String is_subscribe = (String) packageParams.get("is_subscribe");
 51                 String out_trade_no = (String) packageParams.get("out_trade_no");
 52                 String total_fee = (String) packageParams.get("total_fee");
 53                 String cash_fee_s = (String) packageParams.get("cash_fee");
 54                 String cash_fee = String.valueOf(Integer.parseInt(cash_fee_s) / 100);
 55                 String time_end = MctsUtils.numberDateToDate((String) packageParams.get("time_end"));
 56                 String transaction_id = (String) packageParams.get("transaction_id");
 57
 58                     //////////执行自己的业务逻辑(报存订单信息到数据库)////////////////
 59                     System.out.println("支付成功 ,处理业务成功");
 60                     logger.info("支付成功");
 61                     //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
 62                     resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
 63                             + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
 64                   //------------------------------
 65                     //处理业务完毕
 66                     //------------------------------                //向微信服务器发送确认信息,若不发送,微信服务器会间隔不同的时间调用回调方法
 67                     BufferedOutputStream out = new BufferedOutputStream(
 68                             response.getOutputStream());
 69                     out.write(resXml.getBytes());
 70                     out.flush();
 71                     out.close();
 73                     System.out.println("通知微信.异步确认成功");
 74                 } else {
 93                 logger.info("支付失败,错误信息:" + packageParams.get("err_code"));
 94                 resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
 95                         + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
 96
 97                 BufferedOutputStream out = new BufferedOutputStream(
 98                         response.getOutputStream());
 99                 out.write(resXml.getBytes());
100                 out.flush();
101                 out.close();
102                 System.out.println("执行回调函数失败");
103             }
105         } else{
106             logger.info("通知签名验证失败");
107         }
108     }  
  根据GetWeixinUrlUtil.java获取到微信支付订单信息的二维码url,下载一个解析二维码的js插件(jquery.qrcode.min.js),把获取到二维码url在前端页面用jquery.qrcode.min.js解析,就能显示二维码了。  前端页面简略代码:
 1 <script type="text/javascript" src="js/jquery.qrcode.min.js"></script>
 2 <script language="javascript">
 3     $(function(){
 4         var codeUrl = ${erWeiMa};//erWeiMa是后端传的二维码url
 5         $("#code").qrcode({
 6             render: "canvas", //table方式
 7             width: 240, //宽度
 8             height:240, //高度
 9             text: codeUrl //任意内容
10         });
11     });
12 </script>
13
14 <div id="code" style="width: 240px;height: 240px;margin: 0px auto;"></div> 

  其中用到的jar包当时忘记记录了,不知道的可以根据报错信息搜下缺少的jar包。

  

原文地址:https://www.cnblogs.com/kylyww/p/7476953.html

时间: 2024-08-05 18:45:30

java微信扫码支付(模式二)的相关文章

JAVA微信扫码支付模式二功能实现以及回调

一.准备工作 首先吐槽一下微信关于支付这块,本身支持的支付模式就好几种,但是官方文档特别零散,连像样的JAVA相关的demo也没几个.本人之前没有搞过微信支付,一开始真是被它搞晕,折腾两天终于调通了,特此写下来,以享后人吧! 关于准备工作,就"微信扫码支付模式二"官方文档地址在这 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 可以先看看,实际上需要准备的东西有以下几个: 其中APP_ID和APP_SECRET

C# 微信扫码支付API (微信扫码支付模式二)

一.SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1,下载.NET C#版本: 二.微信相关设置:(微信扫码支付模式二) 1. 公众账号ID,公众账号secert ,地址:https://mp.weixin.qq.com/ 2. 商户号,商户支付密钥KEY,商户平台地址:https://pay.weixin.qq.com/ 5. 部署的服务器终端ip及回调页面 (1)部署的服务器终端ip:即程序部署所在的

微信扫码支付模式二之CodeIgniter集成篇

CI:3.0.5 微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 官方API列表:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 二维码生成类库:phpqrcode 走了几天的弯路,直到遇到Lamtin指点(热心网友)

.NET MVC结构框架下的微信扫码支付模式二 API接口开发测试

直接上干货 ,我们的宗旨就是为人民服务.授人以鱼不如授人以渔.不吹毛求疵.不浮夸.不虚伪.不忽悠.一切都是为了社会共同进步,繁荣昌盛,小程序猿.大程序猿.老程序猿还是嫩程序猿,希望这个社会不要太急功近利 ,希望每个IT行业的BOSS要有良知,程序猿的青春年华都是无私默默奉献,都是拿命拼出来了现在的成就,如果卸磨杀驴,如果逼良为娼,请MM你的良心对得起你爹妈吗,你也有家,你也有小孩,你也有父母的. 在这里致敬程序猿, 致敬我们的攻城狮,致敬我们最可爱的人! 珍惜生命,换种活法也是依然精彩. Vie

thinkphp5.0 微信扫码支付模式二

仅供个人参考,方便大家. 一.1)https://pay.weixin.qq.com/index.php/core/home/login  复制此地址 打开微信商户平台. 2)下载安全操作证书(最好在IE下载): 3)安装后的界面 4)下载证书 5)设置32位秘钥(百度秘钥生成可在线生成): 二.1)https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1  打开此链接下载SDK. 2) 下载后的目录结构 3)在thinkphp

微信公众号 扫码支付 模式二 demo

扫码支付 本文附有代码,在下方,如果不熟悉场景的可以看看下面的场景介绍 场景介绍 官网介绍地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 用户扫描商户展示在各种场景的二维码进行支付. 步骤1:商户根据微信支付的规则,为不同商品生成不同的二维码(如图6.1),展示在各种场景,用于用户扫描购买. 步骤2:用户使用微信"扫一扫"(如图6.2)扫描二维码后,获取商品支付信息,引导用户完成支付(如图6.3). 图6

微信支付Native扫码支付模式二之CodeIgniter集成篇

微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 官方API列表:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 二维码生成类库:phpqrcode 走了几天的弯路,直到遇到Lamtin指点(热心网友),他说你既然是集成

微信扫码支付(模式一)

项目开源地址:http://git.oschina.net/javen205/weixin_guide 微信扫码支付(模式一)你有测试成功吗?如果你看到了这篇文章,我想你是在测试中遇到问题了.OK 那现在我们来看看微信扫码支付中的坑. 原生支付URL参数错误 回调接口URL有回调,但是接收不到参数 商户后台返回的数据字段结构不合法 获取商户订单信息超时或者商户返回的httpcode非200 官方文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.

php微信支付(仅pc端扫码支付模式二)详细步骤.----仅适合第一次做微信开发的程序员

本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/10,所以微信支付的版本也是对应此时的版本. 一.前期准备: 首先你们公司开通微信支付功能后,会收到一份邮件,里面有账户相关信息,一般有:微信支付商户号,商户平台登录帐号,商户平台登录密码,申请对应的公众号,公众号APPID. 1.下载demo:用上面信息登陆“微信商户平台”,>>>(右上角开发文档)>