证书

Get/Post请求微信API,以及sign加密
public class PayUtils {
private final static String SERIAL_NO = "xxx";
private final static String MCHID = "xxx";
private static final String SCHEMA = "xxx";
// sendGet请求
public static String sendGet(String url,String sign) throws URISyntaxException {
/** 获取连接客户端工具 **/
CloseableHttpClient httpClient = HttpClients.createDefault();
String entityStr = null;
CloseableHttpResponse response = null;
try {
/** 由于GET请求的参数都是拼装在URL地址后方,所以我们要构建一个URL,带参数 **/
URIBuilder uriBuilder = new URIBuilder(url);
/** 根据带参数的URI对象构建GET请求对象 **/
HttpGet httpGet = new HttpGet(uriBuilder.build());
/** 添加请求头信息 **/
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Authorization", SCHEMA + " " + sign );
/** 传输的类型 **/
httpGet.addHeader("Content-Type", "application/json");
/** 执行请求 **/
response = httpClient.execute(httpGet);
/** 获得响应的实体对象 **/
HttpEntity entity = response.getEntity();
entityStr = EntityUtils.toString(entity);
} catch (IOException e) {
e.printStackTrace();
}
return entityStr;
}
// sendPost请求
public static String sendPost(String url, String param, String sign) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
// conn.setRequestProperty("Charsert", "utf-8");
conn.setRequestProperty("Authorization", SCHEMA + " " + sign);
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
//HttpUrl httpurl = HttpUrl.parse(url);
//getToken
public static String getToken(String method, HttpUrl url, String body) throws Exception {
//32位随机字符串
String nonceStr = UUID.randomUUID().toString().replace("-", "").toString();
long timestamp = System.currentTimeMillis() / 1000;
//生成签名支付串--加密前
String message = buildMessage(method, url, timestamp, nonceStr, body);
String signature = sign(message.getBytes("utf-8"));
return "mchid=\"" + MCHID + "\","
+ "nonce_str=\"" + nonceStr + "\","
+ "timestamp=\"" + timestamp + "\","
+ "serial_no=\"" + SERIAL_NO + "\","
+ "signature=\"" + signature + "\"";
}
//需要sign加密
public static String sign(byte[] message) throws Exception {
Signature sign = Signature.getInstance("SHA256withRSA");
//需要通过密钥加密
PrivateKey privateKey = PemUtil.loadPrivateKey(new FileInputStream("证书放置的路径/src/main/resources/apiclient_key.pem"));
sign.initSign(privateKey); //密钥
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
public 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";
}
}
统一下单
- Controller
@RestController
public class WXPayController {
@Resource
PayService payService;
@RequestMapping("/pay")
public R pay(@RequestBody PayInfo payInfo) throws Exception {
return payService.pay(payInfo);
}
}
- Service
@Service
@PropertySource("classpath:pay.properties")
public class PayServiceImpl implements PayService {
@Value("${mchId}")
private String mchId;
@Value("${appId}")
private String appId;
@Value("https://weixin.qq.com/")
private String notify_url;
@Value("https://api.mch.weixin.qq.com/v3/pay/transactions/h5")
private String pay_url;
private Amount amount;
private Scene_info scene_info;
@Override
public R pay(PayInfo payInfo) throws Exception {
Map<String, Object> paraMap = new HashMap<String, Object>();
amount = new Amount(payInfo.getTotal(), "CNY");
scene_info = new Scene_info(payInfo.getPayer_client_ip(), new H5_info("Wap"));
paraMap.put("mchid", mchId);
paraMap.put("out_trade_no", payInfo.getOut_trade_no());
paraMap.put("appid", appId);
paraMap.put("description", payInfo.getDescription());
paraMap.put("notify_url", notify_url);
paraMap.put("amount", amount);
paraMap.put("scene_info", scene_info);
String body = JSON.toJSONString(paraMap);
HttpUrl httpUrl = HttpUrl.get(pay_url);
String sign = PayUtils.getToken("POST",httpUrl,body);
String result = PayUtils.sendPost(pay_url, body, sign);
String url = null;
if (result.indexOf("h5_url") != -1) {
url = (String)JSON.parse(result);
}else {}
return R.ok();
}
}
订单查询
- Controller
@RestController
@RequestMapping("/pay")
public class PayOrderQueryController {
@Resource
OrderQueryPayService orderQueryPayService;
@RequestMapping(value = "/orderquery")
public String orderQuery(String outTradeNo) {
return orderQueryPayService.orderQuery(outTradeNo);
}
}
- Service
@Service
@Slf4j
public class OrderQueryPayServiceImpl implements OrderQueryPayService {
@Override
public String orderQuery(String outTradeNo) {
String tradeState = null;
String body = "";
String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "?mchid=" + "1499322742";
HttpUrl httpUrl = HttpUrl.get(url);
try {
String sign = PayUtils.getToken("GET", httpUrl, body);
String result = sendGet(url, sign);
log.info("springboot系统-------微信返回字符串数据:" + result);
if (null == result || result.equals("") || result.isEmpty()) {
} else {
Map<String, Object> parseObject = JSONObject.parseObject(result, Map.class);
tradeState = String.valueOf(parseObject.get("trade_state"));//交易状态
}
} catch (Exception e) {
e.printStackTrace();
}
return tradeState;
}
}
优化post请求(使用cn.hutool.http.HttpUtil;)
public static String sendPost(String url, String param, String sign) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
// try {
// URL realUrl = new URL(url);
// // 打开和URL之间的连接
// URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
Map<String, Object> map = new HashMap<>();//存放参数
map.put("param", param);
HashMap<String, String> headers = new HashMap<>();//存放请求头,可以存放多个请求头
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/json");
headers.put("Authorization", SCHEMA + " " + sign);
//发送post请求并接收响应数据
result= HttpUtil.createPost(url).addHeaders(headers).body(param).execute().body();
// conn.setRequestProperty("Accept", "application/json");
// conn.setRequestProperty("Content-Type", "application/json");
// conn.setRequestProperty("Charsert", "utf-8");
// conn.setRequestProperty("Authorization", SCHEMA + " " + sign);
//
// // 发送POST请求必须设置如下两行
// conn.setDoOutput(true);
// conn.setDoInput(true);
// // 获取URLConnection对象对应的输出流
// out = new PrintWriter(conn.getOutputStream());
// // 发送请求参数
// out.print(param);
// // flush输出流的缓冲
// out.flush();
// // 定义BufferedReader输入流来读取URL的响应
// in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String line;
// while ((line = in.readLine()) != null) {
// result += line;
// }
// } catch (Exception e) {
// System.out.println("发送 POST 请求出现异常!" + e);
// e.printStackTrace();
// }
// //使用finally块来关闭输出流、输入流
// finally {
// try {
// if (out != null) {
// out.close();
// }
// if (in != null) {
// in.close();
// }
// } catch (IOException ex) {
// ex.printStackTrace();
// }
// }
return result;
}
推荐使用Post请求
public static String WXsendPost(String url, String param, String sign) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
// try {
// URL realUrl = new URL(url);
// // 打开和URL之间的连接
// URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
Map<String, Object> map = new HashMap<>();//存放参数
map.put("param", param);
HashMap<String, String> headers = new HashMap<>();//存放请求头,可以存放多个请求头
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/json");
headers.put("Authorization", SCHEMA + " " + sign);
//发送post请求并接收响应数据
result= HttpUtil.createPost(url).addHeaders(headers).body(param).execute().body();
// conn.setRequestProperty("Accept", "application/json");
// conn.setRequestProperty("Content-Type", "application/json");
// conn.setRequestProperty("Charsert", "utf-8");
// conn.setRequestProperty("Authorization", SCHEMA + " " + sign);
//
// // 发送POST请求必须设置如下两行
// conn.setDoOutput(true);
// conn.setDoInput(true);
// // 获取URLConnection对象对应的输出流
// out = new PrintWriter(conn.getOutputStream());
// // 发送请求参数
// out.print(param);
// // flush输出流的缓冲
// out.flush();
// // 定义BufferedReader输入流来读取URL的响应
// in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String line;
// while ((line = in.readLine()) != null) {
// result += line;
// }
// } catch (Exception e) {
// System.out.println("发送 POST 请求出现异常!" + e);
// e.printStackTrace();
// }
// //使用finally块来关闭输出流、输入流
// finally {
// try {
// if (out != null) {
// out.close();
// }
// if (in != null) {
// in.close();
// }
// } catch (IOException ex) {
// ex.printStackTrace();
// }
// }
return result;
}
服务端如何防止订单重复支付!
本文详细介绍了微信支付V3中如何使用Get和Post请求调用API,包括证书管理、统一下单及订单查询的实现过程。文章强调了使用Post请求的优化,推荐使用cn.hutool.http.HttpUtil工具类进行请求,并讨论了服务端防止订单重复支付的策略。

1万+

被折叠的 条评论
为什么被折叠?



