微信支付之xml请求和签名
前言
Github:https://github.com/HealerJean
1、组织xml和发起请求
@Override
public String payForCompany() {
SortedMap<Object, Object> sortedMap = new TreeMap<Object, Object>();
sortedMap.put("mch_appid", "appid");
sortedMap.put("mchid", "商户号");
sortedMap.put("nonce_str", UUIDGenerator.generate()); //随机字符串,//随机字符串,不长于32位 微信支付API接口协议中包含字段nonce_str,主要保证签名不可预测。我们推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串。
sortedMap.put("partner_trade_no", OrderCoderUtil.getOrderCode(1L)); //商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
sortedMap.put("openid", "某用户的openid");
// sortedMap.put("check_name", "NO_CHECK"); //校验用户姓名选项 NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名
sortedMap.put("check_name", "FORCE_CHECK"); //校验用户姓名选项 NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名
sortedMap.put("re_user_name", "HealerJean"); //收款用户姓名 收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名
sortedMap.put("amount", "100"); //金额,企业付款金额,单位为分
sortedMap.put("desc", "HealerJean测试付款"); //企业付款描述信息 企业付款操作说明信息。必填。
try {
sortedMap.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress()); //本机 Ip地址 该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP。
} catch (UnknownHostException e) {
throw new AppException(e.getMessage());
}
String requestUrl = WechatApiUrlParams.PAY_QIYE_URL;
String characterEncoding = "UTF-8";
String mySign = PayCommonHttpXmlUtil.createSign(characterEncoding, sortedMap, "Secret");
sortedMap.put("sign", mySign); //签名
String requestXml = XmlUtil.SortedMap2XmlString(sortedMap);
log.info("\n微信支付请求的xml为\n"+requestXml);
// 调用统一下单接口
String resultXml = PayCommonHttpXmlUtil.httpsRequest(requestUrl,"POST",requestXml, weChatMerchant.getMchPassWord());
Map<String,String> map = XmlUtil.wechatXmlToMap(resultXml) ;
if(StringUtils.equals("FAIL",map.get("result_code") )){ //返回报错
throw new AppException(map.get("err_code")+":"+EnumPayErrorType.getDes(map.get("err_code")));
}
return XmlUtil.xml2JSONObject(resultXml).toString();
}
2、签名制作
/**
* 微信支付签名算法sign
*
* @param characterEncoding
* @param parameters
* @return
*/
public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters, String secret ) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + secret); //key为商户平台设置的密钥key
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
3、发起xml请求
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param method 请求方式(GET、POST)
* @param xmlParam 提交的数据
* @return 返回微信服务器响应的信息
*/
public static String httpsRequest(String requestUrl, String method, String xmlParam,String keyStorePassword) {
try
{
// 证书 密码默认是商户号
char[] password = keyStorePassword.toCharArray();
ClassPathResource resource = new ClassPathResource("cert/wechat/apiclient_cert.p12");
InputStream certinputStream = resource.getInputStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(certinputStream, password);
// 实例化密钥库 & 初始化密钥工厂
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password);
// 创建 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf); //证书
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(method);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != xmlParam)
{
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(xmlParam.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
ExceptionLogUtils.log(ce,PayCommonHttpXmlUtil.class );
} catch (IOException e) {
ExceptionLogUtils.log(e,PayCommonHttpXmlUtil.class );
}catch (Exception e) {
ExceptionLogUtils.log(e,PayCommonHttpXmlUtil.class );
}
return null;
}