对接银联和日照银行分开页面

This commit is contained in:
zhouyanli
2026-09-21 14:07:37 +08:00
parent 4f209b8fb7
commit cf8e8263b7
9 changed files with 1357 additions and 100 deletions

View File

@@ -50,11 +50,16 @@
<script setup>
import { ref, onUnmounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getUnionPayTn } from '/pageSubPack/api/apiSub.js'
import { getPushSingle } from '/pageSubPack/api/api.js'
// 支付宝和微信支付
// 银联商务全民付为 App 原生 UTS 插件,不支持小程序/H5,必须条件编译引入,否则其他端构建失败
// #ifdef APP-PLUS
import { upPayWithChannel, upPayRegistry, setPayEnviroment } from '@/uni_modules/xh-uppay'
// #endif
// 银联商务全民付收银台:微信 / 支付宝
const amount = ref('0.00')
const countdownTime = ref('10:00')
@@ -92,7 +97,6 @@
}
const selectedType = ref('wx')
const goBack = () => uni.navigateBack()
const selectPayType = (type) => {
selectedType.value = type
@@ -101,28 +105,69 @@
// #endif
}
// 银联商务渠道号:01 微信原生支付 / 02 支付宝支付 / 03 支付宝小程序 / 11 支付宝2.0
// 渠道号必须与后端下单的产品对应(响应里的 targetSys),对不上会静默失败:
// 微信 targetSys = WXPay → 01
// 支付宝 targetSys = Alipay 2.0 → 11(插件 Android 端 '11' 分支是空壳,未实现)
// 支付宝 targetSys = 支付宝小程序 → 03(需后端改下这个小程序产品才会生效)
const CHANNEL_MAP = { wx: '01', alipay: '03' }
// 传给后端的支付方式,沿用原有枚举 0=微信 / 1=支付宝
const PAY_TYPE_MAP = { wx: '0', alipay: '1' }
// 银联环境:0 正式 / 1 测试。必须与后端下单时所用的银联环境一致,
// 这是后端的配置项、不是前端构建环境;联调报「交易不存在/签名错误」多半是这里对不上。
// 注意:这里只对 iOS 生效,Android 要改插件 utssdk/app-android/AndroidManifest.xml 的 CurrentEnvironment(PROD/TEST)。
const UNIONPAY_ENV = process.env.NODE_ENV === 'development' ? 1 : 0
// 以下常量只在 iOS 生效(Android 的 upPayRegistry 是空实现),且每一项都必须与
// xh-uppay/utssdk/app-ios/info.plist 里 CFBundleURLTypes 的取值完全一致,
// 否则 iOS 上支付完成后回不到本应用。
const WX_APPID = 'wx84b02b2ec80715f4' // 需同步改 info.plist 的 weixin scheme(现在是 demo 值)
// 存疑:暂用项目里微信分享的 Universal Link,但银联商务支付链路可能要求用他们备案的域名,需与其确认
const WX_UNIVERSAL_LINK = 'https://verification.ckdzkj.com/uni-universallinks/__UNI__29C3D60/'
const SCHEME_CLOUD = 'unifyPayDemo' // info.plist 中 ucloud(云闪付回调,暂不用云闪付)
const SCHEME_ALI_MINI = 'qmfpppay' // info.plist 中 aliminipay(支付宝小程序回调)
const SCHEME_ALI = 'umsunifyalisafepay' // info.plist 中 alisafepay(支付宝回调)
const handlePayClick = () => {
handlePay()
}
// 账单明细 id:接口要求 string,多个账单逗号拼接,兼容单个 billId 的旧场景
const toBillIds = (billIds, billId) => {
if (Array.isArray(billIds) && billIds.length) {
return billIds.filter(Boolean).join(',')
}
if (typeof billIds === 'string' && billIds) {
return billIds
}
return billId ? String(billId) : ''
}
const handlePay = async () => {
try {
uni.showLoading({ title: '发起支付中' })
const payTypeMap = { wx: '0', alipay: '1' }
const backendPayType = payTypeMap[selectedType.value] || '1'
const res = await getUnionPayTn({
amount: amount.value,
const billIds = toBillIds(payData.value.billIds, payData.value.billId)
if (!billIds) {
uni.hideLoading()
uni.showToast({ title: '账单信息异常,请返回重新选择', icon: 'none' })
return
}
// deviceCode/deviceType 仅水电表充值传;无值即物业费/停车费/垃圾处理费
const payload = {
amount: Number(amount.value),
orderDesc: (payData.value.type || '缴费') + '缴费',
residentUserId: uni.getStorageSync('userId'),
payType: backendPayType,
deviceCode: payData.value.deviceCode || '',
deviceType: '2',
chargeTypeId: payData.value.chargeTypeId,
chargeItemId: payData.value.chargeItemId,
billId: payData.value.billId,
houseId: payData.value.houseId
})
residentUserId: payData.value.residentUserId || uni.getStorageSync('userId'),
payType: PAY_TYPE_MAP[selectedType.value],
billIds
}
if (payData.value.deviceCode) payload.deviceCode = payData.value.deviceCode
if (payData.value.deviceType) payload.deviceType = payData.value.deviceType
const res = await getUnionPayTn(payload)
console.log('支付接口返回:', JSON.stringify(res.data))
uni.hideLoading()
@@ -131,15 +176,20 @@
return
}
const payType = selectedType.value
// 后端下发银联商务的 appPayRequest,整串 JSON 原样交给 SDK,不要拆开解析
const data = res.data
const payDataStr = typeof data === 'string'
? data
: (data.appPayRequest || data.appRequest || '')
if (payType === 'wx') {
invokeWxPay(data.wx || data.wxPayInfo || data)
} else if (payType === 'alipay') {
invokeAlipay(data.alipay || data.aliPayInfo || data)
if (!payDataStr || typeof payDataStr !== 'string' || !payDataStr.trim().startsWith('{')) {
console.error('未获取到有效的 appPayRequest,后端返回:', JSON.stringify(data))
uni.showToast({ title: '支付参数异常,请联系客服', icon: 'none' })
return
}
invokeUnionPay(payDataStr, CHANNEL_MAP[selectedType.value])
} catch (err) {
uni.hideLoading()
console.log('支付异常', err)
@@ -147,49 +197,96 @@
}
}
// 微信支付
const invokeWxPay = (data) => {
const orderInfo = {
appid: data.appId,
partnerid: data.partnerId || data.partnerid || '',
prepayid: data.prepayId || data.prepayid || (data.package || '').replace('prepay_id=', ''),
package: 'Sign=WXPay',
noncestr: data.nonceStr,
timestamp: data.timeStamp,
sign: data.paySign
// 银联商务综合支付:拉起微信 / 支付宝完成付款
const invokeUnionPay = (payData, channel) => {
// #ifdef APP-PLUS
ensureRegistered()
paying = true
upPayWithChannel({ payData, channel }, (code, info) => {
handlePayResult(String(code), info)
})
// #endif
// #ifndef APP-PLUS
uni.showToast({ title: '当前端暂不支持银联支付', icon: 'none' })
// #endif
}
// 注册和支付环境设置都只对 iOS 生效;Android 调 setPayEnviroment 只会刷警告,
// Android 的环境要改插件 utssdk/app-android/AndroidManifest.xml 里的 CurrentEnvironment。
let registered = false
const ensureRegistered = () => {
if (registered) return
registered = true
// #ifdef APP-PLUS
if (uni.getSystemInfoSync().platform === 'ios') {
setPayEnviroment(UNIONPAY_ENV)
upPayRegistry({
appId: WX_APPID,
link: WX_UNIVERSAL_LINK,
cloudUrl: SCHEME_CLOUD,
aliminipayUrl: SCHEME_ALI_MINI,
aliUrl: SCHEME_ALI
})
}
uni.requestPayment({
provider: 'wxpay',
orderInfo: orderInfo,
success: (res) => {
console.log('微信支付成功', res)
paySuccess()
},
fail: (err) => {
console.error('微信支付失败或取消', err)
uni.showToast({ title: '支付取消或失败', icon: 'none' })
}
})
}
// 支付宝支付
const invokeAlipay = (data) => {
const orderInfo = data.orderInfo || data
uni.requestPayment({
provider: 'alipay',
orderInfo: orderInfo,
success: (res) => {
console.log('支付宝支付成功', res)
paySuccess()
},
fail: (err) => {
console.error('支付宝支付失败或取消', err)
uni.showToast({ title: '支付取消或失败', icon: 'none' })
}
})
// #endif
}
let paying = false // 支付请求是否已发出
let payDone = false // 是否已给出结果提示,避免重复
// Android 端插件不触发回调,用户从微信/支付宝切回来时靠 onShow 兜底;
// iOS 有回调,交给 handlePayResult 处理,这里不插手。
onShow(() => {
if (!paying) return
if (uni.getSystemInfoSync().platform === 'android') {
paying = false
notifyPayPending()
}
})
// 结果码见 xh-uppay readme:0000 只表示「支付请求发送成功」,不代表付款成功,
// 真实结果以银联商务异步通知到后端的结果为准。所以这里不做成功判定,
// 统一引导用户回账单列表看实际状态。
const handlePayResult = (code, info) => {
console.log('银联支付回调', code, JSON.stringify(info))
paying = false
switch (code) {
case '0000':
case '2001': // 订单处理中,结果未知(有可能已支付成功)
notifyPayPending()
break
case '1000':
payDone = true
uni.showToast({ title: '支付已取消', icon: 'none' })
break
case '1001':
payDone = true
uni.showToast({ title: '支付参数错误', icon: 'none' })
break
case '1002':
payDone = true
uni.showToast({ title: '网络异常,请重试', icon: 'none' })
break
case '1003':
payDone = true
uni.showToast({ title: '未安装对应的支付客户端', icon: 'none' })
break
default:
payDone = true
uni.showToast({ title: (info && info.resultMsg) || '支付失败', icon: 'none' })
}
}
const notifyPayPending = () => {
if (payDone) return
payDone = true
uni.showToast({ title: '支付结果确认中,请稍后在账单中查看', icon: 'none' })
setTimeout(() => uni.navigateBack(), 2000)
}
// 支付成功流转:等后端提供「订单查询」接口后,查单确认已支付时再调用这里。
// 目前 SDK 的结果码不足以判定付款成功,所以暂时没有调用点。
const paySuccess = () => {
sendPaySuccessPush()
uni.showToast({ title: '支付成功', icon: 'success' })