微信开发用到的常见的方法~~xmlToMap、MapToXml、签名等等

       近日,在开发微信支付、微信退款、微信付款到零钱、微信订单查询、微信付款到银行卡的功能。以及其他微信API的使用。发现微信API的开发都是同样的套路~~封装参数–》包装成Xml—》提交到Api—》获取返回的内容就行了。因为会有多个API都设计到这些操作,特地抽取出来封装成工具类单独讲,学习完以下这5~8个放法、那么你的开发就很简便了 ~ ~ 一个支付方法简单的十五行代码立马搞定。希望对你们有帮助。个人浅薄的见解
资料下载:目前资料已经删除了,之前有网友吐槽说:资料不全,那就不共享了。也有很多网友加了我qq拿资,咨询怎么做,目前已经解答了有50多位网友的问题了,本人的精力有限,没办法顾及所有网友的问题,所以源码将不再开源。如果有需要加我qq:924155240。发个15~20块吃饭钱,可以把源码发给你+稍稍解答问题
在这里插入图片描述

在这里插入图片描述
一、微信签名的工具类
【温馨提示:】数字签名是一般开发人员容易遇到的错误,记住“你没遇到数字签名错误,都不好意思说自己做过微信开发”。
耐心解决就行

【Description】简单来解释,就是对自己要发送的数据进行加密处理、换句话说假如说你要传递A/B/C,就对这三者进行加密。初开发者的误区:例如看到别人代码拿D和E等去数字签名、然后在自己的开发中就拿D和E去签名,这是错误的做法,会出现数字签名错误。你要看一下你的开发需要传递D和F去后台,那么你应该拿D和F去签名就对了

package com.fh.util.weixin;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import com.fh.controller.app.nrb.bargain.wxconfig;
/**
 * 签名工具类
 * @author 小郑
 * @date 2018年02月22日
 * @Notice:wxconfig.apikey。这句代码是获取商务号设置的api秘钥。这里不方便贴出来,
 * 复制签名代码的人,需要把该常量改成自己商务号的key值。原因是Api规定了签名必须加上自己的key值哦 
 * */
public class SignUtils {

	/**
	 * @param characterEncoding 编码格式 utf-8
	 * */
	public static String creatSign(String characterEncoding,
			SortedMap<Object, Object> parameters) {
		StringBuffer sb = new StringBuffer();
		Set es = parameters.entrySet();
		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 + "&");
			}
		}
		//wxconfig.apikey。这句代码是获取商务号设置的api秘钥。这里不方便贴出来,
		//复制签名代码的人,需要把该常量改成自己商务号的key值。原因是Api规定了签名必须加上自己的key值哦 
		sb.append("key=" + wxconfig.apikey);
		String sign = MD5Utils.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
		System.out.println(sign);
		return sign;
	}
}

这里写图片描述

