batiao-pay/pages/index/index.vue

412 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="wrapper" style="height: 100vh">
<!-- 浏览器不支持提示 -->
<view class="wrapper" id="pay-result" style="background: #fff" v-if="envErrType">
<view class="pay-result-container">
<image src="/static/image/payerr.png" style="width: 96px; height: 96px"></image>
<view class="env-err-text">{{ envErrText }}</view>
</view>
</view>
<view class="wrapper" id="pay-result" style="background: #fff" v-else-if="orderInfo.status === 2">
<view class="pay-result-container">
<image v-if="browerEnv === 'alipay'" src="/static/image/ali-payok.png" style="width: 96px; height: 96px"></image>
<image v-if="browerEnv === 'weixin'" src="/static/image/wx-payok.png" style="width: 96px; height: 96px"></image>
<view class="pay-result-text">支付已完成</view>
</view>
</view>
<!-- 支付页面 -->
<view class="wrapper" id="pay-page" v-else-if="currentPage === 'pay-page'">
<view class="item-name">{{ orderInfo.goodsName }}</view>
<view class="item-count">
<text style="font-size: 26px">¥&nbsp;</text>{{ numberFormat(orderInfo.totalFee) }}
</view>
<!-- <view class="company">重庆八条科技有限公司</view> -->
<!-- 支付按钮 -->
<view class="pay-methods">
<view v-for="item in payMethodList" :key="item.id" class="pay-method-item">
<view class="pay-method-item-left">
<image :src="item.logo" style="width: 30px; height: 30px"></image>
<text class="pay-method-name">{{ item.name }}</text>
</view>
<view class="pay-method-item-right">
<image :src="item.checkIcon" style="width: 18px; height: 18px"></image>
</view>
</view>
</view>
<button id="pay-btn" :class="[`${browerEnv}-btn`]" @click="goPay">
立即支付
</button>
</view>
<!-- 支付结果页面 -->
<view class="wrapper" id="pay-result" style="background: #fff" v-else-if="currentPage === 'pay-result'">
<view class="pay-result-container">
<image :src="payResultItem.icon" style="width: 96px; height: 96px"></image>
<view class="pay-result-text">{{ payResultItem.resultText }}</view>
<button v-if="fromApp" class="back-btn" open-type="launchApp" app-parameter="wechat" :binderror="launchAppError">返回APP</button>
<button v-else class="back-btn" :style="payResultItem.style" @click="goBackPay">
{{ payResultItem.backText }}
</button>
</view>
</view>
</view>
</template>
<script>
import request from "@/lib/request.js";
export default {
data() {
return {
authCode: '',
encOrderId: "",
outTradeNo: "",
browerEnv: "",
orderInfo: {},
currentPage: "pay-page",
paySuccess: true,
payMethodList: [{
name: "支付宝支付",
id: "alipay",
logo: "/static/image/ali-logo.png",
checkIcon: "/static/image/ali-check.png",
},
{
name: "微信支付",
id: "weixin",
logo: "/static/image/wx-logo.png",
checkIcon: "/static/image/wx-check.png",
},
],
timer: null,
fromApp: false,
};
},
computed: {
payResultList() {
return [{
icon: "/static/image/payerr.png",
resultText: "抱歉,订单支付失败",
backText: "重新支付",
style: {background: this.browerEnv === "weixin" ? '#05bf5e' : '#2c78fe', color: '#fff'},
},
{
icon: this.browerEnv === "weixin" ?
"/static/image/wx-payok.png" : "/static/image/ali-payok.png",
resultText: "支付成功",
backText: "返回",
},
];
},
payResultItem() {
return this.paySuccess ? this.payResultList[1] : this.payResultList[0];
},
envErrType() {
if(!this.browerEnv) return '';
if (this.browerEnv === "browser") {
return "envErr:browser";
} else if (!this.encOrderId && !this.outTradeNo) {
return "envErr:noParams";
} else {
return ''
}
},
envErrText() {
const group = {
"envErr:browser": "不支持浏览器,请使用支付宝或微信重新扫码",
"envErr:noParams": "请通过扫描二维码使用小程序",
"envErr:outTradeNo": "获取订单信息失败",
};
return group[this.envErrType];
},
},
methods: {
launchAppError(e) {
console.log(e.detail.errMsg)
},
numberFormat(value) {
if (value) return value.toFixed(2);
return "0.00";
},
// 获取支付宝用户信息
getAliUserInfo() {
// 检查是否已授权
// #ifdef MP-ALIPAY
my.getAuthCode({
scopes: ["auth_base"],
success: (res) => {
console.log("获取授权码成功", res);
this.authCode = res.authCode;
},
fail: (error) => {
console.error("获取授权码失败", error);
uni.showToast({
icon: "none",
title: "获取授权码失败",
});
},
});
// #endif
},
// 获取微信用户信息
getWxUserInfo() {
// #ifdef MP-WEIXIN
uni.getProvider({
service: 'oauth',
success: (res) => {
console.log('getProvider', res.provider)
uni.login({
provider: res.provider,
success: (loginRes) => {
this.authCode = loginRes.code
console.log('loginRes', this.authCode)
}
})
}
})
// #endif
},
// 支付按钮点击事件
async goPay() {
uni.showLoading()
try {
// 应用下单
const {
outTradeNo,
paySource = "jsapi"
} = this.orderInfo;
let extra = {};
// #ifdef MP-ALIPAY
extra.alipayAuthCode = this.authCode;
// #endif
// #ifdef MP-WEIXIN
extra.weixinAuthCode = this.authCode;
// #endif
console.log('authCode',this.authCode)
if (!this.authCode) {
console.error("没有授权码");
return;
}
let orderData = await this.handleOrder({
outTradeNo,
payType: this.browerEnv,
paySource: paySource,
extra,
});
let tradeNo = orderData.tradeNo;
console.log("tradeNo", tradeNo);
if(this.browerEnv === 'alipay') {
// 调起支付宝支付
let res = await this.handleAlipay({
tradeNO: tradeNo,
});
console.log('支付宝支付成功', res)
} else if(this.browerEnv === 'weixin') {
let res = await this.handleWechatPay(orderData);
console.log('微信支付成功', res)
}
// 支付成功
let orderRes = await this.getOrderInfo()
this.currentPage = "pay-result";
if (orderRes.status === 2) {
this.paySuccess = true;
// clearInterval(this.timer)
// this.timer = null
} else {
this.paySuccess = false;
}
uni.hideLoading()
} catch (error) {
console.log('error', error)
this.currentPage = "pay-result";
this.paySuccess = false; // 失败
uni.hideLoading()
}
},
// 查询订单
async getOrderInfo() {
let res = await request({
url: "/api/pay/order",
method: "GET",
data: {
encOrderId: this.encOrderId,
outTradeNo: this.outTradeNo
},
});
const data = {
...res.data,
totalFee: res.data.totalFee / 100,
};
return data;
},
// 应用下单
async handleOrder(data) {
let res = await request({
url: "/api/pay/order",
method: "POST",
data: data,
});
console.log("handleOrder", res.data);
return res.data || {};
},
// 微信支付处理
handleWechatPay(payParams) {
return new Promise((resolve, reject) => {
// 在Uniapp中可以使用uni.requestPayment API
uni.requestPayment({
provider: "wxpay",
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: payParams.signType,
paySign: payParams.paySign,
success: (res) => {
console.log("支付成功:", res);
resolve();
},
fail: (err) => {
console.error("支付失败:", err);
reject(new Error("支付失败"));
},
});
});
},
// 支付宝支付处理
handleAlipay(payParams) {
console.log("支付宝支付处理");
return new Promise((resolve, reject) => {
// 在Uniapp中可以使用uni.requestPayment API
uni.requestPayment({
provider: "alipay",
orderInfo: payParams.tradeNO, // 支付宝交易号
success: (res) => {
if (res.resultCode === "9000") {
console.log("支付成功", res);
// 建议以后端异步通知或主动查询订单状态为准
resolve();
} else {
console.log("支付处理中或失败", res);
// 处理其他结果码
resolve();
}
},
fail: (err) => {
console.error("支付失败:", err);
reject(new Error("支付失败"));
},
});
});
},
async goBackPay() {
this.orderInfo = await this.getOrderInfo();
this.currentPage = "pay-page";
},
// 获取URL参数
getQuery() {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const options = currentPage.options || {};
return options;
},
// 判断浏览器环境是微信/支付宝/普通浏览器
getBrowserEnv() {
// 非H5环境根据平台判断
// #ifdef MP-WEIXIN
return "weixin";
// #endif
// #ifdef MP-ALIPAY
return "alipay";
// #endif
},
extractUrlParams(url) {
if (!url) {
return {};
}
// 使用正则表达式解析URL参数兼容支付宝环境
const params = {};
const queryString = url.split("?")[1];
if (queryString) {
const pairs = queryString.split("&");
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i].split("=");
const key = decodeURIComponent(pair[0]);
const value = decodeURIComponent(pair[1] || "");
params[key] = value;
}
}
return params;
},
},
async onShow() {
console.log("on Show");
// 支付宝
// #ifdef MP-ALIPAY
if (my) {
let res = my.getLaunchOptionsSync();
console.log("res", res);
const qrCode = res.query ? res.query.qrCode : '';
let {
encOrderId
} = this.extractUrlParams(qrCode);
if (encOrderId) {
this.encOrderId = encOrderId;
this.orderInfo = await this.getOrderInfo();
}
this.getAliUserInfo()
}
// #endif
},
async onLoad(options) {
console.log("options", options);
const env = this.getBrowserEnv();
console.log('env', env)
this.browerEnv = env;
if (env === "browser") return;
// 过滤支付方式,只显示当前环境支持的支付方式
this.payMethodList = this.payMethodList.filter((item) => item.id === env);
// #ifdef MP-WEIXIN
if(options.q) { // q: 二维码地址
let {
encOrderId
} = this.extractUrlParams(decodeURIComponent(options.q));
console.log('encOrderId', encOrderId)
if (encOrderId) {
this.encOrderId = encOrderId;
this.orderInfo = await this.getOrderInfo();
}
}
if(options.outTradeNo) {
// app进入的
this.fromApp = true;
this.outTradeNo = options.outTradeNo;
this.orderInfo = await this.getOrderInfo();
}
console.log('encOrderId', this.encOrderId)
console.log('outTradeNo', this.outTradeNo)
this.getWxUserInfo()
// #endif
},
};
</script>
<style>
@import url("/static/app.css");
</style>