大家好,我是小铁。一个有实力的逗比。
上一期咱们说到了微信授权以及获取用户头像和微信昵称,要是没有看的小伙伴们可以去看看。绝的不错的话可以点个赞并收藏一下。小铁在这里谢谢大家了。
新年快到了:实鼠不易,牛转乾坤。在新的一年大家一定都要加油哦!!!!
咱们现在讲一讲,如何用上一期讲到的获取到openid进行微信支付!!
一、【微信支付的前提准备】
微信支付文档
文档在上面,大家可以打开了。咱们一起去看看
- 老规矩,先看图
- 我只是截取出来一部分,大家可以去文档里面自己看去。
3.来,咱们直接上代码,边看边讲。
首先咱们需要导入,微信支付的sdk,就省的咱们拼接签名啥的了。要不即麻烦,又费事。拼错了,还可能导致支付不了。(如果不导入这个依赖的话,下面的“WXPayUtil”的这个方法会飘红的)
<!--微信支付-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
【准备工作】
1)到时候获取ip使用
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
2)调用微信预支付(发送请求)
public static Map<String,String> weChatToPay(Map<String, String> map) throws Exception {
//创建请求地址
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
httpClient.setHttps(true);
//请求参数设置
httpClient.setXmlParam(WXPayUtil.mapToXml(map));
//发送请求
httpClient.post();
//接收请求返回值
String content = httpClient.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) {
return resultMap;
}
throw new RuntimeException("微信调用失败");
}
3)封装了一个"httpClinet"工具类,本人还是建议封装一个
public class HttpClient {
private String url;
private Map<String, String> param;
private Map<String,Object> params;
private int statusCode;
private String content;
private String xmlParam;
private boolean isHttps;
public boolean isHttps() {
return isHttps;
}
public void setHttps(boolean isHttps) {
this.isHttps = isHttps;
}
public String getXmlParam(String content) {
return xmlParam;
}
public void setXmlParam(String xmlParam) {
this.xmlParam = xmlParam;
}
public HttpClient(String url, Map<String, String> param) {
this.url = url;
this.param = param;
}
public HttpClient(String url) {
this.url = url;
}
public void setParameter(Map<String, String> map) {
param = map;
}
public void addParameter(String key, String value) {
if (param == null) {
param = new HashMap<String, String>();
}
param.put(key, value);
}
public void post() throws ClientProtocolException, IOException {
HttpPost http = new HttpPost(url);
setEntity(http);
execute(http);
}
public void put() throws ClientProtocolException, IOException {
HttpPut http = new HttpPut(url);
setEntity(http);
execute(http);
}
public void get() throws ClientProtocolException, IOException {
if (param != null) {
StringBuilder url = new StringBuilder(this.url);
boolean isFirst = true;
for (String key : param.keySet()) {
if (isFirst) {
url.append("?");
} else {
url.append("&");
}
url.append(key).append("=").append(param.get(key));
}
this.url = url.toString();
}
HttpGet http = new HttpGet(url);
execute(http);
}
/**
* set http post,put param
*/
private void setEntity(HttpEntityEnclosingRequestBase http) {
if (param != null) {
List<NameValuePair> nvps = new LinkedList<NameValuePair>();
for (String key : param.keySet()) {
nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
}
http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
}
if (xmlParam != null) {
http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
}
}
private void execute(HttpUriRequest http) throws ClientProtocolException,
IOException {
CloseableHttpClient httpClient = null;
try {
if (isHttps) {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
@Override
public boolean isTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
} else {
httpClient = HttpClients.createDefault();
}
CloseableHttpResponse response = httpClient.execute(http);
try {
if (response != null) {
if (response.getStatusLine() != null) {
statusCode = response.getStatusLine().getStatusCode();
}
HttpEntity entity = response.getEntity();
// 响应内容
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
public int getStatusCode() {
return statusCode;
}
public String getContent() throws ParseException, IOException {
return content;
}
public Map<String, Object> getParams() {
return params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
}
正主来了,咱们现在需要拼内容了,如果你上面都是copy我的了,那这个你直接粘过去就能用了。
String userPayNumber = WxUtil.generateOrderSN();
Map<String,String> map = new HashMap();
map.put("appid", WxConstant.appId);//appid
map.put("body","测试支付");//支付说明
map.put("mch_id",WxConstant.mchId); //商户号
map.put("nonce_str",WXPayUtil.generateNonceStr());//随机字符串
map.put("notify_url","none"); //回调地址,写回调地址,能够通过外网访问到就可以
map.put("openid",openId); //opendid
map.put("out_trade_no",userPayNumber); //订单号
map.put("spbill_create_ip",getIpAddress.getIpAddress(request));//ip
map.put("total_fee","1"); //金额 默认为(分)
map.put("trade_type","JSAPI"); //交易类型
map.put("sign",WXPayUtil.generateSignature(map,WxConstant.return_sign));
//调用微信预支付
Map resultMap = WxUtil.weChatToPay(map);
//下面是返给前端需要的字符串
Map<String, String> jsapiParamMap = new HashMap<>();
String timestamp = String.valueOf(System.currentTimeMillis() / 1000); //时间戳
jsapiParamMap.put("appId",WxConstant.appId);//appid
jsapiParamMap.put("timeStamp",timestamp);//时间戳
jsapiParamMap.put("nonceStr",WXPayUtil.generateNonceStr());//随机字符串
jsapiParamMap.put("package","prepay_id="+resultMap.get("prepay_id"));//调用支付返回的prepay_id
jsapiParamMap.put("signType","MD5");//加密方式
jsapiParamMap.put("paySign",WXPayUtil.generateSignature(jsapiParamMap,WxConstant.return_sign));//签名
jsapiParamMap.put("userPayNumber",userPayNumber); //订单编号
return jsapiParamMap ; 这个就是返回给前端的内容
写完了,就会发现。有的小伙伴不知道怎么填写那个回调地址(第一次写这个微信支付,不知道道回调地址很正常,没事的慢慢来)!!!
直白点说,回调地址就是你微信支付成功了之后,需要给用户修改一系列的状态啥的。或者给用户添加一些信息什么的。。 就是在这个回调地址里面写那些需求和逻辑。
来,跟着我 一起写那个回调地址。
public String weChatPayCallBackAddress(HttpServletRequest request) {
try{
String resXml = "";
InputStream inStream;
inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String result = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> weChatInformMap = WXPayUtil.xmlToMap(result);
//支付成功
if("SUCCESS".equals(weChatInformMap.get("return_code")) && "SUCCESS".equals(weChatInformMap.get("result_code"))){
//获取用户的支付订单号,来进行后续的操作和需求
String payNumber = (String) weChatInformMap.get("out_trade_no");
//todo...
}
Map<String, String> returnMap = new HashMap<>();
returnMap.put("return_code","SUCCESS");
returnMap.put("return_msg","OK");
//支付消息返回给微信端
// return JSON.toJSONString(returnMap);
return WXPayUtil.mapToXml(returnMap);
} catch (Exception e) {
e.printStackTrace();
}
return "通知失败";
}
干货有点多,对于第一次写微信支付的小伙伴可能看的有点懵逼,没关系。一步一步的慢慢看,如果哪里看不懂过了,就在底下评论,小铁看见会回复的! 如果没回复请私信。
【最后的总结】
一般来说,小伙伴们一般都在微信签名的时候会很痛苦,不知道这个签名怎么拼接出来。如果你按照我的上面说的那种来写的话,不需要考虑ASCLL顺序的问题,第三方提供的sdk就帮咱们解决了。 如果,你从微信的那个签名校验哪里能够把签名校验过去的话而放到代码里面,就报错,显示签名错误。这种一般都是你的key,openid,商户号 ,appid 其中一个或者多个错误了,还有注意,那些必填的里面内容一定不能为空,自己debug跑一便,看看内容是否为空。如果为空了,签名也是有可能错误的。
加油吧!亲爱的小伙伴们!!!
为了我们的高薪,一起努力。
最后,这篇微信支付也算完成了,2021年,我们一起牛转乾坤。加油!!!
如果你觉的小铁的文章写的不错的话就行点个关注点个赞转发一下吧!!!