| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- <template>
- <!-- 支付加载提示 -->
- <view v-if="showPayLoading" class="pay-loading-mask">
- <view class="pay-loading-box">
- <view class="loading-spinner"></view>
- <text class="loading-text">处理支付中...</text>
- </view>
- </view>
- </template>
- <script setup>
- import { ref, getCurrentInstance } from "vue";
- import { createPaymentOrder, queryPaymentStatus } from "@/api/payment";
- import { generateCustomId } from "@/utils/util.js";
- // 组件实例
- const instance = getCurrentInstance();
- // 状态管理
- const orderNo = ref("");
- const orderId = ref("");
- const showPayLoading = ref(false);
- const paymentInProgress = ref(false);
- // 回调函数存储
- const callbacks = ref({
- onUniPayCreate: null,
- onUniPaySuccess: null,
- onUniPayCancel: null,
- onUniPayFail: null,
- });
- /**
- * 发起微信支付
- * @param {Object} options - 支付参数
- * @param {number} options.amount - 支付金额(分)
- * @param {string} options.description - 商品描述
- * @param {string} options.openId - 用户openId
- * @param {string} options.orderPrefix - 订单号前缀
- * @param {Function} options.onUniPayCreate - 订单创建成功回调
- * @param {Function} options.onUniPaySuccess - 支付成功回调
- * @param {Function} options.onUniPayCancel - 取消支付回调
- * @param {Function} options.onUniPayFail - 支付失败回调
- */
- const createUniPay = async (options) => {
- // 防止重复发起支付
- if (paymentInProgress.value) return;
- try {
- paymentInProgress.value = true;
- showPayLoading.value = true;
- // 保存回调函数
- Object.keys(callbacks.value).forEach((key) => {
- callbacks.value[key] =
- options[key] && typeof options[key] === "function"
- ? options[key]
- : () => {};
- });
- // 生成订单号(使用公共组件)
- orderNo.value = generateCustomId(options.orderPrefix || "WX");
- // 调用后端创建支付订单
- const { data: payRes } = await createPaymentOrder({
- amount: options.amount,
- description: options.description,
- openId: options.openId,
- orderNo: orderNo.value,
- });
- // 订单创建成功,触发回调
- callbacks.value.onUniPayCreate({
- out_trade_no: orderNo.value,
- ...payRes,
- });
- // 调起微信支付
- await uni.requestPayment({
- provider: "wxpay",
- timeStamp: payRes.timeStamp.toString(),
- nonceStr: payRes.nonceStr,
- package: payRes.package,
- signType: payRes.signType,
- paySign: payRes.paySign,
- success: () => {
- confirmPaymentStatus();
- },
- fail: (err) => {
- showPayLoading.value = false;
- paymentInProgress.value = false;
- if (err.errMsg && err.errMsg.includes("cancel")) {
- callbacks.value.onUniPayCancel(err);
- } else {
- callbacks.value.onUniPayFail(err);
- }
- },
- });
- } catch (err) {
- showPayLoading.value = false;
- paymentInProgress.value = false;
- console.error("支付流程异常:", err);
- callbacks.value.onUniPayFail(err);
- }
- };
- /**
- * 确认支付状态(轮询查询)
- */
- const confirmPaymentStatus = async () => {
- try {
- let checkCount = 0;
- const maxCheckCount = 10; // 最多查询10次
- const checkInterval = 1000; // 每次查询间隔1秒
- const checkStatus = async () => {
- // 超过最大查询次数,视为超时
- if (checkCount >= maxCheckCount) {
- showPayLoading.value = false;
- paymentInProgress.value = false;
- callbacks.value.onUniPayFail(
- new Error("支付结果查询超时,请稍后查看订单状态")
- );
- return;
- }
- checkCount++;
- try {
- // 查询支付状态
- const res = await queryPaymentStatus(orderNo.value);
- // 根据后端返回的支付状态进行处理
- if (res.code === 200) {
- showPayLoading.value = false;
- paymentInProgress.value = false;
- callbacks.value.onUniPaySuccess({
- ...res.data,
- out_trade_no: orderNo.value,
- });
- }
- } catch (err) {
- // 查询接口出错,重试
- console.error(`第${checkCount}次查询支付状态失败:`, err);
- setTimeout(checkStatus, checkInterval);
- }
- };
- // 开始第一次查询
- checkStatus();
- } catch (err) {
- showPayLoading.value = false;
- paymentInProgress.value = false;
- console.error("确认支付状态异常:", err);
- callbacks.value.onUniPayFail(err);
- }
- };
- // 对外暴露方法
- defineExpose({
- createUniPay,
- });
- </script>
- <style scoped>
- /* 支付加载提示样式 */
- .pay-loading-mask {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(0, 0, 0, 0.5);
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 9999;
- }
- .pay-loading-box {
- background-color: white;
- padding: 30rpx 40rpx;
- border-radius: 16rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .loading-spinner {
- width: 50rpx;
- height: 50rpx;
- border: 4rpx solid #eee;
- border-top-color: #07c160;
- border-radius: 50%;
- animation: spin 1s linear infinite;
- margin-bottom: 20rpx;
- }
- .loading-text {
- color: #333;
- font-size: 28rpx;
- }
- /* 旋转动画 */
- @keyframes spin {
- to {
- transform: rotate(360deg);
- }
- }
- </style>
|