微信扣款和退款

扣款接口实现
/**
 * @param :out_trade_no-订单号;total_fee-订单总金额;contract_id-签约成功后,微信返回的委托代扣协议id
 * @Author : lilong
 * @Description :微信支付扣款
 * @Date : 11:16 2018/5/4
 **/
public void wxDeductMoney(String out_trade_no, Integer total_fee, String contract_id) throws Exception {
    //扣款请求的参数集合
    Map<String, String> map = new HashMap<>();
    //签名所需要的参数
    //生成随机数
    String nonce_str = getNonce();
    String body = "HH";
    String detail = "HH";
    String attach = "666";
    String fee_type = "CNY";
    String spbill_create_ip = "192.168.1.1";
    String goods_tag = "WXG";
    String notify_url = "http://www.sz.cn/mvc/wechat/callbackDeductMoney";//回调
    //交易类型---微信委托代扣支付
    String trade_type = "PAP";
    map.put("appid", appid);
    map.put("mch_id", mch_id);
    map.put("nonce_str", nonce_str);
    map.put("body", body);
    map.put("detail", detail);
    map.put("attach", attach);
    map.put("out_trade_no", out_trade_no);
    map.put("total_fee", total_fee.toString());
    map.put("fee_type", fee_type);
    map.put("spbill_create_ip", spbill_create_ip);
    map.put("goods_tag", goods_tag);
    map.put("notify_url", notify_url);
    map.put("trade_type", trade_type);
    map.put("contract_id", contract_id);
    String sign = createSign(map);
    map.put("sign", sign);
    //map 转 xml
    String xmlParams = mapToXml(map);
    String url = "https://api.mch.weixin.qq.com/pay/pappayapply";
    HttpPost post = new HttpPost(url);
    //设置请求头  设置参数格式
    post.setHeader("Content-type", "text/xml; charset=utf-8");
    //表明请求身份----模拟浏览器
    post.setHeader("User-Agent", "Firefox/6.0.2");
    HttpClient client = HttpClients.createDefault();
    post.setEntity(new StringEntity(xmlParams, "UTF-8"));
    HttpResponse response = client.execute(post);
    HttpEntity entity = response.getEntity();
    String result = EntityUtils.toString(entity, "UTF-8");
    System.err.println(扣款返回结果:" + result);
}
支付成功之后返回一下结果

扣款测试:<xml><return_code><![CDATA[SUCCESS]]></return_code>
                <return_msg><![CDATA[OK]]></return_msg>
                <appid><![CDATA[wx05c902527492c474]]></appid>
                <mch_id><![CDATA[1484707102]]></mch_id>
                <nonce_str><![CDATA[mZj50pMP5ucB2F8z]]></nonce_str>
                <sign><![CDATA[E95D4DDC08E67351C1C91D3719F1B8A1]]></sign>
                <result_code><![CDATA[SUCCESS]]></result_code>
                </xml>

将map转化为xml
/**
 * @Author : lilong
 * @Description :map 转 xml
 * @Date : 15:45 2018/5/4
 **/
public String mapToXml(Map<String, String> map) throws Exception {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    org.w3c.dom.Document document = documentBuilder.newDocument();
    org.w3c.dom.Element element = document.createElement("xml");
    document.appendChild(element);
    for (String key : map.keySet()) {
        String value = map.get(key);
        if (value == null) {
            value = "";
        }
        value = value.trim();
        org.w3c.dom.Element filed = document.createElement(key);
        filed.appendChild(document.createTextNode(value));
        element.appendChild(filed);
    }
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    DOMSource source = new DOMSource(document);
    transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    StringWriter write = new StringWriter();
    StreamResult result = new StreamResult(write);
    transformer.transform(source, result);
    String output = write.getBuffer().toString();////.replaceAll("\n|\r", "");
    try {
        write.close();
    } catch (Exception e) {

    }
    return output;
}
退款---退款是需要下载证书并处理
/**
 * @param :out_trade_no:商户订单号 out_refund_no:商户退款单号  total_fee:订单金额  refund_fee:退款金额
 * @Author : lilong
 * @Description :微信退款
 * @Date : 14:44 2018/6/11
 **/
public void weChatRefund(String out_trade_no, String out_refund_no, Integer total_fee, Integer refund_fee) throws Exception {
    //扣款请求的参数集合
    Map<String, String> map = new HashMap<>();
    //签名所需要的参数
    //生成随机数
    String nonce_str = getNonce();
    map.put("appid", appid);
    map.put("mch_id", mch_id);
    map.put("nonce_str", nonce_str);
    //商户订单号
    map.put("out_trade_no", out_trade_no);
    //商户退款单号
    map.put("out_refund_no", out_refund_no);
    map.put("total_fee", total_fee.toString());
    map.put("refund_fee", refund_fee.toString());
    String sign = createSign(map);
    map.put("sign", sign);
    //map 转 xml
    String xmlParams = mapToXml(map);
    //证书
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    FileInputStream instream = new FileInputStream(new File("D:/cert/apiclient_cert.p12"));//退款证书的路径
    try {
        keyStore.load(instream, mch_id.toCharArray());
    } finally {
        instream.close();
    }

    SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
    SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslcontext);
    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslf).build();

    try {

        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");//退款接口

        System.out.println("executing request" + httpPost.getRequestLine());
        StringEntity reqEntity = new StringEntity(xmlParams);
        // 设置类型
        reqEntity.setContentType("application/x-www-form-urlencoded");
        httpPost.setEntity(reqEntity);
        CloseableHttpResponse response = httpclient.execute(httpPost);
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                String line;
                String xmlParam = "";
                while ((line = bufferedReader.readLine()) != null) {
                    xmlParam += line;
                }
                Map<String, String> returnMap = xmlToMap(xmlParam);
                //判断退款状态修改订单状态
                if ("SUCCESS".equals(returnMap.get("return_code"))) {
                    if ("SUCCESS".equals(returnMap.get("result_code"))) {
                        String orderid = returnMap.get("out_trade_no");
                        HahaCounterOrder hahaCounterOrder  = hahaCountMng.getHahaCounterOrdersById(orderid);
                        hahaCounterOrder.setPaymentStatus("ReFund");
                        hahaCountMng.updateOrderCounter(hahaCounterOrder);
                    }
                }
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}
退款之后的返回结果如下,拿到结果之后处理相关逻辑即可。
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx05c902527492c474]]></appid>
<mch_id><![CDATA[1484707102]]></mch_id>
<nonce_str><![CDATA[7EvqWpL2hrRB0c4P]]></nonce_str>
<sign><![CDATA[2F25E9F1DD8268358E1A158C267715D6]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[4200000110201806087283568184]]></transaction_id>
<out_trade_no><![CDATA[201806075802722891]]></out_trade_no>
<out_refund_no><![CDATA[201806075802722891]]></out_refund_no>
<refund_id><![CDATA[50000006902018061205029257575]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>1</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>1</total_fee>
<cash_fee>1</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>1</cash_refund_fee>

</xml>

值得注意的是:退款缺少证书是会报以下异常-->

wx sendpost exception  
org.apache.http.NoHttpResponseException: api.mch.weixin.qq.com:443 failed to respond



猜你喜欢

转载自blog.csdn.net/qq_19167629/article/details/80668801