Compare commits

...

3 Commits

Author SHA1 Message Date
56ffd2073d 画家海外支付 2025-05-19 15:12:51 +08:00
24adb4c68d 画家海外支付 2025-05-19 11:44:09 +08:00
1a7c74b9da 画家海外支付 2025-05-19 11:34:58 +08:00
8 changed files with 243 additions and 2 deletions

View File

@ -0,0 +1,20 @@
import { request } from '@/api-collect-code/http-abroad.js'
// 创建支付订单
export async function abroadCreateOrder(data) {
console.log('data',data);
return await request({
url:"/artshow/overseas/show-pay/createOrder",
method:"POST",
data
})
}
// 获取支付详情
export async function abroadPayInfo(data) {
return await request({
url:"/artshow/overseas/show-pay/info",
method:"POST",
data
})
}

View File

@ -0,0 +1,134 @@
/**
* 本文件目前仅用于画家海外支付
*/
import {useRuntimeConfig} from '#app'
import {ofetch} from 'ofetch'
import {message} from '@/components/x-message/useMessage.js'
import {codeAuthStore} from "@/stores-collect-code/auth/index.js"
let httpStatusErrorHandler
let http
// HTTP 状态码映射 - 使用i18n国际化
export function setupHttp() {
if (http) return http
const {codeToken}= codeAuthStore()
const config = useRuntimeConfig()
const baseURL = config.public.NUXT_PUBLIC_ABROAD_API_BASE // 海外支付接口地址
const router = useRouter()
const i18n = useNuxtApp().$i18n
// 国际化的HTTP状态码映射
const HTTP_STATUS_MAP = {
400: i18n.t('http.error.badRequest'),
401: i18n.t('http.error.unauthorized'),
403: i18n.t('http.error.forbidden'),
404: i18n.t('http.error.notFound'),
500: i18n.t('http.error.serverError'),
502: i18n.t('http.error.badGateway'),
503: i18n.t('http.error.serviceUnavailable'),
504: i18n.t('http.error.gatewayTimeout')
}
const defaultOptions = {
baseURL,
headers: { 'Content-Type': 'application/json' },
timeout: 15000, // 15秒超时
retry: 3,
retryDelay: 1000,
}
http = ofetch.create({
...defaultOptions,
// 请求拦截
async onRequest({ options, request }) {
// 添加 token
options.headers = {
...options.headers,
Authorization: codeToken.value,
'accept-language': i18n.locale.value
}
// GET 请求添加时间戳防止缓存
if (request.toLowerCase().includes('get')) {
options.params = {
...options.params,
_t: Date.now()
}
}
},
// 响应拦截
async onResponse({ response }) {
const data = response._data
// 处理业务错误
if (data.status === 1) {
message.error(data.msg || i18n.t('http.error.operationFailed'))
}
console.log('拦截响应',data)
// 处理登录失效
if (data.status === 401) {
message.error(i18n.t('http.error.loginExpired'))
codeToken.value = '' // 清除 token
router.replace('/collectCode/login')
}
return response
},
// 响应错误处理
async onResponseError({ response, request }) {
// 网络错误
if (!response) {
message.error(i18n.t('http.error.networkError'))
return Promise.reject(new Error(i18n.t('http.error.networkError')))
}
const status = response.status
const data = response._data
// 处理 HTTP 状态错误
const errorMessage = data.msg || HTTP_STATUS_MAP[status] || i18n.t('http.error.requestFailed')
if (Array.isArray(data.msg)) {
data.msg.forEach(item => {
httpStatusErrorHandler?.(item, status)
})
} else {
httpStatusErrorHandler?.(errorMessage, status)
}
message.error(errorMessage)
return Promise.reject(data)
},
})
return http
}
export function createAbortController() {
return new AbortController()
}
export function injectHttpStatusErrorHandler(handler) {
httpStatusErrorHandler = handler
}
export function getHttp() {
if (!http) {
throw new Error(useNuxtApp().$i18n.t('http.error.httpNotInitialized'))
}
return http
}
// 导出请求工具函数
export async function request({url,...options}) {
const http = getHttp()
try {
return await http(url, {...options,body:options.data})
} catch (error) {
throw error
}
}

View File

