WxPayServiceImpl.java
8.6 KB
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package org.theyeasy.weixin.service.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;
import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.servlet.jsp.jstl.core.Config;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.theyeasy.weixin.service.WxPayService;
import org.theyeasy.weixin.util.MD5Util;
import org.theyeasy.weixin.util.WxMessageUtil;
import com.sun.org.apache.xerces.internal.parsers.XMLParser;
import com.w1hd.zzhnc.config.WxPayConfig;
import com.w1hd.zzhnc.vo.Vo_msg;
@Service
public class WxPayServiceImpl implements WxPayService{
@Autowired
WxPayConfig config;
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private String mch_appid = "";
private String mchid = "";
private String key = "";
private String cert_file="";
private String spbill_create_ip="";
@PostConstruct
public void init() {
mch_appid = config.getMchappid();
mchid = config.getMchid();
key = config.getKey();
cert_file = config.getCertFile();
spbill_create_ip = config.getIp();
}
@Override
public Vo_msg payMoney(String partner_trade_no, String openid, int amount, String desc) {
Vo_msg msg = new Vo_msg(-1,null,"未知错误");
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(cert_file));
try {
keyStore.load(instream, mchid.toCharArray());
} finally {
instream.close();
}
String nonce_str = getRandomString(30);
String sign = getSign(nonce_str, partner_trade_no, openid, "NO_CHECK", amount, desc, spbill_create_ip);
System.out.println("sign=" + sign);
//构造xml参数
StringBuffer sb = new StringBuffer();
sb.append("<xml>\n");
sb.append("<mch_appid>").append(mch_appid).append("</mch_appid>").append("\n");
sb.append("<mchid>").append(mchid).append("</mchid>").append("\n");
sb.append("<nonce_str>").append(nonce_str).append("</nonce_str>").append("\n");
sb.append("<partner_trade_no>").append(partner_trade_no).append("</partner_trade_no>").append("\n");
sb.append("<openid>").append(openid).append("</openid>").append("\n");
sb.append("<check_name>").append("NO_CHECK").append("</check_name>").append("\n");
sb.append("<amount>").append(amount).append("</amount>").append("\n");
sb.append("<desc>").append(desc).append("</desc>").append("\n");
sb.append("<spbill_create_ip>").append(spbill_create_ip).append("</spbill_create_ip>").append("\n");
sb.append("<sign>").append(sign).append("</sign>").append("\n");
sb.append("</xml>");
String param = sb.toString();
System.out.println(param);
String uri = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httppost = new HttpPost(uri);
httppost.setEntity(new StringEntity(param, Charset.forName("UTF-8")));
httppost.setHeader("Content-Type","text/xml");
httppost.setHeader("charset","utf-8");
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
StringBuffer sb2 = new StringBuffer();
String text;
while ((text = bufferedReader.readLine()) != null) {
sb2.append(text);
}
log.info(sb2.toString());
Map<String, String> requestMap = WxMessageUtil.parseXml(sb2.toString());
String code = requestMap.get("return_code");
String resultCode = requestMap.get("result_code");
if(code.equals("SUCCESS")&&resultCode.equals("SUCCESS")) //成功
{
String payment_no = requestMap.get("payment_no");
msg = new Vo_msg(0, null, payment_no);
}
else {
String errmsg = requestMap.get("err_code_des");
msg = new Vo_msg(-1,null,errmsg);
log.info("企业付款到零钱失败:" + errmsg);
}
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
} catch (Exception e) {
e.printStackTrace();
msg = new Vo_msg(-1, null, "系统处理失败!");
}
return msg;
}
/**
* 获取签名sign
* @param nonce_str 随机字符串,最长32位
* @param partner_trade_no 订单号
* @param openid 粉丝的openid
* @param check_name 是否实名验证
* @param amount 金额(单位:分)
* @param desc 付款描述
* @param spbill_create_ip 调用api的ip
* @return
*/
private String getSign(String nonce_str,String partner_trade_no, String openid, String check_name, int amount, String desc, String spbill_create_ip) {
String[] array = new String[9];
array[0] = "mch_appid=" + mch_appid;
array[1] = "mchid=" + mchid;
array[2] = "nonce_str=" + nonce_str;
array[3] = "partner_trade_no=" + partner_trade_no;
array[4] = "openid=" + openid;
array[5] = "check_name=" + check_name;
array[6] = "amount=" + amount;
array[7] = "desc=" + desc;
array[8] = "spbill_create_ip=" + spbill_create_ip;
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i <array.length; i++) {
sb.append(array[i]).append("&");
}
sb.append("key=" + key);
String signTemp = sb.toString();
System.out.println(signTemp);
String sign = MD5Util.getMD5(signTemp);
return sign;
}
/**
* 生成签名数据_HmacSHA1加密(用以验证微信服务端发过来的签名),对getSignStr的结果进行加密
*
* @param data
* 待加密的数据
* @param key
* 加密使用的key
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
*/
public static String hash_hmac(String signStr, String key) {
try {
byte[] keyBytes = key.getBytes();
// 根据给定的字节数组构造一个密钥。
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(signStr.getBytes());
String hexBytes = byte2hex(rawHmac).toUpperCase();
return hexBytes;
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
/**
* byte To Hex
* @param b
* @return
*/
public static String byte2hex(final byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
// 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。
stmp = (java.lang.Integer.toHexString(b[n] & 0xFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs;
}
/**
* 构造指定长的随机字符串
* @param length
* @return 指定长度的随机字符串
*/
public static String getRandomString(int length) { // 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();
}
}