JAVA 小程序支付 统一付款
商户系统和微信支付系统主要交互说明 [图片] 步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。 步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见【统一下单API】。 步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay 步骤4:商户APP调起微信支付。api参见本章节【app端开发步骤说明】 步骤5:商户后台接收支付通知。api参见【支付结果通知API】 步骤6:商户后台查询支付结果。,api参见【查询订单API】 API链接:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3 支付的流程为: 先调用统一下单API 接着在小程序wx.requestPayment发起支付 支付完之后会调用支付结果通知 [图片] 后台Java代码:(基于SpringMVC) [代码]/**[代码] [代码] [代码][代码]* 统一下单[代码] [代码] [代码][代码]* @param userId[代码] [代码] [代码][代码]* @param activityId[代码] [代码] [代码][代码]* @param openId[代码] [代码] [代码][代码]* @param orderNo[代码] [代码] [代码][代码]* @param money[代码] [代码] [代码][代码]* @param describe[代码] [代码] [代码][代码]* @param detail[代码] [代码] [代码][代码]* @return[代码] [代码] [代码][代码]*/[代码] [代码] [代码][代码]private[代码] [代码]WxappPayDto prePay(String userId,String activityId,String openId,String orderNo,String money,String describe,String detail){[代码] [代码] [代码][代码]money = String.valueOf(Long.valueOf(money.substring([代码][代码]0[代码][代码], money.length()-[代码][代码]1[代码][代码]))*[代码][代码]100[代码][代码]);[代码] [代码] [代码][代码]String currTime = PayUtils.getCurrTime();[代码] [代码] [代码][代码]//8位日期[代码] [代码] [代码][代码]String strTime = currTime.substring([代码][代码]8[代码][代码], currTime.length());[代码] [代码] [代码][代码]//四位随机数[代码] [代码] [代码][代码]String strRandom = PayUtils.buildRandom([代码][代码]4[代码][代码]) + [代码][代码]""[代码][代码];[代码] [代码] [代码][代码]//10位序列号,可以自行调整。[代码] [代码] [代码][代码]String nonceStr = strTime + strRandom;[代码] [代码] [代码][代码]//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。[代码] [代码] [代码][代码]String notifyUrl = baseUrl+[代码][代码]"/notify"[代码][代码];[代码] [代码] [代码][代码]//附加数据,以一定格式保存userId和activityId。原样返回。[代码] [代码] [代码][代码]String attach = userId+[代码][代码]"#wx#"[代码][代码]+activityId;[代码] [代码] [代码][代码]SortedMap<String, String> packageParams = [代码][代码]new[代码] [代码]TreeMap<String, String>();[代码] [代码] [代码][代码]packageParams.put([代码][代码]"appid"[代码][代码], appId);[代码] [代码] [代码][代码]packageParams.put([代码][代码]"attach"[代码][代码], attach);[代码][代码]//附加数据[代码] [代码] [代码][代码]packageParams.put([代码][代码]"body"[代码][代码], describe);[代码][代码]//商品描述[代码] [代码] [代码][代码]packageParams.put([代码][代码]"detail"[代码][代码], detail);[代码] [代码] [代码][代码]packageParams.put([代码][代码]"mch_id"[代码][代码], mchId);[代码][代码]//商户号[代码] [代码] [代码][代码]packageParams.put([代码][代码]"nonce_str"[代码][代码], nonceStr);[代码][代码]//随机数[代码] [代码] [代码][代码]packageParams.put([代码][代码]"notify_url"[代码][代码], notifyUrl);[代码] [代码] [代码][代码]packageParams.put([代码][代码]"openid"[代码][代码], openId);[代码] [代码] [代码][代码]packageParams.put([代码][代码]"out_trade_no"[代码][代码], orderNo);[代码][代码]//商户订单号[代码] [代码] [代码][代码]packageParams.put([代码][代码]"spbill_create_ip"[代码][代码], spBillCreateIp);[代码][代码]//订单生成的机器 IP[代码] [代码] [代码][代码]packageParams.put([代码][代码]"total_fee"[代码][代码], money);[代码][代码]//总金额[代码] [代码] [代码][代码]packageParams.put([代码][代码]"trade_type"[代码][代码], [代码][代码]"JSAPI"[代码][代码]); [代码] [代码] [代码] [代码] [代码][代码]String sign = PayUtils.createSign(packageParams,key);[代码] [代码] [代码][代码]String xml=[代码][代码]"<xml>"[代码][代码]+[代码] [代码] [代码][代码]"<appid>"[代码][代码]+appId+[代码][代码]"</appid>"[代码][代码]+[代码] [代码] [代码][代码]"<attach>"[代码][代码]+attach+[代码][代码]"</attach>"[代码][代码]+[代码] [代码] [代码][代码]"<body><![CDATA["[代码][代码]+describe+[代码][代码]"]]></body>"[代码][代码]+[代码] [代码] [代码][代码]"<detail><![CDATA["[代码][代码]+detail+[代码][代码]"]]></detail>"[代码][代码]+[代码] [代码] [代码][代码]"<mch_id>"[代码][代码]+mchId+[代码][代码]"</mch_id>"[代码][代码]+[代码] [代码] [代码][代码]"<nonce_str>"[代码][代码]+nonceStr+[代码][代码]"</nonce_str>"[代码][代码]+[代码] [代码] [代码][代码]"<sign>"[代码][代码]+sign+[代码][代码]"</sign>"[代码][代码]+[代码] [代码] [代码][代码]"<notify_url>"[代码][代码]+notifyUrl+[代码][代码]"</notify_url>"[代码][代码]+[代码] [代码] [代码][代码]"<openid>"[代码][代码]+openId+[代码][代码]"</openid>"[代码][代码]+[代码] [代码] [代码][代码]"<out_trade_no>"[代码][代码]+orderNo+[代码][代码]"</out_trade_no>"[代码][代码]+[代码] [代码] [代码][代码]"<spbill_create_ip>"[代码][代码]+spBillCreateIp+[代码][代码]"</spbill_create_ip>"[代码][代码]+[代码] [代码] [代码][代码]"<total_fee>"[代码][代码]+money+[代码][代码]"</total_fee>"[代码][代码]+[代码] [代码] [代码][代码]"<trade_type>JSAPI</trade_type>"[代码][代码]+[代码] [代码] [代码][代码]"</xml>"[代码][代码];[代码] [代码] [代码][代码]String prepay_id=[代码][代码]""[代码][代码];[代码] [代码] [代码][代码]try[代码] [代码]{[代码] [代码] [代码][代码]prepay_id = PayUtils.getPayNo(createOrderURL, xml);[代码] [代码] [代码][代码]if[代码][代码](prepay_id.equals([代码][代码]""[代码][代码])){[代码] [代码] [代码][代码]//错误提示[代码] [代码] [代码][代码]System.out.println([代码][代码]"统一支付接口获取预支付订单出错"[代码][代码]);[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e1) {[代码] [代码] [代码][代码]e1.printStackTrace();[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]SortedMap<String, String> finalpackage = [代码][代码]new[代码] [代码]TreeMap<String, String>();[代码] [代码] [代码][代码]String timestamp = PayUtils.getTimeStamp();[代码] [代码] [代码][代码]String packages = [代码][代码]"prepay_id="[代码][代码]+prepay_id;[代码] [代码] [代码][代码]finalpackage.put([代码][代码]"appId"[代码][代码], appId);[代码] [代码] [代码][代码]finalpackage.put([代码][代码]"nonceStr"[代码][代码], nonceStr); [代码] [代码] [代码][代码]finalpackage.put([代码][代码]"package"[代码][代码], packages); [代码] [代码] [代码][代码]finalpackage.put([代码][代码]"signType"[代码][代码], [代码][代码]"MD5"[代码][代码]);[代码] [代码] [代码][代码]finalpackage.put([代码][代码]"timeStamp"[代码][代码], timestamp); [代码] [代码] [代码][代码]String finalsign = PayUtils.createSign(finalpackage,key);[代码] [代码] [代码] [代码] [代码][代码]WxappPayDto dto = [代码][代码]new[代码] [代码]WxappPayDto();[代码] [代码] [代码][代码]dto.setNonceStr(nonceStr);[代码] [代码] [代码][代码]dto.setPackage_(packages);[代码] [代码] [代码][代码]dto.setPaySign(finalsign);[代码] [代码] [代码][代码]dto.setSignType([代码][代码]"MD5"[代码][代码]);[代码] [代码] [代码][代码]dto.setTimeStamp(timestamp);[代码] [代码] [代码][代码]return[代码] [代码]dto;[代码] [代码] [代码][代码]}[代码] 付款回调地址 [代码]/**[代码] [代码] [代码][代码]* 支付完成通知[代码] [代码] [代码][代码]* @param request[代码] [代码] [代码][代码]* @param response[代码] [代码] [代码][代码]* @return[代码] [代码] [代码][代码]* @throws Exception[代码] [代码] [代码][代码]*/[代码] [代码] [代码][代码]@RequestMapping[代码][代码](value = [代码][代码]"/notify"[代码][代码],method = RequestMethod.POST)[代码] [代码] [代码][代码]public[代码] [代码]String notify(HttpServletRequest request, HttpServletResponse response) [代码][代码]throws[代码] [代码]Exception {[代码] [代码] [代码][代码]BufferedReader br = [代码][代码]new[代码] [代码]BufferedReader([代码][代码]new[代码] [代码]InputStreamReader((ServletInputStream)request.getInputStream()));[代码] [代码] [代码][代码]String line = [代码][代码]null[代码][代码];[代码] [代码] [代码][代码]StringBuilder sb = [代码][代码]new[代码] [代码]StringBuilder();[代码] [代码] [代码][代码]while[代码][代码]((line = br.readLine())!=[代码][代码]null[代码][代码]){[代码] [代码] [代码][代码]sb.append(line);[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]//解析并给微信发回收到通知确认[代码] [代码] [代码][代码]Map map = PayUtils.doXMLParse(sb.toString());[代码] [代码] [代码][代码]String returnCode = map.get([代码][代码]"return_code"[代码][代码]).toString();[代码] [代码] [代码][代码]if[代码][代码](returnCode.equals([代码][代码]"SUCCESS"[代码][代码])){[代码] [代码] [代码][代码]String resultCode = map.get([代码][代码]"result_code"[代码][代码]).toString();[代码] [代码] [代码][代码]if[代码][代码](resultCode.equals([代码][代码]"SUCCESS"[代码][代码])){[代码] [代码] [代码][代码]SortedMap<String, String> packageParams = [代码][代码]new[代码] [代码]TreeMap<String, String>();[代码] [代码] [代码][代码]packageParams.put([代码][代码]"appid"[代码][代码], map.get([代码][代码]"appid"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"attach"[代码][代码], map.get([代码][代码]"attach"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"bank_type"[代码][代码], map.get([代码][代码]"bank_type"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"cash_fee"[代码][代码], map.get([代码][代码]"cash_fee"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"fee_type"[代码][代码], map.get([代码][代码]"fee_type"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"is_subscribe"[代码][代码], map.get([代码][代码]"is_subscribe"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"mch_id"[代码][代码], map.get([代码][代码]"mch_id"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"nonce_str"[代码][代码], map.get([代码][代码]"nonce_str"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"openid"[代码][代码], map.get([代码][代码]"openid"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"out_trade_no"[代码][代码], map.get([代码][代码]"out_trade_no"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"result_code"[代码][代码], map.get([代码][代码]"result_code"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"return_code"[代码][代码], map.get([代码][代码]"return_code"[代码][代码]).toString()); [代码] [代码] [代码][代码]packageParams.put([代码][代码]"time_end"[代码][代码], map.get([代码][代码]"time_end"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"total_fee"[代码][代码], map.get([代码][代码]"total_fee"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"trade_type"[代码][代码], map.get([代码][代码]"trade_type"[代码][代码]).toString());[代码] [代码] [代码][代码]packageParams.put([代码][代码]"transaction_id"[代码][代码], map.get([代码][代码]"transaction_id"[代码][代码]).toString());[代码] [代码] [代码][代码]String sign = PayUtils.createSign(packageParams,key);[代码] [代码] [代码][代码]String originSign = map.get([代码][代码]"sign"[代码][代码]).toString();[代码] [代码] [代码][代码]if[代码][代码](sign.equals(originSign)){[代码] [代码] [代码][代码]//签名一致,保存支付流水[代码] [代码] [代码][代码]String xml=[代码][代码]"<xml>"[代码] [代码] [代码][代码]+[代码][代码]"<return_code>SUCCESS</return_code>"[代码] [代码] [代码][代码]+[代码][代码]"<return_msg>OK</return_msg>"[代码] [代码] [代码][代码]+[代码][代码]"</xml>"[代码][代码];[代码] [代码] [代码][代码]ShopPayLog payLog = [代码][代码]new[代码] [代码]ShopPayLog();[代码] [代码] [代码][代码]payLog.setCreatedAt([代码][代码]new[代码] [代码]Date());[代码] [代码] [代码][代码]payLog.setSource(Source.WeiXin);[代码] [代码] [代码][代码]DecimalFormat df = [代码][代码]new[代码] [代码]DecimalFormat([代码][代码]"######0.00"[代码][代码]); [代码] [代码] [代码][代码]payLog.setTotalFee(String.valueOf(df.format((Double.valueOf(map.get([代码][代码]"total_fee"[代码][代码]).toString())/[代码][代码]100[代码][代码]))));[代码] [代码] [代码][代码]payLog.setTradeNo(map.get([代码][代码]"out_trade_no"[代码][代码]).toString());[代码] [代码] [代码][代码]payLog.setTransactionId(map.get([代码][代码]"transaction_id"[代码][代码]).toString());[代码] [代码] [代码][代码]String attach = map.get([代码][代码]"attach"[代码][代码]).toString();[代码][代码]//userId+"#wx#"+activityId[代码] [代码] [代码][代码]payLog.setUserId(attach.split([代码][代码]"#wx#"[代码][代码])[[代码][代码]0[代码][代码]]);[代码] [代码] [代码][代码]payLog = wxappPayService.save(payLog);[代码] [代码] [代码][代码]WxappUser user = wxappUserService.find(Long.valueOf(attach.split([代码][代码]"#wx#"[代码][代码])[[代码][代码]0[代码][代码]]));[代码] [代码] [代码][代码]WxappActivity activity = wxappActivityService.find(Long.valueOf(attach.split([代码][代码]"#wx#"[代码][代码])[[代码][代码]1[代码][代码]]));[代码] [代码] [代码][代码]WxappActivityApply activityApply = wxappActivityApplyService.findActivityApplyByUserAndActivity(user, activity);[代码] [代码] [代码][代码]//在活动申请表中关联上支付流水的id activityApply.setPayLogId(String.valueOf(payLog.getId()));[代码] [代码] [代码][代码]wxappActivityApplyService.save(activityApply);[代码] [代码] [代码][代码]return[代码] [代码]xml;[代码] [代码] [代码][代码]}[代码][代码]else[代码][代码]{[代码] [代码] [代码][代码]String xml=[代码][代码]"<xml>"[代码] [代码] [代码][代码]+[代码][代码]"<return_code>FAIL</return_code>"[代码] [代码] [代码][代码]+[代码][代码]"<return_msg>签名不一致</return_msg>"[代码] [代码] [代码][代码]+[代码][代码]"</xml>"[代码][代码];[代码] [代码] [代码][代码]return[代码] [代码]xml;[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]}[代码][代码]else[代码][代码]{[代码] [代码] [代码][代码]String xml=[代码][代码]"<xml>"[代码] [代码] [代码][代码]+[代码][代码]"<return_code>FAIL</return_code>"[代码] [代码] [代码][代码]+[代码][代码]"<return_msg>支付通知失败</return_msg>"[代码] [代码] [代码][代码]+[代码][代码]"</xml>"[代码][代码];[代码] [代码] [代码][代码]return[代码] [代码]xml;[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]} [代码][代码]else[代码] [代码]{[代码] [代码] [代码][代码]String xml=[代码][代码]"<xml>"[代码] [代码] [代码][代码]+[代码][代码]"<return_code>FAIL</return_code>"[代码] [代码] [代码][代码]+[代码][代码]"<return_msg>支付通知失败</return_msg>"[代码] [代码] [代码][代码]+[代码][代码]"</xml>"[代码][代码];[代码] [代码] [代码][代码]return[代码] [代码]xml;[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]}[代码] PayUtils.java [代码]import[代码] [代码]java.io.BufferedReader;[代码][代码]import[代码] [代码]java.io.ByteArrayInputStream;[代码][代码]import[代码] [代码]java.io.File;[代码][代码]import[代码] [代码]java.io.FileInputStream;[代码][代码]import[代码] [代码]java.io.IOException;[代码][代码]import[代码] [代码]java.io.InputStream;[代码][代码]import[代码] [代码]java.io.InputStreamReader;[代码][代码]import[代码] [代码]java.io.UnsupportedEncodingException;[代码][代码]import[代码] [代码]java.net.URLEncoder;[代码][代码]import[代码] [代码]java.security.KeyStore;[代码][代码]import[代码] [代码]java.security.MessageDigest;[代码][代码]import[代码] [代码]java.text.SimpleDateFormat;[代码][代码]import[代码] [代码]java.util.Date;[代码][代码]import[代码] [代码]java.util.HashMap;[代码][代码]import[代码] [代码]java.util.Iterator;[代码][代码]import[代码] [代码]java.util.List;[代码][代码]import[代码] [代码]java.util.Map;[代码][代码]import[代码] [代码]java.util.Random;[代码][代码]import[代码] [代码]java.util.Set;[代码][代码]import[代码] [代码]java.util.SortedMap;[代码][代码]import[代码] [代码]java.util.TreeMap;[代码] [代码]import[代码] [代码]javax.net.ssl.SSLContext;[代码][代码]import[代码] [代码]javax.servlet.http.HttpServletRequest;[代码][代码]import[代码] [代码]javax.servlet.http.HttpServletResponse;[代码] [代码]import[代码] [代码]org.apache.http.HttpEntity;[代码][代码]import[代码] [代码]org.apache.http.HttpResponse;[代码][代码]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.entity.StringEntity;[代码][代码]import[代码] [代码]org.apache.http.impl.client.CloseableHttpClient;[代码][代码]import[代码] [代码]org.apache.http.impl.client.DefaultHttpClient;[代码][代码]import[代码] [代码]org.apache.http.impl.client.HttpClients;[代码][代码]import[代码] [代码]org.apache.http.ssl.SSLContexts;[代码][代码]import[代码] [代码]org.apache.http.util.EntityUtils;[代码][代码]import[代码] [代码]org.jdom.Document;[代码][代码]import[代码] [代码]org.jdom.Element;[代码][代码]import[代码] [代码]org.jdom.input.SAXBuilder;[代码] [代码]import[代码] [代码]com.pro.profwxappapi.api.PayApi;[代码] [代码]@SuppressWarnings[代码][代码]([代码][代码]"deprecation"[代码][代码])[代码][代码]public[代码] [代码]class[代码] [代码]PayUtils {[代码][代码] [代码][代码]private[代码] [代码]static[代码] [代码]Object Server;[代码][代码] [代码][代码]@SuppressWarnings[代码][代码]([代码][代码]"deprecation"[代码][代码])[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]DefaultHttpClient httpclient;[代码][代码] [代码][代码]private[代码] [代码]static[代码] [代码]SortedMap parameters;[代码][代码] [代码] [代码] [代码][代码]static[代码] [代码]{[代码][代码] [代码][代码]httpclient = [代码][代码]new[代码] [代码]DefaultHttpClient();[代码][代码] [代码][代码]httpclient = (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(httpclient);[代码][代码] [代码][代码]parameters = [代码][代码]new[代码] [代码]TreeMap();[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 把对象转换成字符串[代码][代码] [代码][代码]* [代码][代码] [代码][代码]* @param obj[代码][代码] [代码][代码]* @return String 转换成字符串,若对象为null,则返回空字符串.[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String toString(Object obj) {[代码][代码] [代码][代码]if[代码] [代码](obj == [代码][代码]null[代码][代码])[代码][代码] [代码][代码]return[代码] [代码]""[代码][代码];[代码] [代码] [代码][代码]return[代码] [代码]obj.toString();[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 把对象转换为int数值.[代码][代码] [代码][代码]* [代码][代码] [代码][代码]* @param obj[代码][代码] [代码][代码]* 包含数字的对象.[代码][代码] [代码][代码]* @return int 转换后的数值,对不能转换的对象返回0。[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]int[代码] [代码]toInt(Object obj) {[代码][代码] [代码][代码]int[代码] [代码]a = [代码][代码]0[代码][代码];[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]if[代码] [代码](obj != [代码][代码]null[代码][代码]) {[代码][代码] [代码][代码]a = Integer.parseInt(obj.toString());[代码][代码] [代码][代码]}[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]a;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取从1970年开始到现在的秒数[代码][代码] [代码][代码]* [代码][代码] [代码][代码]* @param date[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getTimeStamp() {[代码][代码] [代码][代码]long[代码] [代码]seconds = System.currentTimeMillis() / [代码][代码]1000[代码][代码];[代码][代码] [代码][代码]return[代码] [代码]String.valueOf(seconds);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取当前时间 yyyyMMddHHmmss[代码][代码] [代码][代码]* @return String[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getCurrTime() {[代码][代码] [代码][代码]Date now = [代码][代码]new[代码] [代码]Date();[代码][代码] [代码][代码]SimpleDateFormat outFormat = [代码][代码]new[代码] [代码]SimpleDateFormat([代码][代码]"yyyyMMddHHmmss"[代码][代码]);[代码][代码] [代码][代码]String s = outFormat.format(now);[代码][代码] [代码][代码]return[代码] [代码]s;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取当前日期 yyyyMMdd[代码][代码] [代码][代码]* @param date[代码][代码] [代码][代码]* @return String[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String formatDate(Date date) {[代码][代码] [代码][代码]SimpleDateFormat formatter = [代码][代码]new[代码] [代码]SimpleDateFormat([代码][代码]"yyyyMMdd"[代码][代码]);[代码][代码] [代码][代码]String strDate = formatter.format(date);[代码][代码] [代码][代码]return[代码] [代码]strDate;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 取出一个指定长度大小的随机正整数.[代码][代码] [代码][代码]* @param length int 设定所取出随机数的长度。length小于11[代码][代码] [代码][代码]* @return int 返回生成的随机数。[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]int[代码] [代码]buildRandom([代码][代码]int[代码] [代码]length) {[代码][代码] [代码][代码]int[代码] [代码]num = [代码][代码]1[代码][代码];[代码][代码] [代码][代码]double[代码] [代码]random = Math.random();[代码][代码] [代码][代码]if[代码] [代码](random < [代码][代码]0.1[代码][代码]) {[代码][代码] [代码][代码]random = random + [代码][代码]0.1[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]for[代码] [代码]([代码][代码]int[代码] [代码]i = [代码][代码]0[代码][代码]; i < length; i++) {[代码][代码] [代码][代码]num = num * [代码][代码]10[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]([代码][代码]int[代码][代码]) ((random * num));[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取编码字符集[代码][代码] [代码][代码]* @param request[代码][代码] [代码][代码]* @param response[代码][代码] [代码][代码]* @return String[代码][代码] [代码][代码]*/[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getCharacterEncoding(HttpServletRequest request, HttpServletResponse response) {[代码] [代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]== request || [代码][代码]null[代码] [代码]== response) {[代码][代码] [代码][代码]return[代码] [代码]"utf-8"[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]String enc = request.getCharacterEncoding();[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]== enc || [代码][代码]""[代码][代码].equals(enc)) {[代码][代码] [代码][代码]enc = response.getCharacterEncoding();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]== enc || [代码][代码]""[代码][代码].equals(enc)) {[代码][代码] [代码][代码]enc = [代码][代码]"utf-8"[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]enc;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]String URLencode(String content) {[代码][代码] [代码][代码]String URLencode;[代码][代码] [代码][代码]URLencode = replace(Server.equals(content), [代码][代码]"+"[代码][代码], [代码][代码]"%20"[代码][代码]);[代码][代码] [代码][代码]return[代码] [代码]URLencode;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]private[代码] [代码]static[代码] [代码]String replace([代码][代码]boolean[代码] [代码]equals, String string, String string2) {[代码][代码] [代码][代码]return[代码] [代码]null[代码][代码];[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取unix时间,从1970-01-01 00:00:00开始的秒数[代码][代码] [代码][代码]* @param date[代码][代码] [代码][代码]* @return long[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]long[代码] [代码]getUnixTime(Date date) {[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]== date) {[代码][代码] [代码][代码]return[代码] [代码]0[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]date.getTime() / [代码][代码]1000[代码][代码];[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]String QRfromGoogle(String chl) {[代码][代码] [代码][代码]int[代码] [代码]widhtHeight = [代码][代码]300[代码][代码];[代码][代码] [代码][代码]String EC_level = [代码][代码]"L"[代码][代码];[代码][代码] [代码][代码]int[代码] [代码]margin = [代码][代码]0[代码][代码];[代码][代码] [代码][代码]String QRfromGoogle;[代码][代码] [代码][代码]chl = URLencode(chl);[代码][代码] [代码][代码]QRfromGoogle = [代码][代码]"http://chart.apis.google.com/chart?chs="[代码] [代码]+ widhtHeight + [代码][代码]"x"[代码] [代码]+ widhtHeight + [代码][代码]"&cht=qr&chld="[代码][代码] [代码][代码]+ EC_level + [代码][代码]"|"[代码] [代码]+ margin + [代码][代码]"&chl="[代码] [代码]+ chl;[代码][代码] [代码][代码]return[代码] [代码]QRfromGoogle;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 时间转换成字符串[代码][代码] [代码][代码]* @param date 时间[代码][代码] [代码][代码]* @param formatType 格式化类型[代码][代码] [代码][代码]* @return String[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String date2String(Date date, String formatType) {[代码][代码] [代码][代码]SimpleDateFormat sdf = [代码][代码]new[代码] [代码]SimpleDateFormat(formatType);[代码][代码] [代码][代码]return[代码] [代码]sdf.format(date);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getNonceStr() {[代码][代码] [代码][代码]Random random = [代码][代码]new[代码] [代码]Random();[代码][代码] [代码][代码]return[代码] [代码]MD5Utils.MD5Encode(String.valueOf(random.nextInt([代码][代码]10000[代码][代码])), [代码][代码]"UTF-8"[代码][代码]);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 创建签名SHA1[代码][代码] [代码][代码]* @param signParams[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]* @throws Exception[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String createSHA1Sign(SortedMap<String, String> signParams) [代码][代码]throws[代码] [代码]Exception {[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]Set es = signParams.entrySet();[代码][代码] [代码][代码]Iterator it = es.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Map.Entry entry = (Map.Entry) it.next();[代码][代码] [代码][代码]String k = (String) entry.getKey();[代码][代码] [代码][代码]String v = (String) entry.getValue();[代码][代码] [代码][代码]sb.append(k + [代码][代码]"="[代码] [代码]+ v + [代码][代码]"&"[代码][代码]);[代码][代码] [代码][代码]// 要采用URLENCODER的原始值![代码][代码] [代码][代码]}[代码][代码] [代码][代码]String params = sb.substring([代码][代码]0[代码][代码], sb.lastIndexOf([代码][代码]"&"[代码][代码]));[代码][代码] [代码][代码]return[代码] [代码]getSha1(params);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* Sha1签名[代码][代码] [代码][代码]* @param str[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getSha1(String str) {[代码][代码] [代码][代码]if[代码] [代码](str == [代码][代码]null[代码] [代码]|| str.length() == [代码][代码]0[代码][代码]) {[代码][代码] [代码][代码]return[代码] [代码]null[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]char[代码] [代码]hexDigits[] = { [代码][代码]'0'[代码][代码], [代码][代码]'1'[代码][代码], [代码][代码]'2'[代码][代码], [代码][代码]'3'[代码][代码], [代码][代码]'4'[代码][代码], [代码][代码]'5'[代码][代码], [代码][代码]'6'[代码][代码], [代码][代码]'7'[代码][代码], [代码][代码]'8'[代码][代码], [代码][代码]'9'[代码][代码], [代码][代码]'a'[代码][代码], [代码][代码]'b'[代码][代码], [代码][代码]'c'[代码][代码], [代码][代码]'d'[代码][代码], [代码][代码]'e'[代码][代码], [代码][代码]'f'[代码] [代码]};[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]MessageDigest mdTemp = MessageDigest.getInstance([代码][代码]"SHA1"[代码][代码]);[代码][代码] [代码][代码]mdTemp.update(str.getBytes([代码][代码]"UTF-8"[代码][代码]));[代码] [代码] [代码][代码]byte[代码][代码][] md = mdTemp.digest();[代码][代码] [代码][代码]int[代码] [代码]j = md.length;[代码][代码] [代码][代码]char[代码] [代码]buf[] = [代码][代码]new[代码] [代码]char[代码][代码][j * [代码][代码]2[代码][代码]];[代码][代码] [代码][代码]int[代码] [代码]k = [代码][代码]0[代码][代码];[代码][代码] [代码][代码]for[代码] [代码]([代码][代码]int[代码] [代码]i = [代码][代码]0[代码][代码]; i < j; i++) {[代码][代码] [代码][代码]byte[代码] [代码]byte0 = md[i];[代码][代码] [代码][代码]buf[k++] = hexDigits[byte0 >>> [代码][代码]4[代码] [代码]& [代码][代码]0xf[代码][代码]];[代码][代码] [代码][代码]buf[k++] = hexDigits[byte0 & [代码][代码]0xf[代码][代码]];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]new[代码] [代码]String(buf);[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]return[代码] [代码]null[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获得预支付订单号[代码][代码] [代码][代码]* @param url[代码][代码] [代码][代码]* @param xmlParam[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getPayNo(String url, String xmlParam) {[代码][代码] [代码][代码]String prepay_id = [代码][代码]""[代码][代码];[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]String jsonStr = postWithXmlParams(url, xmlParam);[代码][代码] [代码][代码]if[代码] [代码](jsonStr.indexOf([代码][代码]"FAIL"[代码][代码]) != -[代码][代码]1[代码][代码]) {[代码][代码] [代码][代码]return[代码] [代码]prepay_id;[代码][代码] [代码][代码]}[代码][代码] [代码][代码]Map<String, Object> map = doXMLParse(jsonStr);[代码][代码] [代码][代码]prepay_id = (String) map.get([代码][代码]"prepay_id"[代码][代码]);[代码][代码] [代码][代码]System.out.println([代码][代码]"prepay_id:"[代码] [代码]+ prepay_id);[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]prepay_id;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 发送请求[代码][代码] [代码][代码]* @param url 请求路径[代码][代码] [代码][代码]* @param xmlParams xml字符串[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String postWithXmlParams(String url, String xmlParams) {[代码][代码] [代码][代码]HttpPost httpost = HttpClientConnectionManager.getPostMethod(url);[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]httpost.setEntity([代码][代码]new[代码] [代码]StringEntity(xmlParams, [代码][代码]"UTF-8"[代码][代码]));[代码][代码] [代码][代码]HttpResponse response = httpclient.execute(httpost);[代码][代码] [代码][代码]return[代码] [代码]EntityUtils.toString(response.getEntity(), [代码][代码]"UTF-8"[代码][代码]);[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]return[代码] [代码]""[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。[代码][代码] [代码][代码]* @param strxml[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]* @throws JDOMException[代码][代码] [代码][代码]* @throws IOException[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]Map doXMLParse(String strxml) [代码][代码]throws[代码] [代码]Exception {[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]== strxml || [代码][代码]""[代码][代码].equals(strxml)) {[代码][代码] [代码][代码]return[代码] [代码]null[代码][代码];[代码][代码] [代码][代码]}[代码][代码] [代码][代码]Map m = [代码][代码]new[代码] [代码]HashMap();[代码][代码] [代码][代码]InputStream in = String2Inputstream(strxml);[代码][代码] [代码][代码]SAXBuilder builder = [代码][代码]new[代码] [代码]SAXBuilder();[代码][代码] [代码][代码]Document doc = builder.build(in);[代码][代码] [代码][代码]Element root = doc.getRootElement();[代码][代码] [代码][代码]List list = root.getChildren();[代码][代码] [代码][代码]Iterator it = list.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Element e = (Element) it.next();[代码][代码] [代码][代码]String k = e.getName();[代码][代码] [代码][代码]String v = [代码][代码]""[代码][代码];[代码][代码] [代码][代码]List children = e.getChildren();[代码][代码] [代码][代码]if[代码] [代码](children.isEmpty()) {[代码][代码] [代码][代码]v = e.getTextNormalize();[代码][代码] [代码][代码]} [代码][代码]else[代码] [代码]{[代码][代码] [代码][代码]v = getChildrenText(children);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]m.put(k, v);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]// 关闭流[代码][代码] [代码][代码]in.close();[代码][代码] [代码][代码]return[代码] [代码]m;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取子结点的xml[代码][代码] [代码][代码]* @param children[代码][代码] [代码][代码]* @return String[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String getChildrenText(List children) {[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]if[代码] [代码](!children.isEmpty()) {[代码][代码] [代码][代码]Iterator it = children.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Element e = (Element) it.next();[代码][代码] [代码][代码]String name = e.getName();[代码][代码] [代码][代码]String value = e.getTextNormalize();[代码][代码] [代码][代码]List list = e.getChildren();[代码][代码] [代码][代码]sb.append([代码][代码]"<"[代码] [代码]+ name + [代码][代码]">"[代码][代码]);[代码][代码] [代码][代码]if[代码] [代码](!list.isEmpty()) {[代码][代码] [代码][代码]sb.append(getChildrenText(list));[代码][代码] [代码][代码]}[代码][代码] [代码][代码]sb.append(value);[代码][代码] [代码][代码]sb.append([代码][代码]"</"[代码] [代码]+ name + [代码][代码]">"[代码][代码]);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]sb.toString();[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]InputStream String2Inputstream(String str) {[代码][代码] [代码][代码]return[代码] [代码]new[代码] [代码]ByteArrayInputStream(str.getBytes());[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]public[代码] [代码]String getParameter(String parameter) {[代码][代码] [代码][代码]String s = (String) [代码][代码]this[代码][代码].parameters.get(parameter);[代码][代码] [代码][代码]return[代码] [代码]([代码][代码]null[代码] [代码]== s) ? [代码][代码]""[代码] [代码]: s;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 特殊字符处理[代码][代码] [代码][代码]* @param src[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]* @throws UnsupportedEncodingException[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]String UrlEncode(String src) [代码][代码]throws[代码] [代码]UnsupportedEncodingException {[代码][代码] [代码][代码]return[代码] [代码]URLEncoder.encode(src, [代码][代码]"UTF-8"[代码][代码]).replace([代码][代码]"+"[代码][代码], [代码][代码]"%20"[代码][代码]);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 获取package的签名包[代码][代码] [代码][代码]* @param packageParams[代码][代码] [代码][代码]* @param key[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]* @throws UnsupportedEncodingException[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]String genPackage(SortedMap<String, String> packageParams, String key) [代码][代码]throws[代码] [代码]UnsupportedEncodingException {[代码][代码] [代码][代码]String sign = createSign(packageParams, key);[代码] [代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]Set es = packageParams.entrySet();[代码][代码] [代码][代码]Iterator it = es.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Map.Entry entry = (Map.Entry) it.next();[代码][代码] [代码][代码]String k = (String) entry.getKey();[代码][代码] [代码][代码]String v = (String) entry.getValue();[代码][代码] [代码][代码]sb.append(k + [代码][代码]"="[代码] [代码]+ UrlEncode(v) + [代码][代码]"&"[代码][代码]);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]// 去掉最后一个&[代码][代码] [代码][代码]String packageValue = sb.append([代码][代码]"sign="[代码] [代码]+ sign).toString();[代码][代码] [代码][代码]return[代码] [代码]packageValue;[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]String createSign(SortedMap<String, String> packageParams, String key) {[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]Set es = packageParams.entrySet();[代码][代码] [代码][代码]Iterator it = es.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Map.Entry entry = (Map.Entry) it.next();[代码][代码] [代码][代码]String k = (String) entry.getKey();[代码][代码] [代码][代码]String v = (String) entry.getValue();[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]!= v && ![代码][代码]""[代码][代码].equals(v) && ![代码][代码]"sign"[代码][代码].equals(k) && ![代码][代码]"key"[代码][代码].equals(k)) {[代码][代码] [代码][代码]sb.append(k + [代码][代码]"="[代码] [代码]+ v + [代码][代码]"&"[代码][代码]);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]sb.append([代码][代码]"key="[代码] [代码]+ key);[代码][代码] [代码][代码]System.out.println([代码][代码]"md5:"[代码] [代码]+ sb.toString());[代码][代码] [代码][代码]String sign = MD5Utils.MD5Encode(sb.toString(), [代码][代码]"UTF-8"[代码][代码]).toUpperCase();[代码][代码] [代码][代码]System.out.println([代码][代码]"packge签名:"[代码] [代码]+ sign);[代码][代码] [代码][代码]return[代码] [代码]sign;[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 创建package签名[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]boolean[代码] [代码]createMd5Sign(String signParams) {[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]Set es = [代码][代码]this[代码][代码].parameters.entrySet();[代码][代码] [代码][代码]Iterator it = es.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Map.Entry entry = (Map.Entry) it.next();[代码][代码] [代码][代码]String k = (String) entry.getKey();[代码][代码] [代码][代码]String v = (String) entry.getValue();[代码][代码] [代码][代码]if[代码] [代码](![代码][代码]"sign"[代码][代码].equals(k) && [代码][代码]null[代码] [代码]!= v && ![代码][代码]""[代码][代码].equals(v)) {[代码][代码] [代码][代码]sb.append(k + [代码][代码]"="[代码] [代码]+ v + [代码][代码]"&"[代码][代码]);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]// 算出摘要[代码][代码] [代码][代码]String sign = MD5Utils.MD5Encode(sb.toString(), [代码][代码]"utf-8"[代码][代码]).toLowerCase();[代码][代码] [代码][代码]String paySign = [代码][代码]this[代码][代码].getParameter([代码][代码]"sign"[代码][代码]).toLowerCase();[代码][代码] [代码][代码]return[代码] [代码]paySign.equals(sign);[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 输出XML[代码][代码] [代码][代码]* @return[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]public[代码] [代码]String parseXML() {[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]sb.append([代码][代码]"<xml>"[代码][代码]);[代码][代码] [代码][代码]Set es = [代码][代码]this[代码][代码].parameters.entrySet();[代码][代码] [代码][代码]Iterator it = es.iterator();[代码][代码] [代码][代码]while[代码] [代码](it.hasNext()) {[代码][代码] [代码][代码]Map.Entry entry = (Map.Entry) it.next();[代码][代码] [代码][代码]String k = (String) entry.getKey();[代码][代码] [代码][代码]String v = (String) entry.getValue();[代码][代码] [代码][代码]if[代码] [代码]([代码][代码]null[代码] [代码]!= v && ![代码][代码]""[代码][代码].equals(v) && ![代码][代码]"appkey"[代码][代码].equals(k)) {[代码] [代码] [代码][代码]sb.append([代码][代码]"<"[代码] [代码]+ k + [代码][代码]">"[代码] [代码]+ getParameter(k) + [代码][代码]"</"[代码] [代码]+ k + [代码][代码]">\n"[代码][代码]);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]sb.append([代码][代码]"</xml>"[代码][代码]);[代码][代码] [代码][代码]return[代码] [代码]sb.toString();[代码][代码] [代码][代码]}[代码][代码] [代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]String post(String url, String xmlParam){[代码][代码] [代码][代码]StringBuilder sb = [代码][代码]new[代码] [代码]StringBuilder();[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]KeyStore keyStore = KeyStore.getInstance([代码][代码]"PKCS12"[代码][代码]);[代码][代码] [代码][代码]FileInputStream instream = [代码][代码]new[代码] [代码]FileInputStream([代码][代码]new[代码] [代码]File(PayApi.[代码][代码]class[代码][代码].getClassLoader().getResource([代码][代码]"apiclient_cert.p12"[代码][代码]).getPath()));[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]keyStore.load(instream, [代码][代码]"1344023801"[代码][代码].toCharArray());[代码][代码] [代码][代码]} [代码][代码]finally[代码] [代码]{[代码][代码] [代码][代码]instream.close();[代码][代码] [代码][代码]}[代码][代码] [代码] [代码] [代码][代码]// 证书[代码][代码] [代码][代码]SSLContext sslcontext = SSLContexts.custom()[代码][代码] [代码][代码].loadKeyMaterial(keyStore, [代码][代码]"1344023801"[代码][代码].toCharArray())[代码][代码] [代码][代码].build();[代码][代码] [代码][代码]// 只允许TLSv1协议[代码][代码] [代码][代码]SSLConnectionSocketFactory sslsf = [代码][代码]new[代码] [代码]SSLConnectionSocketFactory([代码][代码] [代码][代码]sslcontext,[代码][代码] [代码][代码]new[代码] [代码]String[] { [代码][代码]"TLSv1"[代码] [代码]},[代码][代码] [代码][代码]null[代码][代码],[代码][代码] [代码][代码]SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);[代码][代码] [代码][代码]//创建基于证书的httpClient,后面要用到[代码][代码] [代码][代码]CloseableHttpClient client = HttpClients.custom()[代码][代码] [代码][代码].setSSLSocketFactory(sslsf)[代码][代码] [代码][代码].build();[代码][代码] [代码] [代码] [代码][代码]HttpPost httpPost = [代码][代码]new[代码] [代码]HttpPost(url);[代码][代码]//退款接口[代码][代码] [代码][代码]StringEntity reqEntity = [代码][代码]new[代码] [代码]StringEntity(xmlParam);[代码][代码] [代码][代码]// 设置类型 [代码][代码] [代码][代码]reqEntity.setContentType([代码][代码]"application/x-www-form-urlencoded"[代码][代码]); [代码][代码] [代码][代码]httpPost.setEntity(reqEntity);[代码][代码] [代码][代码]CloseableHttpResponse response = client.execute(httpPost);[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]HttpEntity entity = response.getEntity();[代码][代码] [代码][代码]System.out.println(response.getStatusLine());[代码][代码] [代码][代码]if[代码] [代码](entity != [代码][代码]null[代码][代码]) {[代码][代码] [代码][代码]BufferedReader bufferedReader = [代码][代码]new[代码] [代码]BufferedReader([代码][代码]new[代码] [代码]InputStreamReader(entity.getContent(),[代码][代码]"UTF-8"[代码][代码]));[代码][代码] [代码][代码]String text=[代码][代码]""[代码][代码];[代码][代码] [代码][代码]while[代码] [代码]((text = bufferedReader.readLine()) != [代码][代码]null[代码][代码]) {[代码][代码] [代码][代码]sb.append(text);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]EntityUtils.consume(entity);[代码][代码] [代码][代码]} [代码][代码]catch[代码][代码](Exception e){[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码][代码]finally[代码] [代码]{[代码][代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]response.close();[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](IOException e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码][代码]finally[代码] [代码]{[代码][代码] [代码][代码]httpclient.close();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]return[代码] [代码]sb.toString();[代码][代码] [代码][代码]}[代码][代码]}[代码]