微信相关配置
1、公众平台
授权域名回调
2、商户平台
路径:商户平台:账户中心 》 账户设置 》API安全
1、api 安全配置 (指的是:允许调用接口的白名单配置)
2、证书下载 (本次代码主要使用的是 p12 证书)
企业付款到零钱,是需要 open_id 参数的,open_id 参数的获取,参考其他文章,此处不做记录
主要发起支付的代码
工具类
import com.alibaba.fastjson.JSONObject;
import com.hoohui.project.richeng.model.WeChatEntity;
import com.hoohui.project.richeng.util.PathUtil;
import com.hoohui.util.http.HttpRequestUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class WeChatUtils {
private byte[] certData;
public InputStream getCertStream() {
FileInputStream instream = null;
try {
//此处为 p12 证书文件路径
instream = new FileInputStream(new File(PathUtil.getClassResources() + "/weChat/apiclient_cert.p12"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return instream;
}
/**
* 随机串
*/
public static String getNonceStr() {
UUID uuid = UUID.randomUUID();
return uuid.toString().replace("-", "");
}
/**
* 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序(字典序),并且生成url参数串<br>
* 实现步骤: <br>
*
* @param paraMap 要排序的Map对象
* @param urlEncode 是否需要URLENCODE
* @param keyToLower 是否需要将Key转换为全小写
* true:key转化成小写,false:不转化
* @return
*/
public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
String buff = "";
Map<String, String> tmpMap = paraMap;
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
// 构造URL 键值对的格式
StringBuilder buf = new StringBuilder();
for (Map.Entry<String, String> item : infoIds) {
if (StringUtils.isNotBlank(item.getKey())) {
String key = item.getKey();
String val = item.getValue();
if (urlEncode) {
val = URLEncoder.encode(val, "utf-8");
}
if (keyToLower) {
buf.append(key.toLowerCase() + "=" + val);
} else {
buf.append(key + "=" + val);
}
buf.append("&");
}
}
buff = buf.toString();
if (buff.isEmpty() == false) {
buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {
return null;
}
return buff;
}
}
发起打款的主要方法:
public void toPay() throws Exception {
//1. 调用发起支付的方法
String str = mainPay(map, 3000, 3000, true);
//2. xml 转成 map的 方法
Map<String,String> resultMap = XmlUtil.xml2Map(str);
//3. 根据 result_code 判断是否支付成功
if(resultMap.containsKey("result_code") && StringUtils.equals("SUCCESS",resultMap.getOrDefault("result_code",""))){
// TODO: 2019/9/19 表示支付成功 后进行的操作
}else{
// TODO: 2019/9/19表示支付失败
}
}
/**
* 主要发起支付的方法
*/
public static String mainPay(Map<String,String> params, int connectTimeoutMs, int readTimeoutMs,boolean useCert) throws Exception{
Map<String, String> paraMap = new HashMap<>();
//微信 app_id
paraMap.put("mch_appid", WeChatConfig.APP_ID);
//微信 mch_id
paraMap.put("mchid",WeChatConfig.MCH_ID);
//随机字符串
paraMap.put("nonce_str", WeChatUtils.getNonceStr());
//订单号 可以按照自己的规则生成,不重复即可
paraMap.put("partner_trade_no","wx"+params.getOrDefault("id","")+ DateUtils.getDate("yyyyMMddHHmmss"));
//用户的 open_id
paraMap.put("openid",params.getOrDefault("openid",""));
// 校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
paraMap.put("check_name","FORCE_CHECK");
// 微信的真实姓名
paraMap.put("re_user_name",params.getOrDefault("re_user_name",""));
//金额值,单位为 分
paraMap.put("amount",params.getOrDefault("amount",""));
//企业付款操作说明信息
paraMap.put("desc",params.getOrDefault("desc",""));
//跟白名单没有关系 ,这样写就可以
paraMap.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress());
//将参数排序,并 拼接成字符串
String url = WeChatUtils.formatUrlMap(paraMap, false, false);
//最后加上 商户 api_key
url = url + "&key=" + WeChatConfig.API_KEY; //生成签名 使用商户 key
//md5 加密,转大写
String sign = Md5Utils.md5(url).toUpperCase();
//拼接成xml
StringBuffer xml = new StringBuffer();
xml.append("<xml>");
for (Map.Entry<String, String> entry : paraMap.entrySet()) {
xml.append("<" + entry.getKey() + ">");
xml.append(entry.getValue());
xml.append("</" + entry.getKey() + ">" + "\n");
}
xml.append("<sign>");
xml.append(sign);
xml.append("</sign>");
xml.append("</xml>");
logger.info("xml {} ", xml.toString());
BasicHttpClientConnectionManager connManager;
if (useCert) {
// 证书
char[] password = WeChatConfig.MCH_ID.toCharArray();
//这一步调用获取证书内容
InputStream certStream = new WeChatUtils().getCertStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(certStream, password);
// 实例化密钥库 & 初始化密钥工厂
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password);
// 创建 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1"},
null,
new org.apache.http.conn.ssl.DefaultHostnameVerifier());
connManager = new BasicHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build(),
null,
null,
null
);
} else {
connManager = new BasicHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build(),
null,
null,
null
);
}
org.apache.http.client.HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connManager)
.build();
HttpPost httpPost = new HttpPost(WeChatConfig.MACH_PAY_URL);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
httpPost.setConfig(requestConfig);
StringEntity postEntity = new StringEntity(xml.toString(), "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 " + WeChatConfig.MCH_ID); // TODO: 很重要,用来检测 sdk 的使用情况,要不要加上商户信息?
httpPost.setEntity(postEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity, "UTF-8");
}
© 著作权归作者所有
举报
发表评论
0/200