Java微信支付之服务号支付实现,网上的java微信支付sdk和Demo基本上是水的,看着头疼所以我决心自己开始写Java微信支付之公众号支付,多的不说见下面源码,为了方便使用我分别用了两个Servlet,一个是统一下单UnifiedorderServlet,一个是支付回调PayCallBackServlet,你们可以自己封装。
一是统一下单UnifiedorderServlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONML; import org.json.JSONObject; public class UnifiedorderServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String appid = "" ; // 找微信 private static final String mch_id = "" ; // 找微信 public static final String api_key = "" ; // 找微信 private static final String trade_type = "JSAPI" ; // 写死 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType( "text/html; charset=utf-8" ); PrintWriter out = response.getWriter(); JSONObject jso = new JSONObject(); double money = 0.01 ; String openId = "" , out_trade_no = "" , body = "测试" , ip = "" ; try { out.print(execute(out_trade_no, body, openId, money, ip, jso).toString()); } catch (JSONException e) { e.printStackTrace(); } out.flush(); out.close(); } /** * 微信服务号统一下单支付 * * @param out_trade_no * 订单号 * @param body * 标题 * @param openId * 用户的openId * @param money * 支付金额 * @param ip * 客户端ip * @param request * HttpServletRequest * @return * @throws JSONException */ public JSONObject execute(String out_trade_no, String body, String openId, double money, String ip, JSONObject jso) throws JSONException { StringBuilder xml = new StringBuilder(); String notify_url = "https://test.com/payCallBack" ;// 支付回调地址 String prepay_id = "" , sign = "" , charset = "UTF-8" , nonce_str = "" ; try { String weixinMoney = new java.text.DecimalFormat( "#" ).format(money * 100 ); // 微信是以分为单位的所以要乘以100 nonce_str = getRandomString( 32 ); xml.append( "appid=" ).append(appid).append( "&body=" ).append( new String(body.getBytes(charset), charset)); // 处理中文 xml.append( "&mch_id=" ).append(mch_id).append( "&nonce_str=" ).append(nonce_str); xml.append( "¬ify_url=" ).append(notify_url).append( "&openid=" ).append(openId); xml.append( "&out_trade_no=" ).append(out_trade_no).append( "&spbill_create_ip=" ).append(ip); xml.append( "&total_fee=" ).append(weixinMoney).append( "&trade_type=" ).append(trade_type).append( "&key=" ).append(api_key); sign = MD5Purity(xml.toString()); // System.out.println(xml); xml.delete( 0 , xml.length()); xml.append( "<xml>" ); xml.append( " " ).append(appid).append( "</appid>" ); xml.append( "" ).append(body).append( "" ); xml.append( " <mch_id>" ).append(mch_id).append( "</mch_id>" ); xml.append( " <nonce_str>" ).append(nonce_str).append( "</nonce_str>" ); xml.append( " <openid>" ).append(openId).append( "</openid>" ); xml.append( " <notify_url>" ).append(notify_url).append( "</notify_url>" ); xml.append( " <out_trade_no>" ).append(out_trade_no).append( "</out_trade_no>" ); xml.append( " <spbill_create_ip>" ).append(ip).append( "</spbill_create_ip>" ); xml.append( " <total_fee>" ).append(weixinMoney).append( "</total_fee>" ); xml.append( " <trade_type>" ).append(trade_type).append( "</trade_type>" ); xml.append( " <sign>" ).append(sign).append( "</sign>" ); xml.append( "</xml>" ); HttpURLConnection conn = (HttpURLConnection) new URL( "https://api.mch.weixin.qq.com/pay/unifiedorder" ).openConnection(); conn.setDoOutput( true ); conn.setRequestMethod( "POST" ); conn.setRequestProperty( "Content-Type" , "text/xml" ); conn.setRequestProperty( "Charset" , charset); OutputStream os = conn.getOutputStream(); os.write(xml.toString().getBytes(charset)); xml.delete( 0 , xml.length()); os.close(); int responseCode = conn.getResponseCode(); InputStreamReader in = null ; BufferedReader br = null ; if (responseCode == 200 ) { in = new InputStreamReader(conn.getInputStream(), charset); br = new BufferedReader(in); String retData = null ; while ((retData = br.readLine()) != null ) xml.append(retData); JSONArray childNodes = JSONML.toJSONObject(xml.toString()).getJSONArray( "childNodes" ); int len = childNodes.length() - 1 ; for ( int i = len; i > - 1 ; i--) { JSONObject js = childNodes.getJSONObject(i); if (js.get( "tagName" ).equals( "prepay_id" )) { prepay_id = js.getJSONArray( "childNodes" ).getString( 0 ); break ; } } } if (in != null ) in.close(); if (br != null ) br.close(); conn.disconnect(); // ----------------------------------给h5返回的数据 String timeStamp = System.currentTimeMillis() + "" ; timeStamp = timeStamp.substring( 0 , 10 ); // 微信只要精确到秒 nonce_str = getRandomString( 32 ); jso.put( "appId" , appid); jso.put( "nonceStr" , nonce_str); jso.put( "package" , "prepay_id=" + prepay_id); jso.put( "signType" , "MD5" ); jso.put( "timeStamp" , timeStamp); xml.delete( 0 , xml.length()); xml.append( "appId=" ).append(appid); xml.append( "&nonceStr=" ).append(nonce_str); xml.append( "&package=" ).append(jso.getString( "package" )); xml.append( "&signType=" ).append(jso.getString( "signType" )); xml.append( "&timeStamp=" ).append(timeStamp); xml.append( "&key=" ).append(api_key); sign = MD5Purity( new String(xml.toString().getBytes(charset), charset)); jso.put( "paySign" , sign); //返回的数据主要用在这地方 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 // ----------------------------------给h5返回的数据 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return jso; } /** * MD5 * * @param plainText * @return */ public String MD5Purity(String plainText) { try { MessageDigest md = MessageDigest.getInstance( "MD5" ); md.update(plainText.getBytes( "utf-8" )); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer( "" ); for ( int offset = 0 ; offset < b.length; offset++) { i = b[offset]; if (i < 0 ) i += 256 ; if (i < 16 ) buf.append( "0" ); buf.append(Integer.toHexString(i)); } plainText = buf.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return plainText.toUpperCase(); } /** * 生成一个随机字符串 * * @param length * 表示生成字符串的长度 * @return */ private String getRandomString( int length) { String base = "abcdefghijklmnopqrstuvwxyz0123456789" ; Random random = new Random(); StringBuffer sb = new StringBuffer(); for ( int i = 0 ; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } } |
二是支付回调PayCallBackServlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONML; import org.json.JSONObject; public class PayCallBackServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType( "text/html; charset=utf-8" ); PrintWriter out = response.getWriter(); out.print(doWxServer(request)); out.flush(); out.close(); } /** * 处理微信回调 * * @param request * @return * @throws ServletException * @throws IOException */ public String doWxServer(HttpServletRequest request) { System.out.println( "微信服务号支付回调" ); String inputLine; StringBuilder notityXml = new StringBuilder(); BufferedReader bufferedReader = null ; try { bufferedReader = request.getReader(); while ((inputLine = bufferedReader.readLine()) != null ) notityXml.append(inputLine); if (bufferedReader != null ) bufferedReader.close(); if (notityXml.length() < 10 ) { return "fail" ; } String appid = "" , total_fee = "" , bank_type = "" , cash_fee = "" , fee_type = "" , is_subscribe = "" , mch_id = "" , nonce_str = "" ; String out_trade_no = "" , transaction_id = "" , openid = "" , sign = "" , result_code = "" , return_code = "" , time_end = "" , trade_type = "" ; JSONArray result = JSONML.toJSONObject(notityXml.toString()).getJSONArray( "childNodes" ); int len = result.length(); for ( int i = 0 ; i < len; i++) { JSONObject js = result.getJSONObject(i); Object tagName = js.get( "tagName" ); if (tagName.equals( "appid" )) { appid = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "bank_type" )) { bank_type = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "cash_fee" )) { cash_fee = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "fee_type" )) { fee_type = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "is_subscribe" )) { is_subscribe = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "mch_id" )) { mch_id = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "nonce_str" )) { nonce_str = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "openid" )) { openid = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "out_trade_no" )) { out_trade_no = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "result_code" )) { result_code = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "return_code" )) { return_code = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "time_end" )) { time_end = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "total_fee" )) { total_fee = js.getJSONArray( "childNodes" ).getInt( 0 ) + "" ; } else if (tagName.equals( "trade_type" )) { trade_type = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "transaction_id" )) { transaction_id = js.getJSONArray( "childNodes" ).getString( 0 ); } else if (tagName.equals( "sign" )) { sign = js.getJSONArray( "childNodes" ).getString( 0 ); } } StringBuilder str = new StringBuilder(); str.append( "appid=" ).append(appid).append( "&bank_type=" ).append(bank_type).append( "&cash_fee=" ).append(cash_fee).append( "&fee_type=" ); str.append(fee_type).append( "&is_subscribe=" ).append(is_subscribe).append( "&mch_id=" ).append(mch_id).append( "&nonce_str=" ); str.append(nonce_str).append( "&openid=" ).append(openid).append( "&out_trade_no=" ).append(out_trade_no).append( "&result_code=" ).append(result_code) .append( "&return_code=" ).append(return_code).append( "&time_end=" ).append(time_end).append( "&total_fee=" ).append(total_fee); str.append( "&trade_type=" ).append(trade_type).append( "&transaction_id=" ).append(transaction_id).append( "&key=" ).append(UnifiedorderServlet.api_key); if (!MD5Purity(str.toString()).equals(sign)) { // 验证签名 System.out.println( "微信服务号支付回调签名异常sign=" + sign); System.out.println(str); System.out.println(result); return "fail" ; } total_fee = new java.text.DecimalFormat( "#0.00" ).format(Double.parseDouble(total_fee) / 100 ); // 支付金额以分为单位 return "<xml><return_code><!--[CDATA[SUCCESS]]--></return_code><return_msg><!--[CDATA[OK]]--></return_msg></xml>" ; //成功后给微信返回数据 } catch (JSONException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return "fail" ; } /** * MD5 * * @param plainText * @return */ public String MD5Purity(String plainText) { try { MessageDigest md = MessageDigest.getInstance( "MD5" ); md.update(plainText.getBytes( "utf-8" )); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer( "" ); for ( int offset = 0 ; offset < b.length; offset++) { i = b[offset]; if (i < 0 ) i += 256 ; if (i < 16 ) buf.append( "0" ); buf.append(Integer.toHexString(i)); } plainText = buf.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return plainText.toUpperCase(); } } |
大功告成
总结
以上就是本文关于Java微信支付之服务号支付代码示例的全部内容,希望对大家有所帮助。有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!
原文链接:https://www.2cto.com/kf/201707/544562.html