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