492 lines
12 KiB
Vue
492 lines
12 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="container">
|
|||
|
|
<view class="title-back">
|
|||
|
|
<view class="left-father" @click="goBack">
|
|||
|
|
<image class="back-img" src="https://www.focusnu.com/media/directive/index/left.png" />
|
|||
|
|
<view style="font-size: 30rpx;">缴费账单</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="bgc">
|
|||
|
|
<image class="bgc-img" src="https://www.focusnu.com/media/directive/index/account.png" />
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container" style="margin-top: 550rpx;">
|
|||
|
|
<view class="white-container-top">
|
|||
|
|
<image style="width: 30rpx;height: 30rpx;margin-right: 20rpx;"
|
|||
|
|
src="https://www.focusnu.com/media/directive/index/account/0.png" />
|
|||
|
|
<view style="color: #999999;">
|
|||
|
|
机构名称
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container-bottom">
|
|||
|
|
{{ item.departName }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container">
|
|||
|
|
<view class="white-container-top">
|
|||
|
|
<image style="width: 30rpx;height: 30rpx;margin-right: 20rpx;"
|
|||
|
|
src="https://www.focusnu.com/media/directive/index/account/1.png" />
|
|||
|
|
<view style="color: #999999;">
|
|||
|
|
护理单元
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container-bottom">
|
|||
|
|
{{ item.nuName }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container">
|
|||
|
|
<view class="white-container-top">
|
|||
|
|
<image style="width: 30rpx;height: 30rpx;margin-right: 20rpx;"
|
|||
|
|
src="https://www.focusnu.com/media/directive/index/account/2.png" />
|
|||
|
|
<view style="color: #999999;">
|
|||
|
|
账单金额
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="white-container-bottom">
|
|||
|
|
¥ {{ item.payableAmount }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view
|
|||
|
|
style="display: flex;width: 100%;padding: 0 10%;justify-content: space-between;margin-top: 50rpx;z-index: 1;">
|
|||
|
|
<view class="back-button" @click="goBack">
|
|||
|
|
返回上一步
|
|||
|
|
</view>
|
|||
|
|
<view class="finish-button" @click="initiatePayment">
|
|||
|
|
微信支付
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<!-- <view class="white-content">
|
|||
|
|
<view class="white-title">
|
|||
|
|
NUID:{{ item.nuId }}
|
|||
|
|
</view>
|
|||
|
|
<view class="white-second">
|
|||
|
|
{{ item.departName }}
|
|||
|
|
</view>
|
|||
|
|
<view class="white-center">
|
|||
|
|
{{ item.nuName }}
|
|||
|
|
<image class="center-img" src="https://www.focusnu.com/media/directive/index/sheying.png" />
|
|||
|
|
</view>
|
|||
|
|
<view style="display: flex;width: 85%;position: absolute;bottom: 0rpx;">
|
|||
|
|
<view class="finish-button" v-if="item.nuCanUse==0" @click="goToPay">
|
|||
|
|
绑定护理单元
|
|||
|
|
</view>
|
|||
|
|
<view class="white-button" v-else>
|
|||
|
|
护理单元使用中
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view style="width: 100%;display: flex;justify-content: flex-end;" >
|
|||
|
|
<view class="back-right" @click="goBack">
|
|||
|
|
重新扫码
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
</view> -->
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import {
|
|||
|
|
ref,
|
|||
|
|
reactive
|
|||
|
|
} from 'vue'
|
|||
|
|
import {
|
|||
|
|
onLoad,
|
|||
|
|
onShow
|
|||
|
|
} from '@dcloudio/uni-app';
|
|||
|
|
import {
|
|||
|
|
getOrgNuId,getAccount
|
|||
|
|
} from './api.js'
|
|||
|
|
|
|||
|
|
const goBack = () => {
|
|||
|
|
uni.navigateBack()
|
|||
|
|
}
|
|||
|
|
const item = ref({});
|
|||
|
|
const payurl = ref("")
|
|||
|
|
onLoad(() => {
|
|||
|
|
item.value = uni.getStorageSync('payaccount')
|
|||
|
|
getAccount(item.value.orgCode).then(res=>{
|
|||
|
|
payurl.value = res.result.url
|
|||
|
|
// console.log("res",res.result.url)
|
|||
|
|
})
|
|||
|
|
// console.log("?????",item.value)
|
|||
|
|
})
|
|||
|
|
// 发起支付入口(async)
|
|||
|
|
const initiatePayment = async () => {
|
|||
|
|
try {
|
|||
|
|
const urlpost = `${payurl.value}/weiXinPay/nuBindPay`;
|
|||
|
|
|
|||
|
|
const payload = {
|
|||
|
|
title: '护理单元绑定',
|
|||
|
|
openId: uni.getStorageSync('openid') || '',
|
|||
|
|
amountPrice: item.value.payableAmount ,
|
|||
|
|
orgCode: item.value.nuId.substring(4, 7),
|
|||
|
|
nursingUnit: item.value.nuId ,
|
|||
|
|
orderDesc:`用户绑定护理单元${item.value?.nuId},充值${item.value?.payableAmount}元`,
|
|||
|
|
// customerId: '顾客id',
|
|||
|
|
orderType: 'binding_nu',
|
|||
|
|
price: item.value.payableAmount,
|
|||
|
|
count: 1,
|
|||
|
|
unit: '间',
|
|||
|
|
customerId:uni.getStorageSync('allinfo').id
|
|||
|
|
};
|
|||
|
|
console.log("AAAAAAA",payload)
|
|||
|
|
// 显示 loading
|
|||
|
|
uni.showLoading({
|
|||
|
|
title: '正在请求支付...'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 使用 uni.request 代替 fetch
|
|||
|
|
const res = await new Promise((resolve, reject) => {
|
|||
|
|
uni.request({
|
|||
|
|
url: urlpost,
|
|||
|
|
method: 'POST',
|
|||
|
|
header: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
},
|
|||
|
|
data: payload,
|
|||
|
|
success: (r) => resolve(r),
|
|||
|
|
fail: (e) => reject(e)
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
uni.hideLoading();
|
|||
|
|
|
|||
|
|
// uni.request 返回的结构通常是 { statusCode, data, ... }
|
|||
|
|
const data = res && res.data ? res.data : res;
|
|||
|
|
|
|||
|
|
|
|||
|
|
console.log("data",data)
|
|||
|
|
|
|||
|
|
if(data.nuFailType=="ORG_PAYMENT_DISABLED"){
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '机构已经关闭微信支付功能',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
setTimeout(()=>{
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url:'/pages/oldmanindex/index'
|
|||
|
|
})
|
|||
|
|
},1000)
|
|||
|
|
}else if(data.nuFailType=="NU_HAS_BEEN_BOUND"){
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '护理单元已被其他用户绑定',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
setTimeout(()=>{
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url:'/pages/oldmanindex/index'
|
|||
|
|
})
|
|||
|
|
},1000)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// return
|
|||
|
|
|
|||
|
|
if (!data) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '服务器无响应',
|
|||
|
|
icon: 'error'
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 后端返回包含 appId 等支付所需字段
|
|||
|
|
if (data.appId || data.timeStamp || data.package || data.paySign) {
|
|||
|
|
await callWeixinPay(data);
|
|||
|
|
} else {
|
|||
|
|
// 如果后端使用另一种返回结构,请按实际字段判断
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付信息获取失败',
|
|||
|
|
icon: 'error'
|
|||
|
|
});
|
|||
|
|
console.error('支付返回:', data);
|
|||
|
|
}
|
|||
|
|
} catch (err) {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
console.error('请求失败:', err);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请求失败',
|
|||
|
|
icon: 'error'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 支付调用封装(支持公众号 H5 和微信小程序)
|
|||
|
|
function callWeixinPay(data) {
|
|||
|
|
console.log("????",data)
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// 判断运行平台(H5 / 小程序 / 其它)
|
|||
|
|
const isH5 = (typeof window !== 'undefined') && (typeof navigator !== 'undefined');
|
|||
|
|
const ua = isH5 ? navigator.userAgent || '' : '';
|
|||
|
|
const isWeixinBrowser = /MicroMessenger/i.test(ua);
|
|||
|
|
// const isMpWeixin = (process && process.env && process.env.UNI_PLATFORM === 'mp-weixin');
|
|||
|
|
|
|||
|
|
// --- 微信公众号 H5(WeixinJSBridge) ---
|
|||
|
|
if (isH5 && isWeixinBrowser) {
|
|||
|
|
const invokePay = () => {
|
|||
|
|
// 注意:传递对象字段名必须与后端一致(package 字段名通常是 'package')
|
|||
|
|
try {
|
|||
|
|
window.WeixinJSBridge.invoke(
|
|||
|
|
'getBrandWCPayRequest', {
|
|||
|
|
appId: data.appId,
|
|||
|
|
timeStamp: String(data.timeStamp), // 字符串
|
|||
|
|
nonceStr: data.nonceStr,
|
|||
|
|
package: data.package, // 注意字段名:package
|
|||
|
|
signType: data.signType || 'MD5',
|
|||
|
|
paySign: data.paySign
|
|||
|
|
},
|
|||
|
|
function(res) {
|
|||
|
|
// 微信返回结果
|
|||
|
|
// 成功: "get_brand_wcpay_request:ok"
|
|||
|
|
// 取消/失败: 其他值
|
|||
|
|
if (res && (res.err_msg === 'get_brand_wcpay_request:ok' || res.err_msg ===
|
|||
|
|
'get_brand_wcpay_request:ok')) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付成功'
|
|||
|
|
});
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url:'/pages/oldmanindex/paysuccess'
|
|||
|
|
})
|
|||
|
|
// resolve(res);
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付失败或取消',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
// reject(res);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('WeixinJSBridge 调用异常', e);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付调用失败',
|
|||
|
|
icon: 'error'
|
|||
|
|
});
|
|||
|
|
reject(e);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (typeof window.WeixinJSBridge === 'undefined') {
|
|||
|
|
document.addEventListener('WeixinJSBridgeReady', invokePay, false);
|
|||
|
|
} else {
|
|||
|
|
invokePay();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// --- 微信小程序(mp-weixin): 使用 uni.requestPayment(需后端返回小程序支付签名字段) ---
|
|||
|
|
// if (isMpWeixin) {
|
|||
|
|
// data 里应该包含 timeStamp, nonceStr, package, signType, paySign, 或者后端直接给出 prepayId 等
|
|||
|
|
try {
|
|||
|
|
uni.requestPayment({
|
|||
|
|
provider: 'wxpay',
|
|||
|
|
timeStamp: String(data.timeStamp || data.timeStampStr || ''), // 小程序需要字符串
|
|||
|
|
nonceStr: data.nonceStr || '',
|
|||
|
|
package: data.package || data.packageStr || '', // e.g. 'prepay_id=xxx'
|
|||
|
|
signType: data.signType || 'MD5',
|
|||
|
|
paySign: data.paySign || '',
|
|||
|
|
success: (res) => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付成功'
|
|||
|
|
});
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url:'/pages/oldmanindex/paysuccess'
|
|||
|
|
})
|
|||
|
|
resolve(res);
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('小程序支付失败或取消', err);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付失败或取消',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
reject(err);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('uni.requestPayment 调用异常', e);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '支付调用失败',
|
|||
|
|
icon: 'error'
|
|||
|
|
});
|
|||
|
|
reject(e);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// --- 其它平台或 H5 非微信 浏览器 ---
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '无法发起支付',
|
|||
|
|
content: isH5 ?
|
|||
|
|
'当前在浏览器环境中无法直接发起微信支付,请在微信公众号内打开或使用小程序。' :
|
|||
|
|
'当前平台不支持微信支付,请使用微信小程序或公众号 H5 页面支付。',
|
|||
|
|
showCancel: false
|
|||
|
|
});
|
|||
|
|
reject(new Error('unsupported platform for Weixin pay'));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.container {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
width: 100%;
|
|||
|
|
background-color: #F7F7F7;
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
.title-back {
|
|||
|
|
margin-top: 100rpx;
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100rpx;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.left-father {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
.back-img {
|
|||
|
|
width: 45rpx;
|
|||
|
|
height: 40rpx;
|
|||
|
|
margin-left: 40rpx;
|
|||
|
|
margin-right: 15rpx;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-content {
|
|||
|
|
width: 94%;
|
|||
|
|
margin-left: 3%;
|
|||
|
|
height: 450rpx;
|
|||
|
|
border-radius: 50rpx;
|
|||
|
|
background-color: #fff;
|
|||
|
|
position: relative;
|
|||
|
|
padding: 50rpx;
|
|||
|
|
|
|||
|
|
.white-title {
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-second {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
margin-top: 10rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-center {
|
|||
|
|
margin-top: 50rpx;
|
|||
|
|
font-size: 35rpx;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
font-weight: 600;
|
|||
|
|
|
|||
|
|
.center-img {
|
|||
|
|
width: 45rpx;
|
|||
|
|
height: 35rpx;
|
|||
|
|
margin-left: 20rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.back-right {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
width: 25%;
|
|||
|
|
height: 80rpx;
|
|||
|
|
margin-right: 50rpx;
|
|||
|
|
// margin: 0rpx auto;
|
|||
|
|
// margin-bottom: 50rpx;
|
|||
|
|
margin-top: 50rpx;
|
|||
|
|
color: #fff;
|
|||
|
|
background: linear-gradient(to bottom, #00C9FF, #0076FF);
|
|||
|
|
border-radius: 30rpx;
|
|||
|
|
font-size: 33rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-button {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
width: 60%;
|
|||
|
|
height: 90rpx;
|
|||
|
|
margin: 0rpx auto;
|
|||
|
|
margin-bottom: 50rpx;
|
|||
|
|
margin-top: 20rpx;
|
|||
|
|
background: linear-gradient(to bottom, #f3f3f5, #dee4e9);
|
|||
|
|
border-radius: 35rpx;
|
|||
|
|
font-size: 33rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bgc {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bgc-img {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-container {
|
|||
|
|
width: 90%;
|
|||
|
|
margin-top: 30rpx;
|
|||
|
|
margin-left: 5%;
|
|||
|
|
height: 200rpx;
|
|||
|
|
background-color: #fff;
|
|||
|
|
padding-left: 50rpx;
|
|||
|
|
border-radius: 35rpx;
|
|||
|
|
z-index: 1;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
.white-container-top {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.white-container-bottom {
|
|||
|
|
font-size: 35rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-top: 20rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.finish-button {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
width: 44%;
|
|||
|
|
height: 90rpx;
|
|||
|
|
// margin: 0rpx auto;
|
|||
|
|
margin-bottom: 80rpx;
|
|||
|
|
color: #fff;
|
|||
|
|
background: linear-gradient(to right, #00C9FF, #0076FF);
|
|||
|
|
border-radius: 37rpx;
|
|||
|
|
font-size: 33rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.back-button {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
width: 44%;
|
|||
|
|
height: 90rpx;
|
|||
|
|
margin-bottom: 80rpx;
|
|||
|
|
border: 2rpx solid #c3cacd;
|
|||
|
|
background: linear-gradient(to bottom, #f3f3f5, #dee4e9);
|
|||
|
|
border-radius: 37rpx;
|
|||
|
|
font-size: 33rpx;
|
|||
|
|
}
|
|||
|
|
</style>
|