商城小程序(9.登录与支付)

一、点击结算按钮进行条件判断

用户点击了结算按钮之后,需要先后判断是否勾选了要结算的商品,是否选择了收货地址,是否登录。

在my-settle组件中,为结算按钮绑定点击事件处理函数:

在这里插入图片描述.
在user.js中封装token数据,用于判断用户是否登录
在这里插入图片描述
在my-settle组件中,调用相关数据判断是否登录
在这里插入图片描述

在my-settle组件中的methods节点中声明settlement事件处理函数:

在这里插入图片描述
未选中商品点击结算时:

在这里插入图片描述
有地址,有商品,没有token登录时:
在这里插入图片描述

二、登录

本章主要设计登录页面my.vue的编写
在这里插入图片描述

1、实现登录和用户信息组件的按需展示

components下创建登录组件

在这里插入图片描述

创建userinfo用户信息组件
在这里插入图片描述
在my-user页面,使用两个组件
在这里插入图片描述
my.vue页面获取user.js中的token值,来实现判断是否登录
在这里插入图片描述

按需展示页面,没有登录的话跳转到用户登录页面
在这里插入图片描述

2、实现登录组件的基本布局

渲染my-login组件的UI结构

<template>
	<view class="login-container">
		<uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
		<button type="primary" class="btn-login">一键登录</button>
		<text class="tips-text">登录后尽享更多权益</text>
	</view>
</template>

美化样式


<style lang="scss">
.login-container {
	height: 750rpx;
	background-color: #F8F8F8;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	position: relative;
	overflow: hidden;
	&::after {
		content: ' ';
		display: block;
		width: 100%;
		height: 40px;
		background-color: white;
		position: absolute;
		bottom: 0;
		left: 0;
		border-radius: 100%;
		transform: translateY(50%);
	}
	
	.btn-login {
		width: 90%;
		border-radius: 100px;
		margin: 15px 0;
		background-color: #C00000;
	}
	.tips-text {
		font-size: 12px;
		color: gray;
	}
}
</style>

在这里插入图片描述

3、点击登录获取微信用户的基本信息

先看获取token的接口,需要的参数,以及返回类型
在这里插入图片描述
在这里插入图片描述

为登录button按钮绑定,获取用户的基本信息
在这里插入图片描述

在method中声明事件处理函数

		methods: {
			//用户授权之后,获取用户信息
			getUserProfile() {
				
				uni.getUserProfile({
					// 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 
					desc: '请求授权',
					success: (res) => {
						console.log(res)
						// 这部分是更新用户信息的
						// this.updateUserInfo(res.userInfo)
						// this.getToken(res)
					},
					fail: (res) => {
						return uni.showToast({
							title: '用户取消了登录授权!',
							duration: 1500,
							icon: 'none',
						})
					}
				})
			}
		}

成功获取用户信息
在这里插入图片描述
这里要注意,那vx开发者工具的此处调成低版本,不然只能在真机上演示
在这里插入图片描述

4、将用户的基本信息存储到vuex

在user.js中定义保存用户信息的参数userinfo,以及创建更新用户信息,保存用户信息的方法
在这里插入图片描述
在my-login页面调用持久化存储
在这里插入图片描述

5、获取token字符串

前面成功获取了后面4个,这里完成获取code功能
在这里插入图片描述

因为这个后端接口有时候会有问题,获取不到token,所以我们方便测试,直接把返回结果封装一个loginResult方便我们后续的开发

