微信支付以前就听说过,身边的同事也有弄过,但是自己因为没有遇到相关业务因此也没有去研究过。最近工作上可能会遇到微信支付因此也进行了些许研究,只是做到了接口掉通而已,并没有太深入,对微信支付已经很熟悉的同学请绕道走。
微信支付你需要了解内容 1.微信支付常用支付模式JSAPI支付
JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模块完成收款。
APP支付
APP支付是指商户通过在移动端应用APP中集成开放SDK调起微信支付模块来完成支付。目前微信支付支持手机系统有:IOS(苹果)、Android(安卓)和WP(Windows Phone)
Native支付
Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。
小程序支付
2.各种模式使用场景商户已有微信小程序,用户通过好友分享或扫描二维码在微信内打开小程序时,可以调用微信支付完成下单购买的流程。
| 支付模式 | 使用场景 |
|---|---|
| JSAPI支付 | 线下场所、公众号场景和PC网站场景。 |
| APP支付 | APP支付适用于在移动端APP中集成微信支付功能的场景 |
| Native支付 | Native支付适用于PC网站、实体店单品或订单、媒体广告支付等场景 |
| 小程序支付 | 小程序中唤起支付界面 |
| 付款码支付 | ----- |
4.支付接口联调准备参数JSAPI支付:C端使用B端程序,B端直接拉起支付界面,由C端完成支付,如:微信支付中手机话费充值
APP支付:C端使用B端开发的APP时,在APP中拉起支付界面
Native支付:由B端生成一个支付二维码,然后C端进行扫码拉起支付界面支付,如:菜市场买菜时微信支付
小程序支付:和APP支付一个道理
由于支付涉及到商家,因此必须搞到商家相关的几个参数(自己注册成为商家是需要营业执照的,因此各位同学自己想办法吧),我测试的时候是直接用的别的企业的相关参数,所以不能共享出来的,所需参数内容,如下:
| 参数名称 | 参数讲解 |
|---|---|
| APPID | 由微信生成的应用ID,全局唯一。 |
| 商户号 | 直连商户的商户号,由微信支付生成并下发。 |
| 支付密钥 | 由商户提供用于进行验证支付 |
| 回调函数 | 由商户提供一个可外网访问的接口用于接收支付结果(不可带参数) |
| 商户订单号 | 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 |
微信支付其实对每个支付模式都提供了一套完整的api接口,每个支付模式在官网都有非常详情的Api文档,此处我研究的是Native支付,因此提供一个Native的文档参考地址。
接口调用提示:微信支付并不是我们所想的简单的调用一下接口就OK了,比如Native支付是需要我们先调用下单接口(自己指定一个不重复的订单号),生成一个订单并返回二维码链接,用户扫码支付完成后,微信会自动调用我们提供的回调地址,将支付结果反馈给我们。我们下单生成的订单也是有用处的,比如进行支付的订单查询,退款等等
此处我只实现了Native方式中的下单和回调函数的开发,至于其他接口也是同样的道理,大家可以举一反三。
1.下单接口@GetMapping("/pay/{orderId}")
public void wxPay(@PathVariable("orderId")String orderId, HttpServletResponse response) throws Exception {
// 产品相关参数
WeChatParams ps = new WeChatParams();
ps.setBody("商品描述");
// 商品价格,注意是以分为单位,后面不能有小数点
ps.setTotal_fee("1");
// 订单ID
ps.setOut_trade_no(orderId);
// 附加参数,随便设置
ps.setAttach(UUID.randomUUID().toString().replace("-",""));
SortedMap
2.将地址生成二维码工具方法
@SuppressWarnings({"unchecked", "rawtypes"})
public static void encodeQrcode(String content, HttpServletResponse response) {
if (StringUtils.isBlank(content)) {
return;
}
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
Hashtable hints = new Hashtable();
//设置容错级别最高
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//设置字符编码为utf-8
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
//二维码空白区域,最小为0也有白边,只是很小,最小是6像素左右
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = null;
try {
bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 250, 250, hints);
BufferedImage image = toBufferedImage(bitMatrix);
//输出二维码图片流
try {
response.setHeader("Content-Type", "image/jpeg");
ImageIO.write(image, "png", response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
} catch (WriterException e1) {
e1.printStackTrace();
}
}
private static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) == true ? BLACK : WHITE);
}
}
return image;
}
3.回调方法
@RequestMapping("/notify")
public void wechatNotifyUrlPc(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader reader = request.getReader();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String xmlString = buffer.toString();
request.getReader().close();
// 验证签名前不要修改reqParam中的键值对的内容,否则会验签不过
if (!WXPayUtil.isSignaturevalid(xmlString, WeChatProperties.apiKey)) {
System.out.println("验证签名结果[失败].");
} else {
Map map = XMLUtil.doXMLParse(xmlString);
String resultCode = map.get("result_code");
if ("SUCCESS".equalsIgnoreCase(resultCode)) {
// TODO 支付成功,做后续业务逻辑处理
System.out.println("支付成功,请继续作业");
} else {
// TODO 失败,做失败业务逻辑处理
System.out.println("支付失败,请排查原因");
}
}
// 响应微信端,阻止其持续调用
response.getWriter().write(" ");
}
小结
本文只是简单的贴出来核心的代码,并不是很全面,需要全面的代码的同学请移步到码云下载我的源码哈。本文的内容,经过清测,是可以调用并接收通知的,请大家放心使用。
源码地址:https://gitee.com/zhaobolan/wechat_pay_native



