1. 程式人生 > >java實現微信退款

java實現微信退款

微信退款之前需要在常量中配置退款地址,退款的地址必須是可以直接訪問的。(之前的申請商戶平臺及在開放平臺申請賬號不在描述)在調起之前需要下載商戶平臺上的證書將其放在專案src下。
這裡寫圖片描述
微信退款回撥url :微信官方建議在提交退款申請後進行退款回撥url配置,便於通知退款的結果。配置在微信商戶平臺-》交易中心-》退款配置欄進行退款結果回撥通知配置。配置的url必須為可以直接訪問的類似付款成功回撥url。
這裡寫圖片描述
配置成功後在回撥的url中處理退款後的結果。微信給返回的引數如下:
這裡寫圖片描述
對於加密資訊req_info的解密步驟如下。
這裡寫圖片描述
解密過程中需要先到oracle官網下載對應java版本的sercity包,然後將下載後的包中兩個jar複製到jdk/jre/lib/security/包下並覆蓋原jar.另外需要在專案中引入一個bcprov-jdk15on-158.jar
這裡寫圖片描述


退款部分程式碼:

// 構造向微信傳送引數的實體類
    private Unifiedorder unifiedorder = new Unifiedorder();
    // 微信的引數
    private WeixinConfigUtils config = new WeixinConfigUtils();
    public static final String ALGORITHM = "AES/ECB/PKCS7Padding"; 
    private RefundOrder refundOrder = new RefundOrder();
    @Resource
    private AESDecodeUtil aesDecodeUtil;
