必备条件
- 1,必须注册微信支付的商户号
- 2,企业小程序必须通过认证
- 3,小程序关联微信支付商户号
一,小程序关联微信商户
1,登录小程序后台,点击关联更多商户号
2,关联商户号需要用到appid,点击如下所示的关联更多AppID
把我们小程序的appid复制下
然后去授权关联我们的微信支付商户号
微信商户号申请下来以后,就可以直接微信扫码登录了,然后就可以在商户号里关联小程序了。
商户号里关联好,我们需要去小程序里确认下授权。
授权完成以后,我们的小程序端会出现下面这样的,点击下确认即可。
点击下上图的确认,然后再点击下图所示的授权。
可以看到我们的小程序和微信商户号成功的关联起来了
到这里我们小程序和商户号的关联操作就完成了。
二,开通云开发并绑定微信商户号
1,然后新建小程序,开始代码部分。
这里的appid一定要是你关联过微信支付商户的,并且还得是企业小程序。这里创建项目时记得选择不使用云服务,因为使用默认云开发的话,会创建一大堆无用的文件。
2,开通云开发功能
会弹出协议,直接点确定就可以了
3,给你的云开发环境起个名,英文或者拼音
现在云开发只可以免费试用一个月,学习的话,一个月够了,所以这里支付方式,随便选一个就行了。下一步的选择配额,也随便选一个就行了,然后提交。
等待创建云开发,创建好以后如下。
4,然后点击设置,全局配置,可以看到有个微信支付配置
image.png
有的同学这里看不到微信支付配置,是因为你的小程序开发工具版本过低。最好下载最新版本的开发者工具。
5,云开发配置微信商户号。
添加完以后还需要手机上进行授权确认
6,手机微信上进行确认
可以看到这里已经授权绑定了
退款的我们后面会再讲。
这个时候我们准备工作就全部做好了,接下来就要愉快的写代码。
三,云开发支付代码的编写
1,看官方文档,其实说的很详细了,接下来我带大家过一遍。
这里也把官方链接贴出来给大家。
其实官方有给我们完整的示例。
我们只需要把这段代码复制到我们自己的云函数里就行了。
2,创建云开发统一支付的云函数
我们首先要创建云函数的根目录
然后新建云函数pay0610
然后把官方示例直接复制到我们自己的云函数里
3,把云函数里的信息替换成我们自己的
上面标注重要的是一定要替换成自己的。然后保存修改,部署云函数
4,编写页面
在index.wxml里写一个按钮,点击的时候调起我们的支付云函数
然后在index.js里编写点击事件
我们这个时候直接点击支付,看看会不会调起支付
这个时候一大堆爆红,仔细看下,可以看出我们云开发环境id没有初始化。
5,app.js里配置云开发环境id
这里取到环境id
然后在app.js里配置
然后我们再点击下支付,可以看到我们成功的调起了支付
6,然后我用手机微信支付下试试
支付成功后,我们的控制台也会有相应的日志打印。
到这里我们就可以成功的在小程序里使用微信支付了,后面无非把价格和商品名字做活,做成动态传入的。
后面我也会把源码放到网盘里,有需要的同学,去我公号里回复‘云开发支付’就可以获取了。
第四节,商品订单支付案例讲解
上面我们学会了支付功能,那么我们接下来就用一个简单的案例来教大家试下一个简单的商城小程序,包含以下功能
- 1,商品列表
- 2,订单列表(分已支付和待支付)
- 3,支付功能
- 4,解决一些支付中常见的问题
老规矩,先看下效果图
页面比较简陋,因为我这里主要教大家如何实现支付功能的,所以页面美化的问题,大家课下有时间时,自己做下美化就行了。
一,在app.json里配置tabbar多页面
由于我们这里用到了两个页面,还是在我们前面章节的基础上,直接改造页面。我们配置多页面就要用到tabbar了。所以我们先创建一个order页面,页面如何创建,我这里就不再累述了。小程序基础的课里讲了很多遍。
然后在app.json里配置如下
由于这里的配置不是本节的学习重点,这里把代码给到大家,大家直接粘贴到自己项目里就可以的。
"tabBar": { "color": "#a9b7b7", "selectedColor": "#11cd6e", "borderStyle": "white", "list": [{ "selectedIconPath": "image/home_yes.png", "iconPath": "image/home_no.png", "pagePath": "pages/good/good", "text": "商品首页" }, { "selectedIconPath": "image/order_yes.png", "iconPath": "image/order_no.png", "pagePath": "pages/order/order", "text": "我的订单" } ] },
这里用到的图片资源,我给大家放到了课程配套资源里,如下
大家课下找石头哥索要就行了(限购课用户奥),把资源下载下来以后,新建一个image文件夹,然后把资源放到image文件下就可以了。
到这里tabbar配置好了,我们接下来就要开始代码部分了。
二,把商品做活,放到数据库里
我们前面学习的时候,用的是本地数据,接下来我就来给大家演示下,如何把商品数据放到数据库,方便后期动态修改。
1,在云开发数据库里新建goods集合(表)
创建好以后,记得把权限改为所有人可读写
创建好goods集合以后,就要往里面添加数据了,把我们之前本地写死的数据,就可以做成活的了。
添加好的数据如下
2,改造商品列表代码
我们之前的商品数据是写死在本地的,这次我们就可以请求云开发数据库里的数据了,后期可以动态增删,修改。
通过上图我们可以看出,已经成功的请求到了数据库里的商品数据,接下来把数据动态的绑定到小程序页面上就可以了。
可以看到,我们的数据已经成功的显示出来了。
到这里我们的商品列表页改造就算完成了。
三,创建订单
我们之前学习是点击购买就直接支付了,没有一个订单来动态的记录。所以我们这一节,先来教大家如何新建订单。
1,新建order表
我们要在云开发数据库里生成订单,其实就是往订单表里增加数据。所以还是要先新建order集合(表)
这里要注意下,我们的订单表的权限设置为“仅创建者可读写”,为什么呢?
因为我们每个人的订单肯定不想让别人看到吧。所以我们设置完仅创建者可读写,那么这个订单就只有我们自己可以看。上面的goods表只所以设置为所有人可读,是因为我们的商品数据是要每个客户都能看到的。
2,创建订单代码编写
我们上面order表创建好以后,我们用户再点购买的时候,就不能直接去支付了,应该先创建一个订单,然后再去支付。下面我们就分解开。教大家实现订单的创建。
上面代码注释很清楚了,我们创建订单时需要往订单里保存商品名,金额,下单时间,订单状态。然后看下order表里的订单数据如下
这样我们新的订单就创建成功了。
创建订单时,我们有用到一个获取当前时间的方法,这个方法是我们自定义的,由于不是本节学习重点,我就把这个方法的代码贴出来给大家,大家后面直接把代码放到自己项目里用就行了。
// 获取当前时间的工具方法 _getCurrentTime() { var d = new Date(); var month = d.getMonth() + 1; var date = d.getDate(); var day = d.getDay(); var hours = d.getHours(); var minutes = d.getMinutes(); var seconds = d.getSeconds(); var ms = d.getMilliseconds(); var curDateTime = d.getFullYear() + '年'; if (month > 9) curDateTime += month + '月'; else curDateTime += month + '月'; if (date > 9) curDateTime = curDateTime + date + "日"; else curDateTime = curDateTime + date + "日"; if (hours > 9) curDateTime = curDateTime + hours + "时"; else curDateTime = curDateTime + hours + "时"; if (minutes > 9) curDateTime = curDateTime + minutes + "分"; else curDateTime = curDateTime + minutes + "分"; return curDateTime; },
四,订单支付
我们上面创建好订单以后,应该在订单创建成功的回调里调起支付。其实支付的代码和我们前面学习基本都一样,唯一变化的就是要把我们新建的订单id传给支付云函数,把订单id作为支付时的单号。
上图是我们创建订单时,返回的信息,可以看到返回信息里有一个_id字段,这个字段在我们order表里也有。
其实我们支付的时候单号要保证唯一性,其实这个_id是微信官方自动为我们创建的,是唯一的,所以可以直接拿来用的,那么我们把之前的goPay支付方法稍微改造下。把这个_id作为订单号传给支付云函数。
可以看出我们在创建订单成功的回调里去调起支付,依然可以支付成功。
我们的pay0611云函数唯一的变化就是把订单号做成了活的。
重点注意: 我们的云函数只要有任何改动,都要记得重新部署云函数。
到这里我们的支付和订单部分就改造完成了,接下来就要去实现订单的未支付和已支付列表了。
五,订单页面的展示(分已支付和未支付)
这一节知识点比较多,也比较复杂,我先把代码贴给大家,会在视频里仔细给大家一步步讲解。
- order.wxml
这里切换未支付和已支付的分类栏代码如下:
<!--导航条--> <view class="navbar"> <lable wx:for="{{navbar}}" data-idx="{{index}}" class="item {{currentTab==index ? 'active' : ''}}" wx:key="unique" bindtap="navbarTap"> <text>{{item}}</text> </lable> </view> <!-- 列表区域 --> <view wx:if="{{list.length>0}}"> <!-- 外层 --> <view wx:for="{{list}}" wx:key="key"> <!-- 编号 --> <view class='itemRoot'> <text class='seriac_name'>商品:{{item.goodName}}</text> <text class='seriac_name'>金额:{{item.totalFee}}元</text> <text class='seriac_name'>下单时间:{{item.time}}</text> <text wx:if="{{item.status==0}}" class='coent_log_base' data-item='{{item}}' bindtap='payOrder'>去支付</text> </view> </view> </view> <!-- 否则 --> <view wx:else class='cont_count'> <label class='none_tab'>数据为空哦~~</label> </view>
对应的样式order.wxss如下
/* 顶部菜单切换 */ .navbar { display: flex; background: #fff; } .none_tab { position: relative; top: 20rpx; color: #999; font-size: 32rpx; } .navbar .item { position: relative; flex: auto; font-size: 27rpx; width: 100rpx; text-align: center; line-height: 80rpx; color: #333; border-bottom: 6rpx solid #ddd; } .navbar .item.active { color: #333; border-bottom: 6rpx solid #46b5fc; } .navbar .item.active:after { content: ""; display: block; position: absolute; bottom: 0; left: 0; right: 0; height: 4rpx; } /*列表为空 */ .cont_count { padding-top: 6rpx; position: relative; width: 100%; text-align: center; /* height: 620rpx; */ /* border-bottom: 6rpx solid #ddd; */ margin-bottom: 6rpx; background-color: #fff; } /* 列表*/ .itemRoot { position: relative; display: flex; flex-direction: column; width: 90%; padding: 20rpx; border-bottom: 1rpx solid #d4d4d4; } .seriac_name { font-size: 28rpx; color: #333; left: 0rpx; margin-left: 15rpx; } .coent_log_base { position: absolute; top: 55%; color: #46b5fc; right: 0rpx; display: inline-block; width: 180rpx; height: 56rpx; text-align: center; border: 1rpx solid #46b5fc; font-size: 30rpx; line-height: 56rpx; }
roder.js
这里是重点代码,直接把完整的代码贴给大家。
var app = getApp() let DB = wx.cloud.database(); let orderStatus = 0; //0新下单未支付,1支付成功 Page({ data: { // 顶部菜单切换 navbar: ["未支付", "已支付"], // 默认选中菜单 currentTab: 0, list: [] }, //顶部tab切换 navbarTap: function (e) { let index = e.currentTarget.dataset.idx; this.setData({ currentTab: index }) console.log("index", index) //0新下单未支付,1支付成功 if (index == 1) { orderStatus = 1; } else { orderStatus = 0; } this.getMyOrderList(); }, onLoad() { this.getMyOrderList(); }, //获取订单 getMyOrderList() { let that = this; DB.collection("order") .where({ status: orderStatus }) .get({ success: function (res) { console.log("获取成功", res.data) let datalist = res.data; console.log(res); if (datalist && datalist.length > 0) { that.setData({ list: datalist }) } else { that.setData({ list: [] }) } } }) }, //支付订单 payOrder(event) { let good = event.currentTarget.dataset.item console.log('支付的good', good) wx.cloud.callFunction({ name: 'pay0611', data: { outTradeNo: good._id, goodName: good.name, totalFee: good.totalFee }, success: res => { console.log("获取支付参数成功", res) const payment = res.result.payment //调起支付 wx.requestPayment({ ...payment, success(res) { console.log('支付成功', res) }, fail(res) { console.error('支付失败', res) } }) }, fail: res => { console.log("获取支付参数失败", res) }, }) } })