大修改
This commit is contained in:
1 parent
a1cbc9404a
commit
e81481623c
47 files changed
+1453
-285
No files matched your search
@@ -0,0 +1,143 @@
|
||||
// pages/buy/buy.js
|
||||
//
|
||||
// 商业化页面:所有购买入口都落到这里。
|
||||
// 职责是「确认订单 → 拉起微信支付 → 确认发货」,课程详情不在这里展示。
|
||||
// UI 待设计,wxml 现在只有一个占位块,支付链路已经就位。
|
||||
const api = require('../../utils/api');
|
||||
const format = require('../../utils/format');
|
||||
const store = require('../../utils/store');
|
||||
|
||||
const POLL_INTERVAL = 1500;
|
||||
const POLL_MAX = 8;
|
||||
|
||||
Page({
|
||||
data: {
|
||||
code: '',
|
||||
loading: true,
|
||||
buying: false,
|
||||
owned: false,
|
||||
title: '',
|
||||
coverUrl: '',
|
||||
priceYuan: '',
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
const code = options && options.code;
|
||||
// 没带课程号说明是误入(比如直接输路径打开),不该停在这个页面
|
||||
if (!code) {
|
||||
this.rejectOut('缺少课程参数');
|
||||
return;
|
||||
}
|
||||
this.setData({ code: code });
|
||||
this.load(code);
|
||||
},
|
||||
|
||||
load(code) {
|
||||
api
|
||||
.getCourse(code)
|
||||
.then((course) => {
|
||||
this.setData({
|
||||
loading: false,
|
||||
owned: course.owned,
|
||||
title: course.title || '',
|
||||
coverUrl: course.coverUrl || '',
|
||||
priceYuan: format.fenToYuan(course.priceFen),
|
||||
});
|
||||
// 已经拥有就不用再买了,避免重复下单
|
||||
if (course.owned) this.rejectOut('你已经拥有这门课程');
|
||||
})
|
||||
.catch((err) => {
|
||||
this.setData({ loading: false });
|
||||
// 课程被下架或课程号拼错,后端会返回错误,这里按同样的方式退出
|
||||
this.rejectOut((err && err.message) || '课程不存在');
|
||||
});
|
||||
},
|
||||
|
||||
/** 进错页面(没带课程、课程不存在、已经买过):提示一句然后退出去。 */
|
||||
rejectOut(message) {
|
||||
wx.showToast({ title: message, icon: 'none' });
|
||||
setTimeout(() => this.back(), 1500);
|
||||
},
|
||||
|
||||
/** 退回上一页;没有上一页(直接打开)就回知识页,避免停在死页面。 */
|
||||
back() {
|
||||
if (getCurrentPages().length > 1) {
|
||||
wx.navigateBack();
|
||||
return;
|
||||
}
|
||||
wx.switchTab({ url: '/pages/kecheng/kecheng' });
|
||||
},
|
||||
|
||||
/** 购买:下单 → 拉起支付 → 轮询订单状态确认发货。 */
|
||||
buyNow() {
|
||||
if (this.data.buying || !this.data.code) return;
|
||||
|
||||
// 购买的前置条件:用户主动使用过登录功能。静默登录不算。
|
||||
if (!store.isLoggedIn()) {
|
||||
wx.showModal({
|
||||
title: '请先登录',
|
||||
content: '使用微信登录后才能购买课程',
|
||||
confirmText: '去登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.navigateTo({ url: '/pages/LoginOrOutDetails/LoginOrOutDetails' });
|
||||
}
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof wx.requestVirtualPayment !== 'function') {
|
||||
wx.showToast({ title: '当前微信版本不支持支付,请升级微信', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ buying: true });
|
||||
wx.showLoading({ title: '发起支付', mask: true });
|
||||
|
||||
api
|
||||
.createOrder(this.data.code)
|
||||
.then((order) => {
|
||||
wx.hideLoading();
|
||||
return api.requestVirtualPayment(order.payData).then(() => order.outTradeNo);
|
||||
})
|
||||
.then((outTradeNo) => this.waitForDelivery(outTradeNo))
|
||||
.catch((err) => {
|
||||
wx.hideLoading();
|
||||
this.setData({ buying: false });
|
||||
// 用户主动取消不算错误
|
||||
if (err && err.errMsg && err.errMsg.indexOf('cancel') >= 0) return;
|
||||
wx.showToast({ title: (err && err.message) || '支付失败', icon: 'none' });
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 支付成功后权益由服务端发货推送发放,存在秒级延迟,这里轮询确认。
|
||||
* 即便轮询全部超时也不会丢单:服务端有定时查单兜底。
|
||||
*/
|
||||
waitForDelivery(outTradeNo) {
|
||||
let attempts = 0;
|
||||
const poll = () => {
|
||||
attempts += 1;
|
||||
return api.getOrder(outTradeNo).then((order) => {
|
||||
if (order.status === 2) {
|
||||
this.setData({ buying: false, owned: true });
|
||||
wx.showToast({ title: '购买成功', icon: 'success', mask: true });
|
||||
setTimeout(() => this.back(), 1500);
|
||||
return;
|
||||
}
|
||||
if (attempts >= POLL_MAX || order.status === 3 || order.status === 4) {
|
||||
this.setData({ buying: false });
|
||||
wx.showToast({ title: '支付已提交,开通可能稍有延迟', icon: 'none', duration: 3000 });
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL)).then(poll);
|
||||
});
|
||||
};
|
||||
return poll();
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
return { title: '叶雷讲数学', path: '/pages/index/index' };
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<!--pages/buy/buy.wxml-->
|
||||
|
||||
<!-- UI 待设计。支付链路(buyNow / waitForDelivery)已经在 buy.js 里就位,
|
||||
设计稿定了直接替换下面这个占位块即可。 -->
|
||||
<view class="buy-page">
|
||||
<text class="buy-placeholder">购买页(待设计)</text>
|
||||
</view>
|
||||
@@ -0,0 +1,14 @@
|
||||
/* pages/buy/buy.wxss */
|
||||
|
||||
/* 占位样式,UI 定稿后连同 wxml 一起替换 */
|
||||
.buy-page {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 70vh;
|
||||
}
|
||||
|
||||
.buy-placeholder {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
Reference in new issue
Block a user