第8章 莫凡商城的支付功能及订单详情页设计
第8章莫凡商城的支付功能及订单详情页设计
在一个购物狂欢节的筹备中,工程师正在为微信小程序添加新功能。
他们想让用户在购买商品时能够方便快捷地完成支付,深入研究了微信小程序的支付API之后,通过调用接口,成功实现了从商品选择到支
付的整个流程。同时,为了提升用户体验,工程师还利用画布组件和画布API,在支付成功后的页面上绘制了一个庆祝的动画,用户看到后
纷纷表示惊喜和满意。通过微信小程序支付API和画布功能的结合使用,工程师成功地为用户带来了既实用又有趣的购物体验。
微信小程序只能使用微信支付这一种支付方式。支付是小程序常用的功能,微信小程序提供了支付相关API。本章将介绍支付功能设计,以
及支付功能实现的整个流程。画布组件及画布API可用来自定义一些页面,如设计分享页面,可以通过页面生成图片然后进行分享,这时就
可以使用画布组件及画布API来实现页面生成图片的功能。

8.1支付API
微信小程序支付功能的实现步骤如下。
(1)微信小程序调用wx.login(),获取用户登录凭证code。
(2)微信小程序将用户登录凭证code传输给开发者后台服务器。
(3)开发者后台服务器根据用户登录凭证code向微信服务器请求获取唯一标识openid。
(4)商户后端服务器获取到唯一标识openid后,调用统一下单支付接口,获取预支付交易会话标识prepay_id。
(5)商户后端服务器调用签名,并返回支付需要使用的参数。
(6)微信小程序调用wx.requestPayment()发起微信支付。
(7)商户后端服务器接收微信服务器的通知并处理微信服务器返回的结果。
微信小程序提供了微信支付接口,可以使用wx.requestPayment()来进行微信支付,其参数说明如表8.1所示。
表8.1 wx.requestPayment()的参数说明
属性类型是否必填说明
timeStampstring是时间戳,从1970年1月1日00:00:00至今的秒数
nonceStrstring是随机字符串,长度为32个字符以下
packagestring是统一下单支付接口返回的prepay_id参数值,提交格式为prepay_id=*
signTypestring是签名算法,支持MD5、HMAC-SHA256、RSA
paySignstring是签名,具体签名方案见微信支付文档
successfunction否接口调用成功的回调函数
failfunction否接口调用失败的回调函数
completefunction否接口调用结束的回调函数(调用成功、失败都会执行)
示例代码如下:
wx.requestPayment({
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
success:function(res){
},
fail:function(res){
}
})
除了可以使用wx.requestPayment()来进行微信支付之外,从基础库 2.22.1版本开始支持在插件中发起微信支付,需要使用
wx.requestPluginPayment(),其参数说明如表8.2所示。
表8.2 wx.requestPluginPayment()的参数说明
属性类型是否必填说明
versionstring是插件版本。develop为开发版,trial为体验版,release为正式版
feenumber是显示在页面中的金额,单位为元
paymentArgsobject是显示在页面中的货币符号的代码,默认值:CNY
currencyTypestring否显示在页面中的货币符号的代码,默认值:CNY
successfunction否接口调用成功的回调函数
failfunction否接口调用失败的回调函数
completefunction否接口调用结束的回调函数(调用成功、失败都会执行)

注意
(1)小程序与插件绑定在同一个微信开放平台账号上,且小程序与插件均为微信开放账号的同主体/关联主体时,调用此接口将直接唤起收银台。
(2)这个接口本身可以在微信开发者工具中使用,但功能页的跳转目前不支持在微信开发者工具中调试,请在真机上测试。
(3)跳转到支付功能页需要在app.json文件中配置 "functionalPages": true。
示例代码如下:
wx.requestPluginPayment({
version: 'release',
fee: 100,
paymentArgs: {},
currencyType: 'CNY',
success:function(res){
},
fail:function(res){
}
})
8.2项目实战:使用AI编程工具辅助实现支付功能1
.任务目标
实现莫凡商城小程序的支付功能,学习微信支付功能的相关知识。
莫凡商城小程序在提交订单页和订单详情页都可以发起商品支付,系统将计算出需要支付的总金额,并发起支付。本节实现订单详情页发
起商品支付功能,图8.1展示了提交订单页。

图8.1 提交订单页
2.任务实施
打开通义灵码,输入“微信小程序实现提交订单页发起商品支付功能,只需要给出JS部分。”并发送,如图8.2所示。

