在线支付系列【14】微信支付实战篇之Native支付下单
有道无术,术尚可求,有术无道,止于术。
文章目录
- Native支付
- 产品介绍
- 业务流程图
- 1. 下单
- 2. 支付
- 3. 并行处理
- Native下单API
- 案例演示
- 1. 环境搭建
- 2. 创建商户订单
- 3. 集成微信支付下单API
- 4. 测试
Native支付
产品介绍
Native支付
是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。
开通流程:在入驻时选择PC网站场景的商户系统默认开通此功能,其他商户如有需要,可以在入驻后前往商户平台-产品中心-Native支付-申请开通。
应用场景:适用于PC网站、实体店单品或订单、媒体广告支付等场景。
具体操作流程如下:
步骤一: 商户根据微信支付的规则,为不同商品生成不同的二维码(如图3.1),展示在各种场景,用于用户扫描购买。
步骤二: 用户使用微信“扫一扫”(如图3.2)扫描二维码后,获取商品支付信息,引导用户完成支付(如图3.3)。
步骤三: 用户确认支付,输入支付密码(如图3.4)。
步骤四: 支付完成后会提示用户支付成功(如图3.5),商户后台得到支付成功的通知,然后进行发货处理。
业务流程图
1. 下单
用户在PC网站购买商品,选中后,提交订单,商户后台系统收到后,生成商品订单(1)。
生成订单后,商户后台系统调用微信支付Native下单API(2)。
商户调用Native
下单API
后,分正常返回和异常返回情况:
- 正常返回:返回
code_url
,商户可根据返回的code_url
来生成调用OpenSDK
的签名以执行下一步。 - 异常返回:返回
http code
或错误码,商户可根据http code
列表 或错误码说明来排查原因并执行下一步操作
微信支付生成预支付交易订单,也就是微信那边的支付订单,并返回支付二维码链接code_url
,(3)。
商户根据返回的code_url
生成二维码供用户扫描。成功获取支付二维码链接(code_url)
后,需要在前端生成二维码供用户扫描支付(4)。
二维码链接对应格式:
weixin://weixin://pay.weixin.qq.com/bizpayurl/up?pr=NwY5Mz9&groupid=00
生成二维码见下图:
注意事项:
- 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。二维码的有效期是2小时。
- 微信支付已经不支持通过长按识别二维码的方式或通过相册识别二维码的方式完成支付。
更多二维码的相关背景知识可参考文档。
2. 支付
生成二维码后,用户使用微信扫一扫二维码,提交扫码链接给微信支付(5)。
微信支付验证链接有效性,并返回需要用户支付授权(6)。
用户确认并输入密码支付,提交支付授权给微信支付(7)。
微信支付验证授权,完成支付交易(8)。
3. 并行处理
在完成支付交易后,微信会返回支付结果,发送微信消息提醒(9)。
用户支付是不经过商家的,商家需要通过以下两种方式获取订单状态:
- 支付结果通知:用户支付成功后,微信支付会将支付成功的结果以回调通知的形式同步给商户,商户的回调地址需要在调用下单API时传入
notify_url
参数(10)。 - 主动调用:当因网络抖动或本身
notify_url
存在问题等原因,导致无法接收到回调通知时,商户也可主动调用查询订单API来获取订单状态(11)。
用户支付,商家收到支付成功消息,进行发货操作(12)。
Native下单API
商户Native
支付下单接口,微信后台系统返回链接参数code_url
,商户后台系统将code_url
值生成二维码图片,用户使用微信客户端扫码后发起支付。
适用对象: 直连商户
请求URL:https://api.mch.weixin.qq.com/v3/pay/transactions/native
请求方式:POST
详细接口描述,参考官方Native下单API。
案例演示
1. 环境搭建
引入以下框架:
- hutool
- mybatis-plus
- springdoc
创建商品表、订单表。(注:在上篇微信支付之Spring Boot集成官方SDK文档基础上进行操作)
使用代码生成器生成基础代码。
2. 创建商户订单
创建订单状态枚举类:
@AllArgsConstructor
@Getter
public enum OrderStatusEnum {SUCCESS(0, "支付成功"),NOT_PAY(1, "未支付"),CLOSED(2, "超时已关闭"),CANCEL(3, "用户已取消"),REFUND_PROCESSING(4, "退款中"),REFUND_SUCCESS(5, "已退款"),REFUND_ABNORMAL(6, "退款异常");/*** 状态码*/private final int code;/*** 描述*/private final String desc;
}
在商户订单服务层编写创建商户订单逻辑:
@Transactionalpublic OrderEntity saveOrder(String userId, String goodsId) {GoodsEntity goods = goodsService.getById(goodsId);if (ObjectUtil.isNull(goods)) {throw new IllegalArgumentException("未查询到当前商品信息");}OrderEntity order = new OrderEntity();order.setCount(1);order.setMoney(1);// 1分order.setUserId(userId);order.setGoodId(goodsId);order.setStatus(OrderStatusEnum.NOT_PAY.getCode());// 1 未支付order.setOutTradeNo(IdUtil.fastSimpleUUID()); // 商户订单号 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一save(order); // 保存订单log.info("订单创建成功:" + order);return order;}
3. 集成微信支付下单API
创建Native支付 API枚举类,封装所有API
接口地址。
@AllArgsConstructor
@Getter
public enum WechatPayNativeApiEnum {PLACE_ORDER("https://api.mch.weixin.qq.com/v3/pay/transactions/native", "下单");/*** API地址*/private final String address;/*** 描述*/private final String desc;
创建微信支付服务层接口,集成所有微信支付API的逻辑都在这里。
public interface WechatPayService {/*** Native下单并支付** @param userId 用户ID* @param goodsId 商品ID* @return 二维码Base64字符串*/String saveOrderAndPay(String userId, String goodsId) throws Exception;/*** Native下单,返回支付二维码链接*/String nativePay(String merchantId, String appId, String description, String outTradeNo, String notifyUrl, Integer total) throws Exception;}
编写微信支付服务层实现类,实现下单并生成支付二维码功能。
@Slf4j
@Service
@RequiredArgsConstructor
public class WechatPayServiceImpl implements WechatPayService {private final OrderService orderService;private final GoodsService goodsService;private final WechatPayProperties wechatPayProperties;private final ObjectMapper objectMapper;private final CloseableHttpClient httpClient;@Overridepublic String saveOrderAndPay(String userId, String goodsId) throws Exception {// 1. 新增订单OrderEntity order = orderService.saveOrder(userId, goodsId);GoodsEntity goods = goodsService.getById(order.getGoodId());// 2. 调用微信Native下单String codeUrl = nativePay(wechatPayProperties.getMerchantId(),wechatPayProperties.getAppId(),goods.getShopName() + "-" + goods.getName(),order.getOutTradeNo(),"https://www.weixin.qq.com/wxpay/pay.php",order.getMoney());order.setCodeUrl(codeUrl);orderService.updateById(order);// 保存订单二维码// 3. 返回二维码图片QrConfig qrConfig = new QrConfig(300, 300);return QrCodeUtil.generateAsBase64(codeUrl, qrConfig, "png");}@Overridepublic String nativePay(String merchantId, String appId, String description, String outTradeNo, String notifyUrl, Integer total) throws Exception {// 构建POST请求HttpPost httpPost = new HttpPost(WechatPayNativeApiEnum.PLACE_ORDER.getAddress());httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type", "application/json; charset=utf-8");// 使用JSON库,构建请求参数对象ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("mchid", merchantId) // 直连商户号.put("appid", appId) // 应用ID.put("description", description)// 商品描述.put("notify_url", notifyUrl) // 通知地址.put("out_trade_no", outTradeNo);// 商户订单号rootNode.putObject("amount") // 订单金额对象.put("total", total); // 总金额,单位为分objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));// 执行请求CloseableHttpResponse response = httpClient.execute(httpPost);// 获取响应String bodyAsString = EntityUtils.toString(response.getEntity());int statusCode = response.getStatusLine().getStatusCode();// 响应状态码if (statusCode != 200) {throw new RuntimeException("下单失败");}// 返回二维码Map<String, String> resultMap = objectMapper.readValue(bodyAsString, Map.class);return resultMap.get("code_url");}
}
添加商户下单访问接口。
@RestController
@RequestMapping("/pay/wechat")
@RequiredArgsConstructor
@Tag(name = "WechatPayController")
public class WechatPayController {private final WechatPayService wechatPayService;@Operation(summary = "下单")@PostMapping("/native")public R<String> nativeOrder(String userId, String goodsId) throws Exception {String pay = wechatPayService.saveOrderAndPay(userId, goodsId);return R.success(pay);}
}
4. 测试
启动项目,Swagger
访问下单接口。
返回响应如下:
打开Base64
转图片工具,输入Base64
字符串转为图片(实际开发时前端负责生成二维码)。
打开微信扫一扫,弹出支付页面,输入密码,交易成功。
在线支付系列【14】微信支付实战篇之Native支付下单相关推荐
- QCC304x系列开发教程(实战篇) 之 QCC3040之RF测试
查看全部教程开发请点击:高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看本文全部文章请点击:QCC304x系列开发教程(实战篇) 之 QCC3040之RF测试 更新记录链接:QCC514x- ...
- QCC304x系列开发教程(实战篇) 之 QCC304x之DFU(固件升级)
高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看全部文章地址QCC304x系列开发教程(实战篇) 之 QCC304x之DFU(固件升级)_心跳包的博客-CSDN博客 版权归作者所有,未经允许 ...
- QCC304x系列开发教程(实战篇) 之5.3 QCC3040之QACT用户指南
高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看全部文章地址QCC304x系列开发教程(实战篇) 之5.3 QCC3040之QACT用户指南_心跳包的博客-CSDN博客 版权归作者所有,未 ...
- QCC304x系列开发教程(实战篇)之4.2QCC3040之MDE按键导入配置
查看全部教程开发请点击:高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看本文全部文章请点击:QCC304x系列开发教程(实战篇)之4.2QCC3040之MDE按键导入配置 ========= ...
- QCC304x系列开发教程(实战篇) 之10.2 QCC3040之教你调试入仓和出仓情景下的程序运行
查看全部教程开发请点击:高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看本文全部文章请点击:QCC304x系列开发教程(实战篇) 之10.2 QCC3040之教你调试入仓和出仓情景下的程序运 ...
- QCC304x系列开发教程(实战篇)之5.2 QCC3040之提示音
查看全部教程开发请点击:高通蓝牙耳机QCC304x开发详解汇总(持续更新中) 查看本文全部文章请点击:QCC304x系列开发教程(实战篇)之5.2 QCC3040之提示音 更新记录链接:QCC514x ...
- 聚合支付,实现微信和支付宝扫一码支付
聚合支付,实现微信和支付宝扫一码支付 1 目标 我们要实现的目标是:用微信客户端扫二维码的时候,用微信支付,用支付宝扫二维码的时候用支付宝支付.这就要求我们对微信和支付宝做一个聚合,在平台内做一个客户 ...
- python手机代码编辑器_Python入门系列14 - 代码编辑器PyCharm篇
Python入门系列14 代码编辑器PyCharm篇 本篇文字为2412字,阅读时间约为7分钟. 1 前言 古人云:工欲善其事必先利其器!写代码也一样,虽然好多人都说,初学者不推荐使用很高大上,智能, ...
- 调试系列2:bugreport实战篇
原址 一.Bugreport 文章Bugreport源码篇(一)从源码角度阐释了Bugreport,那么本文则是从实战角度来说说,如何看懂bugreport,对于通过bugreport获取到内容往往非 ...
最新文章
- 第二十二章:动画(十四)
- attr与prop的区别
- MaxCompute在电商场景中如何进行漏斗模型分析
- 去掉viewstate保持在页面中的一大串字符的方法
- 飞鸽传书:造假与成功
- mysql 远程登陆设置_MYSQL远程登录权限设置
- 【转载】你不得不知道的深度学习网络画图工具
- 计算机网络中使用最广泛的交换技术是什么,04741计算机网络原理试题及答案201604...
- MOOS学习笔记3——命令行
- 基于OptiSystem的波分+时分复用混合光网络系统
- “网络蚂蚁”的Java实现
- 模电八:集成运算放大器(下)
- 网络1711班 C语言第七次作业批改总结
- 福禄克FLUKE光纤测试仪OTDR OFP系列
- 计算机显示桌面图标不见了,电脑显示器桌面图标不见了怎么办
- 腹肌锻炼视频(01):四种方法打造完美腹肌
- Nginx基础篇-Nginx的编译参数
- 计算机声音音乐小星星,迷你世界电路音乐教学 小星星音乐电路
- PC端生成小程序二维码海报并下载
- 常见问题:try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候执行?
热门文章
- BSL215C INFINEON 英飞凌 电子元器件
- 面试六十家公司的深圳体验(转贴)
- js三座大山之异步-微任务宏任务区别
- 从1G到5G,46年屏幕变化下,富士康、乐动体育、苹果、三星、华为的浴火重生路
- SpringBoot中注入RedisTemplate泛型异常
- python ElementTree解析xml
- Python-简单小说爬虫(以《天官赐福》为例)
- Intellij IDEA 调试功
- Hybrid TLB Coalescing:Improving TLB Translation Coverage under Diverse Fragmented Memory Allocations
- c++ socket服务器端和客户端实例(实现简单监控功能)