1. 程式人生 > >微信服務號開發----公眾號支付退款

微信服務號開發----公眾號支付退款

1、微信支付開發文件

下載地址

微信商戶平臺-》賬戶設定-》 API安全 中下載的

下載之後存放在本地一個英文命名的資料夾下,解壓。

3、證書解壓之後是


4、程式碼

package com.kp.wxpay;

import java.util.SortedMap;
import java.util.TreeMap;




/** 
 * @author: py
 * @version:2017年1月10日 上午11:17:59 
 * @Desc  微信退款 申請以及退款
 * //api地址:http://mch.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
 */
public class WXPayRefundUtil {

	String appid = ""; //微信公眾號apid
	String appsecret = " "; //微信公眾號appsecret
	public static String mch_id = " ";  //微信商戶id
	String op_user_id = " ";//操作員帳號, 預設為商戶號
	String partnerkey = " ";//商戶平臺上的那個KEY
	/**
	 * @date 2017年1月10日上午10:36:50 void
	 * @Des:退款
	 */
	public void wechatRefund() {
		// 商戶系統內部的退款單號,商戶系統內部唯一,同一退款單號多次請求只退一筆
		String out_refund_no = " ";
		String out_trade_no = "256165";// 商戶側傳給微信的訂單號
		String total_fee = "1";// 總金額
		String refund_fee = "1";// 退款金額
		String nonce_str = "20bdx4b25826b";// 隨機字串
		
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		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);
		packageParams.put("op_user_id", op_user_id);

		RequestHandler reqHandler = new RequestHandler(
				null, null);
		reqHandler.init(appid, appsecret, partnerkey);

		String sign = reqHandler.createSign(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>"+
				 "<op_user_id>" + op_user_id + "</op_user_id>" + 
				 "</xml>";
		
		/*<xml>
		   <appid>wx2421b1c4370ec43b</appid>
		   <mch_id>10000100</mch_id>
		   <nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str>
		   <op_user_id>10000100</op_user_id>
		   <out_refund_no>1415701182</out_refund_no>
		   <out_trade_no>1415757673</out_trade_no>
		   <refund_fee>1</refund_fee>
		   <total_fee>1</total_fee>
		   <transaction_id></transaction_id>
		   <sign>FE56DD4AA85C0EECA82C35595A69E153</sign>
		</xml>*/
		String createOrderURL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		try {
			String s= ClientCustomSSL.doRefund(createOrderURL, xml);
			System.out.println("s:"+s);
			
			//改變支付資料庫中的是否退款
			//新增退款資料庫資料
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * @date 2017年1月10日上午10:37:47 void
	 * @Des:退款查詢
	 */
	public void querywechatRefund() {
		// 商戶系統內部的退款單號,商戶系統內部唯一,同一退款單號多次請求只退一筆
		String transaction_id = "656565";
		String nonce_str = "5616556165";// 隨機字串
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appid);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("transaction_id", transaction_id);
		RequestHandler reqHandler = new RequestHandler(
				null, null);
		reqHandler.init(appid, appsecret, partnerkey);
		String sign = reqHandler.createSign(packageParams);
		String xml = "<xml>" + 
				"<appid>" + appid + "</appid>" + 
				"<mch_id>"+ mch_id + "</mch_id>" + 
				"<nonce_str>" + nonce_str+ "</nonce_str>" + 
				"<sign><![CDATA[" + sign + "]]></sign>"+
				"<transaction_id>" + transaction_id + "</transaction_id>"+ 
				 "</xml>";
		
		/*<xml>
		   <appid>wx2421b1c4370ec43b</appid>
		   <mch_id>10000100</mch_id>
		   <nonce_str>0b9f35f484df17a732e537c37708d1d0</nonce_str>
		   <out_refund_no></out_refund_no>
		   <out_trade_no>1415757673</out_trade_no>
		   <refund_id></refund_id>
		   <transaction_id></transaction_id>
		   <sign>66FFB727015F450D167EF38CCC549521</sign>
		</xml>*/
		
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/refundquery";
		try {
			String s= ClientCustomSSL.doRefund(createOrderURL, xml);
			System.out.println("s:"+s);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	
	
	public static void main(String[] args) {
		WXPayRefundUtil refund=new WXPayRefundUtil();
//		refund.wechatRefund();//申請退款
		refund.querywechatRefund();//查詢退款
		
		
		
	}
	
	

}


5、這個類中需要填寫雙向證書解壓的路徑

package com.kp.wxpay;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
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.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;



public class ClientCustomSSL {

    public static String doRefund(String url,String data) throws Exception {
    	/**
    	 * 注意PKCS12證書 是從微信商戶平臺-》賬戶設定-》 API安全 中下載的
    	 */
    	
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File("E:/bmjcompany/wxpaycert/cert/apiclient_cert.p12"));//P12檔案目錄
        try {
        	/**
        	 * 此處要改
        	 * */
            keyStore.load(instream, WXPayRefundUtil.mch_id.toCharArray());//這裡寫密碼..預設是你的MCHID
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        /**
    	 * 此處要改
    	 * */
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, WXPayRefundUtil.mch_id.toCharArray())//這裡也是寫密碼的  
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
        	HttpPost httpost = new HttpPost(url); // 設定響應頭資訊
        	httpost.addHeader("Connection", "keep-alive");
        	httpost.addHeader("Accept", "*/*");
        	httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        	httpost.addHeader("Host", "api.mch.weixin.qq.com");
        	httpost.addHeader("X-Requested-With", "XMLHttpRequest");
        	httpost.addHeader("Cache-Control", "max-age=0");
        	httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
    		httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
               return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}

其他程式碼可下載檢視

6、原始碼地址