Java实现Native微信支付 超完整流程!!!
前言:最近公司准备在平板“***App”订单页面新建收款页完成收款功能,实现 微信扫码、支付宝扫码、网银扫码 收款功能。
- 项目环境介绍
- 微信支付文档
2.1 业务流程说明 - 前期准备
3.1 微信公众账号如何获取?
3.2 商户号如何获取?
3.3 API密钥如何获取? - 后端接口编写
4.1 依赖和工具类
4.2 生成二维码链接接口
4.3 查询订单支付状态接口
4.4 关闭交易订单接口
4.5 统一下单支付成功之后回调通知接口
总结
1.项目环境介绍
jdk 1.8
postgresql(远程)
maven 3.6.2
备注(该文章只展示后端实现流程)
2. 微信支付文档
官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 选择Native支付
2.1 业务流程说明
1.根据公司系统订单,新建收款,触发后端接口“生成微信支付二维码”,后端返回二维码链接code_url给前端,前端转成二维码,用户通过微信扫码支付。
2.通过接口生成支付链接后,触发后端接口“查询订单支付状态”该接口在指定的一个时间内重复校验,在规定时间内状态都为未支付状态,则系统判定支付失效,给前端返回"二维码失效",触发后端“关闭订单接口”。
3.二维码展示给客户,客户支付完成之后完成业务逻辑,修改订单状态,生成订单信息等等。调“支付成功回调接口”
3. 前期准备
3.1 获取微信公众账号
公众账号ID是什么:微信支付分配的公众账号ID(公众号appid)
申请地址:https://mp.weixin.qq.com/
该地址申请公众号,完成之后会分配公众号appId.公众号可关联
3.2 商户号如何获取?
商户号是什么:微信支付分配的商户号,关联公众号
申请地址:https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal
3.3 API密钥如何获取?
获取地址:https://mp.weixin.qq.com/
该地址申请公众号,完成之后会分配AppSecret
4. 后端接口编写
4.1 依赖和工具类
在pom 文件引入微信支付 SDK 依赖
<!-- 微信支付 SDK -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
自定义微信支付工具类
import org.apache.commons.lang.StringUtils;
/**
* 自定义微信支付工具类
*
* @author: fuqin
* @date: 2022/1/7
*/
public class CommonUtil {
/**
* 发送 http 请求
*
* @param requestUrl 请求路径
* @param requestMethod 请求方式(GET/POST/PUT/DELETE/...)
* @param outputStr 请求参数体
* @return 结果信息
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取ip
*
* @param request 请求
* @return ip 地址
*/
public static String getIp(HttpServletRequest request) {
if (request == null) {
return "";
}
String ip = request.getHeader("X-Requested-For");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader(