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();
|
}
|
|
}
|