前言:以前接APP支付,微信遇到了一點點坑,爲了方便之後copy,把以前寫的代碼粘貼出來。須要的同窗能夠參考一下,具體參數說明還請詳細查看官方文檔:php
支付寶回調參數說明:https://doc.open.alipay.com/docs/doc.htm?treeId=193&articleId=105301&docType=1java
微信支付回調參數:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3git
1.0 導入xml支持算法
<!--XML支持--> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.7</version> </dependency> <dependency> <groupId>org.jdom</groupId> <artifactId>jdom2</artifactId> <version>2.0.6</version> </dependency> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>
1.1 微信統一下單apache
/** * 統一下單 * * @param orderSn * @param totalFee * @param spBillCreateIP * @return */ public static Map<Object, Object> sendWxPayRequest(String orderSn, String totalFee, String spBillCreateIP) { //簽名 SortedMap<Object, Object> parameters = new TreeMap<>(); parameters.put("appid", Constant.APPID); parameters.put("body", Constant.ORDER_NAME); parameters.put("mch_id", Constant.MCH_ID); parameters.put("nonce_str", String.valueOf(new Date().getTime())); parameters.put("notify_url", Constant.CONFIGMAP.get("weixin.asynchronousNotifyUrl")); parameters.put("out_trade_no", orderSn); parameters.put("spbill_create_ip", spBillCreateIP); parameters.put("total_fee", totalFee); parameters.put("trade_type", "APP"); String sign = createSign("utf-8", parameters); //請求xml參數 StringBuffer requestStr = new StringBuffer("<xml>"); requestStr.append("<appid><![CDATA["); requestStr.append(parameters.get("appid")); requestStr.append("]]></appid>"); requestStr.append("<body><![CDATA["); requestStr.append(parameters.get("body")); requestStr.append("]]></body>"); requestStr.append("<mch_id><![CDATA["); requestStr.append(parameters.get("mch_id")); requestStr.append("]]></mch_id>"); requestStr.append("<nonce_str><![CDATA["); requestStr.append(parameters.get("nonce_str")); requestStr.append("]]></nonce_str>"); requestStr.append("<notify_url><![CDATA["); requestStr.append(parameters.get("notify_url")); requestStr.append("]]></notify_url>"); requestStr.append("<out_trade_no><![CDATA["); requestStr.append(parameters.get("out_trade_no")); requestStr.append("]]></out_trade_no>"); requestStr.append("<spbill_create_ip><![CDATA["); requestStr.append(parameters.get("spbill_create_ip")); requestStr.append("]]></spbill_create_ip>"); requestStr.append("<total_fee><![CDATA["); requestStr.append(parameters.get("total_fee")); requestStr.append("]]></total_fee>"); requestStr.append("<trade_type><![CDATA["); requestStr.append(parameters.get("trade_type")); requestStr.append("]]></trade_type>"); requestStr.append("<sign><![CDATA["); requestStr.append(sign); requestStr.append("]]></sign>"); requestStr.append("</xml>"); try { String body = HttpUtil.post(Constant.ORDER_URL, requestStr.toString()); String resultStr = new String(body.getBytes("ISO-8859-1"), "utf-8"); SortedMap<Object, Object> resultMap = XMLUtil.doXMLParse(resultStr); logger.info("微信統一下單響應參數= {}", JSON.toJSON(resultMap)); if (Constant.SUCCESS.equals(resultMap.get("result_code"))) { String package1 = "Sign=WXPay"; SortedMap<Object, Object> payParameters = new TreeMap<>(); payParameters.put("appid", Constant.APPID); payParameters.put("partnerid", Constant.MCH_ID); payParameters.put("prepayid", resultMap.get("prepay_id")); payParameters.put("package", package1); payParameters.put("noncestr", String.valueOf(new Date().getTime())); payParameters.put("timestamp", new Date().getTime() / 1000); String paySign = SignUtil.createSign("utf-8", payParameters); payParameters.put("sign", paySign.toUpperCase()); return payParameters; } else { logger.warn("微信統一下單錯誤:{}", JSON.toJSON(resultMap)); } return null; } catch (Exception ex) { logger.warn("微信統一下單異常 ex:", ex); } return null; }
1.2 XmlUtil代碼json
package com.wangnian.util.wechat.pay; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; public class XmlUtil { /** * 解析xml,返回第一級元素鍵值對。若是第一級元素有子節點,則此節點的值是子節點的xml數據。 * * @param strxml * @return * @throws JDOMException * @throws IOException */ public static SortedMap<Object, Object> doXMLParse(String strxml) throws JDOMException, IOException { if (null == strxml || "".equals(strxml)) { return null; } SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); 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 = XMLUtil.getChildrenText(children); } parameters.put(k, v); } //關閉流 in.close(); return parameters; } /** * 獲取子結點的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(XMLUtil.getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } /** * 獲取xml編碼字符集 * * @param strxml * @return * @throws IOException * @throws JDOMException */ public static String getXMLEncoding(String strxml) throws JDOMException, IOException { InputStream in = String2Inputstream(strxml); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(in); in.close(); return (String) doc.getProperty("encoding"); } public static InputStream String2Inputstream(String str) { return new ByteArrayInputStream(str.getBytes()); } }
1.3 SignUtil代碼api
package com.wangnian.util.wechat.pay; import com.wangnian.api.config.Constant; import java.security.MessageDigest; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.logging.Logger; /** * Created by http://my.oschina.net/wangnian on 2016/7/27. */ public class SignUtil { /** * 微信支付簽名算法sign * * @param characterEncoding * @param parameters * @return */ public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) { 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=" + Constant.WEIXIN_KEY); String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) resultSb.append(byteToHexString(b[i])); return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n += 256; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) resultString = byteArrayToHexString(md.digest(resultString .getBytes())); else resultString = byteArrayToHexString(md.digest(resultString .getBytes(charsetname))); } catch (Exception exception) { } return resultString; } private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; public static String resultSuccess() { return "<xml>\n" + " <return_code><![CDATA[SUCCESS]]></return_code>\n" + " <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>"; } }
1.4 微信通知回調微信
/** * 微信回調地址 * * @param request * @return */ @RequestMapping(value = "/weixin/asynchronousNotify", method = RequestMethod.POST) public String wexinNotify(HttpServletRequest request) { try { InputStream inStream = request.getInputStream(); ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); String resultStr = new String(outSteam.toByteArray(), "utf-8"); SortedMap<String, String> resultMap = XmlUtil.doXMLParse(resultStr);//將xml轉成排序以後的map logger.info("微信支付回調地址請求參數=requst:{}", JSON.toJSON(resultMap)); String result_code = resultMap.get("result_code");//業務結果 String is_subscribe = resultMap.get("is_subscribe");//是否關注了微信公衆號 String out_trade_no = resultMap.get("out_trade_no");//訂單號 String transaction_id = resultMap.get("transaction_id");//微信支付訂單號 相似於支付寶的交易號 String sign = resultMap.get("sign");//簽名 String total_fee = resultMap.get("total_fee");//訂單總金額 單位爲 分 String openid = resultMap.get("openid");//用戶在商戶appid下的惟一標識 String time_end = resultMap.get("time_end"); String bank_type = resultMap.get("bank_type"); //簽名驗證 String signStr = SignUtil.createSign("UTF-8", resultMap); logger.warn("驗證= signStr:{},sign:{}", signStr, sign); if (!signStr.equals(sign)) { logger.warn("微信支付回調地址請求參數簽名驗證失敗= signStr:{},sign:{}", signStr, sign); mailTools.SendMail("微信支付回調地址請求參數簽名驗證失敗", "signStr:" + signStr + ",sign:" + sign, null); return "error"; } if (result_code.equals("SUCCESS")) { logger.info("支付成功= 訂單號:{},交易號:{}", out_trade_no, transaction_id); BigDecimal bigDecimal_total_fee = new BigDecimal(total_fee); BigDecimal bigDecimal = bigDecimal_total_fee.divide(new BigDecimal(100)); //TODO 支付成功處理業務邏輯 } //通知微信.異步確認成功.必寫.否則會一直通知後臺.八次以後就認爲交易失敗了. return WeixinUtil.resultSuccess(); } catch (Exception ex) { logger.warn("微信支付回調地址處理異常:{}", ex); mailTools.SendMail("環境異常,微信支付回調地址處理異常", "異常", ex); ex.printStackTrace(); } return "success"; }
1.5 httpUtil代碼app
package com.wangnian.util.net; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; 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.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.security.KeyStore; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; /** * Http工具類 * Created by wangnian on 2016/6/2. */ public class HttpUtil { private static Logger logger = LoggerFactory.getLogger(HttpUtil.class); /** * get請求 * * @param url * @return */ public static String get(String url) { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpget = new HttpGet(url); try { CloseableHttpResponse response = httpClient.execute(httpget); HttpEntity httpEntity = response.getEntity(); String strResult = EntityUtils.toString(httpEntity); logger.debug("url:{},response:{}", url, strResult); return strResult; } catch (Exception ex) { logger.warn("excption:{}", ex); } finally { httpget.releaseConnection(); try { httpClient.close(); } catch (IOException e) { logger.error("httpclient.close() Failure :{} " + e); } } return null; } /** * 帶參數的get請求 * * @param url * @param parMap * @return */ public static String get(String url, Map<String, String> parMap) { String body = null; HttpClientBuilder httpclientBuilder = HttpClientBuilder.create(); CloseableHttpClient httpclient = httpclientBuilder.build(); HttpGet httpget = new HttpGet(url); List<NameValuePair> nvps = new ArrayList<>(); Set<Map.Entry<String, String>> paramsEntry = parMap.entrySet(); for (Map.Entry<String, String> paramEntry : paramsEntry) { nvps.add(new BasicNameValuePair(paramEntry.getKey(), paramEntry.getValue())); } try { String str = EntityUtils.toString(new UrlEncodedFormEntity(nvps, "UTF-8")); httpget.setURI(new URI(httpget.getURI().toString() + "?" + str)); CloseableHttpResponse response = httpclient.execute(httpget); try { logger.debug("http get status is : {}", response.getStatusLine());//狀態碼,通常狀態碼爲200時,爲正常狀態 HttpEntity entity = response.getEntity(); body = EntityUtils.toString(entity, "UTF-8"); EntityUtils.consume(entity); } finally { response.close(); } } catch (Exception e) { logger.info("Http Get Method Failure : {}", e); } finally { httpget.releaseConnection(); try { httpclient.close(); } catch (IOException e) { logger.error("httpclient.close() Failure :{} " + e); } } logger.info("response body : {}", body); return body; } /** * 帶參數post請求 * * @param url * @return */ public static String post(String url, Map<String, String> map) { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpost = new HttpPost(url); if (map != null) { List<NameValuePair> nvps = new ArrayList<>(); for (String key : map.keySet()) { nvps.add(new BasicNameValuePair(key, map.get(key))); } httpost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); } try { CloseableHttpResponse response = httpClient.execute(httpost); String strResult = EntityUtils.toString(response.getEntity()); logger.debug("url:{} ,map:{},response:{}", url, map, strResult); return strResult; } catch (Exception ex) { logger.warn("excption:{}", ex); } finally { httpost.releaseConnection(); try { httpClient.close(); } catch (IOException e) { logger.error("httpclient.close() Failure :{} " + e); } } return null; } /** * RAW Post請求 * * @param url * @param Body * @return * @throws UnsupportedEncodingException */ public static String post(String url, String Body) { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpost = new HttpPost(url); httpost.setEntity(new StringEntity(Body, Consts.UTF_8)); try { CloseableHttpResponse response = httpClient.execute(httpost); String strResult = EntityUtils.toString(response.getEntity()); logger.debug("url:{} ,Body:{},response:{}", url, Body, strResult); return strResult; } catch (Exception ex) { logger.warn("excption:{}", ex); } finally { httpost.releaseConnection(); try { httpClient.close(); } catch (IOException e) { logger.error("httpclient.close() Failure :{} " + e); } } return null; } /** * 微信API請求 (帶證書) * * @param url * @param Body * @return * @throws UnsupportedEncodingException */ public static String weixinApipost(String url, String Body) { HttpPost httpost = null; CloseableHttpClient httpClient = null; try { KeyStore keyStore = KeyStore.getInstance("PKCS12"); FileInputStream instream = new FileInputStream(new File("C:/Users/Administrator/Desktop/apiclient_cert.p12")); try { keyStore.load(instream, "1370249302".toCharArray()); } finally { instream.close(); } SSLContext sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore, "1370249302".toCharArray()) .build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpClient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); httpost = new HttpPost(url); httpost.setEntity(new StringEntity(Body, Consts.UTF_8)); CloseableHttpResponse response = httpClient.execute(httpost); String strResult = EntityUtils.toString(response.getEntity()); logger.debug("url:{} ,Body:{},response:{}", url, Body, strResult); return strResult; } catch (Exception ex) { logger.warn("excption:{}", ex); } finally { httpost.releaseConnection(); try { httpClient.close(); } catch (IOException e) { logger.error("httpclient.close() Failure :{} " + e); } } return null; } }
2.0 導入支付寶的jar包dom
<!--阿里支付--> <dependency> <groupId>com.alibaba</groupId> <artifactId>alipay</artifactId> <version>20160828220058</version> </dependency>
注意公共的maven裏是沒有這個jar包的,須要本身導入到本身的私服maven裏,或者直接依賴jar包
2.1生成支付寶請求籤名
Map<String, String> map = new HashMap<>(); //實例化客戶端 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", alipay_app_id, APP_PRIVATE_KEY, "json", CHARSET_UTF8, ALIPAY_PUBLIC_KEY, "RSA2"); //實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); //SDK已經封裝掉了公共參數,這裏只須要傳入業務參數。如下方法爲sdk的model入參方式(model和biz_content同時存在的狀況下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setBody(""); model.setSubject(""); model.setOutTradeNo(orderNo); model.setTimeoutExpress("30m"); model.setTotalAmount(orderPrice); model.setProductCode("QUICK_MSECURITY_PAY"); request.setBizModel(model); request.setNotifyUrl(alipayNotifyUrl); try { //這裏和普通的接口調用不一樣,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); map.put("orderString", response.getBody());//就是orderString 能夠直接給客戶端請求,無需再作處理。 } catch (AlipayApiException e) { throw new BusinessException("獲取支付寶參數錯誤"); } return map;
2.2 支付寶通知回調
/** * 支付寶異步的通知 */ @RequestMapping(value = "/alipay/asynchronousNotify", method = RequestMethod.POST) public String alipayNotify(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException { logger.info("支付寶回調地址請求參數=requst:{}", JSON.toJSON(request.getParameterMap())); //獲取支付寶POST過來反饋信息) Map requestParams = request.getParameterMap(); Map<String, String> params = MapConverter.requestParameterMapToHashMap(requestParams); //獲取支付寶POST過來反饋信息) boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ali_public_key, AlipayConfig.input_charset) //調用SDK驗證簽名 if (signVerified) { //按照支付結果異步通知中的描述,對支付結果中的業務內容進行1\2\3\4二次校驗,校驗成功後在response中返回success,校驗失敗返回failure //商戶訂單號 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); //支付寶交易號 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); //交易狀態 String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8"); //支付帳號 String buyer_email = new String(request.getParameter("buyer_email").getBytes("ISO-8859-1"), "UTF-8"); //支付的金額 BigDecimal total_fee = new BigDecimal(request.getParameter("total_fee"));//支付寶原樣返回 1.00 String refund_status = request.getParameter("refund_status");//支付寶退款字段 //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以上僅供參考)// if (trade_status.equals("TRADE_FINISHED")) { logger.info("支付失敗= 訂單號:{},支付寶交易號:{}", out_trade_no, trade_no); } else if (trade_status.equals("TRADE_SUCCESS")) { if (refund_status != null) { logger.info("退款成功= 訂單號:{},支付寶交易號:{}", out_trade_no, trade_no); return "success"; } logger.info("支付成功= 訂單號:{},支付寶交易號:{}", out_trade_no, trade_no); //TODO 支付成功處理業務邏輯,須要注意避免重複處理 } } else { // TODO 驗籤失敗則記錄異常日誌,並在response中返回failure. } return "success"; }
須要導入jar包
package com.wangnian; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradeRefundRequest; import com.alipay.api.response.AlipayTradeRefundResponse; import static com.fengchao.api.config.Constant.RSA_PRIVATE; public class Test { public static void main(String[] args) throws AlipayApiException { // 支付寶的公鑰,調用接口 String ali_public_key = "WIGfMA0GCSqGSIb3DQECAQUAA4GNADCBiQKBGQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB"; AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", "2016062701558376", RSA_PRIVATE, "json", "GBK", ali_public_key); AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); request.setBizContent("{" + " \"out_trade_no\":\"147254841304887\"," + //訂單號 " \"trade_no\":\"2016083021001004360293292481\"," +//交易號 " \"refund_amount\":0.01," +//推薦金額 " \"refund_reason\":\"正常退款\"," +//退款備註 " \"out_request_no\":\"HZ01RF0023\"" +//標識一次退款請求,同一筆交易屢次退款須要保證惟一,如需部分退款,則此參數必傳。 " }"); AlipayTradeRefundResponse response = alipayClient.execute(request); if ("10000".equals(response.getCode())) {//退款成功 @TODO 處理業務 } else { //失敗 response.getCode(); response.getSubCode(); response.getSubMsg(); } } }
package com.wangnian; import com.wangnian.api.config.Constant; import com.wangnian.util.net.HttpUtil; import com.wangnian.util.wechat.pay.XmlUtil; import java.util.Date; import java.util.SortedMap; import java.util.TreeMap; import static com.fengchao.util.wechat.pay.SignUtil.createSign; /** * Created by http://my.oschina.net/wangnian on 2016/8/30. */ public class Test1 { public static void main(String[] args) { //簽名 SortedMap<Object, Object> parameters = new TreeMap<>(); parameters.put("appid", Constant.APPID); parameters.put("mch_id", Constant.MCH_ID); parameters.put("nonce_str", String.valueOf(new Date().getTime())); parameters.put("out_trade_no", "147201368144688");//訂單號 parameters.put("out_refund_no", "1");//退款ID parameters.put("total_fee", "1");//訂單總金額 parameters.put("refund_fee", "1");//訂單退款金額 parameters.put("op_user_id", Constant.MCH_ID);//操做員賬號, 默認爲商戶號 String sign = createSign("utf-8", parameters); //請求xml參數 StringBuffer requestStr = new StringBuffer("<xml>"); requestStr.append("<appid><![CDATA["); requestStr.append(parameters.get("appid")); requestStr.append("]]></appid>"); requestStr.append("<mch_id><![CDATA["); requestStr.append(parameters.get("mch_id")); requestStr.append("]]></mch_id>"); requestStr.append("<nonce_str><![CDATA["); requestStr.append(parameters.get("nonce_str")); requestStr.append("]]></nonce_str>"); requestStr.append("<out_trade_no><![CDATA["); requestStr.append(parameters.get("out_trade_no")); requestStr.append("]]></out_trade_no>"); requestStr.append("<out_refund_no><![CDATA["); requestStr.append(parameters.get("out_refund_no")); requestStr.append("]]></out_refund_no>"); requestStr.append("<total_fee><![CDATA["); requestStr.append(parameters.get("total_fee")); requestStr.append("]]></total_fee>"); requestStr.append("<refund_fee><![CDATA["); requestStr.append(parameters.get("refund_fee")); requestStr.append("]]></refund_fee>"); requestStr.append("<op_user_id><![CDATA["); requestStr.append(parameters.get("op_user_id")); requestStr.append("]]></op_user_id>"); requestStr.append("<sign><![CDATA["); requestStr.append(sign); requestStr.append("]]></sign>"); requestStr.append("</xml>"); try { String body = HttpUtil.weixinApipost(Constant.REFUND_URL, requestStr.toString()); String resultStr = new String(body.getBytes("ISO-8859-1"), "utf-8"); SortedMap<Object, Object> resultMap = XmlUtil.doXMLParse(resultStr); if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) { @TODO 處理業務邏輯 } else { resultMap.get("return_msg"); resultMap.get("err_code_des"); } } catch (Exception ex) { } } }
博客地址:https://my.oschina.net/wangnian