|
@@ -36,7 +36,7 @@
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="popup-content-btn">
|
|
<view class="popup-content-btn">
|
|
- <button class="popup-content-btn-s" @tap="handlePay">
|
|
|
|
|
|
+ <button class="popup-content-btn-s" @tap="handlePay(false)">
|
|
确认支付
|
|
确认支付
|
|
<uni-icons color="#FFF" type="icon-renminbi1688" size="16" custom-prefix="iconfont"></uni-icons>
|
|
<uni-icons color="#FFF" type="icon-renminbi1688" size="16" custom-prefix="iconfont"></uni-icons>
|
|
{{ amount }}
|
|
{{ amount }}
|
|
@@ -48,7 +48,11 @@
|
|
</template>
|
|
</template>
|
|
<script setup>
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import { ref } from 'vue'
|
|
-import { getEnableCodeList } from '@/api/common'
|
|
|
|
|
|
+import { onHide, onShow } from '@dcloudio/uni-app'
|
|
|
|
+// import { userStore } from '@/store/user'; const useUserStore = userStore()
|
|
|
|
+import { getSocialUser, socialUserBind, payOrderSubmit, getOrderPayStatus, getEnableCodeList } from '@/api/common'
|
|
|
|
+import { createTradeOrder, getUnpaidOrder } from '@/api/new/position'
|
|
|
|
+const emit = defineEmits(['paySuccess'])
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
title: { // 标题
|
|
title: { // 标题
|
|
@@ -83,7 +87,7 @@ const payTypeList = ref([])
|
|
const getPayMethodsList = async () => {
|
|
const getPayMethodsList = async () => {
|
|
payTypeList.value = []
|
|
payTypeList.value = []
|
|
try {
|
|
try {
|
|
- const res = await getEnableCodeList({appId: 14})
|
|
|
|
|
|
+ const res = await getEnableCodeList({appId: 15})
|
|
if (!res?.data?.length) {
|
|
if (!res?.data?.length) {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
@@ -113,15 +117,206 @@ const handleClose = () => {
|
|
tabBarControl(true)
|
|
tabBarControl(true)
|
|
popup.value.close()
|
|
popup.value.close()
|
|
}
|
|
}
|
|
-const handleOpen = () => {
|
|
|
|
|
|
+const query = ref(null)
|
|
|
|
+const handleOpen = (val) => {
|
|
|
|
+ query.value = val
|
|
tabBarControl(false)
|
|
tabBarControl(false)
|
|
popup.value.open('bottom')
|
|
popup.value.open('bottom')
|
|
}
|
|
}
|
|
|
|
|
|
-// 支付
|
|
|
|
-const handlePay = async () => {
|
|
|
|
|
|
+// 设置 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
|
|
|
|
+ ) {
|
|
|
|
+ bindWeiXin()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+let interTimer = null
|
|
|
|
+let payLoading = false
|
|
|
|
+const checkPayStatus = async (id) => {
|
|
|
|
+ if (!id) return
|
|
|
|
+ try {
|
|
|
|
+ if (payLoading || !interTimer) return
|
|
|
|
+ payLoading = true
|
|
|
|
+ const res = await getOrderPayStatus({ id })
|
|
|
|
+ if (res?.data?.status === 10) {
|
|
|
|
+ if (interTimer) clearInterval(interTimer)
|
|
|
|
+ emit('paySuccess')
|
|
|
|
+ // setTimeout(async () => {
|
|
|
|
+ // const _userInfo = await useUserStore.getUserInfo()
|
|
|
|
+ // userInfo.value = _userInfo
|
|
|
|
+ // getMemberList() // 刷新套餐列表
|
|
|
|
+ // }, 1500)
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.log(error)
|
|
|
|
+ } finally {
|
|
|
|
+ payLoading = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 计时器
|
|
|
|
+const initIntervalFun = () => {
|
|
|
|
+ if (interTimer) clearInterval(interTimer)
|
|
|
|
+
|
|
|
|
+ // 查询是否已经支付
|
|
|
|
+ const id = orderInfo.value?.payOrder?.id || orderInfo.value?.order?.payOrderId
|
|
|
|
+ if (id) {
|
|
|
|
+ interTimer = setInterval(() => {
|
|
|
|
+ checkPayStatus(id)
|
|
|
|
+ }, 1000)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const orderInfo = ref({})
|
|
|
|
+const weChatMiniProgramPay = async (data) => {
|
|
|
|
+ orderInfo.value = data
|
|
|
|
+ let res = await prepay(channelValue.value, data); // 预支付
|
|
|
|
+ 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) => {
|
|
|
|
+ initIntervalFun()
|
|
|
|
+ popup.value.close()
|
|
|
|
+ uni.showToast({ title: '支付成功', icon: 'none'})
|
|
|
|
+ },
|
|
|
|
+ fail: (err) => {
|
|
|
|
+ if (err.errMsg === 'requestPayment:fail cancel') {
|
|
|
|
+ uni.showToast({ title: '支付已取消', icon: 'none'})
|
|
|
|
+ } else {
|
|
|
|
+ uni.showToast({ title: '支付失败', icon: 'none'})
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 确认支付
|
|
|
|
+const handlePay = async (retry = false) => {
|
|
|
|
+ if (!channelValue.value) {
|
|
|
|
+ uni.showToast({ title: '请选择支付方式', icon: 'none'})
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // 判断是否已有创建好的订单,有就直接跳转支付,没有就创建订单
|
|
|
|
+ try {
|
|
|
|
+ const params = {
|
|
|
|
+ spuId: query.value?.spuId, // 商品编号
|
|
|
|
+ type: query.value?.type // 订单类型 0平台订单|1发布职位|2发布众聘职位|3会员套餐|4企业会员套餐|5招聘会门票
|
|
|
|
+ }
|
|
|
|
+ if (!params.spuId || params.type === null || params.type === undefined) return
|
|
|
|
+ const res = await getUnpaidOrder(params) // 查询订单
|
|
|
|
+ if (res.data) {
|
|
|
|
+ // 获取支付码
|
|
|
|
+ weChatMiniProgramPay(res.data)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if (!retry) setOrderCreated() // 创建订单
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.log(error)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const setOrderCreated = async () => {
|
|
|
|
+ const params = {
|
|
|
|
+ spuId: query.value?.spuId, // 商品编号
|
|
|
|
+ type: query.value?.type, // 订单类型 0平台订单|1发布职位|2发布众聘职位|3会员套餐|4企业会员套餐|5招聘会门票
|
|
|
|
+ price: query.value?.price, // 价格
|
|
|
|
+ spuName: query.value?.spuName, // 商品名称
|
|
|
|
+ }
|
|
|
|
+ if (!params.spuId || params.type === null || params.type === undefined || !params.price || !params.spuName) return
|
|
|
|
+ await createTradeOrder(params)
|
|
|
|
+ handlePay(true) // 避免死循环
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+onShow(() => {
|
|
|
|
+ if (orderInfo && orderInfo.value?.id) initIntervalFun()
|
|
|
|
+})
|
|
|
|
+onHide(() => {
|
|
|
|
+ if (interTimer) clearInterval(interTimer)
|
|
|
|
+})
|
|
|
|
+
|
|
defineExpose({
|
|
defineExpose({
|
|
handleOpen
|
|
handleOpen
|
|
})
|
|
})
|