微信退款
对于支付宝app退款没啥好写的,直接看https://docs.open.alipay.com/api_1/alipay.trade.refund这个,支付宝开发文档给出了具体的demo
下来重点来说微信退款,毕竟感觉微信的开发文档有些懒,不像支付宝开发文档服务的如此周到
1、微信退款是需要证书的,就是这个小东西,我把他直接放到项目中了,如果有好的建议,好朋友们使劲提

下来就开始大片的微信退款代码吧,走起。。。。。。
package com.kpcx.pay.weixin; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.SocketTimeoutException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ResourceBundle; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import javax.net.ssl.SSLContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; 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.config.RequestConfig; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.ConnectionPoolTimeoutException; 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 com.alibaba.fastjson.JSONObject; import com.kpcx.util.RandCharsUtils; import com.kpcx.util.Tool; import com.kpcx.util.WXSignUtils; /** * 微信申请退款接口 * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,调用此接口 */ @WebServlet("/create/WxOrderRefund") public class WxOrderRefund extends HttpServlet { private static final long serialVersionUID = 1L; ResourceBundle bundle = ResourceBundle.getBundle("weixin"); //连接超时时间,默认10秒 private int socketTimeout = 10000; //传输超时时间,默认30秒 private int connectTimeout = 30000; //请求器的配置 private RequestConfig requestConfig; //HTTP请求器 private CloseableHttpClient httpClient; /** * 微信申请退款接口 */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getSession().getServletContext().getRealPath("/"); try { initCert(path); //加载证书 } catch (UnrecoverableKeyException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (KeyManagementException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (KeyStoreException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String param = request.getParameter("param"); JSONObject o = JSONObject.parseObject(param); String out_trade_no = o.getString("out_trade_no"); String refund_desc = o.getString("refund_desc"); String total_fee1=o.getString("total_fee"); String refund_fee1=o.getString("refund_fee"); String out_refund_no = UUID.randomUUID().toString().substring(0, 32);// 退款单号,随机生成 ,但长度应该跟文档一样(32位)(卖家信息校验不一致,请核实后再试) String total_fee = Tool.yuanToFen(total_fee1);//订单的总金额,以分为单位(填错了貌似提示:同一个out_refund_no退款金额要一致) String refund_fee = Tool.yuanToFen(refund_fee1);// 退款金额,以分为单位(填错了貌似提示:同一个out_refund_no退款金额要一致) //随机字符串 String nonce_str = RandCharsUtils.getRandomString(16); //微信公众平台文档:“基本配置”--》“开发者ID” String appid =bundle.getString("appid"); //商户号 //微信公众平台文档:“微信支付”--》“商户信息”--》“商户号”,将该值赋值给partner String mch_id = bundle.getString("mch_id"); // String op_user_id = mch_id;//就是MCHID SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); packageParams.put("appid", appid); packageParams.put("mch_id", mch_id); packageParams.put("nonce_str", nonce_str); packageParams.put("out_trade_no", out_trade_no); packageParams.put("out_refund_no", out_refund_no); packageParams.put("total_fee", total_fee); packageParams.put("refund_fee", refund_fee); if(refund_desc != null && !"".equals(refund_desc)){ packageParams.put("refund_desc", refund_desc); } String sign = WXSignUtils.createSign("UTF-8", packageParams); String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign><![CDATA[" + sign + "]]></sign>" + "<out_trade_no>" + out_trade_no + "</out_trade_no>" + "<out_refund_no>" + out_refund_no + "</out_refund_no>" + "<total_fee>" + total_fee + "</total_fee>" + "<refund_fee>" + refund_fee + "</refund_fee>"; if(refund_desc != null && !"".equals(refund_desc)){ xml += "<refund_desc>" + refund_desc + "</refund_desc>"; } xml += "</xml>"; HttpPost httpPost = new HttpPost(bundle.getString("refundUrl")); //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别 StringEntity postEntity = new StringEntity(xml, "UTF-8"); httpPost.addHeader("Content-Type", "text/xml"); httpPost.setEntity(postEntity); //设置请求器的配置 httpPost.setConfig(requestConfig); String data = ""; try { HttpResponse response1 = httpClient.execute(httpPost); HttpEntity entity = response1.getEntity(); String result = EntityUtils.toString(entity, "UTF-8"); data = Tool.xmlChangeJson(result); } catch (ConnectionPoolTimeoutException e) { } catch (ConnectTimeoutException e) { } catch (SocketTimeoutException e) { } catch (Exception e) { } finally { httpPost.abort(); } JSONObject json = new JSONObject(); JSONObject object = JSONObject.parseObject(data); // 把所有关于金额的字段都转成元为单位 if("SUCCESS".equals(object.getString("return_code"))&&"SUCCESS".equals(object.getString("result_code"))){ object.put("total_fee", Tool.fenToYuan(object.getString("total_fee"))); object.put("refund_fee", Tool.fenToYuan(object.getString("refund_fee"))); object.put("cash_fee", Tool.fenToYuan(object.getString("cash_fee"))); object.put("cash_refund_fee", Tool.fenToYuan(object.getString("cash_refund_fee"))); object.put("coupon_refund_fee", Tool.fenToYuan(object.getString("coupon_refund_fee"))); json.put("Code", "0"); json.put("Result", object); }else{ json.put("Code", "1"); json.put("err_code", object.getString("err_code")); json.put("msg", object.getString("err_code_des")); } response.getWriter().write(json.toString()); //结果返回到filter,记录到日志中 request.setAttribute("outStr", json.toString()); } /** * post方法 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } /** * 加载证书 * @param path * @throws IOException * @throws KeyStoreException * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyManagementException */ private void initCert(String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException { //拼接证书的路径 KeyStore keyStore = KeyStore.getInstance("PKCS12"); //加载本地的证书进行https加密传输 FileInputStream instream = new FileInputStream(new File(path+"/WEB-INF/cert/apiclient_cert.p12")); try { keyStore.load(instream, bundle.getString("mch_id").toCharArray()); //加载证书密码,默认为商户ID } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } finally { instream.close(); } // Trust own CA and all self-signed certs SSLContext sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore, bundle.getString("mch_id").toCharArray()) //加载证书密码,默认为商户ID .build(); // Allow TLSv1 protocol only SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpClient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); //根据默认超时限制初始化requestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build(); } }
如果其中有几个工具类找不到,就在上一篇的微信支付代码中去找吧,在这就不过多的粘贴了
浙公网安备 33010602011771号