package com.ibeetl.admin.core.service; import com.ibeetl.admin.core.util.MD5Util; 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 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=""+ ""+act_name+""+ ""+client_ip+""+ ""+mch_billno+""+ ""+mch_id+""+ ""+nonce_str+""+ ""+remark+""+ ""+re_openid+""+ ""+send_name+""+ ""+scene_id+""+ ""+total_amount+""+ ""+total_num+""+ ""+wxappid+""+ ""+wishing+""+ ""+sign+""+ ""; 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) { // TODO Auto-generated catch block e1.printStackTrace(); } } public String createSign(SortedMap 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 dataMap = new HashMap(); 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) { // TODO Auto-generated catch block 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(); } }