@Action("weixinRefund") public String weixinRefund() { try { String out_trade_no = getRequest().getParameter("out_trade_no"); String refund_fee = getRequest().getParameter("refund_fee"); aLiPay = aLiPayService.searchALiPayByOutTradeNo(out_trade_no); if (aLiPay != null) { // 引數組 String appid = aLiPay.getApp
_id(); String mch_id = config.mch_id; String nonce_str = RandCharsUtils.getRandomString(16); String out_refund_no = UuIdUtils.getUUID(); Integer total_fee = aLiPay.getTotalFee(); // 構造簽名 parameters.put("appid", appid); parameters.put("mch_id", mch_id); parameters.put("nonce_str", nonce_str); parameters.put("out_trade_no", out_trade_no); parameters.put("out_refund_no", out_refund_no); parameters.put("total_fee", total_fee); parameters.put("refund_fee", refund_fee); parameters.put("op_user_id", mch_id); String sign = WXSignUtils.createSign("UTF-8", parameters); // 向微信傳送xml訊息 // Unifiedorder unifiedorder = new Unifiedorder(); unifiedorder.setAppid(appid); unifiedorder.setMch_id(mch_id); unifiedorder.setSign(sign); unifiedorder.setNonce_str(nonce_str); unifiedorder.setOut_trade_no(out_trade_no); unifiedorder.setOut_refund_no(out_refund_no); unifiedorder.setTotal_fee(total_fee); unifiedorder.setRefund_fee(Integer.valueOf(refund_fee)); unifiedorder.setOp_user_id(mch_id); String xmlInfo = HttpXmlUtils.refundXml(unifiedorder); unifiedorder = null; try { CloseableHttpResponse response = HttpUtil.Post( weixinConstant.REFUND_URL, xmlInfo, true); // 輸出退款後的資訊 String refundXml = EntityUtils.toString(response.getEntity(), "utf-8"); Map<String, String> refundOrderMap = HttpXmlUtils.parseRefundXml(refundXml); if (refundOrderMap.size()>0) { if (refundOrderMap.get("result_code").equals("SUCCESS") && refundOrderMap.get("return_code").equals("SUCCESS")) { refundOrder.setAppid(refundOrderMap.get("appid")); refundOrder.setMch_id(refundOrderMap.get("mch_id")); refundOrder.setTransaction_id(refundOrderMap.get("transaction_id")); refundOrder.setOut_trade_no(refundOrderMap.get("out_trade_no")); refundOrder.setOut_refund_no(refundOrderMap.get("out_refund_no")); refundOrder.setRefund_id(refundOrderMap.get("refund_id")); refundOrder.setRefund_fee(Integer.valueOf(refundOrderMap.get("refund_fee"))); refundOrder.setTatol_fee(Integer.valueOf(refundOrderMap.get("total_fee"))); refundOrder.setRefund_status(WeixinRefundStatusConstant.APPLY_SUCCESS); refundOrderService.saveOrder(refundOrder); msg.put("stateCode", MsgCode.SUCCESS); msg.put("message ", "退款申請成功"); refundOrderService.saveOrder(refundOrder); }else { msg.put("stateCode", MsgCode.ERROR); msg.put("message ", "退款申請失敗"); } }else { msg.put("stateCode", MsgCode.ERROR); msg.put("message ", "退款申請失敗"); } try { // 關閉流 EntityUtils.consume(response.getEntity()); } finally { response.close(); } } catch (Exception e) { msg.put("stateCode", MsgCode.SYS_ERROR); msg.put("message ", "伺服器異常"); } } else { msg.put("stateCode", MsgCode.ERROR); msg.put("message ", "退款申請失敗"); } Struts2Utils.renderJson(JSONObject.toJSONString(msg, SerializerFeature.DisableCircularReferenceDetect)); return NONE; } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); return "500"; } } /** * 微信退款回撥url * */ @Action("refundNotifyUrl") public String refundNotifyUrl() throws IOException { try { Map<String, String> resultMap = JdomParseXmlUtils.getWeixinResult( Struts2Utils.getRequest(), Struts2Utils.getResponse()); if (resultMap.get("return_code").equals("SUCCESS")) { String reqInfo = resultMap.get("req_info"); String result = aesDecodeUtil.decode(reqInfo); Map<String, String> resultMaps = HttpXmlUtils.parseRefundNotifyXml(result); refundOrder = refundOrderService.getOrderByOutRefundNo(resultMaps.get("out_refund_no")); if (resultMaps.get("refund_status").equals("SUCCESS")){ refundOrder.setRefund_status(WeixinRefundStatusConstant.REFUND_SUCCESS); }else if (resultMaps.get("refund_status").equals("CHANGE")) { refundOrder.setRefund_status(WeixinRefundStatusConstant.REFUND_FAIL); }else if (resultMaps.get("refund_status").equals("REFUNDCLOSE")) { refundOrder.setRefund_status(WeixinRefundStatusConstant.REFUND_CLOSED); } refundOrder.setRefund_rew_account(resultMaps.get("refund_recv_account")); System.out.println(resultMaps.get("refund_recv_account")); refundOrderService.updateOrder(refundOrder); refundOrder = null; unifiedorder.setReturn_code("SUCCESS"); } unifiedorder.setReturn_code("SUCCESS"); String refundXml = HttpXmlUtils.refundXml(unifiedorder); Struts2Utils.getResponse().getWriter().write(refundXml); Struts2Utils.getResponse().getWriter().flush(); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); return "500"; } return null; }
package com.wellness.platfront.common.weixinutil;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
生成隨機串
/**
 * nonce_str隨即字串
* @author 
 * @date 2017/08/10
 */
public class RandCharsUtils {
    private static SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

    public static String getRandomString(int length) { //length表示生成字串的長度
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";   
        Random random = new Random();   
        StringBuffer sb = new StringBuffer();
        int number = 0;
        for (int i = 0; i < length; i++) {   
            number = random.nextInt(base.length());   
            sb.append(base.charAt(number));   
        }   
        return sb.toString();   
    }   

    /*
     * 訂單開始交易的時間
     */
    public static String timeStart(){
        return df.format(new Date());
    }

    /*
     * 訂單開始交易的時間
     */
    public static String timeExpire(){
        Calendar now=Calendar.getInstance();
        now.add(Calendar.MINUTE,30);
        return df.format(now.getTimeInMillis());
    }

}

生成簽名的類

package com.wellness.platfront.common.weixinutil;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

/**
 * 微信支付簽名
 * @author 
 * @date 2017/08/10
 */
public class WXSignUtils {
    /**
     * 微信支付簽名演算法sign
     * @param characterEncoding
     * @param parameters
     * @return
     */
    @SuppressWarnings("rawtypes")
    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=" + weixinConstant.KEY);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }
}

向微信傳送訊息的類

package com.wellness.platfront.common.weixinutil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;

import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.wellness.platfront.business.wechat.service.RefundOrderService;
import com.wellness.platfront.entity.weixin.Transfers;
import com.wellness.platfront.entity.weixin.Unifiedorder;
/**
 * post提交xml格式的引數
 * @author
 * @date 2017/08/10
 */
public class HttpXmlUtils {
    @Resource
    private RefundOrderService refundOrderService;
    public static XStream xStream = new XStream(new DomDriver("UTF-8",
            new XmlFriendlyNameCoder("-_", "_")));
    /**
     * 開始post提交引數到介面
     * 並接受返回
     * @param url
     * @param xml
     * @param method
     * @param contentType
     * @return
     */
    public static String xmlHttpProxy(String url,String xml,String method,String contentType){
        InputStream is = null;
        OutputStreamWriter os = null;
        try {
            URL _url = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
            conn.setDoInput(true);   
            conn.setDoOutput(true);   
            conn.setRequestProperty("Content-type", "text/xml");
            conn.setRequestProperty("Pragma:", "no-cache");  
            conn.setRequestProperty("Cache-Control", "no-cache");  
            conn.setRequestMethod("POST");
            os = new OutputStreamWriter(conn.getOutputStream());
            os.write(new String(xml.getBytes(contentType)));
            os.flush();
            //返回值
            is = conn.getInputStream();
            return getContent(is, "utf-8");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                if(os!=null){os.close();}
                if(is!=null){is.close();}
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * 解析返回的值
     * @param is
     * @param charset
     * @return
     */
    public static String getContent(InputStream is, String charset) {
        String pageString = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        StringBuffer sb = null;
        try {
            isr = new InputStreamReader(is, charset);
            br = new BufferedReader(isr);
            sb = new StringBuffer();
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            pageString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null){
                    is.close();
                }
                if(isr!=null){
                    isr.close();
                }
                if(br!=null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            sb = null;
        }
        return pageString;
    }
    /**
     * 解析申請退款之後微信返回的值並進行存庫操作
     * @throws IOException 
     * @throws JDOMException 
     */
    public static Map<String, String> parseRefundXml(String refundXml) throws JDOMException, IOException{
        ParseXMLUtils.jdomParseXml(refundXml);
        StringReader read = new StringReader(refundXml);
        // 建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        // 建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();
        // 通過輸入源構造一個Document
        org.jdom.Document doc;
        doc = (org.jdom.Document) sb.build(source);
        org.jdom.Element root = doc.getRootElement();// 指向根節點
        List<org.jdom.Element> list = root.getChildren();
        Map<String, String> refundOrderMap = new HashMap<String, String>();
        if(list!=null&&list.size()>0){
            for (org.jdom.Element element : list) {
                refundOrderMap.put(element.getName(), element.getText());
            }
            return refundOrderMap;
            }
        return null;
    }
    /**
     * 解析申請退款之後微信退款回撥返回的字串中內容
     * @throws IOException 
     * @throws JDOMException 
     */
    public static Map<String, String> parseRefundNotifyXml(String refundXml) throws JDOMException, IOException{
        ParseXMLUtils.jdomParseXml(refundXml);
        StringReader read = new StringReader(refundXml);
        // 建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        // 建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();
        // 通過輸入源構造一個Document
        org.jdom.Document doc;
        doc = (org.jdom.Document) sb.build(source);
        org.jdom.Element root = doc.getRootElement();// 指向根節點
        List<org.jdom.Element> list = root.getChildren();
        Map<String, String> resultMap = new HashMap<>();
        if(list!=null&&list.size()>0){
            for (org.jdom.Element element : list){
                resultMap.put(element.getName(), element.getText());
            }
        return resultMap;
        }
        return null;
    }
    /**
     * h5支付時 解析返回的值並返回prepareid
     * @throws IOException 
     * @throws JDOMException 
     */
    public static Map<String, String> getUrl(Unifiedorder unifiedorder) throws JDOMException, IOException{
        String xmlInfo = HttpXmlUtils.xmlH5Info(unifiedorder);
        String wxUrl = weixinConstant.URL;
        String method = "POST";
        String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
        ParseXMLUtils.jdomParseXml(weixinPost);
        StringReader read = new StringReader(weixinPost);
        // 建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        // 建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();
        // 通過輸入源構造一個Document
        org.jdom.Document doc;
        doc = (org.jdom.Document) sb.build(source);
        org.jdom.Element root = doc.getRootElement();// 指向根節點
        List<org.jdom.Element> list = root.getChildren();
        String prepayId =null;
        Map<String, String> msg = new HashMap<String, String>();
        if(list!=null&&list.size()>0){
            for (org.jdom.Element element : list) {
            msg.put(element.getName(), element.getText());
            }
            }
        return msg;
    }
    /**
     * 解析返回的值並返回prepareid
     * @throws IOException 
     * @throws JDOMException 
     */
    public static String getPrepareId(Unifiedorder unifiedorder) throws JDOMException, IOException{
        String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
        String wxUrl = weixinConstant.URL;
        String method = "POST";
        String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
        ParseXMLUtils.jdomParseXml(weixinPost);
        StringReader read = new StringReader(weixinPost);
        // 建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        // 建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();
        // 通過輸入源構造一個Document
        org.jdom.Document doc;
        doc = (org.jdom.Document) sb.build(source);
        org.jdom.Element root = doc.getRootElement();// 指向根節點
        List<org.jdom.Element> list = root.getChildren();
        String prepayId =null;
        if(list!=null&&list.size()>0){
            for (org.jdom.Element element : list) {
                if ( "prepay_id".equals(element.getName())) {
                    prepayId= element.getText();
                    break;
                }
            }
            }
        return prepayId;
    }
    /**
     * 向微信傳送企業付款請求並解析返回結果
     * @throws IOException 
     * @throws JDOMException 
     */
    public static Map<String, String> getTransfersMap(Transfers transfers) throws JDOMException, IOException{
        String xmlInfo = HttpXmlUtils.xmlTransfer(transfers);
        String wxUrl = weixinConstant.WITHDRAW_URL;
        String method = "POST";
        String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
        ParseXMLUtils.jdomParseXml(weixinPost);
        StringReader read = new StringReader(weixinPost);
        // 建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        // 建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();
        // 通過輸入源構造一個Document
        org.jdom.Document doc;
        doc = (org.jdom.Document) sb.build(source);
        org.jdom.Element root = doc.getRootElement();// 指向根節點
        List<org.jdom.Element> list = root.getChildren();
        Map<String, String> transferMap=new HashMap<>();
        if(list!=null&&list.size()>0){
            for (org.jdom.Element element : list) {
                transferMap.put(element.getName(), element.getText());
            }
            }
        return transferMap;
    }
    /**
     * 構造退款xml引數
     * @param xml
     * @return
     */
    public static String refundXml(Unifiedorder unifiedorder){
            xStream.autodetectAnnotations(true);
            xStream.alias("xml", Unifiedorder.class);
            return xStream.toXML(unifiedorder);
    }
    /**
     * 構造企業付款xml引數
     * @param xml
     * @return
     */
    public static String transferXml(Transfers transfers){
            xStream.autodetectAnnotations(true);
            xStream.alias("xml", Transfers.class);
            return xStream.toXML(transfers);
    }
    /**
     * 構造xml引數
     * @param xml
     * @return
     */
    public static String xmlInfo(Unifiedorder unifiedorder){

        if(unifiedorder!=null){
            StringBuffer bf = new StringBuffer();
            bf.append("<xml>");

            bf.append("<appid><![CDATA[");
            bf.append(unifiedorder.getAppid());
            bf.append("]]></appid>");

            bf.append("<mch_id><![CDATA[");
            bf.append(unifiedorder.getMch_id());
            bf.append("]]></mch_id>");

            bf.append("<nonce_str><![CDATA[");
            bf.append(unifiedorder.getNonce_str());
            bf.append("]]></nonce_str>");

            bf.append("<sign><![CDATA[");
            bf.append(unifiedorder.getSign());
            bf.append("]]></sign>");

            bf.append("<body><![CDATA[");
            bf.append(unifiedorder.getBody());
            bf.append("]]></body>");

            bf.append("<detail><![CDATA[");
            bf.append(unifiedorder.getDetail());
            bf.append("]]></detail>");

            bf.append("<attach><![CDATA[");
            bf.append(unifiedorder.getAttach());
            bf.append("]]></attach>");

            bf.append("<out_trade_no><![CDATA[");
            bf.append(unifiedorder.getOut_trade_no());
            bf.append("]]></out_trade_no>");

            bf.append("<total_fee><![CDATA[");
            bf.append(unifiedorder.getTotal_fee());
            bf.append("]]></total_fee>");

            bf.append("<spbill_create_ip><![CDATA[");
            bf.append(unifiedorder.getSpbill_create_ip());
            bf.append("]]></spbill_create_ip>");

            bf.append("<time_start><![CDATA[");
            bf.append(unifiedorder.getTime_start());
            bf.append("]]></time_start>");

            bf.append("<time_expire><![CDATA[");
            bf.append(unifiedorder.getTime_expire());
            bf.append("]]></time_expire>");

            bf.append("<notify_url><![CDATA[");
            bf.append(unifiedorder.getNotify_url());
            bf.append("]]></notify_url>");

            bf.append("<trade_type><![CDATA[");
            bf.append(unifiedorder.getTrade_type());
            bf.append("]]></trade_type>");

            bf.append("</xml>");
            return bf.toString();
        }
        return "";
    }
    /**
     * 構造xml引數
     * @param xml
     * @return
     */
    public static String xmlH5Info(Unifiedorder unifiedorder){
        if(unifiedorder!=null){
            StringBuffer bf = new StringBuffer();
            bf.append("<xml>");

            bf.append("<appid><![CDATA[");
            bf.append(unifiedorder.getAppid());
            bf.append("]]></appid>");

            bf.append("<mch_id><![CDATA[");
            bf.append(unifiedorder.getMch_id());
            bf.append("]]></mch_id>");

            bf.append("<nonce_str><![CDATA[");
            bf.append(unifiedorder.getNonce_str());
            bf.append("]]></nonce_str>");

            bf.append("<sign><![CDATA[");
            bf.append(unifiedorder.getSign());
            bf.append("]]></sign>");

            bf.append("<body><![CDATA[");
            bf.append(unifiedorder.getBody());
            bf.append("]]></body>");


            bf.append("<attach><![CDATA[");
            bf.append(unifiedorder.getAttach());
            bf.append("]]></attach>");

            bf.append("<out_trade_no><![CDATA[");
            bf.append(unifiedorder.getOut_trade_no());
            bf.append("]]></out_trade_no>");

            bf.append("<total_fee><![CDATA[");
            bf.append(unifiedorder.getTotal_fee());
            bf.append("]]></total_fee>");

            bf.append("<spbill_create_ip><![CDATA[");
            bf.append(unifiedorder.getSpbill_create_ip());
            bf.append("]]></spbill_create_ip>");

            bf.append("<notify_url><![CDATA[");
            bf.append(unifiedorder.getNotify_url());
            bf.append("]]></notify_url>");

            bf.append("<trade_type><![CDATA[");
            bf.append(unifiedorder.getTrade_type());
            bf.append("]]></trade_type>");

            bf.append("<scene_info><![CDATA[");
            bf.append(unifiedorder.getScene_info());
            bf.append("]]></scene_info>");

            bf.append("</xml>");
            return bf.toString();
        }
        return "";
    }
    /**
     * 構造退款xml引數
     * @param xml
     * @return
     */
    public static String xmlTransfer(Transfers transfers){

        if(transfers!=null){
            StringBuffer bf = new StringBuffer();
            bf.append("<xml>");

            bf.append("<mch_appid><![CDATA[");
            bf.append(transfers.getMch_appid());
            bf.append("]]></mch_appid>");

            bf.append("<mchid><![CDATA[");
            bf.append(transfers.getMchid());
            bf.append("]]></mchid>");

            bf.append("<nonce_str><![CDATA[");
            bf.append(transfers.getNonce_str());
            bf.append("]]></nonce_str>");

            bf.append("<sign><![CDATA[");
            bf.append(transfers.getSign());
            bf.append("]]></sign>");

            bf.append("<partner_trade_no><![CDATA[");
            bf.append(transfers.getPartner_trade_no());
            bf.append("]]></partner_trade_no>");


            bf.append("<openid><![CDATA[");
            bf.append(transfers.getOpenid());
            bf.append("]]></openid>");

            bf.append("<check_name><![CDATA[");
            bf.append(transfers.getCheck_name());
            bf.append("]]></check_name>");

            bf.append("<amount><![CDATA[");
            bf.append(transfers.getAmount());
            bf.append("]]></amount>");

            bf.append("<desc><![CDATA[");
            bf.append(transfers.getDesc());
            bf.append("]]></desc>");

            bf.append("<spbill_create_ip><![CDATA[");
            bf.append(transfers.getSpbill_create_ip());
            bf.append("]]></spbill_create_ip>");

            bf.append("</xml>");
            return bf.toString();
        }
        return "";
    }
    /**
     * post請求並得到返回結果
     * @param requestUrl
     * @param requestMethod
     * @param output
     * @return
     */
    public static String httpsRequest(String requestUrl, String requestMethod, String output) {
        try{
            URL url = new URL(requestUrl);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setRequestMethod(requestMethod);
            if (null != output) {
                OutputStream outputStream = connection.getOutputStream();
                outputStream.write(output.getBytes("UTF-8"));
                outputStream.close();
            }
            // 從輸入流讀取返回內容
            InputStream inputStream = connection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            connection.disconnect();
            return buffer.toString();
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return "";
    }
}

載入證書

package com.wellness.platfront.common.weixinutil;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;

public class HttpUtil {
    /**
     * 傳送post請求
     * 
     * @param url
     *            請求地址
     * @param outputEntity
     *            傳送內容
     * @param isLoadCert
     *            是否載入證書
     */
    public static CloseableHttpResponse Post(String url, String outputEntity, boolean isLoadCert) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8編碼,否則到API伺服器XML的中文不能被成功識別
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(new StringEntity(outputEntity, "UTF-8"));
        if (isLoadCert) {
            // 載入含有證書的http請求
            return HttpClients.custom().setSSLSocketFactory(CertUtil.initCert()).build().execute(httpPost);
        } else {
            return HttpClients.custom().build().execute(httpPost);
        }
    }
}

載入證書的類

package com.wellness.platfront.common.weixinutil;

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

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;

/**
 * 載入證書的類
 * @author 
 * @since 2017/08/16
 */

@SuppressWarnings("deprecation")
public class CertUtil {
    private static  WeixinConfigUtils config = new WeixinConfigUtils();
    /**
     * 載入證書
     */
    public static SSLConnectionSocketFactory initCert() throws Exception {
        FileInputStream instream = null;
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        instream = new FileInputStream(new File(weixinConstant.PATH));
        keyStore.load(instream, config.mch_id.toCharArray());

        if (null != instream) {
            instream.close();
        }

        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,config.mch_id.toCharArray()).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        return sslsf;
    }
}

解密微信退款中返回相關資訊的字串

package com.wellness.platfront.common.weixinutil;

import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Service;

import com.wellness.platfront.common.wechat.utils.MD5;

/**
 * 解密微信退款中返回相關資訊的字串
 * @author 
 * @since 2017/09/05
 */
@Service
public class AESDecodeUtil {

     public static final String ALGORITHM = "AES/ECB/PKCS7Padding"; 
     public String decode(String reqInfo) throws Exception{
        try {
            byte[] decodeBase64 = Base64.decodeBase64(reqInfo);
            String md5Key = MD5.MD5Encode(weixinConstant.KEY);
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance(ALGORITHM);  
            SecretKey keySpec = new SecretKeySpec(md5Key.getBytes(), "AES"); //生成加密解密需要的Key  
            cipher.init(Cipher.DECRYPT_MODE, keySpec);  
            byte[] decoded = cipher.doFinal(decodeBase64);  
            String  result = new String(decoded, "UTF-8");  
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
     }
}

微信解析xml:帶有CDATA格式的

package com.wellness.platfront.common.weixinutil;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java
            
           

相關推薦

java實現退款

微信退款之前需要在常量中配置退款地址,退款的地址必須是可以直接訪問的。(之前的申請商戶平臺及在開放平臺申請賬號不在描述)在調起之前需要下載商戶平臺上的證書將其放在專案src下。 微信退款回撥url :微信官方建議在提交退款申請後進行退款回撥url配置,便於

java實現支付,退款,部分退款服務端

由於公司業務需要,最近搞微信退款功能,今天抽空在此記錄一下,以後用到也可以到這來看一眼。廢話不多說,進入正題。 微信支付以及付款呢,先要有個證書,不清楚的,還要有證書,可以去微信平臺看證書怎麼下載 https://pay.weixin.qq.com, APP_ID,MCH_

java實現公眾號房卡牛牛六人平臺開發搭建文章采集接口程序

package ecs util 系統 public address 用戶id 狀態 get 日誌實體類,用戶記錄用戶登錄登出 LogRec.javapackage q.dms.test; import java.util.Date; /** 實體類 包含用戶登錄的id,

java實現小程序服務端(登錄)

value ssi 讀取 ive ping 我們 不存在 @param 感受                             java實現微信小程序服務端    微信小程序如今被廣泛使用,微信小程序按照微信官網的定義來說就是:    微信小程序是一種全新的連接用

PHP實現退款的分析與原始碼實現

* 1.微信退款到零錢要求必傳證書,需要到https://pay.weixin.qq.com 賬戶中心->賬戶設定->API安全->下載證書,然後修改程式碼中的證書路徑  * 2.該檔案需放到支付授權目錄下,可以在微信支付商戶平臺->產品中心->開發配置中設定。&nb

JAVA實現網頁授權的實列程式碼

1、需要有一個公眾號(我這裡用的測試號),拿到AppID和AppSecret; 2、進入公眾號開發者中心頁配置授權回撥域名。具體位置:介面許可權-網頁服務-網頁賬號-網頁授權獲取使用者基本資訊-修改 注意,這裡僅需填寫全域名(如www.qq.com、www.baidu.c

JAVA實現掃碼支付回撥Demo

掃碼效果演示圖 專案結構圖: 微信實現JAVA掃碼支付的Demo原始碼,做這個做的很辛苦,熬夜了幾個晚上才把支付和回撥做好的,在這裡貼一下相關程式碼,以免更多開發者避免遇到這些坑,有不動的問題可以加我Q76949433,提供技術支援 package com.

java實現h5支付

微信h5支付需要在微信商戶平臺-》產品中心開通h5支付。 官網提供的開發文件中需要的引數: h5支付主要是scene_info中的引數wap_url必須是可以訪問到的地址。spbill_create_ip的獲取必須和調起微信支付的ip一致。

java實現授權獲取使用者openid及授權使用者相關資訊

首先需要在微信公眾平臺申請賬號並在微信公眾平臺->設定->公眾號設定->功能設定中設定或者在平臺下介面許可權->網頁許可權->網頁授權中設定授權域名。跳轉到授權頁面的url:https://open.weixin.qq.com/co

Java實現小程式登入 獲取使用者資訊

小程式比公眾號授權登入 更加簡單 其實沒什麼是後臺需要處理的 前端傳過來一個code 我們儲存以下通過code獲取過來的openid就可以 其他的使用者資訊 前端小程式那邊可以獲取。首先既然是小程式登入 你要有一個你自己的小程式還是要拿到你自己的appid和appSecret

Java實現朋友圈分享圖

pict tst 純java googl 分享圖片 gas desc 地址 section 純Java實現微信朋友圈分享圖 1.實現分享圖的效果 2.開發環境 2.1 JDK * oracle‘s jdk 1.8以上 2.2 字體 * 若選擇了微軟雅黑字體又是代碼部署到L

JAVA實現授權登入

1.先寫一個工具類 AuthUtil.java 來存放APPID等資訊 public class AuthUtil { public static final String APPID = "換成自己的APPID "; public static final Strin

java實現登入(SSM)

提醒:本文章可能需要一定的java基礎,所需jar包也需要自己尋找效果圖:掃描後獲取的資料openid:(微信唯一標識)headimgurl:頭像nickname:暱稱(其他就不列舉啦)1.註冊微信開放平臺開發者賬號並建立一個或一個以上的網站應用點選檢視進入下圖2.把授權回撥

php 實現退款

大家好,我是小編,最近在調微信退款介面,發現有許多坑,更大家分享一下 ① 要是在測試的時候,網頁提示 curl 58 說明 證書的路徑出現問題(這裡要填物理路徑,也就是絕對路徑) ②網頁提示curl 52 說明你的證書引入少了,在官方的demo上只有兩個證書 apiclie

java實現公眾號支付

前面做了app微信支付的回撥處理,現在需要做微信公眾號的支付,花了一天多時間,終於折騰出來了!鑑於坑爹的微信官方沒有提供java版的demo,所以全靠自己按照同樣坑爹的文件敲敲敲,所以記錄下來,以供自己及後來人參考,不足之處,還請指正。 首先,我們貼出呼叫支付介面的H5頁

java實現公眾號授權登入獲取使用者資訊流程

參考地址微信公眾號開發文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432 前提:需要申請認證的微信公眾號;獲取對應的APPID和APPSECRET;並且還需要獲取到使用者資訊許可權

[]小程式/Java實現支付

@Controller @RequestMapping("/pay") public class WeChatPayController { public final static Logger logger = LoggerFa

Java實現掃碼支付---方式二

話不多說直接上程式碼: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.

Java實現開發--"接入"

Java實現微信開發–”接入” 使用Java開發語言,進行微信”接入”,有如下要求: 1、有一定Java基礎 2、對微信公眾號有一定了解 3、瞭解測試號、訂閱號、公眾號區別 4、本文只是進行簡單”接

JAVA實現支付

1.微信支付官方文件微信官網連結 2.可以看到這些支付方式。 3.在此介紹公眾號支付和app支付。後面的開發基本看下文件就沒什麼問題了。 4.開發之前需要準備前期公眾。 5.首先需要申請公眾號並且開通支付等設定一些配置東西,這裡就不廢話了。 6.程