微信退款

对于支付宝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();

    }
   
    
}

如果其中有几个工具类找不到,就在上一篇的微信支付代码中去找吧,在这就不过多的粘贴了

posted on 2017-12-06 16:27  lmcc  阅读(830)  评论(0)    收藏  举报

导航