getToken(info) {
				uni.login({
					provider: 'weixin',
					success: (res) => {
						// console.log('login-res', res)
						if (res && res.errMsg === 'login:ok') {
							const query = {
								code: res.code,
								encryptedData: info.encryptedData,
								iv: info.iv,
								rawData: info.rawData,
								signature: info.signature
							}
							console.log("query", query)
							// const { data: loginResult } = uni.$http.post('/api/public/v1/users/wxlogin', query)
							//获取token失败时候使用
							const loginResult = {
								"message": {
									"user_id": 12,
									"user_email_code": null,
									"is_active": null,
									"user_sex": "男",
									"user_qq": "",
									"user_tel": "",
									"user_xueli": "本科",
									"user_hobby": "",
									"user_introduce": null,
									"create_time": 1525402223,
									"update_time": 1525402223,
									"token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIzLCJpYXQiOjE1NjQ3MzAwNzksImV4cCI6MTAwMTU2NDczMDA3OH0.YPt-XeLnjV-_1ITaXGY2FhxmCe4NvXuRnRB8OMCfnPo"
								},
								"meta": {
									"msg": "登录成功",
									"status": 200
								}
							}
							console.log(loginResult)
							if (loginResult.meta.status !== 200) {
								return uni.showToast({
									title: '登录失败!',
									duration: 1500,
									icon: 'none',
								})
							}
							this.updateToken(loginResult.message.token)
							uni.showToast({
								title: '登录成功!',
								duration: 1500,
								icon: 'none',
							})
							this.navigateBack()
						} else {
							return uni.showToast({
								title: '登录失败!',
								duration: 1500,
								icon: 'none',
							})
						}
					},
					fail: (err) => {
						return uni.showToast({
							title: '登录失败!',
							duration: 1500,
							icon: 'none',
						})
					}
				})
			}

一键登录,登录成功

在这里插入图片描述
成功返回token,以及后端请求用户信息
在这里插入图片描述

6、将token存储到vuex

在这里插入图片描述

在这里插入图片描述
在my-login组件中,把vuex中的updateToken方法映射到当前组件中使用
在这里插入图片描述
在这里插入图片描述

三、用户信息

1、实现用户头像昵称区域的基本布局

my-userinfo.vue页面

<template>
	<view class="my-userinfo-container">
		<!-- 头像和昵称区域 -->
		<view class="top-box">
			<image src="" class="avatar"></image>
			<view class="nickname">xxx</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			};
		}
	}
</script>

<style lang="scss">
	.my-userinfo-container {
		height: 100%;
		background-color: #F4F4F4;
		
		.top-box {
			height: 400rpx;
			background-color: #C00000;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: column;
			
			.avatar {
				width: 90px;
				height: 90px;
				border-radius: 45px;
				border: 2px solid #FFF;
				box-shadow: 0 1px 5px black;
			}
			.nickname {
				font-size: 16px;
				color: #FFF;
				font-weight: bold;
				margin-top: 10px;
			}
		}
	}
</style>

在这里插入图片描述

2、渲染用户的头像和昵称

在这里插入图片描述
在这里插入图片描述

3、渲染第一个面板区域

UI结构

		<!-- 面板区域 -->
		<view class="panel-list">
			<!-- 第1个面板 -->
			<view class="panel">
				<view class="panel-body">
					<view class="panel-item">
						<text>8</text>
						<text>收藏的店铺</text>
					</view>
					<view class="panel-item">
						<text>14</text>
						<text>收藏的商品</text>
					</view>
					<view class="panel-item">
						<text>18</text>
						<text>关注的商品</text>
					</view>
					<view class="panel-item">
						<text>84</text>
						<text>组件</text>
					</view>
				</view>
			</view>
		</view>

美化样式

.panel-list {
		padding: 0 10px;
		position: relative;
		top: -10px;
		.panel {
			background-color: white;
			border-radius: 3px;
			margin-bottom: 8px;
			.panel-body {
				display: flex;
				justify-content: space-around;
				.panel-item {
					display: flex;
					flex-direction: column;
					align-items: center;
					justify-content: space-around;
					padding: 10px 0;
					font-size: 13px;
				}
			}
		}
	}

在这里插入图片描述

4、渲染第二个面板区域

UI结构

<!-- 面板区域 -->
		<view class="panel-list">
			<!-- 第1个面板 -->
			<view class="panel">
				<view class="panel-body">
					<view class="panel-item">
						<text>8</text>
						<text>收藏的店铺</text>
					</view>
					<view class="panel-item">
						<text>14</text>
						<text>收藏的商品</text>
					</view>
					<view class="panel-item">
						<text>18</text>
						<text>关注的商品</text>
					</view>
					<view class="panel-item">
						<text>84</text>
						<text>组件</text>
					</view>
				</view>
			</view>
			
			<!-- 第二个面板 -->
			<view class="panel">
				<view class="panel-title">
					我的订单
				</view>
				<view class="panel-body">
					<view class="panel-item">
						<image src="/static/icon2.png" class="icon"></image>
						<text>待付款</text>
					</view>
					<view class="panel-item">
						<image src="/static/icon1.png" class="icon"></image>
						<text>待收货</text>
					</view>
					<view class="panel-item">
						<image src="/static/icon3.png" class="icon"></image>
						<text>退款/退货</text>
					</view>
					<view class="panel-item">
						<image src="/static/icon4.png" class="icon"></image>
						<text>全部订单</text>
					</view>
				</view>
			</view>
		</view>