@ -3,6 +3,7 @@
import { onMounted, ref } from "vue";
import { authStore } from "~/stores/auth/index.js";
import { orderQuery } from "~/api/goods/index.js";
import {abroadPayInfo} from "~/api-collect-code/abroad/index"
import { WebSocketClient } from "@/utils/websocket";
const config = useRuntimeConfig();
definePageMeta({

View File

@ -6,12 +6,14 @@ import { showLoadingToast, closeToast } from "vant";
import { authStore } from "~/stores/auth/index.js";
import { message } from "~/components/x-message/useMessage.js";
import { createOrder, offlineQrcode } from "~/api-collect-code/goods/index.js";
import {abroadCreateOrder} from "~/api-collect-code/abroad/index.js"
import { codeAuthStore } from "~/stores-collect-code/auth/index.js";
import { useI18n } from "vue-i18n";
const amount = ref("");
const router = useRouter();
const route = useRoute();
const type=route.query.type
const { t } = useI18n();
const { checkoutSessionUrl, qrUid, qrData, codePKey, codePayUid } =
codeAuthStore();
@ -38,7 +40,7 @@ const getData = async () => {
}
};
//
getData();
// getData();
const confirmPay = async () => {
const res = await createOrder({
price: qrData.value.price,
@ -62,6 +64,30 @@ const confirmPay = async () => {
});
}
};
//
const abroadPay=async ()=>{
if(!route.query.qrUid){
return
}
const res=await abroadCreateOrder({
QrUid:route.query.qrUid
});
if(res.status===0){
codePKey.value = res.data.checkoutSessionUrl;
codePayUid.value = res.data.payUid;
window.location.href = res.data.checkoutSessionUrl;
}
}
// typetype=abroad
const payment=async ()=>{
if(type==="abroad"){
await abroadPay()
}else{
await getData()
}
}
payment()
</script>
<template>

View File

@ -0,0 +1,55 @@
<script setup>
import { orderQuery } from "~/api/goods/index.js";
import { abroadCreateOrder } from "~/api-collect-code/abroad";
definePageMeta({
i18n: "payment.text1",
});
const router = useRouter();
const { t } = useI18n();
const route = useRoute();
const resData = ref({});
//
const res=await abroadPayInfo({QrUid:route.query.qrUid})
if (res.status === 0) {
resData.value = res.data;
}
const statusLabel = {
1: t("payment.text2"),
2: t("payment.text3"),
3: t("payment.text4"),
4: t("payment.text5"),
};
const goHome = () => {
router.push("/");
};
</script>
<template>
<div
class="w-[100vw] h-screen-nav bg-[url('@/static/images/3532@2x.png')] bg-cover grow-1 flex flex-col items-center px-30px"
>
<div class="flex flex-col items-center mt-150px">
<img
class="w-119px h-120px mb-36px"
src="@/static/images/5554@2x1.png"
alt=""
/>
<div class="text-#000 text-16px mb-25px">
{{ statusLabel[resData.PaymentStatus] }}!
</div>
<div class="text-#999 text-16px">
{{ resData.CurrencyType===1?'人民币':'美元' }}{{ resData.Amount }}
</div>
</div>
<!-- <div class="w-full mt-auto mb-40px">
<van-button type="primary" block @click="goHome">
回到首页
</van-button>
</div>-->
</div>
</template>
<style scoped></style>

View File

@ -1,6 +1,8 @@
import { setupHttp } from '@/api/http'
import { setupHttp as setupHttp1} from '@/api-collect-code/http'
import { setupHttp as abroadSetupHttp } from '~/api-collect-code/http-abroad'
export default defineNuxtPlugin(() => {
setupHttp()
setupHttp1()
abroadSetupHttp()
})

1
env/.env.prod vendored
View File

@ -4,3 +4,4 @@ NUXT_PUBLIC_SOCKET_URL=wss://auction.szjixun.cn
NUXT_API_SECRET=prod-secret
NUXT_PUBLIC_PKEY=pk_live_51QfbSAAB1Vm8VfJqEVY2uFHPn9N4sDbOaCzht8IVKoylYBrYvdUsmsnCzGxIoN9skBCvI5PsxLJcf4PlytXIr1aX00mFJBXSB8
NUXT_PUBLIC_ABROAD_API_BASE=https://erpapi.fontree.cn

4
env/.env.test vendored
View File

@ -3,4 +3,6 @@ NUXT_PUBLIC_API_BASE=https://auction-test.szjixun.cn
NUXT_PUBLIC_API_COLLECT_CODE=http://auction-test.szjixun.cn
NUXT_API_SECRET=test-secret
NUXT_PUBLIC_SOCKET_URL=wss://auction-test.szjixun.cn
NUXT_PUBLIC_PKEY=pk_test_51QfbSAAB1Vm8VfJq3AWsR4k2mZjnlF7XFrmlbc6XVXrtwXquAUfwzZmOFDbxMIAwqJBgqao8KLt2wmPc4vNOCTeo00WB78KtfV
NUXT_PUBLIC_PKEY=pk_test_51QfbSAAB1Vm8VfJq3AWsR4k2mZjnlF7XFrmlbc6XVXrtwXquAUfwzZmOFDbxMIAwqJBgqao8KLt2wmPc4vNOCTeo00WB78KtfV
NUXT_PUBLIC_ABROAD_API_BASE=http://114.218.158.24:9020