|
@@ -2,8 +2,8 @@
|
|
|
<view>
|
|
|
<view class="vipBox">
|
|
|
<view class="avatar">
|
|
|
- <img :src="getUserAvatar(baseInfo?.avatar, baseInfo?.sex)" alt="" class="img-box">
|
|
|
- <image src="/static/svg/vip.svg" class="vipIcon"></image>
|
|
|
+ <img :src="getUserAvatar(baseInfo?.avatar, baseInfo?.sex)" alt="" class="img-box" :class="{'img-box-atc': userInfo?.vipExpireDate}">
|
|
|
+ <image v-if="userInfo.value?.vipExpireDate" src="/static/svg/vip.svg" class="vipIcon"></image>
|
|
|
</view>
|
|
|
<view class="nameBox">
|
|
|
<view class="name font-weight-bold font-size-16">{{ baseInfo?.name || userInfo?.phone }}</view>
|
|
@@ -20,7 +20,7 @@
|
|
|
<view
|
|
|
class="card"
|
|
|
:class="{ recommend: val.recommend, vipFlag: val.my, active: val.id === chooseId}"
|
|
|
- @tap="handleChoose(val.id)"
|
|
|
+ @tap="handleChoose(val, index)"
|
|
|
>
|
|
|
<text>{{ val.name }}</text>
|
|
|
<view>
|
|
@@ -107,11 +107,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed, watch } from 'vue'
|
|
|
-
|
|
|
+import { ref, computed } from 'vue'
|
|
|
import { getUserAvatar } from '@/utils/avatar'
|
|
|
import { userStore } from '@/store/user'
|
|
|
import { getMembershipPackageList } from '@/api/vip'
|
|
|
+// import { orderCreated, getOrder, payOrderSubmit } from '@/api/common'
|
|
|
+import { orderCreated, getOrder, getSocialUser, socialUserBind, payOrderSubmit } from '@/api/common'
|
|
|
const useUserStore = userStore()
|
|
|
|
|
|
const baseInfo = computed(() => useUserStore?.baseInfo)
|
|
@@ -153,11 +154,10 @@ const list = computed(() => {
|
|
|
})
|
|
|
|
|
|
const current = ref(0)
|
|
|
-
|
|
|
const payType = ref([
|
|
|
{
|
|
|
name: '微信支付',
|
|
|
- value: 'wxpay',
|
|
|
+ value: 'wx_lite',
|
|
|
icon: 'icon-weixinzhifu',
|
|
|
color: '#1AAD19'
|
|
|
}
|
|
@@ -170,14 +170,18 @@ const payType = ref([
|
|
|
])
|
|
|
|
|
|
const payTypeCurrent = ref(0)
|
|
|
-
|
|
|
+const channel = ref('')
|
|
|
const radioChange = (index) => {
|
|
|
+ channel.value = payType[index].value
|
|
|
payTypeCurrent.value = index
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-const handleChoose = (id) => {
|
|
|
- chooseId.value = id
|
|
|
+const chooseIndex = ref(0)
|
|
|
+const chooseItem = ref(null)
|
|
|
+const handleChoose = (val, index) => {
|
|
|
+ chooseId.value = val.id
|
|
|
+ chooseIndex.value = index
|
|
|
+ chooseItem.value = val
|
|
|
}
|
|
|
|
|
|
const handleOpen = () => {
|
|
@@ -188,9 +192,153 @@ const handleClose = () => {
|
|
|
popup.value.close()
|
|
|
}
|
|
|
|
|
|
+// 设置 openid 到本地存储,目前只有 pay 支付时会使用
|
|
|
+const setOpenid = (openid) => {
|
|
|
+ uni.setStorageSync('openid', openid)
|
|
|
+}
|
|
|
+
|
|
|
+const bind = () => {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ // 1. 获得微信 code
|
|
|
+ const codeResult = await uni.login()
|
|
|
+ if (codeResult.errMsg !== 'login:ok') {
|
|
|
+ return resolve(false)
|
|
|
+ }
|
|
|
+ // 2. 绑定账号 // // 社交快捷登录
|
|
|
+ const obj = {
|
|
|
+ type: socialType,
|
|
|
+ code: codeResult.code,
|
|
|
+ state: 'default',
|
|
|
+ }
|
|
|
+ const bindResult = await socialUserBind(obj);
|
|
|
+ if (bindResult.code === 0) {
|
|
|
+ setOpenid(bindResult.data)
|
|
|
+ return resolve(true)
|
|
|
+ } else {
|
|
|
+ return resolve(false)
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const bindWeiXin = () => {
|
|
|
+ uni.showModal({
|
|
|
+ title: '微信支付',
|
|
|
+ content: '请先绑定微信再使用微信支付',
|
|
|
+ success: function (res) {
|
|
|
+ if (res.confirm) {
|
|
|
+ // 微信小程序绑定
|
|
|
+ bind()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const socialType = 34; // 社交类型 - 微信小程序
|
|
|
+
|
|
|
+// 预支付
|
|
|
+const prepay = async (channel, orderData) => {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ let data = {
|
|
|
+ id: orderData.payOrder.id,
|
|
|
+ channelCode: channel,
|
|
|
+ channelExtras: {},
|
|
|
+ };
|
|
|
+ // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
|
|
|
+ if (['wx_pub', 'wx_lite'].includes(channel)) {
|
|
|
+ const userRes = await getSocialUser(socialType)
|
|
|
+ const openid = userRes?.data?.openid ? userRes.data.openid : null
|
|
|
+ // 如果获取不到 openid,微信无法发起支付,此时需要引导
|
|
|
+ if (!openid) {
|
|
|
+ bindWeiXin()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ data.channelExtras.openid = openid
|
|
|
+ }
|
|
|
+ // 发起预支付 API 调用
|
|
|
+ payOrderSubmit(data).then((res) => {
|
|
|
+ // 成功时
|
|
|
+ res.code === 0 && resolve(res)
|
|
|
+ // 失败时
|
|
|
+ if (res.code !== 0 && res.msg.indexOf('无效的openid') >= 0) {
|
|
|
+ // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid 不正确的情况
|
|
|
+ if (
|
|
|
+ res.msg.indexOf('无效的openid') >= 0 || // 获取的 openid 不正确时,或者随便输入了个 openid
|
|
|
+ res.msg.indexOf('下单账号与支付账号不一致') >= 0
|
|
|
+ ) {
|
|
|
+ // https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
|
|
|
+ bindWeiXin()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const weChatMiniProgramPay = async (orderData) => {
|
|
|
+ let res = await prepay('wx_lite', orderData); // 预支付
|
|
|
+ if (res?.code !== 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 调用微信小程序支付
|
|
|
+ const payConfig = res?.data?.displayContent ? JSON.parse(res.data.displayContent) : null
|
|
|
+ if (!payConfig) return uni.showToast({ title: '购买失败', icon: 'none'})
|
|
|
+ uni.requestPayment({
|
|
|
+ provider: 'wxpay',
|
|
|
+ timeStamp: payConfig.timeStamp,
|
|
|
+ nonceStr: payConfig.nonceStr,
|
|
|
+ package: payConfig.packageValue,
|
|
|
+ signType: 'RSA',
|
|
|
+ paySign: payConfig.paySign,
|
|
|
+ success: (res) => {
|
|
|
+ popup.value.close()
|
|
|
+ uni.showToast({ title: '支付成功', icon: 'none'})
|
|
|
+ useUserStore.getUserInfo()
|
|
|
+ // this.payResult('success');
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ if (err.errMsg === 'requestPayment:fail cancel') {
|
|
|
+ uni.showToast({ title: '支付已取消', icon: 'none'})
|
|
|
+ } else {
|
|
|
+ // this.payResult('fail');
|
|
|
+ uni.showToast({ title: '支付失败', icon: 'none'})
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+// uni.showToast({ title: '支付升级中', icon: 'none'})
|
|
|
// 支付
|
|
|
const handlePay = async () => {
|
|
|
- uni.showToast({ title: '支付升级中', icon: 'none'})
|
|
|
+ const val = chooseItem.value
|
|
|
+ try {
|
|
|
+ const res = await getOrder({
|
|
|
+ spuId: val.id, // 商品编号
|
|
|
+ type: val.type
|
|
|
+ })
|
|
|
+ if (res.data) {
|
|
|
+ // 获取支付码
|
|
|
+ weChatMiniProgramPay(res.data)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ await orderCreated({
|
|
|
+ spuId: val.id, // 商品编号
|
|
|
+ spuName: val.name, // 商品名称
|
|
|
+ price: val.price*100, // 价格
|
|
|
+ type: val.type // 订单类型 0平台订单|1求职端订单|2招聘端订单|3会员套餐
|
|
|
+ })
|
|
|
+
|
|
|
+ const _res = await getOrder({
|
|
|
+ spuId: val.id, // 商品编号
|
|
|
+ type: val.type
|
|
|
+ })
|
|
|
+
|
|
|
+ // 获取支付码
|
|
|
+ weChatMiniProgramPay(_res.data)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ } finally {
|
|
|
+ val.loading = false
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const getMemberList = async () => {
|
|
@@ -207,6 +355,8 @@ const getMemberList = async () => {
|
|
|
}
|
|
|
if (item.recommend) {
|
|
|
recommend.value = index // 推荐套餐
|
|
|
+ chooseIndex.value = index
|
|
|
+ chooseItem.value = item
|
|
|
}
|
|
|
return {
|
|
|
...item,
|
|
@@ -219,17 +369,27 @@ const getMemberList = async () => {
|
|
|
})
|
|
|
// 低于当前套餐的(套餐)不展示
|
|
|
memberList.value = vipFlagIndex ? list.slice(vipFlagIndex) : list
|
|
|
- handleChoose(memberList.value[0]?.id)
|
|
|
+ handleChoose(memberList.value[0], recommend.value)
|
|
|
if ((!userInfo.value?.vipFlag || userInfo.value?.vipExpireDate - new Date().getTime() > 0 ) && typeof recommend.value === 'number') {
|
|
|
current.value = parseInt(recommend.value / 2)
|
|
|
chooseId.value = memberList.value[recommend.value]?.id
|
|
|
+ chooseIndex.value = recommend.value
|
|
|
+ chooseItem.value = memberList.value[recommend.value]
|
|
|
}
|
|
|
} catch (error) {
|
|
|
uni.showToast({ title: '查询数据失败,请重试', icon: 'none' })
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
getMemberList()
|
|
|
+
|
|
|
+// const getPayMethodsList = async () => {
|
|
|
+// try {
|
|
|
+// } catch (error) {
|
|
|
+// // uni.showToast({ title: '查询数据失败,请重试', icon: 'none' })
|
|
|
+// }
|
|
|
+// }
|
|
|
+// getPayMethodsList()
|
|
|
+
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
@@ -250,6 +410,9 @@ getMemberList()
|
|
|
border-radius: 50%;
|
|
|
border: 1px solid gold;
|
|
|
}
|
|
|
+ .img-box-atc {
|
|
|
+ border: 1px solid gold;
|
|
|
+ }
|
|
|
.vipIcon {
|
|
|
position: absolute;
|
|
|
width: 50%;
|