我们来看看一下效果图吧!
我是用微信开发工具的,所以到了支付功能会提示用二维码扫描,如果在真机上就是支付弹框输入支付密码的页面了!
这个页面的功能如下
1、典型的购物车,勾选价格与物品件数都发生变换
2、在线填写信息,支付的时候回把页面上的信息全部都存储数据库里面
3、微信支付功能
这个页面的wxml如下
<view class='header1'>
<view class='header'>
<view class='header_con flex_between'>
<view class='left'>
共计{{items.length}}件商品
</view>
</view>
</view>
</view>
<view class='header2'>
<view class='header'>
<view class='header_con flex_between'>
<input value='牌位列表' disabled='{{title_disabled}}' focus="{{!title_disabled}}">
</input>
</view>
</view>
</view>
<!-- 以上无标签缺少 -->
<view class='onlinechoose'>
<view class='hotel_list flex_center' wx:for="{{items}}" wx:key="items" wx:for-item="i">
<view class='list_cons flex_start'>
<!-- 单选 -->
<view data-id="{{index}}" data-variable="{{i}}" bindtap='select'>
<view wx:if="{{management_good}}" class='lefts'>
<block wx-if="{{!i.checked}}">
<view class='icon_none'></view>
</block>
<block wx-if="{{i.checked}}">
<icon type="success" size="30" color="red" />
</block>
</view>
</view>
<!-- 单选 -->
<view class='right'>
<view class='name'>
<view style="background-color:red;color:white">{{i.father}}</view>
<view class="nb">
<input value="{{i.fname}}" placeholder="请填写姓名" bindblur="eidtfname" data-id="{{index}}" class="instyle" />
</view>
</view>
<view class='name'>
阳上
<view class="na"> {{i.child}} </view>
<view class="na">
<input value="{{i.cname}}" placeholder="请填写姓名" bindblur="eidtcname" data-id="{{index}}" class="instyle" />
</view>
</view>
<view class='name'>
地址
<view class="nb">
<input value="{{i.address}}" bindblur="eidtadd" data-id="{{index}}" class="instyle" placeholder="请填写地址"></input>
</view>
</view>
<view class='name'>
牌价{{i.price}}
<view class="sign-setting-border {{i.price==50?'selected':''}} " bindtap="selectApply" data-id="50" data-pr="{{index}}">大牌位</view>
<view class="sign-setting-border {{i.price==500?'selected':''}}" bindtap="selectApply" data-id="500" data-pr="{{index}}">小牌位</view>
</view>
</view>
<!-- right -->
</view>
<!-- 一个小的for循环 -->
</view>
<!-- 完整的 -->
</view>
<!-- 大封口 -->
<!-- 姓名 -->
<view class="vname" style="margin-top:9rpx">
姓 名
<view class="nb">
<input placeholder="请输入付款人姓名" value='{{oname}}' bindinput='setoname' class="instyle"></input>
</view>
</view>
<view class="vname">
手机号码
<view class="nb">
<input placeholder="请输入付款人手机号码" value='{{tell}}' bindinput='settell' class="instyle"></input>
</view>
</view>
<!-- 手机号码 -->
<view class='bottom flex_between' wx:if="{{management_good}}">
<view class='left flex_start'>
<block wx:if="{{select_all}}">
<view bindtap='select_none' class='flex_start'>
<icon type="success" size="30" color="red" />
<view>
取消全选
</view>
</view>
</block>
<block wx:if="{{!select_all}}">
<view bindtap='select_all' class='flex_start'>
<view class='select_none'>
</view>
<view>
全选
</view>
</view>
</block>
</view>
<view class='right flex_end'>
<view style='text-align:right'>
<view class='all'>
共计{{middlearr.length}}个牌位
</view>
</view>
<view bindtap='paygoods' class='sure'>
支付{{money}}元
</view>
</view>
</view>
wxss页面如下
.instyle{
border: 0.5px solid #cfcfcf;
}
.header1{
background-color: #f5f5f5;
}
.header2{
background-color: #ffffff;
}
.header {
width: 100%;
height: 80rpx;
border-bottom: 1rpx solid #d6d6d6;
}
.header .header_con {
width: 700rpx;
height: 80rpx;
margin: 0 auto;
color: #333;
font-size: 30rpx;
}
.header .header_con image{
width: 44rpx;
height: 44rpx;
}
.header .header_con .right{
color: #ff4965;
}
.bottom{
width: 100%;
height: 100rpx;
border-top: 1rpx solid #d6d6d6;
background-color: #fff;
position: relative;
}
.bottom .left{
margin-left: 25rpx;
}
.bottom .left .select_none{
width: 60rpx;
height: 60rpx;
border: 1rpx solid #d6d6d6;
border-radius: 50%;
}
.bottom .right .all{
color: #ff830f;
font-size: 26rpx;
}
.bottom .right .gray{
color: #666666;
font-size: 22rpx;
}
.bottom .right .sure{
margin-left: 22rpx;
width: 220rpx;
height: 100rpx;
line-height: 100rpx;
text-align: center;
background-color: #ff4965;
color: #fff;
}
/*列表*/
.onlinechoose{
width: 750rpx;
margin-top: 15rpx;
background-color: #ffffff;
font-size: 32rpx;
}
.onlinechoose .hotel_list{
width: 750rpx;
height:350rpx;
border-bottom: 1rpx solid #d6d6d6;
background-color: #ffffff;
}
.onlinechoose .hotel_list .icon_none{
width: 50rpx;
height: 50rpx;
border: 1rpx solid #113852;
border-radius: 50%;
}
.onlinechoose .hotel_list .list_cons{
width: 700rpx;
height: 200rpx;
}
.onlinechoose .list_cons .lefts{
width: 80rpx;
}
.onlinechoose .list_cons image{
width: 200rpx;
height: 200rpx;
margin-right: 25rpx;
}
.list_cons .right{
width: 395rpx;
height: 200rpx;
}
.list_cons .right .name{
font-size: 32rpx;
color: #333333;
font-weight: 700;
letter-spacing: 3rpx;
margin-bottom: 20rpx;
}
.list_cons .right .list1{
margin-bottom: 17rpx;
}
.list_cons .right .list1 .condition1{
font-size: 28rpx;
color: #999999;
margin-bottom: 15rpx;
}
.list_cons .right .list1 .condition2{
font-size: 24rpx;
color: #999999;
}
.list_cons .right .list1 .act{
color: #2d8622;
}
.list_cons .right .list1 .r{
font-size: 24rpx;
color: #ff4965;
}
.list_cons .right .list1 .big{
font-size: 32rpx;
}
.list_cons .right .lists2{
height: 36rpx;
line-height: 36rpx;
font-size: 22rpx;
}
.list_cons .right .lists2 .left{
width: 162rpx;
text-align: center;
color: #ff4965;
border: 1rpx solid #ff4965;
box-sizing: border-box;
border-radius: 5rpx;
}
.list_cons .right .lists2 .right2{
color: #999999;
}
.flex_center{
display: flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
}
.flex_between{
display: flex;
display: -webkit-flex;
justify-content: space-between;
align-items: center;
}
.flex_start{
display: flex;
display: -webkit-flex;
justify-content: flex-start;
align-items: center;
}
.flex_end{
display: flex;
display: -webkit-flex;
justify-content: flex-end;
align-items: center;
}
.name{
display: flex;
flex-direction: row;
width: 500px;
margin-bottom:17px;
}
.na{
width: 93px;
margin-left: 15px;
}
.nb{
margin-left: 50px;
}
.nc{
margin-left: 50px;
margin-top: 10px;
}
.vname{
display: flex;
flex-direction: row;
width: 500px;
margin-bottom:17px;
margin-left: 44px;
}
/* 布局 */
.sign-setting-border{
margin-left: 2%;
width: 12%;
float: left;
height: 24px;
line-height: 26px;
border-radius: 20px;
background-color: #ffffff;
color: #999999;
font-size: 14px;
text-align: center;
font-family: -apple-system;
margin-bottom: 15px;
border: 1px solid #DBDBDB;
}
.selected{
background-color: #FFA404;
color: rgba(255, 255, 255, 1);
border:1px solid #FFA404;
}
js代码如下
Page({
data: {
title_disabled: true,//控制修改表头名字
management_good: false,
select_all: false,
middlearr: [],
tell:'',
oname:'',
idx:'',
money:0,
applyList: [{ id: "50", name: "小牌位" },
{ id: "500", name: "大牌位" }],
items: [
{ father: "先祖父", fname: "", address: "", child: "孝孙", cname: "",price:'50', checked: false },
{ father: "先祖母", fname: "", address: "", child: "孝孙", cname: "", price: '50', checked: false },
{ father: "先父", fname: "", address: "", child: "孝子", cname: "", price: '50',checked: false },
{ father: "先母", fname: "", address: "", child: "孝子", cname: "", price: '50',checked: false },
{ father: "姓氏门中", fname: "", address: "", child: "孝后裔", cname: "", price: '50',checked: false },
{ father: "冤亲债主", fname: "", address: "", child: "结冤人", cname: "", price: '50', checked: false },
{ father: "无名婴儿", fname: "", address: "", child: "母亲", cname: "", price: '50', checked: false },
{ father: "普利十方", fname: "", address: "", child: " ", cname: "", price: '50',checked: false },
{ father: "四生六道", fname: "", address: "", child: "", cname: "", price: '50',checked: false},
]
},
selectApply: function (e) {
let id = e.target.dataset.id
let pr = e.target.dataset.pr
console.log(id,pr)
var fname = 'items[' + pr + '].price'
this.setData({ [fname]: id });
//更新总价
var all = 0;
var arr = this.data.items;
for (let i = 0; i < arr.length; i++) {
if (arr[i].checked) {
all = all + Number(arr[i].price);
}
};
this.setData({
money: all
})
//更新总价
},
onLoad:function(){
this.management()
},
//变更fname成功
eidtfname(event){
var c = event.detail.value;
var id = event.currentTarget.dataset.id;
var fname = 'items[' + id + '].fname'
this.setData({ [fname]:c});
},
//变更cname成功
eidtcname(event) {
var c = event.detail.value;
var id = event.currentTarget.dataset.id;
var cname = 'items[' + id + '].cname'
this.setData({ [cname]: c });
},
//变更地址成功
eidtadd(event) {
var c = event.detail.value;
var id = event.currentTarget.dataset.id;
var address = 'items[' + id + '].address'
this.setData({ [address]: c });
},
paygoods:function(){
var arr2 = this.data.middlearr;
//1、校验,必须被勾选才能支付
if (arr2.length>0){
//2、被勾选的fname cname address必须不为空
for(let i=0;i<arr2.length;i++){
if (arr2[i].fname == "" || arr2[i].cname==""||arr2[i].address==""){
wx.showToast({
title: '失败,信息没填',
icon: 'fail',
duration: 1000,
mask: true
})
return;
}
}
//3、手机号码,姓名不能为空
if(this.data.oname==""){
wx.showToast({
title: '姓名不能为空',
icon: 'fail',
duration: 1000,
mask: true
})
return;
}
if (this.data.tell == "" ){
wx.showToast({
title: '手机号码不能为空',
icon: 'fail',
duration: 1000,
mask: true
})
return;
}
console.log(this.data.money);
//3、手机号码,姓名不能为空
//拉起支付
this.pay(arr2);
console.log("获取的购物车是:", arr2);
//拉起支付
}else{
wx.showToast({
title: '未勾选清单',
icon: 'fail',
duration: 1000,
mask: true
})
return;
}
},
//支付功能
pay(arr2) {
var that=this;
const db = wx.cloud.database({});
const cont = db.collection('info');
const bcont = db.collection('bill');
var timestamp = that.getNowFormatDate();
var money = that.data.money;
money = (money * 100).toFixed()
console.log("支付的金额是:", money);
wx.cloud.callFunction({
name: 'payment',
data: { total_fee: money }, // 可传入相关参数。
success: res => {
var list = res.result
console.log("统一下单信息:",list)
if (!res.result.appId) return
wx.requestPayment({
...res.result,
success: res => {
//把订单信息存储起来
for(let i=0;i<arr2.length;i++){
//把数据给云数据库
cont.add({
data: {
father:arr2[i].father,
fname: arr2[i].fname,
child: arr2[i].child,
cname: arr2[i].cname,
address:arr2[i].address,
tell: that.data.tell,
oname: that.data.oname,
date: timestamp,
preid: list.package,
},
success: function (res) {
console.log(res._id)
wx.showModal({
title: '成功',
content: '立牌位成功',
showCancel: false
})
}
});
//把数据给云数据库
}//for
//信息存储起来
//存储账单信息
bcont.add({
data: {
preid: list.package,
openid: list.appId,
oname: that.data.oname,
money: that.data.money,
date: timestamp,
tell: that.data.tell
},
success: function (res) {
wx.showModal({
title: '成功',
content: '阿弥陀佛',
showCancel: false
})
}
});
//存储账单信息
}
})
}
})
},
//设置手机号码
settell(e) {
this.setData({
tell: e.detail.value
})
},
//设置订单姓名
setoname(e) {
this.setData({
oname: e.detail.value
})
},
// 改变类目的名字
change_classname: function () {
let that = this;
that.setData({
title_disabled: !that.data.title_disabled,
});
// 这里自动获取焦点
},
finish_classname: function () {
let that = this;
that.setData({
title_disabled: !that.data.title_disabled,
})
},
// 管理商品
management: function () {
let that = this;
that.setData({
management_good: true,
})
},
// 选择
select: function (e) {
var that = this;
let arr2 = [];
if (that.data.management_good == false) {
return;
} else {
var arr = that.data.items;
var index = e.currentTarget.dataset.id;
var itm = e.currentTarget.dataset.variable;
arr[index].checked = !arr[index].checked;
//这里进行赋值处理
console.log(itm);
//计算总价格
var all=0;
for (let i = 0; i < arr.length; i++) {
if (arr[i].checked) {
arr2.push(arr[i]);
all = all + Number(arr[i].price);
}
};
that.setData({
items: arr,
middlearr: arr2,
money:all
})
}
},
//设置时间
getNowFormatDate:function() {//获取当前时间
var time = Math.round(new Date() / 1000)
console.log("时间戳位:", time);
return time;
},
// 全选
select_all: function () {
let that = this;
that.setData({
select_all: !that.data.select_all
})
if (that.data.select_all) {
let arr = that.data.items;
let arr2 = [];
var all=0;
for (let i = 0; i < arr.length; i++) {
if (arr[i].checked == true) {
arr2.push(arr[i]);
all = all + Number(arr[i].price);
} else {
arr[i].checked = true;
arr2.push(arr[i]);
all = all + Number(arr[i].price);
}
}
that.setData({
items: arr2,
middlearr: arr2,
money:all
})
}
},
// 取消全选
select_none: function () {
let that = this;
that.setData({
select_all: !that.data.select_all
})
let arr = that.data.items;
let arr2 = [];
for (let i = 0; i < arr.length; i++) {
arr[i].checked = false;
arr2.push(arr[i]);
}
that.setData({
items: arr2,
middlearr: []
})
},
})
后端我是用的是云开发的云函数
支付功能是payment函数
需要安装依赖wx-server-sdk与tenpay
这里有一个详细的例子讲解微信支付的 https://blog.csdn.net/tian_jiangnan/article/details/105527674
//云开发实现支付
const cloud = require('wx-server-sdk')
cloud.init()
//1,引入支付的三方依赖
const tenpay = require('tenpay');
//2,配置支付信息
const config = {
appid: 'appid',
mchid: '商户号',
partnerKey: '商户key',
notify_url: 'https://www.baidu.com/',
spbill_create_ip: '127.0.0.1' //这里填这个就可以
};
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let {
total_fee
} = event;
//3,初始化支付
const api = tenpay.init(config);
const nonceStr = Math.random().toString(36).substr(2, 15)
const timeStamp = parseInt(Date.now() / 1000) + ''
const out_trade_no = "otn" + nonceStr + timeStamp
let result = await api.getPayParams({
out_trade_no: out_trade_no,
body: '牌位',
total_fee: total_fee, //订单金额(分),
openid: wxContext.OPENID //付款用户的openid
});
return result;
}
这里我只用到了两个云函数,一个是payment一个是login
至于安装依赖可以看看我
这里有一个详细的例子讲解微信支付的 https://blog.csdn.net/tian_jiangnan/article/details/105527674 里面有详细步骤
最后不要忘记把两个云函数上传并且部署
在app.js里面配置云开发环境
//app.js
App({
onLaunch: function () {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
env: '你的云开发环境的ID',
traceUser: true,
})
//获取openid
/**
* 打开小程序的时候首先获得用户openid
*/
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
this.globalData.openid = res.result.openid
},
fail: err => {
console.error('[云函数] [login] 调用失败', err)
}
})
//获取openid
//获取openid
}
//获取openid
this.globalData = {
}
}
})