图8.2 发送需求
3.AI生成
通义灵码根据需求生成了实现支付功能的代码,图8.3展示了通义灵码生成提交订单页发起商品支付功能。

图8.3 通义灵码生成提交订单页发起商品支付功能
4.优化建议
在运行AI生成的代码后,发现其结果与我们的实际需求还有一定的差距,可以在以下两个方面进行优化。
- 对于微信支付这种功能,等到代码生成完毕之后,可以通过查看微信
官方API进行对比和修改。
- 对于这种只需要逻辑的功能,我们只需要生成JS部分。
8.3画布组件及画布API
利用canvas组件可以自定义一些图像或者图形,如绘制正方形、圆形等形状,也可以将页面生成图片。
canvas组件默认宽度为300px、高度为225px,在使用时需要有唯一的标识canvas-id,同一页面中的canvas-id不可重复,如果使用一个已经
出现过的canvas-id,该canvas标识对应的画布将被隐藏并不再正常工作。canvas组件有手指触摸动作开始、手指触摸后移动、手指触摸动
作结束、手指触摸动作被打断等事件canvas组件的属性如表8.3所示。
表8.3 canvas组件的属性
属性类型默认值说明
typestring指定canvas的类型,当前仅支持WebGL
canvas-idstringcanvas组件的唯一标识符
disable-scrollbooleanfalse当手指在canvas中移动时,禁止屏幕滚动及下拉刷新
bindtouchstarteventhandle手指触摸动作开始
bindtouchmoveeventhandle手指触摸后移动
bindtouchendeventhandle手指触摸动作结束
bindtouchcanceleventhandle手指触摸动作被打断,如来电提醒、消息弹窗
bindlongtapeventhandle手指长按500 ms之后触发,触发了长按事件后移动手指不会触发屏幕滚动
binderroreventhandle当发生错误时触发error事件, detail = {errMsg: 'something wrong'}
canvas组件需要和画布API一起使用,可以使用 wx.createCanvasContext()创建Canvas Context对象,然后返回
CanvasContext对象。CanvasContext对象有以下方法。
- CanvasContext.draw():将在绘图上下文中的描述(路径、变形、样
式)画到画布中。
- CanvasContext.createLinearGradient():创建一个线性的渐变颜色。
返回的CanvasGradient对象需要使用CanvasGradient.addColorStop()来指定渐变点,至少要两个。
- CanvasContext.createCircularGradient():创建一个圆形的渐变颜
色。渐变起点在圆心、终点在圆周。返回的CanvasGradient对象需要使用CanvasGradient.addColorStop()来指定渐变点,至少要两个。
- CanvasContext.createPattern():对指定的图像创建模式,可在指定
的方向上重复元图像。
- CanvasContext.measureText():测量文本尺寸信息,目前仅返回文
本宽度,同步接口。
- CanvasContext.save():保存绘图上下文。
- CanvasContext.restore():恢复之前保存的绘图上下文。
- CanvasContext.beginPath():开始创建一个路径。需要调用fill()或者
stroke()才会使用路径进行填充或描边,在最开始的时候相当于调用了一次beginPath()。同一个路径内的多次setFillStyle()、
setStrokeStyle()、setLineWidth()等设置,以最后一次设置为准。
- CanvasContext.moveTo():把路径移动到画布中的指定点,不创建线
条。用stroke()方法来画线条。
- CanvasContext.lineTo():增加一个点,然后创建一条从上次指定点到
新点的线段。用stroke()方法来画线条。
- CanvasContext.quadraticCurveTo():创建二次贝塞尔曲线路径。曲
线的起点为路径中的前一个点。
- CanvasContext.bezierCurveTo():创建三次贝塞尔曲线路径。曲线的
起点为路径中的前一个点。
- CanvasContext.arc():创建一条弧线。若要创建一个圆,可以指定起
始弧度为0、终止弧度为2×Math.PI。用stroke()或者fill()方法在画布中画弧线。
- CanvasContext.rect():创建一个矩形路径。需要用fill()或stroke()方
法将矩形画到画布中。
- CanvasContext.arcTo():根据控制点和半径绘制圆弧路径。
- CanvasContext.clip():从原始画布中剪切任意形状和尺寸。一旦剪切
了某个区域,所有之后的绘图就都会被限制在该区域内(即不能访问画布上的其他区域)。可以在使用clip()方法前使用save()方法对当前画
布区域进行保存,并在之后通过restore()方法对其进行恢复。
- CanvasContext.fillRect():填充一个矩形。可以用setFillStyle()方法设
置矩形的填充色,如果未设置,则默认为黑色。
- CanvasContext.strokeRect():画一个矩形(非填充)。可以用
setStrokeStyle()方法设置矩形线条的颜色,如果未设置,则默认为黑色。
- CanvasContext.clearRect():清除画布上在该矩形区域内的内容。
- CanvasContext.fill():对当前路径中的内容进行填充。默认填充色为
黑色。
- CanvasContext.stroke():画出当前路径的边框。默认颜色为黑色。
- CanvasContext.closePath():闭合一个路径,即连接起点和终点。如
果闭合路径后没有调用fill()或stroke()方法并开启了新的路径,那么之前的路径将不会被渲染。
- CanvasContext.scale():在调用后,新创建的路径横、纵坐标会被缩
放。多次调用则缩放倍数会相乘。
- CanvasContext.rotate():以原点为中心顺时针旋转当前坐标轴,多
次调用则旋转的角度会叠加。原点可以用translate()方法修改。
- CanvasContext.translate():对当前坐标系的原点(0,0)进行变换。默
认的坐标系原点在页面左上角。
- CanvasContext.drawImage():绘制图像到画布。
- CanvasContext.strokeText():在给定的位置(x,y)绘制文本描边。
- CanvasContext.transform():使用矩阵多次叠加当前变换。
- CanvasContext.setTransform():使用矩阵重新设置(覆盖)当前变
换。
- CanvasContext.setFillStyle():设置填充色。
- CanvasContext.setStrokeStyle():设置描边颜色。
- CanvasContext.setShadow():设定阴影样式。
- CanvasContext.setGlobalAlpha():设置全局画笔的透明度。
- CanvasContext.setLineWidth():设置线条的宽度。
- CanvasContext.setLineJoin():设置线条的交点样式。
- CanvasContext.setLineCap():设置线条的端点样式。
- CanvasContext.setLineDash():设置虚线样式。
- CanvasContext.setMiterLimit():设置最大斜接长度。斜接长度指的
是在两条线交汇处内角和外角之间的距离,当 CanvasContext.setLineJoin()为miter时才有效。
- CanvasContext.fillText():在画布上填充文本。
- CanvasContext.setFontSize():设置字体的字号。
- CanvasContext.setTextAlign():设置文字的对齐方式。
- CanvasContext.setTextBaseline():设置文字的竖直对齐。
- wx.createOffscreenCanvas():创建离屏画布实例。
- wx.canvasToTempFilePath():把当前画布指定区域的内容导出为指
定大小的图片。在draw()回调里调用该方法才能保证图片导出成功。
- wx.canvasPutImageData():将像素数据绘制到画布。在自定义组件
下,第二个参数传入自定义组件实例this,以操作组件内的canvas组件。
- wx.canvasGetImageData():获取画布区域隐含的像素数据。
- Canvas.getContext():该方法返回canvas的绘图上下文。
- Canvas.createImage():创建一个图片对象(仅支持在WebGL中使
用,暂不支持在Offscreen Canvas中使用)。
- Canvas.requestAnimationFrame():在下次进行重绘时执行动画帧请
求(仅支持在WebGL中使用)。
- Canvas.cancelAnimationFrame():取消由requestAnimationFrame添
加到计划中的动画帧请求(仅支持在WebGL中使用)。
示例代码如下:
<!-- canvas.wxml -->
<canvas style="width:300px;height:200px;"canvas-id="firstCanvas"></canvas>
<!-- 当使用绝对定位时,文档流后边的canvas的显示层级高于前边的canvas-->
<canvas style="width: 400px; height: 500px;" canvas-id="secondCanvas"></canvas>
<!-- 因为canvas-id与前一个canvas重复,该canvas不会显示,并会发送一个错误事件到 AppService -->
<canvas style="width: 400px; height: 500px;" canvas-id="secondCanvas" binderror=
"canvasIdErrorCallback"> </canvas>
// canvas.js
Page({
canvasIdErrorCallback: function (e) {
console.error(e.detail.errMsg)
},
onReady: function (e) {
// 使用wx.createContext获取绘图上下文context
var context = wx.createContext()
context.setStrokeStyle("#00ff00")
context.setLineWidth(5)
context.rect(0, 0, 200, 200)
context.stroke()
context.setStrokeStyle("#ff0000")
context.setLineWidth(2)
context.moveTo(160, 100)
context.arc(100, 100, 60, 0, 2 * Math.PI, true)
context.moveTo(140, 100)
context.arc(100, 100, 40, 0, Math.PI, false)
context.moveTo(85, 80)
context.arc(80, 80, 5, 0, 2 * Math.PI, true)
context.moveTo(125, 80)
context.arc(120, 80, 5, 0, 2 * Math.PI, true)
context.stroke()
// 调用wx.drawCanvas(),通过canvasId指定在哪张画布上绘制,通过actions指定绘制行为
wx.drawCanvas({
canvasId: 'firstCanvas',
actions: context.getActions() // 获取绘图动作数组
})
}
})
8.4项目实战:使用AI编程工具辅助实现支付完成
页1
.任务目标
实现支付完成页,学习支付完成后页面的跳转。
在提交订单页或订单详情页支付成功后,跳转到支付完成页,支付完成页包括“支付成功”图标和“查看详情”按钮。
2.任务实施
下面来实现莫凡商城小程序的支付完成页。
(1)在app.json文件里添加支付完成页路径 “pages/paySuccess/paySuccess”。
(2)打开通义灵码,输入以下内容并发送,如图8.4所示。
微信小程序实现支付完成页,该页面包括“支付成功”图标和“查看详情”
按钮,图标居中显示,下面显示文字“支付成功”,整个页面背景为白色。