美化

	.panel-list {
		padding: 0 10px;
		position: relative;
		top: -10px;
		.panel {
			background-color: white;
			border-radius: 3px;
			margin-bottom: 8px;
			
			.panel-title {
				line-height: 40px;
				padding-left: 10px;
				font-size: 15px;
				border-bottom: 1px solid #F4F4F4;
			}
			
			.panel-body {
				display: flex;
				justify-content: space-around;
				.panel-item {
					display: flex;
					flex-direction: column;
					align-items: center;
					justify-content: space-around;
					padding: 10px 0;
					font-size: 13px;
					
					.icon {
						width: 35px;
						height: 35px;
					}
				}
			}
		}
	}

在这里插入图片描述

5、渲染第三个面板区域

UI结构

			<!-- 第三个面板 -->
			<view class="panel">
				<view class="panel-list-item">
					<text>收货地址</text>
					<uni-icons type="arrowright" size="15"></uni-icons>
				</view>
				<view class="panel-list-item">
					<text>联系客服</text>
					<uni-icons type="arrowright" size="15"></uni-icons>
				</view>
				<view class="panel-list-item">
					<text>退出登录</text>
					<uni-icons type="arrowright" size="15"></uni-icons>
				</view>
			</view>

美化

	.panel-list-item{
		display: flex;
		justify-content: space-between;
		align-items: center;
		font-size: 15px;
		padding: 0 10px;
		line-height: 45px;
	}

在这里插入图片描述

6、实现退出登录功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、三秒后自动跳转

在购物车页面,当用户点击《结算》按钮时,如果用户没有登录,则3秒后自动跳转到登录页

1、三秒后自动跳转到登录页面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是上面代码也存在问题,我们并没有给定时设定边界值,秒数会一直减,以及当下一次打开页面,seconds秒数不重置问题
在这里插入图片描述
改造delayNavigate方法:

			// 延时导航到my页面
			delayNavigate() {
				this.seconds = 3
				this.showTips(this.seconds)
				setInterval(() => {
					this.seconds--
					if(this.seconds <= 0){
						clearInterval(this.timer)	
						uni.switchTab({
							url: '/pages/my/my'
						})
						return
					}
					this.showTips(this.seconds)
				}, 1000)
			},

在这里插入图片描述

2、登录成功后再返回之前的页面

在自动跳转到登录页面成功之后,把返回页面的信息存储到vuex中,从而方便登录成功之后,重新返回之前的页面

返回页面的信息对象,主要包括{ openType,from } 两个属性,其中openType表示以哪种方式导航回之前的页面;from表示之前页面的url地址

在这里插入图片描述
在这里插入图片描述
改造my-settle组件method节点中的delayNavigate方法,当成功跳转到my页面之后,将重定向的信息对象存储到vuex中:

			// 延时导航到my页面
			delayNavigate() {
				this.seconds = 3
				this.showTips(this.seconds)
				setInterval(() => {
					this.seconds--
					if(this.seconds <= 0){
						clearInterval(this.timer)	
						uni.switchTab({
							url: '/pages/my/my',
							success: () => {
								this.updateRedirectInfo({
									openType: 'switchTab',
									from: '/pages/cart/cart'
								})
							}
						})
						return
					}
					this.showTips(this.seconds)
				}, 1000)
			},

在这里插入图片描述
在这里插入图片描述

登录成功,自动跳转到购物车页面
在这里插入图片描述

五、微信支付

1、微信支付的流程

在这里插入图片描述

2、创建订单

在settlement点击结算按钮绑定订单创建的方法 payOrder()

在这里插入图片描述

