注册微信商户
微信支付平台:https://pay.weixin.qq.com/index.php/core/home/login
开发文档
https://pay.weixin.qq.com/wiki/doc/api/index.html
这里以 Native 支付为例。
调用统一下单接口 → 等待微信回调。
栗子
添加 maven 依赖:
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
支付方法:
- 查看产品,可以找到 appid、mch_id、key(自定义,需要在平台配置)。
- 生成签名(sign):https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3
- notify_url:外网可以访问的回调地址。(需要在平台配置)
@RequestMapping(value = "/goPay")
public String goPay(@RequestParam("taskId") String taskId, ModelMap map) {
try {
Order order = orderService.get(taskId);
Map<String, String> param = new HashMap<String, String>();
param.put("appid", app_id);
String body = order.getRequestId();
param.put("body", body);
param.put("mch_id", mch_id);
String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");
param.put("nonce_str", nonce_str);
param.put("notify_url", notify_url);
String out_trade_no = taskId + "_" + new Date().getTime();
param.put("out_trade_no", out_trade_no);
param.put("spbill_create_ip", spbill_create_ip);
param.put("total_fee", order.getAmount() + "");
param.put("trade_type", trade_type);
String sign_0 = "appid=" + app_id + "&body=" + body + "&mch_id=" + mch_id + "&nonce_str=" + nonce_str + "¬ify_url=" + notify_url + "&out_trade_no=" + out_trade_no + "&spbill_create_ip=" + spbill_create_ip + "&total_fee=" + order.getAmount() + "&trade_type=" + trade_type + "&key=" + key;
String sign = DigestUtils.md5DigestAsHex(sign_0.getBytes()).toUpperCase();
param.put("sign", sign);
String xml = WXPayUtil.mapToXml(param);
String returnXml = HttpClientUtil.sendPost(placeanorder_url, xml);
Map<String, String> returnMap = WXPayUtil.xmlToMap(returnXml);
map.addAttribute("code_url", returnMap.get("code_url"));
map.addAttribute("order", order);
} catch (Exception e) {
e.printStackTrace();
}
return "wxpay";
}
生成二维码(QRCode):
- 微信的返回信息中的 code_url 是二维码的地址,但是不能直接显示,需要用
QRCode 转一下。 - QRCode:https://www.runoob.com/w3cnote/javascript-qrcodejs-library.html
<script type="text/javascript" src="http://static.runoob.com/assets/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="http://static.runoob.com/assets/qrcode/qrcode.min.js"></script>
<script>
var qrcode = new QRCode(document.getElementById("qrcode"), {
width: 200,
height: 200
});
function makeCode() {
var elText = document.getElementById("text");
qrcode.makeCode(elText.value);
}
makeCode();
</script>
<input id="text" type="hidden" th:value="${code_url}"/><br/>
<div id="qrcode" style="padding-left: 37%;"></div>
回调方法:
@RequestMapping(value = "/notify")
public String notify(HttpServletRequest request) throws Exception {
InputStream inStream = request.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
String result = "";
String line;
while ((line = in.readLine()) != null) {
result += line;
}
Map<String, String> returnMap = WXPayUtil.xmlToMap(result);
String out_trade_no = returnMap.get("out_trade_no");
if (out_trade_no != null && out_trade_no.contains("_")) {
out_trade_no = out_trade_no.split("_")[0];
Order order = new Order();
order.setRequestId(out_trade_no);
order.setPay(Integer.parseInt(returnMap.get("cash_fee")));
order.setState(2);
orderService.savePay(order);
}
return "redirect:/order/toOrder";
}
如果回调方法不能实现跳转,可以在页面加一个每秒执行的任务,查看订单的状态,如果完成了,就跳转到订单列表页。
window.setInterval(function () {
$.get("/order/getState?id=" + $("#id").val(), function (data) {
if (data == 2) {
location.href = "/order/toOrder";
}
})
}, 1000)