图8.4 发送需求
3.AI生成
通义灵码根据需求生成了实现支付完成页的代码,包括WXML布局、 WXSS样式及JS数据绑定,如图8.5所示。

图8.5 通义灵码生成支付完成页
4.优化建议
在运行AI生成的代码后,发现其结果与我们的实际需求还有一定的差距,可以从以下几个方面进行优化。
- 对需求进行更加细致的描述后再次进行生成,例如给出图标具体大
小,文字与图标的间距等。
- 把生成的示例图标替换成实际的图标地址。
- 根据自己的实际需求手动调整代码,使页面保持美观。
5.页面展示
代码经过优化后,运行代码,页面样式如图8.6所示。

图8.6 支付完成页
8.5 项目实战:使用AI编程工具辅助实现我的订单页
面1
.任务目标
实现我的订单页面,巩固列表动态渲染、页签切换的知识。
莫凡商城小程序的我的订单页面包含“待付款”列表、“待收货”列表、 “已完成”列表。
2.任务实施
下面来实现莫凡商城小程序的我的订单页面。
(1)在app.json文件里添加我的订单页面路径 “pages/myOrder/myOrder”。
(2)打开通义灵码,输入以下内容并发送,如图8.7所示。

图8.7 发送需求
微信小程序实现我的订单页面,页面最上方有“待付款”“待收货”“已完成”这3个tab,选中tab,文字变橙色,底部边框也变橙色,3个tab可以
通过点击进行切换,每个订单上方显示商城名称,中间部分左边显示图书封面,右边上面显示图书名称、下面显示商品价格,如果是“待付
款”tab,右下方显示“去支付”和“删除订单”两个按钮,如果是“待收货”
tab或“已完成”tab,右下方显示“再次购买”和“删除订单”两个按钮。
3.AI生成
通义灵码根据需求生成了实现我的订单页面的代码,包括WXML布局、 WXSS样式及JS数据绑定,如图8.8所示。

