log.info("生成微信app支付订单");
String outTradeNo = IdWorker.get32UUID();//平台内部订单变化
BigDecimal amount = new BigDecimal(20);
log.info("调用统一下单api");
//调用统一下单api
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
//请求body参数
Gson gson = new Gson();
Map parmsMap = new HashMap<>();
parmsMap.put("mchid", mchId);
parmsMap.put("out_trade_no", outTradeNo);
parmsMap.put("appid", appid);
parmsMap.put("description", "本次下单");
parmsMap.put("notify_url", "微信支付回调地址");//地址必须白名单,可外网访问
Map amountMap = new HashMap();
//微信亦分为单位调整为*100
amountMap.put("total",amount.multiply(new BigDecimal("100")).intValue());
amountMap.put("currency", "CNY");
parmsMap.put("amount", amountMap);
String jsonParams = gson.toJson(parmsMap);
log.info("请求参数:" + jsonParams);
StringEntity entity = new StringEntity(jsonParams, "utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = wxPayClient.execute(httpPost);
try {
String bodyAsString = EntityUtils.toString(response.getEntity());
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
log.info("app下单成功,返回结果" + bodyAsString);
//插入数据库
} else if (statusCode == 204) { //处理成功,无返回Body
log.info("成功");
} else {
log.info("app下单失败,响应码=" + statusCode + ",返回结果=" + bodyAsString);
throw new IOException("request failed");
}
//响应结果
HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
String prepayId = resultMap.get("prepay_id");
log.info("生成prepayId:" + prepayId);
//appid 根据不同app适配 //privateKeyPath 商户私钥文件地址
JSONObject jsonObject = WxAppPayTuneUp(prepayId, appid, mchId, privateKeyPath);
log.info(jsonObject);
} finally {
response.close();
}
public static JSONObject WxAppPayTuneUp(String prepayId, String appId, String mchId, String privateKeyPath) throws Exception {
if (StringUtils.isNotBlank(prepayId)) {
long timestamp = System.currentTimeMillis() / 1000;
String nonceStr = generateNonceStr();
//加载签名
String packageSign = sign(buildMessage(appId, timestamp, nonceStr, prepayId).getBytes(), private_key_path);
JSONObject jsonObject = new JSONObject();
jsonObject.put("appId", appId);
jsonObject.put("prepayId", prepayId);
jsonObject.put("timeStamp", timestamp);
jsonObject.put("nonceStr", nonceStr);
jsonObject.put("package", "Sign=WXPay");
jsonObject.put("signType", "RSA");
jsonObject.put("sign", packageSign);
jsonObject.put("partnerId", mchId);
return jsonObject;
}
return new JSONObject();
}
/**
* 按照前端签名文档规范进行排序,\n是换行
*
* @param appId appId
* @param timestamp 时间
* @param nonceStr 随机字符串
* @param prepay_id prepay_id
* @return
*/
public static String buildMessage(String appId, long timestamp, String nonceStr, String prepay_id) {
return appId + "\n" + timestamp + "\n" + nonceStr + "\n" + prepay_id + "\n";
}
public static String sign(byte[] message, String privateKeyPath) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
//签名方式
Signature sign = Signature.getInstance("SHA256withRSA");
//私钥
sign.initSign(PemUtil.loadPrivateKey(new FileInputStream(privateKeyPath)));
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
支付微信回调
/**
* 微信支付成功后.异步请求该接口
*
* @param request
* @return
* @throws IOException
*/
@PostMapping("/weChatNotify")
public String nativeNotity(HttpServletRequest request, HttpServletResponse response) throws Exception {
Gson gson = new Gson();
// 应答对象
Map<String, String> map = new HashMap<>();
// 处理通知参数
String body = HttpUtils.readData(request);
JSONObject jsonObject = JSONObject.parseObject(body);
String eventType = (String) jsonObject.get("event_type");
JSONObject resource = (JSONObject) jsonObject.get("resource");
String associated_data = (String) resource.get("associated_data");
String nonce = (String) resource.get("nonce");
String ciphertext = (String) resource.get("ciphertext");
String UUID = UUID.randomUUID().toString().replaceAll("-", "");
AesUtil aesUtil = new AesUtil(UUID.getBytes());
String s = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
JSONObject jsonObject1 = JSONObject.parseObject(s);
String outTradeNo = jsonObject1.getString("out_trade_no");
try {
//如果微信返回状态为TRANSACTION.SUCCESS
if (eventType.equals("TRANSACTION.SUCCESS")) {
response.setStatus(200);
map.put("code", "TRANSACTION.SUCCESS");
map.put("message", "成功");
}
} catch (Exception e) {
throw new RuntimeException("更新工友豆数量失败!");
}
map.put("code", "ERROR");
map.put("message", "失败");
return gson.toJson(map);
}
/**
* 将通知参数转化为字符串
* @param request
* @return
*/
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder result = new StringBuilder();
br = request.getReader();
for (String line; (line = br.readLine()) != null; ) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}