小程序微信支付
/**
* 小程序支付
*/
public JSONObject minMpPay(String reqBody) throws Exception {
//第一步获取prepay_id
String prepayId = WxPayV3Util.v3PayGet("v3/pay/transactions/jsapi", reqBody, wxPayConfig.getAmchId(), wxPayConfig.getMchSerialNo(), privateKey);
if (prepayId == null) {
return null;
}
//第二步获取调起支付的参数
return WxPayV3Util.wxMpUp(prepayId, wxPayConfig.getMpAppId(), privateKey);
}
reqBody:
官方参数
{
"mchid": "1900006XXX",
"out_trade_no": "1217752501201407033233368318",
"appid": "wxdace645e0bc2cXXX",
"description": "Image形象店-深圳腾大-QQ公仔",
"notify_url": "https://weixin.qq.com/",
"amount": {
"total": 1,
"currency": "CNY"
},
"payer": {
"openid": "o4GgauInH_RCEdvrrNGrntXDuXXX"
}
}
调用微信支付服务,返回预支付id:
/**
* 微信支付下单
*
* @param url 请求地址(只需传入域名之后的路由地址)
* @param jsonStr 请求体 json字符串 此参数与微信官方文档一致
* @param mercId 商户ID
* @param serialNo 证书序列号
* @param privateKey 私钥
* @return 订单支付的参数
* @throws Exception
*/
public static String v3PayGet(String url, String jsonStr, String mercId, String serialNo, PrivateKey privateKey) throws Exception {
String body = "";
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(url_prex + url);
//装填参数
StringEntity s = new StringEntity(jsonStr, charset);
s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
"application/json"));
//设置参数到请求对象中
httpPost.setEntity(s);
String post = getToken("POST", HttpUrl.parse(url_prex + url), mercId, serialNo, privateKey, jsonStr);
//设置header信息
//指定报文头【Content-type】、【User-Agent】
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Authorization",
"WECHATPAY2-SHA256-RSA2048 " + post);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, charset);
log.info("下单结果:{}", body);
}
EntityUtils.consume(entity);
//释放链接
response.close();
switch (url) {
//返回APP支付所需的参数
case "v3/pay/transactions/app":
//返回JSAPI支付所需的参数
case "v3/pay/transactions/jsapi":
return JSON.parseObject(body).getString("prepay_id");
//返回native的请求地址
case "v3/pay/transactions/native":
return JSON.parseObject(body).getString("code_url");
//返回h5支付的链接
case "v3/pay/transactions/h5":
return JSON.parseObject(body).getString("h5_url");
default:
return null;
}
}
getToken 方法(签名)
/**
* 生成组装请求头
*
* @param method 请求方式
* @param url 请求地址
* @param mercId 商户ID
* @param serialNo 证书序列号
* @param privateKey 私钥
* @param body 请求体
* @return 组装请求的数据
* @throws Exception
*/
static String getToken(String method, HttpUrl url, String mercId, String serialNo, PrivateKey privateKey, String body) throws Exception {
String nonceStr = UUID.randomUUID().toString().replace("-", "");
long timestamp = System.currentTimeMillis() / 1000;
String message = buildMessage(method, url, timestamp, nonceStr, body);
String signature = sign(message.getBytes("UTF-8"), privateKey);
return "mchid=\"" + mercId + "\","
+ "nonce_str=\"" + nonceStr + "\","
+ "timestamp=\"" + timestamp + "\","
+ "serial_no=\"" + serialNo + "\","
+ "signature=\"" + signature + "\"";
}
buildMessage方法--组装签名。对url进行编码
/**
* 组装签名加载
*
* @param method 请求方式
* @param url 请求地址
* @param timestamp 请求时间
* @param nonceStr 请求随机字符串
* @param body 请求体
* @return 组装的字符串
*/
static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
String canonicalUrl = url.encodedPath();
if (url.encodedQuery() != null) {
canonicalUrl += "?" + url.encodedQuery();
}
return method + "\n"
+ canonicalUrl + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ body + "\n";
}
生成签名
/**
* 生成签名
*
* @param message 请求体
* @param privateKey 私钥
* @return 生成base64位签名信息
* @throws Exception
*/
static String sign(byte[] message, PrivateKey privateKey) throws Exception {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privateKey);
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
微信小程序支付调起
/**
* 微信调起支付参数
* 返回参数如有不理解 请访问微信官方文档
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_1_4.shtml
*
* @param prepayId 微信下单返回的prepay_id
* @param appId 应用ID(appid)
* @param privateKey 私钥
* @return 当前调起支付所需的参数
* @throws Exception
*/
public static JSONObject wxMpUp(String prepayId, String appId, PrivateKey privateKey) throws Exception {
String time = System.currentTimeMillis() / 1000 + "";
String nonceStr = UUID.randomUUID().toString().replace("-", "");
String packageStr = "prepay_id=" + prepayId;
ArrayList<String> list = new ArrayList<>();
list.add(appId);
list.add(time);
list.add(nonceStr);
list.add(packageStr);
//加载签名
String packageSign = sign(buildSignMessage(list).getBytes(), privateKey);
JSONObject jsonObject = new JSONObject();
jsonObject.put("appid", appId);
jsonObject.put("timeStamp", time);
jsonObject.put("nonceStr", nonceStr);
jsonObject.put("packages", packageStr);
jsonObject.put("signType", "RSA");
jsonObject.put("paySign", packageSign);
return jsonObject;
}
/**
* 构造签名串
*
* @param signMessage 待签名的参数
* @return 构造后带待签名串
*/
static String buildSignMessage(ArrayList<String> signMessage) {
if (signMessage == null || signMessage.size() <= 0) {
return null;
}
StringBuilder sbf = new StringBuilder();
for (String str : signMessage) {
sbf.append(str).append("\n");
}
return sbf.toString();
}
官方文档参数