课程目标
掌握二维码生成插件qrious的使用
能够说出微信支付开发的整体思路
能够调用微信支付接口(统一下单)生成支付二维码
能够调用微信支付接口(查询订单)查询支付状态
实现支付日志的生成与订单状态的修改
一. 二维码
1.1 什么是二维码
二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。
图示:
1.2 二维码的优势:
信息容量大, 可以容纳多达1850个大写字母或2710个数字或500多个汉字
应用范围广, 支持文字,声音,图片,指纹等等…
容错能力强, 即使图片出现部分破损也能使用
成本低, 容易制作
1.3 二维码的容错级别:
L级(低) 7%的码字可以被恢复。
M级(中) 的码字的15%可以被恢复。
Q级(四分)的码字的25%可以被恢复。
H级(高) 的码字的30%可以被恢复。
二. 二维码生成插件qrious:
2.1 qrious是一款基于HTML5 Canvas的纯JS二维码生成插件。通过qrious.js可以快速生成各种二维码,你可以控制二维码的尺寸颜色,还可以将生成的二维码进行Base64编码。
2.2 qrious.js二维码插件的可用配置参数如下:
方块确定方位,黑色代表1,白色代表0
三. 微信扫码支付
3.1 介绍:
微信扫码支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于 PC 网站支付、实体店单品或订单支付、媒体广告支付等场景。
3.2 申请步骤:(了解)
第一步:注册公众号(类型须为:服务号)
请根据营业执照类型选择以下主体注册:个体工商户| 企业/公司| 政府| 媒体| 其他类型。
第二步:认证公众号
公众号认证后才可申请微信支付,认证费:300 元/次。
第三步:提交资料申请微信支付
登录公众平台,点击左侧菜单【微信支付】,开始填写资料等待审核,审核时间为 1-5个工作日内。
第四步:开户成功,登录商户平台进行验证
资料审核通过后,请登录联系人邮箱查收商户号和密码,并登录商户平台填写财付通备付金打的小额资金数额,完成账户验证。
第五步:在线签署协议
本协议为线上电子协议,签署后方可进行交易及资金结算,签署完立即生效。
四. 微信支付SDK
4.1 微信支付接口调用的整体思路:
按 API 要求组装参数,以 XML 方式发送(POST)给微信支付接口(URL),微信支付接口也是以 XML 方式给予响应。程序根据返回的结果(其中包括支付 URL)生成二维码或判断订单状态
简单来讲:通过URL将一些参数告诉给微信,然后接受返回值生成二维码
4.2 释义:
appid:微信公众账号或开放平台 APP 的唯一标识
mch_id:商户号 (配置文件中的 partner)
partnerkey:商户密钥
sign:数字签名, 根据微信官方提供的密钥和一套算法生成的一个加密信息, 就是为了保证交易的安全性【每次都不同】
4.3 微信支付SDK
微信支付提供了 SDK, 下载后打开源码,install 到本地仓库;
导入依赖:
4.4 我们主要会用到微信支付 SDK 的以下功能:
获取随机字符串
五. 查询状态
5.1 思路:
前端循环调用后端
后端循环调用微信支付查询结果,前端调用后端
5.2 交易状态类型:
SUCCESS: 支付成功
REFUND : 转入退款
NOTPAY: 未支付
CLOSED: 已关闭
REVOKED: 已撤销
USERPAYING: 用户支付中
PAYERROR: 支付失败(其他原因,银行返回失败)
支付状态机等可以查看相关文档
六. 支付日志需求
6.1 思路:
在用户下订单时,判断如果为微信支付,就向支付日志表添加一条记录,信息包括支付总金额,订单id(多个),用户id,下单时间等信息,支付状态为0(未支付);
生成的支付日志对象放入reids中,以用户id作为key,这样在生成支付二维码时就可以从redis中提取支付日志对象中的金额和订单号;
当用户支付成功后,修改支付日志的支付状态为1(已支付),并记录微信传递给我们的交易流水号。根据订单id(多个)修改订单的状态为2(已付款).
七. 微信支付准备:
7.1 业务流程:
选择商品以及相应的规格和数量后点击"加入购物车"。
当加入购物车后跳转到购物车列表页面,对收货地址,商品添加或者删除等操作后点击"结算"
当带着参数进入结算页的时候,首先对使用微信支付和货到付款等方式进行判断,然后跳转到相应的页面
页面通过与微信官方交互然后自动生成二维码,用户扫码之后显示"付款成功"或者"付款失败"等.
7.2 技术分析[准备阶段]:
微信支付功能必须为服务号才能申请微信付款功能,这个由公司完成并提供给我们相关的账户和密码;
查看微信支付SDK文档,获取大概的流程;
首先应该在本地仓库中配好微信支付SDK的jar包,并引入微信支付SDK的依赖
八. 支付流程图
九. 流程及代码
9.1 首先生成微信二维码:
准备:
通过HttpClient工具类实现对远程支付接口的调用
参考文档:统一下单API
开始:
创建一个map集合,将需要发送给微信的数据存入map集合内
通过HttpClient发送给微信
获取XML结果后调用WXPayUtil工具类将它转为Map格式的数据
创建一个新的Map集合,将获取的结果存入新建的map集合内 【这里的数据是要展现给前端的,所以只存一些需要展示的,不必所有都存入,否则安全性有影响】
将集合返回
建立一个生成微信二维码的方法,调用雪花算法将订单号和支付类型作为方法参数调用,将得到的map集合返回上去;
建立一个本地支付的方法,指向
建立一个本地生成二维码的方法,前端页面调用此方法进行查询后端,获取结果后得到订单编号和金额大小,同时在这里生成二维码,将订单编号和金额大小都返回到前端页面;
pay.html:
首先引入js相关文件,创建二维码的js文件,以及绑定初始调用ng-init生成二维码功能
将放置二维码图片的地方
显示订单:订单号: 显示金额:¥{{money}}元
9.2 然后,检测支付状态:
准备:
需求:
当用户支付成功的时候我们应该跳转到成功页面,提示:恭喜您,付款成功啦!,支付方式:微信支付 支付金额:xxxx元
当用户支付失败的时候我们应该跳转到失败页面,提示:支付失败,请稍后再试! 失败原因:… 提供一个重新支付按钮以及跳转到品优购首页的功能
实现思路:
我们可以通过HttpClient工具类实现对远程支付接口的调用
微信接口链接:
参考文档: 查询订单API
思路:
我们可以在后端建立查询状态方法,方法内通过循环查询,如果获取到结果则进行判断:
如果结果为Null,则返回空map集合,
前端进行循环调用查询状态方法。前端controller.js对返回的结果进行判断:
开始:
创建查询状态方法,接收参数订单编号
实现查询状态方法,新建一个HashMap,然后存入公众号id,商户号id,订单号,随机字符串,以及查询订单状态的url地址;
【URL地址是微信提供的,其他通过配置文件注入和参数接收】
通过WXPayUtil将Map集合转为XML格式的字符串,然后通过HttpClient传入url地址发送获取状态;
接收状态并将其转为Map集合,然后返回结果,如果获取失败则打印异常;
1. 先定义一个实体类
2. 循环调用Service层的查询订单状态方法并获取返回值;
3. 对返回值进行判断,如果
5. 线程等待每3秒执行一次
创建查询状态方法并指向查询状态的地址和方法,传给它订单编号;
中创建查询状态方法,方法中对返回结果进行判断,
- 如果返回结果为true,则跳转到支付成功页面
- 如果返回结果为false,则跳转到失败页面
将该方法在createNative生成二维码的时候进行调用,这样在二维码生成的时候就完成了查询订单状态的功能;
因为二维码是初始化init就进行调用,所以生成二维码开始起就可以对二维码状态进行查询;
9.3再然后,我们需要加一个查询时间限制
准备:
需求:
如果用户到了二维码页面一直未支付,或是关掉了支付页面,我们的代码会一直循环调用微信接口,这样会对程序造成很大的压力。所以我们要加一个时间限制或是循环次数限制,当超过时间或次数时,跳出循环。
实现思路:
可以在中的查询状态方法内定义一个计时器,
在 前端中中再添加一个判断,如果成功则跳转,如果失败则进行判断,如果返回的结果是二维码超时,则重新生成二维码,否则就跳转到失败页面;
、
9.4 再然后,支付成功页面我们应该显示金额
准备:
需求:现在我们支付成功页面显示的是固定的值,怎么显示真正的支付金额呢?我们这里可以使用 angularJS 的页面传参来解决
实现思路:
中的查询支付状态方法内,如果返回的result是true,支付成功,那么我们在跳转到支付成功页面的时候应该传入参数:$scope.money [付款金额]
开始:
:
- 跳转页面传参,当支付成功后跳转到成功页面的时候传入付款金额
- 用表达式显示金额:
支付金额:¥{{getMoney()}}元
9.5 最后,我们应该添加一个支付日志的功能
准备:
需求:
- 系统中无法查询到支付记录
- 支付后订单状态没有改变
实现思路:
在用户下订单时,判断如果为微信支付,就想支付日志表添加一条记录,信息包括支付总金额、订单 ID(多个)、用户 ID 、下单时间等信息,支付状态为 0(未支付)
生成的支付日志对象放入 redis 中,以用户 ID 作为 key,这样在生成支付二维码时就可以从 redis 中提取支付日志对象中的金额和订单号。
当用户支付成功后,修改支付日志的支付状态为 1(已支付),并记录微信传递给我们的交易流水号。根据订单 ID(多个)修改订单的状态为 2(已付款)。
分析表结构:根据需求我们应该独立建立一个订单支付日志表,它应该包含:支付订单号,创建事件,支付完成时间,支付金额,交易流水,交易状态,支付类型,订单表id串
具体思路[解决系统中无法查询到支付记录]:
interface:
* 首先我们在接口中创建一个通过用户id查询redis中订单的办法。
service:
然后在实现类中的生成二维码方法中先获取当前用户,
通过当前用户userid查询redis返回一个payLog日志对象,
然后对其进行判断如果该日志不存在则返回一个【即这个值为null】
如果该日志存在,则将日志中的订单编号和商品金额作为参数调用返回;
具体思路[解决支付后订单状态没有改变]
创建一个修改订单状态的方法,并传入订单编号,和交易号的的方法;
首先要明确做的三件事情:
修改支付日志状态
修改关联的订单的状态
清除缓存中的支付日志对象
实现接口新建的修改订单状态方法
通过日志操作类通过订单编号查询到payLog对象,然后修改payLog对象内的属性,如交易状态,交易号等
通过日志类payLog()获取订单号列表然后查询到orderList值,
orderList的值为"xxx,xxx,xxx",我们可以通过spilt(",")方法获取到订单号数组。
遍历订单编号,通过订单操作类方法查询id值获得订单,如果订单存在则修改状态,并覆盖订单;
通过redisTemplate查找删除日志id;
在微信支付接口有成功返回状态时,调用修改状态的方法