| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import { createOrder, getEcardPrices, queryOrder } from "@/api/modules/pay";
- import { useEnv } from "./useEnv";
- import { usePayStore } from "@/store/payStore";
- import config from "@/config";
- import { Pay } from "@/types";
- export const usePay = () => {
- const payStore = usePayStore();
- const { price } = storeToRefs(payStore);
- const ready = ref(false);
- const loading = ref(false);
- const outTradeNo = ref('');
- const h5url = ref('');
- const queryTimes = ref(10);
- const callback = ref<Pay.OrderPayCallback>({});
- let webview: PlusWebviewWebviewObject | HTMLIFrameElement | undefined = undefined;
- const formatPrice = computed(() => {
- return price.value / 100;
- });
- const getPrice = async () => {
- const res = await getEcardPrices({});
- const card = res.data?.at(0);
- if (card) {
- payStore.setPrice(card.price)
- ready.value = true;
- }
- }
- const pay = async () => {
- loading.value = true;
- uni.$ie.showLoading('支付中...');
- try {
- const { data } = await createOrder({
- totalFee: price.value,
- type: undefined
- });
- uni.$ie.hideLoading();
- outTradeNo.value = data.outTradeNo;
- h5url.value = data.h5url;
- if (outTradeNo && h5url) {
- clearResultFrame()
- webview = await createResultFrame(h5url.value);
- } else {
- throw new Error('支付地址缺失');
- }
- } catch (error) {
- loading.value = false;
- uni.$ie.showToast('下单失败,请稍后再试');
- }
- }
- const checkOrderStatus = async () => {
- if (!outTradeNo.value) {
- return;
- }
- const no = outTradeNo.value.split('_')[1];
- if (!no) {
- console.error('checkOrderStatus: 订单号格式错误');
- callback.value.onFailed?.();
- return;
- }
- let queryCount = 0; // 当前查询次数
- const queryInterval = 3000; // 查询间隔(毫秒)
- let timerId: ReturnType<typeof setTimeout> | null = null;
- /**
- * 停止查询
- */
- const stopQuery = () => {
- if (timerId) {
- clearTimeout(timerId);
- timerId = null;
- clearResultFrame();
- }
- loading.value = false;
- uni.$ie.hideLoading();
- };
- /**
- * 执行查询
- */
- const query = async () => {
- try {
- queryCount++;
- const { data } = await queryOrder(no);
- console.log(`checkOrderStatus: 第 ${queryCount} 次查询订单状态`);
- console.log(JSON.stringify(data))
- if (!data) {
- console.error('checkOrderStatus: 查询结果为空');
- stopQuery();
- callback.value.onFailed?.();
- return;
- }
- // 支付成功
- if (data.isPaySuccess) {
- console.log('checkOrderStatus: 支付成功');
- stopQuery();
- callback.value.onSuccess?.();
- return;
- }
- // 支付失败
- if (data.isPayFailed) {
- console.log('checkOrderStatus: 支付失败');
- stopQuery();
- callback.value.onFailed?.();
- return;
- }
- // 未支付状态
- if (data.isUnPaid) {
- // 如果已达到最大查询次数,回调失败
- if (queryCount >= queryTimes.value) {
- console.log(`checkOrderStatus: 已查询 ${queryTimes.value} 次,仍未支付,回调失败`);
- stopQuery();
- callback.value.onFailed?.();
- return;
- }
- // 继续查询
- timerId = setTimeout(() => {
- query();
- }, queryInterval);
- } else {
- // 未知状态,回调失败
- console.error('checkOrderStatus: 未知的支付状态', data);
- stopQuery();
- callback.value.onFailed?.();
- }
- } catch (error) {
- // 查询过程中发生错误,回调失败
- console.error('checkOrderStatus: 查询订单状态失败', error);
- stopQuery();
- callback.value.onFailed?.();
- }
- };
- // 开始第一次查询
- uni.$ie.showLoading('支付查询中...')
- query();
- }
- const createResultFrame = async (url: string) => {
- const { isH5, isWap2App } = useEnv();
- if (isH5.value) {
- await sleep()
- const iframe = document.createElement('iframe');
- const style = `width:0px;height:0px;position: absolute;opacity: 0;z-index: -1;outline:none;border:none;`;
- iframe.setAttribute('style', style);
- iframe.setAttribute('sandbox', 'allow-scripts allow-top-navigation allow-same-origin');
- iframe.style.position = 'absolute';
- iframe.src = url;
- iframe.onload = () => checkOrderStatus()
- iframe.onerror = () => console.error('Payment: iframe加载失败')
- document.body.appendChild(iframe);
- return iframe
- } else if (isWap2App.value) {
- const style: PlusWebviewWebviewStyles = {
- webviewBGTransparent: true,
- opacity: 0,
- render: 'always',
- zindex: -1,
- width: '1px',
- height: '1px',
- top: '0px',
- left: '0px',
- additionalHttpHeaders: {
- Referer: config.paySiteUrl,
- }
- };
- const wv = plus.webview.create(url, 'wechatPayWebview', style);
- wv.addEventListener('loaded', (e) => {
- checkOrderStatus();
- }, false);
- wv.show();
- return wv;
- }
- }
- const clearResultFrame = () => {
- const { isH5, isWap2App } = useEnv();
- if (webview) {
- if (isH5.value) {
- document.body.removeChild(webview as HTMLIFrameElement)
- } else if (isWap2App.value) {
- (webview as PlusWebviewWebviewObject).close();
- }
- webview = undefined;
- }
- }
- const sleep = (time: number = 300) => {
- return new Promise(resolve => {
- setTimeout(resolve, time);
- });
- }
- const setCallback = (cb: Pay.OrderPayCallback) => {
- callback.value = cb;
- }
- getPrice();
- return {
- getPrice,
- price,
- formatPrice,
- ready,
- pay,
- loading,
- setCallback
- }
- }
|