| package com.xzx.gc.role.service;  | 
|   | 
| import org.apache.http.HttpEntity;  | 
| import org.apache.http.client.ClientProtocolException;  | 
| 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.entity.StringEntity;  | 
| import org.apache.http.impl.client.CloseableHttpClient;  | 
| import org.apache.http.impl.client.HttpClients;  | 
| import org.apache.http.ssl.SSLContexts;  | 
| import org.apache.http.util.EntityUtils;  | 
| import org.jdom2.Document;  | 
| import org.jdom2.Element;  | 
| import org.jdom2.input.SAXBuilder;  | 
| import org.slf4j.Logger;  | 
| import org.slf4j.LoggerFactory;  | 
|   | 
| import javax.net.ssl.SSLContext;  | 
| import java.io.*;  | 
| import java.security.KeyStore;  | 
| import java.security.MessageDigest;  | 
| import java.util.*;  | 
|   | 
| public class WxPayService {  | 
|   | 
|     static Logger log = LoggerFactory.getLogger(WxPayService.class);  | 
|   | 
|     void index(){  | 
|         String currTime = System.currentTimeMillis()+"";  | 
|         //8位日期  | 
|         String strTime = currTime.substring(8, currTime.length());  | 
|         //四位随机数  | 
|         String strRandom = (Math.random()*5+1)*1000 + "";  | 
|         String str=currTime.substring(0, currTime.length()-6) + strRandom;  | 
|         //10位序列号,可以自行调整。  | 
|         String nonce_str=strTime;//随机字符串  | 
|         String mch_id="1546567611";//商户号  | 
|         String mch_billno=str;//商户订单号  | 
|         String wxappid="wx6d7dfd9073dfa875";//公众账号appid  | 
|         String send_name="shanghuming";//商户名称(微信红包发送者名称,最好用英文)  | 
|         String re_openid="4w5uj7RaLq5S1twuflFcM8k";//用户openId  | 
|         String total_amount="1";//付款金额  | 
|         int total_num=1;//红包发放总人数  | 
|         String wishing="happy";//红包祝福语  | 
|         String client_ip="192.168.1.0";//ip地址  | 
|         String act_name="ceshiactivity";//活动名称  | 
|         String remark="ceshi";  | 
|         String scene_id="PRODUCT_5";//场景id  | 
|         String key="QUJvGnZT17N4TAQHISnST6mqLJbaAM5F";//商户号API密钥  | 
|         SortedMap<String, String> packageParams = new TreeMap<>();  | 
|         packageParams.put("act_name", act_name);  | 
|         packageParams.put("client_ip", client_ip);  | 
|         packageParams.put("mch_billno", mch_billno);  | 
|         packageParams.put("mch_id", mch_id);  | 
|         packageParams.put("nonce_str",nonce_str);  | 
|         packageParams.put("remark", remark);  | 
|         packageParams.put("re_openid", re_openid);  | 
|         packageParams.put("send_name", send_name);  | 
|         packageParams.put("scene_id", scene_id);  | 
|         packageParams.put("total_amount", total_amount+"");  | 
|         packageParams.put("total_num", total_num+"");  | 
|         packageParams.put("wishing", wishing);  | 
|         packageParams.put("wxappid", wxappid);  | 
|         //生成签名  | 
|         String sign = createSign(packageParams,key,"UTF-8");  | 
|         String xmlTest="<xml>"+  | 
|                 "<act_name>"+act_name+"</act_name>"+  | 
|                 "<client_ip>"+client_ip+"</client_ip>"+  | 
|                 "<mch_billno>"+mch_billno+"</mch_billno>"+  | 
|                 "<mch_id>"+mch_id+"</mch_id>"+  | 
|                 "<nonce_str>"+nonce_str+"</nonce_str>"+  | 
|                 "<remark>"+remark+"</remark>"+  | 
|                 "<re_openid>"+re_openid+"</re_openid>"+  | 
|                 "<send_name>"+send_name+"</send_name>"+  | 
|                 "<scene_id>"+scene_id+"</scene_id>"+  | 
|                 "<total_amount>"+total_amount+"</total_amount>"+  | 
|                 "<total_num>"+total_num+"</total_num>"+  | 
|                 "<wxappid>"+wxappid+"</wxappid>"+  | 
|                 "<wishing>"+wishing+"</wishing>"+  | 
|                 "<sign>"+sign+"</sign>"+  | 
|                 "</xml>";  | 
|         System.out.println(xmlTest);  | 
|         String notify_url="https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";  | 
|         String prepay_id="";  | 
|         try {  | 
|             prepay_id =reqPost(notify_url, xmlTest);  | 
|             if(prepay_id.contains("成功")){  | 
|                 log.info("================支付成功==============");  | 
|             }else{  | 
|                 log.info("================支付失败==================");  | 
|             }  | 
|         } catch (Exception e1) {  | 
|             e1.printStackTrace();  | 
|         }  | 
|   | 
|     }  | 
|   | 
|   | 
|     public String createSign(SortedMap<String, String> paraMap,String key,String charset) {  | 
|         StringBuffer sb = new StringBuffer();  | 
|         Set es = paraMap.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 (null != v && !"".equals(v) && !"sign".equals(k)  | 
|                     && !"key".equals(k)) {  | 
|                 sb.append(k + "=" + v + "&");  | 
|             }  | 
|         }  | 
|         sb.append("key=" + key);  | 
|         System.out.println("===========签名参数====="+sb.toString());  | 
|         String sign = md5Password(sb.toString()).toUpperCase();  | 
|         // String sign = MD5Util.encode(sb.toString()).toUpperCase();  | 
|         System.out.println("===========生成的签名是====="+sign);  | 
|         return sign;  | 
|   | 
|     }  | 
|   | 
|     /**  | 
|      * 生成32位md5码  | 
|      *  | 
|      * @param key  | 
|      * @return  | 
|      */  | 
|     public static String md5Password(String key) {  | 
|         char hexDigits[] = {  | 
|                 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'  | 
|         };  | 
|         try {  | 
|             byte[] btInput = key.getBytes();  | 
|             // 获得MD5摘要算法的 MessageDigest 对象  | 
|             MessageDigest mdInst = MessageDigest.getInstance("MD5");  | 
|             // 使用指定的字节更新摘要  | 
|             mdInst.update(btInput);  | 
|             // 获得密文  | 
|             byte[] md = mdInst.digest();  | 
|             // 把密文转换成十六进制的字符串形式  | 
|             int j = md.length;  | 
|             char str[] = new char[j * 2];  | 
|             int k = 0;  | 
|             for (int i = 0; i < j; i++) {  | 
|                 byte byte0 = md[i];  | 
|                 str[k++] = hexDigits[byte0 >>> 4 & 0xf];  | 
|                 str[k++] = hexDigits[byte0 & 0xf];  | 
|             }  | 
|             return new String(str);  | 
|         } catch (Exception e) {  | 
|             return null;  | 
|         }  | 
|     }  | 
|   | 
|   | 
|   | 
|     String reqPost(String url,String xmlParam) throws Exception{  | 
|         KeyStore keyStore  = KeyStore.getInstance("PKCS12");  | 
|         //读取商户证书(我下载下来的证书保存到D盘,根据自己实际情况填写)  | 
|         // FileInputStream instream = new FileInputStream(new File("D:/10016225.p12"));  | 
|         try (FileInputStream instream = new FileInputStream(new File("D:/apiclient_cert.p12"))){  | 
|             keyStore.load(instream, "1546567611".toCharArray());  | 
|         }  | 
|   | 
|         // Trust own CA and all self-signed certs  | 
|         SSLContext sslcontext = SSLContexts.custom()  | 
|                 .loadKeyMaterial(keyStore, "1546567611".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();  | 
|         HttpPost httpPost = new HttpPost(url);  | 
|         CloseableHttpResponse response1;  | 
|         String prepay_id = "";  | 
|         try {  | 
|             httpPost.setEntity(new StringEntity(xmlParam));  | 
|             response1 = httpclient.execute(httpPost);  | 
|             try {  | 
|                 int status = response1.getStatusLine().getStatusCode();  | 
|                 if(status>=200&&status<400){  | 
|                     System.out.println(response1.getStatusLine());  | 
|                     HttpEntity entity1 = response1.getEntity();  | 
|                     String jsonStr = EntityUtils.toString(entity1, "UTF-8");  | 
|                     Map<String, Object> dataMap = new HashMap<String, Object>();  | 
|                     System.out.println("返回数据:"+jsonStr);  | 
|   | 
|                     if(jsonStr.indexOf("FAIL")!=-1){  | 
|                         return prepay_id;  | 
|                     }  | 
|                     //我的项目的编码为GBK,再次改编码防止乱码出错  | 
|                     jsonStr=new String(jsonStr.getBytes("UTF-8"), "GBK");  | 
|                     Map map = doXMLParse(jsonStr);  | 
|                     String return_code  = (String) map.get("return_code");  | 
|                     if("SUCCESS".equals(return_code)){  | 
|                         prepay_id  = (String) map.get("return_msg");  | 
|                     }  | 
|                 }  | 
|                 return prepay_id;  | 
|             } catch (Exception e) {  | 
|                 e.printStackTrace();  | 
|   | 
|             } finally {  | 
|                 response1.close();  | 
|             }  | 
|         } catch (ClientProtocolException e1) {  | 
|             e1.printStackTrace();  | 
|   | 
|         } catch (IOException e1) {  | 
|             e1.printStackTrace();  | 
|   | 
|         }  | 
|         return null;  | 
|     }  | 
|   | 
|   | 
|     /**  | 
|      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。  | 
|      * @param strxml  | 
|      * @return  | 
|      * @throws Exception  | 
|      * @throws IOException  | 
|      */  | 
|     public static Map doXMLParse(String strxml) throws Exception {  | 
|         if(null == strxml || "".equals(strxml)) {  | 
|             return null;  | 
|         }  | 
|   | 
|         Map m = new HashMap();  | 
|         InputStream in = new ByteArrayInputStream(strxml.getBytes());  | 
|         SAXBuilder builder = new SAXBuilder();  | 
|         Document doc = builder.build(in);  | 
|         Element root = doc.getRootElement();  | 
|         List list = root.getChildren();  | 
|         Iterator it = list.iterator();  | 
|         while(it.hasNext()) {  | 
|             Element e = (Element) it.next();  | 
|             String k = e.getName();  | 
|             String v = "";  | 
|             List children = e.getChildren();  | 
|             if(children.isEmpty()) {  | 
|                 v = e.getTextNormalize();  | 
|             } else {  | 
|                 // v = getChildrenText(children);  | 
|             }  | 
|   | 
|             m.put(k, v);  | 
|         }  | 
|         //关闭流  | 
|         in.close();  | 
|         return m;  | 
|     }  | 
|   | 
|     public static void main(String[] args) throws Exception{  | 
|         WxPayService wxPayService = new WxPayService();  | 
|         wxPayService.index();  | 
|     }  | 
|   | 
| }  |