二、将当前的map结合转化成xml格式 ~~ 微信请求参数是必须要封装成Xml格式的,在java中写xml很不方便,但是写Map集合很方便。故需要提供map转化xml的方法


    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key: data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.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 writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        }
        catch (Exception ex) {
        }
        return output;
    }
 /*
     * 将SortedMap<Object,Object> 集合转化成 xml格式
     */
    public static String getRequestXml(SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {
                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
            }else {
                sb.append("<"+k+">"+v+"</"+k+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

这里写图片描述

这里写图片描述
三、xml转化成map或者Bean
微信返回的信息是Xml格式、需要一个工具类把它解析成Map集合或者是一个Bean。方便我们去获取里面返回值。这里会介绍两种方式,一种是转化成Map集合,通过get出来使用,这个方法是通用的,第二种是转化成Bean、这种的话不通用。每个bean基本都不大一样,需要定制

 //通用的。返回map格式
 /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. 
            Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

    }
//不通用的、返回Bean格式

//以企业付款到零钱为例子~~根据Api会返回的参数,书写一个Bean类型
package com.fh.entity.nrb.xiaozheng;
/**
 * 
 * 企业 付款到 客户  的 实体类
 * @author xiaozheng
 * @version 1.0 
 * @description: 收集企业 支付给客户成功后的返回信息
 * @time : 2018-01-16 16:00:00
 */
public class EnterpriceToCustomer {
	/*	<xml>
		<return_code><![CDATA[SUCCESS]]></return_code>
		<return_msg><![CDATA[]]></return_msg>
		<mchid><![CDATA[1488323162]]></mchid>
		<nonce_str><![CDATA[o9fcpfvqow1aks48a2omvayu1ne7c709]]></nonce_str>
		<result_code><![CDATA[SUCCESS]]></result_code>
		<partner_trade_no><![CDATA[xvuct0087w4t1dpr87iqj98w5f71ljae]]></partner_trade_no>
		<payment_no><![CDATA[1000018301201801163213961289]]></payment_no>
		<payment_time><![CDATA[2018-01-16 14:52:16]]></payment_time>
		</xml>
	*/
	
	private String return_code;
	private String return_msg;
	private String mchid;
	private String nonce_str;
	private String result_code;
	private String partner_trade_no;
	private String payment_no;
	private String payment_time;

	/*
	 * 支付错误时,返回的代码
	 *  key是:return_code,值是:SUCCESS
		key是:return_msg,值是:支付失败
		key是:mch_appid,值是:wx49c22ad731b679c3
		key是:mchid,值是:1488323162
		key是:result_code,值是:FAIL
		key是:err_code,值是:AMOUNT_LIMIT
		key是:err_code_des,值是:付款金额超出限制。低于最小金额1.00元或累计超过20000.00元。
	 * 
	 */
	private String err_code;
	private String err_code_des;

	public String getErr_code() {
		return err_code;
	}
	public void setErr_code(String errCode) {
		err_code = errCode;
	}
	public String getErr_code_des() {
		return err_code_des;
	}
	public void setErr_code_des(String errCodeDes) {
		err_code_des = errCodeDes;
	}
	public String getReturn_code() {
		return return_code;
	}
	public void setReturn_code(String returnCode) {
		return_code = returnCode;
	}
	public String getReturn_msg() {
		return return_msg;
	}
	public void setReturn_msg(String returnMsg) {
		return_msg = returnMsg;
	}
	public String getMchid() {
		return mchid;
	}
	public void setMchid(String mchid) {
		this.mchid = mchid;
	}
	public String getNonce_str() {
		return nonce_str;
	}
	public void setNonce_str(String nonceStr) {
		nonce_str = nonceStr;
	}
	public String getResult_code() {
		return result_code;
	}
	public void setResult_code(String resultCode) {
		result_code = resultCode;
	}
	public String getPartner_trade_no() {
		return partner_trade_no;
	}
	public void setPartner_trade_no(String partnerTradeNo) {
		partner_trade_no = partnerTradeNo;
	}
	public String getPayment_no() {
		return payment_no;
	}
	public void setPayment_no(String paymentNo) {
		payment_no = paymentNo;
	}
	public String getPayment_time() {
		return payment_time;
	}
	public void setPayment_time(String paymentTime) {
		payment_time = paymentTime;
	}
	@Override
	public String toString() {
		return "EnterpriceToCustomer [err_code=" + err_code + ", err_code_des="
				+ err_code_des + ", mchid=" + mchid + ", nonce_str="
				+ nonce_str + ", partner_trade_no=" + partner_trade_no
				+ ", payment_no=" + payment_no + ", payment_time="
				+ payment_time + ", result_code=" + result_code
				+ ", return_code=" + return_code + ", return_msg=" + return_msg
				+ "]";
	}
}

/** 
	下面是需要通过跟节点,找找到对应的类属性,手动把它set进去。因此API返回的参数不一样。需要写每个返回的Bean。看个人的习惯呗~~我喜欢用bean存储数据的方式
	* 解析企业支付申请 
	* 解析的时候自动去掉CDMA 
	* @param xml 
	*/ 
	@SuppressWarnings("unchecked") 
	public static EnterpriceToCustomer parseXmlToMapEnterpriceToCustomer(String xml){ 
			EnterpriceToCustomer enterpriceToCustomer = new EnterpriceToCustomer(); 
			try { 
					StringReader read = new StringReader(xml); 
					// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入 
					InputSource source = new InputSource(read); 
					// 创建一个新的SAXBuilder 
					SAXBuilder sb = new SAXBuilder(); 
					// 通过输入源构造一个Document 
					Document doc; 
					doc = (Document) sb.build(source); 
				
					Element root = doc.getRootElement();// 指向根节点 
					List<Element> list = root.getChildren(); 
				
					if(list!=null&&list.size()>0){ 
					for (Element element : list) { 
						System.out.println("key是:"+element.getName()+",值是:"+element.getText()); 
						if("return_code".equals(element.getName())){ 
								enterpriceToCustomer.setReturn_code(element.getText()); 
							} 
					
						if("return_msg".equals(element.getName())){ 
								enterpriceToCustomer.setReturn_msg(element.getText()); 
							} 
						
						if("mchid".equals(element.getName())){ 
							enterpriceToCustomer.setMchid(element.getText()); 
						}
						
						if("nonce_str".equals(element.getName())){ 
							enterpriceToCustomer.setNonce_str(element.getText()); 
						}
						if("result_code".equals(element.getName())){ 
							enterpriceToCustomer.setResult_code(element.getText()); 
						}
						if("partner_trade_no".equals(element.getName())){ 
							enterpriceToCustomer.setPartner_trade_no(element.getText()); 
						}
						if("payment_no".equals(element.getName())){ 
							enterpriceToCustomer.setPayment_no(element.getText()); 
						}
						if("payment_time".equals(element.getName())){ 
							enterpriceToCustomer.setPayment_time(element.getText()); 
						}	
						//错误的编码
						/*
						   private String err_code;
						   private String err_code_des;
						 * */
						if("err_code".equals(element.getName())){ 
							enterpriceToCustomer.setErr_code(element.getText()); 
						}
						if("err_code_des".equals(element.getName())){ 
							enterpriceToCustomer.setErr_code_des(element.getText()); 
						}	
						
					}
				}
				

			} catch (JDOMException e) { 
			e.printStackTrace(); 
			} catch (IOException e) { 
			e.printStackTrace(); 
			}catch (Exception e) { 
			e.printStackTrace(); 
			} 
				
			return enterpriceToCustomer; 
		} 

四、Post请求+证书~~亲测可以的

package com.fh.entity.nrb.weixinResult;
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; 

import com.fh.controller.app.nrb.bargain.wxconfig;



/** 
* This example demonstrates how to create secure connections with a custom SSL 
* context. 
*/ 
public class ClientCustomSSL { 

@SuppressWarnings("deprecation")
public static String doRefund(String url,String data) throws Exception { 
		/** 
		* 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的 
		*/ 
		
		KeyStore keyStore = KeyStore.getInstance("PKCS12"); 
		/**
		*此处要改
		*wxconfig.SSLCERT_PATH : 指向你的证书的绝对路径,带着证书去访问
		*/
		
		FileInputStream instream = new FileInputStream(new File(wxconfig.SSLCERT_PATH));//P12文件目录 
		try { 
		/** 
		* 此处要改 
		* 
		* 下载证书时的密码、默认密码是你的MCHID mch_id
		* */ 
		keyStore.load(instream, wxconfig.SSLCERT_PASSWORD.toCharArray());//这里写密码
		} finally { 
			instream.close(); 
		} 
		
		// Trust own CA and all self-signed certs 
		/** 
		* 此处要改 
		* 下载证书时的密码、默认密码是你的MCHID mch_id
		* */ 
		SSLContext sslcontext = SSLContexts.custom() 
		.loadKeyMaterial(keyStore, wxconfig.SSLCERT_PASSWORD.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(); 
		} 
	} 
} 

其他的。遇到了会补充上来。还有一个get方式,不需要证书的提交,稍后补充呗

  • 11
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值