async payOrder() {
				//1. 创建订单
				//1.1 组织订单的信息对象:
				const orderInfo = {
					order_price: 0.01,
					consignee_addr: this.addstr,
					goods: this.cart.filter(x => x.goods_state).map(x => ({
						goods_id: x.goods_id,
						goods_number: x.goods_count,
						goods_price: x.goods_price
					}))
				}
				// 1.2 发起请求创建订单
				const { data : res } = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/create',
					data: orderInfo,
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				console.log(res)
				if(res.meta.status !== 200){
					return uni.showToast({
						title: '订单创建失败!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 1.3 得到服务器相应的“订单编号”
				const orderNumber = res.message.order_number
				console.log(orderNumber)
			},

点击结算按钮,成功返回订单编号
在这里插入图片描述

在这里插入图片描述

3、订单预支付

改造my-settle组件的payOrder方法,实现订单预支付功能;

			async payOrder() {
				//1. 创建订单
				//1.1 组织订单的信息对象:
				const orderInfo = {
					order_price: 0.01,
					consignee_addr: this.addstr,
					goods: this.cart.filter(x => x.goods_state).map(x => ({
						goods_id: x.goods_id,
						goods_number: x.goods_count,
						goods_price: x.goods_price
					}))
				}
				// 1.2 发起请求创建订单
				const { data : res } = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/create',
					data: orderInfo,
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				console.log(res)
				if(res.meta.status !== 200){
					return uni.showToast({
						title: '订单创建失败!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 1.3 得到服务器相应的“订单编号”
				const order_number = res.message.order_number
				// 2. 订单预支付
				// 2.1发起请求获取订单的支付信息
				console.log(order_number)
				const { data : res2} = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/req_unifiedorder',
					data: {
						'order_number' : order_number
					},
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				console.log(res2)
				// 2.2预支付订单生成失败
				if(res2.meta.status !== 200){
					return uni.showToast({
						title: '订单预支付失败!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 2.3得到订单支付相关的必要参数
				const payInfo = res2.message.pay
				console.log(payInfo)
				// 3. 发起微信支付
			},

在这里插入图片描述

4、发起微信支付

在这里插入图片描述

async payOrder() {
				//1. 创建订单
				//1.1 组织订单的信息对象:
				const orderInfo = {
					order_price: 0.01,
					consignee_addr: this.addstr,
					goods: this.cart.filter(x => x.goods_state).map(x => ({
						goods_id: x.goods_id,
						goods_number: x.goods_count,
						goods_price: x.goods_price
					}))
				}
				// 1.2 发起请求创建订单
				const { data : res } = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/create',
					data: orderInfo,
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				console.log(res)
				if(res.meta.status !== 200){
					return uni.showToast({
						title: '订单创建失败!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 1.3 得到服务器相应的“订单编号”
				const order_number = res.message.order_number
				// 2. 订单预支付
				// 2.1发起请求获取订单的支付信息
				console.log(order_number)
				const { data : res2} = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/req_unifiedorder',
					data: {
						'order_number' : order_number
					},
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				console.log(res2)
				// 2.2预支付订单生成失败
				if(res2.meta.status !== 200){
					return uni.showToast({
						title: '订单预支付失败!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 2.3得到订单支付相关的必要参数
				const payInfo = res2.message.pay
				console.log(payInfo)
				// 3. 发起微信支付
				// 3.1 调用uni.requestPayment() 发起微信支付
				const [err, succ] = await uni.requestPayment(payInfo)
				// 3.2 未完成支付
				if(err) {
					return uni.showToast({
						title: '订单未支付!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 3.3 完成了支付,进一步查询支付的结构
				const {data : res3} = await uni.request({
					url: 'https://api-hmugo-web.itheima.net/api/public/v1/my/orders/chkOrder',
					data: {
						'order_number' : order_number
					},
					method: 'POST',
					header: {
						'Authorization': this.token
					},
				})
				// 3.4 检查订单未完成支付
				if(res3.meta.status !== 200) {
					return uni.showToast({
						title: '订单未支付!',
						duration: 1500,
						icon: 'none',
					})
				}
				// 3.5检查订单完成支付
				uni.showToast({
					title: '订单支付完成!',
					duration: 1500,
					icon: 'success',
				})
			},

在这里插入图片描述
在这里插入图片描述

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值