图8.8 通义灵码生成我的订单页面
4.优化建议
在运行AI生成的代码后,发现结果与我们的实际需求还有一定的差距,可以从以下两个方面进行优化。
- 对需求进行更加细致的描述后再次进行生成,例如把这3个tab如何布
局以及被选中后是什么样式进行详细描述。
- 根据自己的实际需求手动调整页面样式。页面生成后,我们可以根据
自己需求手动对按钮大小、边框颜色、文字颜色、标题间距等进行调整,使页面保持美观。
5.页面展示
代码经过优化后,运行代码,页面样式如图8.9所示。

图8.9 我的订单页面
8.6 项目实战:实现订单详情页1
.任务目标
实现订单详情页,巩固页面布局设计的相关知识。
莫凡商城小程序的订单详情页用来显示已经下单的商品,该订单如果支付成功,就不再显示“去付款”按钮,否则显示“去付款”按钮。
2.任务实施
下面来实现莫凡商城订单详情页。
(1)在app.json文件里添加订单详情页路径 “pages/orderDetail/orderDetail”。
(2)订单详情页与立即购买页面类似,我们可以把立即购买页面的代码复制到订单详情页,再根据实际需求进行修改。
3.页面展示
代码经过优化后,运行代码,页面样式如图8.10所示。

图8.10 订单详情页