mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-10 22:19:31 +00:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a62f930de5 | ||
![]() |
29cc17635a | ||
![]() |
4d7fbdc71f | ||
![]() |
5beac2939e | ||
![]() |
8e23238c98 | ||
![]() |
b952affe49 | ||
![]() |
966b876ecc | ||
![]() |
5a1c056132 | ||
![]() |
f2df62584d | ||
![]() |
97466ee5e7 | ||
![]() |
052af82748 | ||
![]() |
e3061291e7 | ||
![]() |
28456e9fbd | ||
![]() |
73183f0509 |
@@ -7,7 +7,7 @@ VITE_PUBLIC_PATH=/
|
||||
# 接口前缀
|
||||
VITE_GLOB_API_URL_PREFIX=/server
|
||||
|
||||
# 接口地址留空即可
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=
|
||||
|
||||
# 跨域代理,您可以配置多个 ,请注意,没有换行符
|
||||
@@ -19,5 +19,5 @@ VITE_DROP_CONSOLE=false
|
||||
# 接口超时时间
|
||||
VITE_GLOB_API_TIMEOUT=30000
|
||||
|
||||
# 文件上传地址
|
||||
# 文件上传地址 未使用
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
|
@@ -4,7 +4,7 @@ VITE_PUBLIC_PATH=/
|
||||
# 接口前缀
|
||||
VITE_GLOB_API_URL_PREFIX=/server
|
||||
|
||||
# 接口地址留空即可
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=
|
||||
|
||||
# 控制台不输出console
|
||||
@@ -21,7 +21,7 @@ VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE=false
|
||||
# 接口超时时间
|
||||
VITE_GLOB_API_TIMEOUT=30000
|
||||
|
||||
# 文件上传地址
|
||||
# 文件上传地址 未使用
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
|
||||
|
||||
|
2
LICENSE
2
LICENSE
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2021 bootx Authors. All Rights Reserved.
|
||||
Copyright (c) 2022 济南易杯光年软件技术有限公司 Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@@ -1,5 +1,11 @@
|
||||
# Dax-Pay-UI
|
||||
|
||||
|
||||
## ❗使用须知
|
||||
|
||||
`DaxPay`是一款基于`Apache License 2.0`协议分发的开源软件,受中华人民共和国相关法律法规的保护和限制,可以在符合[《用户授权使用协议》](用户授权使用协议.txt)和
|
||||
[《Apache License 2.0》](LICENSE)开源协议情况下进行免费使用、学习和交流。**在使用前请阅读上述协议,如果不同意请勿进行使用。**
|
||||
|
||||
## 🍈项目介绍
|
||||
|
||||
> DaxPay是一套基于Bootx-Platform脚手架构建的一套开源支付网关系统,已经对接支付宝、微信支付相关的接口,以及扩展了钱包支付、储值卡支付、现金支付等新的支付方式。
|
||||
|
@@ -2,7 +2,7 @@ import { useUserStoreWithOut } from '/@/store/modules/user'
|
||||
import { computed } from 'vue'
|
||||
import { getAppEnvConfig } from '/@/utils/env'
|
||||
const useUserStore = useUserStoreWithOut()
|
||||
const { VITE_GLOB_API_URL } = getAppEnvConfig()
|
||||
const { VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX } = getAppEnvConfig()
|
||||
|
||||
export function useUpload(uploadUrl: string) {
|
||||
/**
|
||||
@@ -18,7 +18,7 @@ export function useUpload(uploadUrl: string) {
|
||||
* 上传地址
|
||||
*/
|
||||
const uploadAction = computed(() => {
|
||||
return VITE_GLOB_API_URL + uploadUrl
|
||||
return VITE_GLOB_API_URL + VITE_GLOB_API_URL_PREFIX + uploadUrl
|
||||
})
|
||||
return {
|
||||
tokenHeader,
|
||||
|
@@ -1,11 +1,11 @@
|
||||
// github repo url
|
||||
export const GITHUB_URL = 'https://github.com/xxm1995/bootx-platform'
|
||||
export const GITHUB_URL = 'https://github.com/dromara/dax-pay'
|
||||
|
||||
// gitee repo url
|
||||
export const GITEE_URL = 'https://gitee.com/bootx/bootx-platform'
|
||||
export const GITEE_URL = 'https://gitee.com/dromara/dax-pay'
|
||||
|
||||
// 文档地址
|
||||
export const DOC_URL = 'https://gitee.com/bootx/bootx-platform'
|
||||
export const DOC_URL = 'https://bootx.gitee.io/'
|
||||
|
||||
// 预览地址
|
||||
export const SITE_URL = 'http://v3.platform.bootx.cn/'
|
||||
export const SITE_URL = 'https://daxpay.demo.bootx.cn/'
|
||||
|
@@ -16,10 +16,10 @@
|
||||
<div class="my-auto">
|
||||
<img :alt="title" src="../../assets/svg/login-box-bg.svg" class="w-1/2 -mt-16 -enter-x" />
|
||||
<div class="mt-10 font-medium text-white -enter-x">
|
||||
<span class="inline-block mt-4 text-3xl"> 开箱即用的中后台管理系统</span>
|
||||
<span class="inline-block mt-4 text-3xl"> 开箱即用的支付网关系统</span>
|
||||
</div>
|
||||
<div class="mt-5 font-normal text-white dark:text-gray-500 -enter-x"
|
||||
>基于Vite+Vue3打造,支持支付收单、工作流(Flowable)、三方对接等模块
|
||||
>基于Vite+Vue3打造,支持支付宝、微信支付、云闪付等支付方式的统一网关系统
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -38,4 +38,6 @@ export interface AlipayRecord extends BaseEntity {
|
||||
gatewayOrderNo?: string
|
||||
// 终端ip
|
||||
ip?: string
|
||||
// 网关时间
|
||||
gatewayTime?: string
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@
|
||||
<a-descriptions-item label="业务类型">
|
||||
<a-tag>{{ dictConvert('AlipayRecordType', alipayRecord.type) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="网关时间">
|
||||
{{ alipayRecord.gatewayTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="记录时间">
|
||||
{{ alipayRecord.createTime }}
|
||||
</a-descriptions-item>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
<b-query :query-params="model.queryParam" :fields="fields" :default-item-count="3" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
@@ -23,7 +23,7 @@
|
||||
<vxe-column field="amount" title="金额" />
|
||||
<vxe-column field="orderId" title="本地订单ID" width="170" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单号" width="170" />
|
||||
<vxe-column field="createTime" title="记录时间" sortable />
|
||||
<vxe-column field="gatewayTime" title="网关时间" sortable />
|
||||
<vxe-column fixed="right" width="50" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
@@ -44,7 +44,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { page } from './AlipayRecord.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
@@ -54,7 +54,8 @@
|
||||
import AlipayRecordInfo from './AlipayRecordInfo.vue'
|
||||
import ALink from '/@/components/Link/Link.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, sortChange, sortParam, pages, model, loading } =
|
||||
@@ -62,18 +63,23 @@
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
let alipayRecordInfo = $ref<any>()
|
||||
|
||||
const alipayRecordInfo = $ref<any>()
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
|
||||
const fields = [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
]
|
||||
let recordTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'type', type: LIST, name: '记录类型', placeholder: '请选择记录类型', selectList: recordTypeList },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
] as QueryField[]
|
||||
})
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initData()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
@@ -84,6 +90,13 @@
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
recordTypeList = await dictDropDown('AlipayRecordType')
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
<b-query :query-params="model.queryParam" :fields="fields" :default-item-count="3" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
@@ -53,9 +53,10 @@
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import CashRecordInfo from './CashRecordInfo.vue'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, sortChange, sortParam, pages, model, loading } =
|
||||
@@ -63,23 +64,41 @@
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' }] as QueryField[]
|
||||
})
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
const cashRecordInfo = $ref<any>()
|
||||
|
||||
let recordTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'type', type: LIST, name: '记录类型', placeholder: '请选择记录类型', selectList: recordTypeList },
|
||||
] as QueryField[]
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initData()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*/
|
||||
function vxeBind() {
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
recordTypeList = await dictDropDown('CashRecordType')
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<alipay-config-edit ref="alipay" @ok="ok" />
|
||||
<wechat-pay-config-edit ref="wechat" @ok="ok" />
|
||||
<union-pay-config-edit ref="union" @ok="ok" />
|
||||
<wallet-config-edit ref="wallet" @ok="ok" />
|
||||
<voucher-config-edit ref="voucher" @ok="ok" />
|
||||
<cash-config-edit ref="cash" @ok="ok" />
|
||||
@@ -15,11 +16,13 @@
|
||||
import WalletConfigEdit from '/@/views/payment/channel/wallet/config/WalletConfigEdit.vue'
|
||||
import VoucherConfigEdit from '/@/views/payment/channel/voucher/config/VoucherConfigEdit.vue'
|
||||
import CashConfigEdit from '/@/views/payment/channel/cash/config/CashConfigEdit.vue'
|
||||
import UnionPayConfigEdit from '/@/views/payment/channel/union/config/UnionPayConfigEdit.vue'
|
||||
|
||||
const { createMessage } = useMessage()
|
||||
|
||||
let alipay = $ref<any>()
|
||||
let wechat = $ref<any>()
|
||||
let union = $ref<any>()
|
||||
let wallet = $ref<any>()
|
||||
let voucher = $ref<any>()
|
||||
let cash = $ref<any>()
|
||||
@@ -38,6 +41,10 @@
|
||||
wechat.init(record)
|
||||
break
|
||||
}
|
||||
case payChannelEnum.UNION_PAY: {
|
||||
union.init(record)
|
||||
break
|
||||
}
|
||||
case payChannelEnum.WALLET: {
|
||||
wallet.init(record)
|
||||
break
|
||||
|
63
src/views/payment/channel/union/config/UnionPayConfig.api.ts
Normal file
63
src/views/payment/channel/union/config/UnionPayConfig.api.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { defHttp } from '/@/utils/http/axios'
|
||||
import { Result } from '/#/axios'
|
||||
import { BaseEntity, KeyValue } from '/#/web'
|
||||
|
||||
/**
|
||||
* 获取单条
|
||||
*/
|
||||
export function getConfig() {
|
||||
return defHttp.get<Result<UnionPayConfig>>({
|
||||
url: '/union/pay/config/getConfig',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
export function update(obj: UnionPayConfig) {
|
||||
return defHttp.post({
|
||||
url: '/union/pay/config/update',
|
||||
data: obj,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取云闪付支持支付方式
|
||||
*/
|
||||
export function findPayWayList() {
|
||||
return defHttp.get<Result<KeyValue[]>>({
|
||||
url: '/union/pay/config/findPayWays',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付配置
|
||||
*/
|
||||
export interface UnionPayConfig extends BaseEntity {
|
||||
// 商户号
|
||||
machId?: string
|
||||
// 商户收款账号
|
||||
seller?: string
|
||||
// 是否启用
|
||||
enable: boolean
|
||||
// 签名类型
|
||||
signType?: string
|
||||
// 是否为证书签名
|
||||
certSign?: boolean
|
||||
// 应用私钥证书
|
||||
keyPrivateCert?: string | null
|
||||
// 私钥证书对应的密码
|
||||
keyPrivateCertPwd?: string | null
|
||||
// 中级证书
|
||||
acpMiddleCert?: string | null
|
||||
// 根证书
|
||||
acpRootCert?: string | null
|
||||
// 异步通知页面路径
|
||||
notifyUrl?: string
|
||||
// 页面跳转同步通知页面路径
|
||||
returnUrl?: string
|
||||
// 是否沙箱环境
|
||||
sandbox?: boolean
|
||||
// 支持的支付类型
|
||||
payWays?: string[]
|
||||
}
|
273
src/views/payment/channel/union/config/UnionPayConfigEdit.vue
Normal file
273
src/views/payment/channel/union/config/UnionPayConfigEdit.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<basic-drawer
|
||||
showFooter
|
||||
v-bind="$attrs"
|
||||
width="60%"
|
||||
title="云闪付支付配置"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
@close="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form
|
||||
class="small-from-item"
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
<a-form-item label="主键" name="id" :hidden="true">
|
||||
<a-input v-model:value="form.id" :disabled="showable" />
|
||||
</a-form-item>
|
||||
<a-form-item label="商户号" name="machId">
|
||||
<a-input v-model:value="form.machId" :disabled="showable" placeholder="请输入商户号" />
|
||||
</a-form-item>
|
||||
<a-form-item label="是否启用" name="enable">
|
||||
<a-switch checked-children="启用" un-checked-children="停用" v-model:checked="form.enable" />
|
||||
</a-form-item>
|
||||
<a-form-item label="签名类型" name="signType">
|
||||
<a-select
|
||||
allowClear
|
||||
:disabled="showable"
|
||||
:options="signTypeList"
|
||||
v-model:value="form.signType"
|
||||
style="width: 100%"
|
||||
placeholder="选择支付方式"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item name="keyPrivateCert" label="应用私钥证书">
|
||||
<a-upload
|
||||
v-if="!form.keyPrivateCert"
|
||||
:disabled="showable"
|
||||
name="file"
|
||||
:multiple="false"
|
||||
:action="uploadAction"
|
||||
:headers="tokenHeader"
|
||||
:showUploadList="false"
|
||||
@change="(info) => handleChange(info, 'keyPrivateCert')"
|
||||
>
|
||||
<a-button type="primary" preIcon="carbon:cloud-upload"> 证书上传 </a-button>
|
||||
</a-upload>
|
||||
<a-input v-else defaultValue="acp_enc.cer" disabled>
|
||||
<template #addonAfter v-if="!showable">
|
||||
<a-tooltip>
|
||||
<template #title> 删除上传的证书文件 </template>
|
||||
<icon @click="form.keyPrivateCert = ''" icon="ant-design:close-circle-outlined" :size="20" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="私钥证书密码" name="keyPrivateCertPwd">
|
||||
<a-input allow-clear v-model:value="form.keyPrivateCertPwd" :disabled="showable" placeholder="请输入私钥证书密码" />
|
||||
</a-form-item>
|
||||
<a-form-item name="acpMiddleCert" label="中级证书">
|
||||
<a-upload
|
||||
v-if="!form.acpMiddleCert"
|
||||
:disabled="showable"
|
||||
name="file"
|
||||
:multiple="false"
|
||||
:action="uploadAction"
|
||||
:headers="tokenHeader"
|
||||
:showUploadList="false"
|
||||
@change="(info) => handleChange(info, 'acpMiddleCert')"
|
||||
>
|
||||
<a-button type="primary" preIcon="carbon:cloud-upload"> 证书上传 </a-button>
|
||||
</a-upload>
|
||||
<a-input v-else defaultValue="acp_middle.cer" disabled>
|
||||
<template #addonAfter v-if="!showable">
|
||||
<a-tooltip>
|
||||
<template #title> 删除上传的证书文件 </template>
|
||||
<icon @click="form.acpMiddleCert = ''" icon="ant-design:close-circle-outlined" :size="20" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item name="acpRootCert" label="根证书">
|
||||
<a-upload
|
||||
v-if="!form.acpRootCert"
|
||||
:disabled="showable"
|
||||
name="file"
|
||||
:multiple="false"
|
||||
:action="uploadAction"
|
||||
:headers="tokenHeader"
|
||||
:showUploadList="false"
|
||||
@change="(info) => handleChange(info, 'acpRootCert')"
|
||||
>
|
||||
<a-button type="primary" preIcon="carbon:cloud-upload"> 证书上传 </a-button>
|
||||
</a-upload>
|
||||
<a-input v-else defaultValue="acp_root.cer" disabled>
|
||||
<template #addonAfter v-if="!showable">
|
||||
<a-tooltip>
|
||||
<template #title> 删除上传的证书文件 </template>
|
||||
<icon @click="form.acpRootCert = ''" icon="ant-design:close-circle-outlined" :size="20" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item name="notifyUrl">
|
||||
<template #label>
|
||||
<basic-title helpMessage="此处为本网关接收通知的地址, 而不是客户系统接收通知所需的地址"> 异步通知地址 </basic-title>
|
||||
</template>
|
||||
<a-input v-model:value="form.notifyUrl" :disabled="showable" placeholder="请输入服务器异步通知地址" />
|
||||
</a-form-item>
|
||||
<a-form-item name="returnUrl">
|
||||
<template #label>
|
||||
<basic-title helpMessage="此处为本网关接收通知的地址, 而不是客户系统接收通知所需的地址"> 同步通知地址 </basic-title>
|
||||
</template>
|
||||
<a-input v-model:value="form.returnUrl" :disabled="showable" placeholder="请输入页面跳转同步通知地址" />
|
||||
</a-form-item>
|
||||
<a-form-item label="支持支付方式" name="payWays">
|
||||
<a-select
|
||||
allowClear
|
||||
mode="multiple"
|
||||
:disabled="showable"
|
||||
:options="payWayList"
|
||||
v-model:value="form.payWays"
|
||||
style="width: 100%"
|
||||
placeholder="选择支付方式"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="测试环境" name="sandbox">
|
||||
<a-switch checked-children="是" un-checked-children="否" v-model:checked="form.sandbox" />
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="remark">
|
||||
<a-textarea v-model:value="form.remark" :disabled="showable" placeholder="请输入备注" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
<template #footer>
|
||||
<a-space>
|
||||
<a-button key="cancel" @click="handleCancel">取消</a-button>
|
||||
<a-button v-if="!showable" key="forward" :loading="confirmLoading" type="primary" @click="handleOk">保存</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</basic-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
||||
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
|
||||
import { BasicDrawer } from '/@/components/Drawer'
|
||||
import Icon from '/@/components/Icon/src/Icon.vue'
|
||||
import { useUpload } from '/@/hooks/bootx/useUpload'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
import BasicTitle from '/@/components/Basic/src/BasicTitle.vue'
|
||||
import { getConfig, update, findPayWayList, UnionPayConfig } from './UnionPayConfig.api'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
|
||||
const { handleCancel, search, diffForm, labelCol, wrapperCol, modalWidth, title, confirmLoading, visible, editable, showable } =
|
||||
useFormEdit()
|
||||
// 文件上传
|
||||
const { tokenHeader, uploadAction } = useUpload('/union/pay/config/toBase64')
|
||||
const { createMessage } = useMessage()
|
||||
const { dictDropDown } = useDict()
|
||||
|
||||
// 表单
|
||||
const formRef = $ref<FormInstance>()
|
||||
let rawForm: any
|
||||
let form = $ref<UnionPayConfig>({
|
||||
id: null,
|
||||
seller: '',
|
||||
enable: false,
|
||||
notifyUrl: '',
|
||||
returnUrl: '',
|
||||
payWays: [],
|
||||
sandbox: false,
|
||||
})
|
||||
// 校验
|
||||
const rules = computed(() => {
|
||||
return {
|
||||
machId: [{ required: true, message: '请输入商户号' }],
|
||||
wxAppId: [{ required: true, message: '请输入应用编号' }],
|
||||
// certSign: [{ required: true, message: '请选择是否为证书签名' }],
|
||||
signType: [{ required: true, message: '请选择签名类型' }],
|
||||
keyPrivateCert: [{ required: true, message: '请上传应用私钥证书' }],
|
||||
keyPrivateCertPwd: [{ required: true, message: '请输入应用私钥证书密码' }],
|
||||
acpMiddleCert: [{ required: true, message: '请上传中级证书' }],
|
||||
acpRootCert: [{ required: true, message: '请上传根证书' }],
|
||||
enable: [{ required: true, message: '请选择是否启用' }],
|
||||
notifyUrl: [{ required: true, message: '请输入异步通知页面地址' }],
|
||||
returnUrl: [{ required: true, message: '请输入同步通知页面地址' }],
|
||||
apiVersion: [{ required: true, message: '请选择支付API版本' }],
|
||||
apiKeyV2: [{ required: true, message: '请输入V2秘钥' }],
|
||||
sandbox: [{ required: true, message: '请选择是否为沙箱环境' }],
|
||||
payWays: [{ required: true, message: '请选择支持的支付类型' }],
|
||||
} as Record<string, Rule[]>
|
||||
})
|
||||
|
||||
let payWayList = $ref<LabeledValue[]>([])
|
||||
let signTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
// 事件
|
||||
const emits = defineEmits(['ok'])
|
||||
/**
|
||||
* 入口
|
||||
*/
|
||||
function init() {
|
||||
visible.value = true
|
||||
resetForm()
|
||||
getInfo()
|
||||
}
|
||||
// 获取信息
|
||||
async function getInfo() {
|
||||
confirmLoading.value = true
|
||||
findPayWayList().then(({ data }) => {
|
||||
payWayList = data
|
||||
})
|
||||
getConfig().then(({ data }) => {
|
||||
rawForm = { ...data }
|
||||
form = data
|
||||
confirmLoading.value = false
|
||||
})
|
||||
signTypeList = await dictDropDown('UnionPaySignType')
|
||||
}
|
||||
// 保存
|
||||
function handleOk() {
|
||||
formRef?.validate().then(async () => {
|
||||
confirmLoading.value = true
|
||||
await update({
|
||||
...form,
|
||||
...diffForm(rawForm, form, 'keyPrivateCert', 'keyPrivateCertPwd', 'acpMiddleCert', 'acpRootCert'),
|
||||
}).finally(() => {
|
||||
confirmLoading.value = false
|
||||
})
|
||||
handleCancel()
|
||||
createMessage.success('保存成功')
|
||||
emits('ok')
|
||||
})
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
function resetForm() {
|
||||
nextTick(() => {
|
||||
formRef?.resetFields()
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 文件上传
|
||||
*/
|
||||
function handleChange(info, fieldName) {
|
||||
// 上传完毕
|
||||
if (info.file.status === 'done') {
|
||||
const res = info.file.response
|
||||
if (!res.code) {
|
||||
form[fieldName] = res.data
|
||||
createMessage.success(`${info.file.name} 上传成功!`)
|
||||
} else {
|
||||
createMessage.error(`${res.msg}`)
|
||||
}
|
||||
} else if (info.file.status === 'error') {
|
||||
createMessage.error('上传失败')
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
init,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
43
src/views/payment/channel/union/record/UnionPayRecord.api.ts
Normal file
43
src/views/payment/channel/union/record/UnionPayRecord.api.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { defHttp } from '/@/utils/http/axios'
|
||||
import { Result, PageResult } from '/#/axios'
|
||||
import { BaseEntity } from '/#/web'
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
export function page(params) {
|
||||
return defHttp.get<Result<PageResult<UnionPayRecord>>>({
|
||||
url: '/union/pay/record/page',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
*/
|
||||
export function get(id) {
|
||||
return defHttp.get<Result<UnionPayRecord>>({
|
||||
url: '/union/pay/record/findById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录
|
||||
*/
|
||||
export interface UnionPayRecord extends BaseEntity {
|
||||
// 标题
|
||||
title?: string
|
||||
// 业务类型
|
||||
type?: string
|
||||
// 金额
|
||||
amount?: string
|
||||
// 交易订单号
|
||||
orderId?: string
|
||||
// 交易订单号
|
||||
gatewayOrderNo?: string
|
||||
// 终端ip
|
||||
ip?: string
|
||||
// 网关时间
|
||||
gatewayTime?: string
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
title="查看"
|
||||
v-bind="$attrs"
|
||||
:loading="confirmLoading"
|
||||
:width="modalWidth"
|
||||
:visible="visible"
|
||||
:mask-closable="showable"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-descriptions bordered title="" :column="{ md: 1, sm: 1, xs: 1 }">
|
||||
<a-descriptions-item label="标题">
|
||||
{{ unionPayRecord.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="金额(分)">
|
||||
{{ unionPayRecord.amount }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="本地订单号">
|
||||
{{ unionPayRecord.orderId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="网关订单号">
|
||||
{{ unionPayRecord.gatewayOrderNo }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="业务类型">
|
||||
<a-tag>{{ dictConvert('UnionPayRecordType', unionPayRecord.type) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="网关时间">
|
||||
{{ unionPayRecord.gatewayTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="记录时间">
|
||||
{{ unionPayRecord.createTime }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-spin>
|
||||
<template #footer>
|
||||
<a-button key="cancel" @click="handleCancel">取消</a-button>
|
||||
</template>
|
||||
</basic-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { get, UnionPayRecord } from './UnionPayRecord.api'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { BasicModal } from '/@/components/Modal'
|
||||
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
|
||||
const {
|
||||
initFormEditType,
|
||||
handleCancel,
|
||||
search,
|
||||
labelCol,
|
||||
wrapperCol,
|
||||
modalWidth,
|
||||
title,
|
||||
confirmLoading,
|
||||
visible,
|
||||
editable,
|
||||
showable,
|
||||
formEditType,
|
||||
} = useFormEdit()
|
||||
const { dictConvert } = useDict()
|
||||
|
||||
let loading = $ref(false)
|
||||
let unionPayRecord = $ref<UnionPayRecord>({})
|
||||
|
||||
/**
|
||||
* 入口
|
||||
*/
|
||||
function init(record: UnionPayRecord) {
|
||||
visible.value = true
|
||||
unionPayRecord = record
|
||||
initData(record.id as string)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData(alipayId) {
|
||||
loading = true
|
||||
const { data } = await get(alipayId)
|
||||
loading = false
|
||||
unionPayRecord = data
|
||||
}
|
||||
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
121
src/views/payment/channel/union/record/UnionPayRecordList.vue
Normal file
121
src/views/payment/channel/union/record/UnionPayRecordList.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :fields="fields" :default-item-count="3" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
<vxe-table
|
||||
row-id="id"
|
||||
ref="xTable"
|
||||
:data="pagination.records"
|
||||
:loading="loading"
|
||||
:sort-config="{ remote: true, trigger: 'cell' }"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<vxe-column type="seq" title="序号" width="60" />
|
||||
<vxe-column field="title" title="标题" />
|
||||
<vxe-column field="type" title="类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('UnionPayRecordType', row.type) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="amount" title="金额" />
|
||||
<vxe-column field="orderId" title="本地订单ID" width="170" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单号" width="170" />
|
||||
<vxe-column field="gatewayTime" title="网关时间" sortable />
|
||||
<vxe-column fixed="right" width="50" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<union-pay-record-info ref="unionPayRecordInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { page } from './UnionPayRecord.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import ALink from '/@/components/Link/Link.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { LIST, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import UnionPayRecordInfo from './UnionPayRecordInfo.vue'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, sortChange, sortParam, pages, model, loading } =
|
||||
useTablePage(queryPage)
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
let unionPayRecordInfo = $ref<any>()
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
let recordTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
const fields = [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'type', type: LIST, name: '记录类型', placeholder: '请选择记录类型', selectList: recordTypeList },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
]
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initData()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*/
|
||||
function vxeBind() {
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
recordTypeList = await dictDropDown('UnionPayRecordType')
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
function show(record) {
|
||||
unionPayRecordInfo.init(record)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
...sortParam,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
return Promise.resolve()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
@@ -23,7 +23,7 @@
|
||||
<a-input v-model:value="form.appSecret" :disabled="showable" placeholder="APPID对应的接口密码,用于获取接口调用凭证时使用" />
|
||||
</a-form-item>
|
||||
<a-form-item label="是否启用" name="enable">
|
||||
<a-switch v-model:checked="form.enable" />
|
||||
<a-switch checked-children="启用" un-checked-children="停用" v-model:checked="form.enable" />
|
||||
</a-form-item>
|
||||
<a-form-item name="notifyUrl">
|
||||
<template #label>
|
||||
|
@@ -38,4 +38,6 @@ export interface WechatPayRecord extends BaseEntity {
|
||||
gatewayOrderNo?: string
|
||||
// 终端ip
|
||||
ip?: string
|
||||
// 网关时间
|
||||
gatewayTime?: string
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@
|
||||
<a-descriptions-item label="业务类型">
|
||||
<a-tag>{{ dictConvert('WechatPayRecordType', wechatPayRecord.type) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="网关时间">
|
||||
{{ wechatPayRecord.gatewayTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="记录时间">
|
||||
{{ wechatPayRecord.createTime }}
|
||||
</a-descriptions-item>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
<b-query :query-params="model.queryParam" :fields="fields" :default-item-count="3" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
@@ -23,7 +23,7 @@
|
||||
<vxe-column field="amount" title="金额" />
|
||||
<vxe-column field="orderId" title="本地订单ID" width="170" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单号" width="170" />
|
||||
<vxe-column field="createTime" title="记录时间" sortable />
|
||||
<vxe-column field="gatewayTime" title="网关时间" sortable />
|
||||
<vxe-column fixed="right" width="50" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
@@ -44,9 +44,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { page, WechatPayRecord } from './WechatPayRecord.api'
|
||||
import { page } from './WechatPayRecord.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
@@ -54,7 +54,8 @@
|
||||
import WechatPayRecordInfo from './WechatPayRecordInfo.vue'
|
||||
import ALink from '/@/components/Link/Link.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, sortChange, sortParam, pages, model, loading } =
|
||||
@@ -62,18 +63,23 @@
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
let wechatPayRecordInfo = $ref<any>()
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
const wechatPayRecordInfo = $ref<any>()
|
||||
|
||||
const fields = [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
]
|
||||
let recordTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单ID', placeholder: '请输入完整本地订单ID' },
|
||||
{ field: 'type', type: LIST, name: '记录类型', placeholder: '请选择记录类型', selectList: recordTypeList },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
] as QueryField[]
|
||||
})
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initData()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
@@ -83,6 +89,12 @@
|
||||
function vxeBind() {
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
}
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
recordTypeList = await dictDropDown('WechatPayRecordType')
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
|
@@ -110,7 +110,7 @@
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'paymentId', type: STRING, name: '支付ID', placeholder: '请输入完整支付ID' },
|
||||
{ field: 'id', type: STRING, name: '支付ID', placeholder: '请输入完整支付ID' },
|
||||
{ field: 'businessNo', type: STRING, name: '业务号', placeholder: '请输入业务号' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
{ field: 'title', type: STRING, name: '标题', placeholder: '请输入标题' },
|
||||
|
@@ -0,0 +1,43 @@
|
||||
import { defHttp } from '/@/utils/http/axios'
|
||||
import { PageResult, Result } from '/#/axios'
|
||||
import { BaseEntity } from '/#/web'
|
||||
|
||||
/**
|
||||
* 明细分页
|
||||
*/
|
||||
export function page(params) {
|
||||
return defHttp.get<Result<PageResult<ReconcileDetail>>>({
|
||||
url: '/order/reconcile/detail/page',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 明细详情
|
||||
*/
|
||||
export function get(id: string) {
|
||||
return defHttp.get<Result<ReconcileDetail>>({
|
||||
url: '/order/reconcile/detail/findById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用支付对账记录
|
||||
*/
|
||||
export interface ReconcileDetail extends BaseEntity {
|
||||
// 关联对账订单ID
|
||||
recordOrderId?: string
|
||||
// 交易类型
|
||||
type?: string
|
||||
// 订单id
|
||||
paymentId?: string
|
||||
// 订单id
|
||||
refundId?: string
|
||||
// 网关订单号
|
||||
gatewayOrderNo?: string
|
||||
// 交易金额
|
||||
amount?: string
|
||||
// 商品名称
|
||||
title?: string
|
||||
}
|
@@ -9,23 +9,20 @@
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-descriptions bordered title="" :column="{ md: 1, sm: 1, xs: 1 }">
|
||||
<a-descriptions-item label="商品名称">
|
||||
<a-descriptions-item label="订单名称">
|
||||
{{ form.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="交易金额">
|
||||
{{ form.amount }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="支付订单ID">
|
||||
{{ form.paymentId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="退款订单ID" v-if="form.refundId">
|
||||
{{ form.refundId }}
|
||||
<a-descriptions-item label="本地订单ID">
|
||||
{{ form.orderId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="网关订单号">
|
||||
{{ form.gatewayOrderNo }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="交易类型">
|
||||
<a-tag>{{ dictConvert('PayReconcileTrade', form.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ReconcileTrade', form.type) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ form.createTime }}
|
||||
@@ -44,7 +41,7 @@
|
||||
import { FormInstance } from 'ant-design-vue/lib/form'
|
||||
import { BasicModal } from '/@/components/Modal'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import { getDetail, ReconcileDetail } from './ReconcileOrder.api'
|
||||
import { get, ReconcileDetail } from './ReconcileDetail.api'
|
||||
const {
|
||||
initFormEditType,
|
||||
handleCancel,
|
||||
@@ -70,7 +67,7 @@
|
||||
function init(record) {
|
||||
visible.value = true
|
||||
confirmLoading.value = true
|
||||
getDetail(record.id).then(({ data }) => {
|
||||
get(record.id).then(({ data }) => {
|
||||
form = data
|
||||
confirmLoading.value = false
|
||||
})
|
@@ -2,23 +2,29 @@
|
||||
<basic-drawer forceRender v-bind="$attrs" title="对账单明细列表" width="60%" :visible="visible" @close="visible = false">
|
||||
<b-query :query-params="model.queryParam" :default-item-count="3" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
|
||||
<vxe-table
|
||||
row-id="id"
|
||||
ref="xTable"
|
||||
:data="pagination.records"
|
||||
:loading="loading"
|
||||
:sort-config="{ remote: true, trigger: 'cell' }"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="title" title="商品名称" />
|
||||
<vxe-column field="title" title="订单名称" />
|
||||
<vxe-column field="amount" title="交易金额" />
|
||||
<vxe-column field="paymentId" title="支付订单ID" />
|
||||
<vxe-column field="refundId" title="退款订单ID" />
|
||||
<vxe-column field="orderId" title="本地订单ID" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单号" />
|
||||
<vxe-column field="repairType" title="交易类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('PayReconcileTrade', row.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ReconcileTrade', row.type) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="createTime" title="创建时间" />
|
||||
<vxe-column field="orderTime" title="订单时间" sortable />
|
||||
<vxe-column fixed="right" width="60" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<span>
|
||||
<a href="javascript:" @click="show(row)">查看</a>
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
@@ -38,19 +44,21 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { pageDetail, ReconcileDetail } from './ReconcileOrder.api'
|
||||
import { page, ReconcileDetail } from './ReconcileDetail.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import ReconcileDetailInfo from './ReconcileDetailInfo.vue'
|
||||
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import BasicDrawer from '/@/components/Drawer/src/BasicDrawer.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import ALink from '/@/components/Link/Link.vue'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, sortChange, pages, sortParam, model, loading } =
|
||||
useTablePage(queryPage)
|
||||
const { notification, createMessage } = useMessage()
|
||||
const { dictDropDown, dictConvert } = useDict()
|
||||
|
||||
@@ -60,10 +68,9 @@
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: STRING, name: '订单名称', placeholder: '请输入订单名称' },
|
||||
{ field: 'paymentId', type: STRING, name: '本地支付ID', placeholder: '请输入本地支付ID' },
|
||||
{ field: 'refundId', type: STRING, name: '本地退款ID', placeholder: '请输入本地退款ID' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入网关订单号' },
|
||||
{ field: 'type', type: LIST, name: '交易类型', placeholder: '请选择交易类型', selectList: reconcileTradeList },
|
||||
{ field: 'orderId', type: STRING, name: '本地订单', placeholder: '请输入本地订单ID' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入网关订单号' },
|
||||
] as QueryField[]
|
||||
})
|
||||
let visible = $ref(false)
|
||||
@@ -85,7 +92,7 @@
|
||||
* 初始化基础数据
|
||||
*/
|
||||
async function initData() {
|
||||
reconcileTradeList = await dictDropDown('PayReconcileTrade')
|
||||
reconcileTradeList = await dictDropDown('ReconcileTrade')
|
||||
}
|
||||
/**
|
||||
* 入口
|
||||
@@ -94,6 +101,8 @@
|
||||
function init(record) {
|
||||
visible = true
|
||||
reconcileDetail = record
|
||||
model.queryParam = {}
|
||||
xTable?.clearSort()
|
||||
queryPage()
|
||||
}
|
||||
|
||||
@@ -102,9 +111,10 @@
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
pageDetail({
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
...sortParam,
|
||||
recordOrderId: reconcileDetail?.id,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
57
src/views/payment/order/reconcile/diff/ReconcileDiff.api.ts
Normal file
57
src/views/payment/order/reconcile/diff/ReconcileDiff.api.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { defHttp } from '/@/utils/http/axios'
|
||||
import { PageResult, Result } from '/#/axios'
|
||||
import { BaseEntity } from '/#/web'
|
||||
|
||||
/**
|
||||
* 对账差异分页
|
||||
*/
|
||||
export function page(params) {
|
||||
return defHttp.get<Result<PageResult<ReconcileRecord>>>({
|
||||
url: '/order/reconcile/diff/page',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 对账差异详情
|
||||
*/
|
||||
export function get(id: string) {
|
||||
return defHttp.get<Result<ReconcileRecord>>({
|
||||
url: '/order/reconcile/diff/findById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用支付对账记录
|
||||
*/
|
||||
export interface ReconcileRecord extends BaseEntity {
|
||||
// 关联对账订单ID
|
||||
recordOrderId?: string
|
||||
// 交易类型
|
||||
type?: string
|
||||
// 订单id
|
||||
paymentId?: string
|
||||
// 订单id
|
||||
refundId?: string
|
||||
// 网关订单号
|
||||
gatewayOrderNo?: string
|
||||
// 交易金额
|
||||
amount?: string
|
||||
// 商品名称
|
||||
title?: string
|
||||
// 差异内容
|
||||
diffs?: ReconcileDiff[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 差异内容
|
||||
*/
|
||||
export interface ReconcileDiff {
|
||||
// 字段名
|
||||
fieldName?: string
|
||||
// 本地订单字段值
|
||||
localValue?: string
|
||||
// 网关订单字段值
|
||||
gatewayValue?: string
|
||||
}
|
95
src/views/payment/order/reconcile/diff/ReconcileDiffInfo.vue
Normal file
95
src/views/payment/order/reconcile/diff/ReconcileDiffInfo.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
title="对账订单详情"
|
||||
v-bind="$attrs"
|
||||
:loading="confirmLoading"
|
||||
:width="750"
|
||||
:visible="visible"
|
||||
:mask-closable="showable"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-descriptions bordered title="" :column="{ md: 1, sm: 1, xs: 1 }">
|
||||
<a-descriptions-item label="订单标题">
|
||||
{{ form.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="交易金额">
|
||||
{{ form.amount }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="对账单ID">
|
||||
{{ form.recordId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item v-if="form.detailId" label="对账单明细ID">
|
||||
{{ form.detailId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="本地订单ID">
|
||||
{{ form.orderId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item v-if="form.gatewayOrderNo" label="网关订单号">
|
||||
{{ form.gatewayOrderNo }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单类型">
|
||||
<a-tag>{{ dictConvert('ReconcileTrade', form.orderType) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="差异类型">
|
||||
<a-tag>{{ dictConvert('ReconcileDiffType', form.diffType) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单时间">
|
||||
{{ form.orderTime }}
|
||||
</a-descriptions-item>
|
||||
<template v-if="form.diffs">
|
||||
<a-descriptions-item :label="`${item.fieldName}[差异]`" :key="item" v-for="item in form.diffs">
|
||||
<a-tag>本地</a-tag> : {{ item.localValue }}<br /><a-tag>远程</a-tag> : {{ item.gatewayValue }}
|
||||
</a-descriptions-item>
|
||||
</template>
|
||||
</a-descriptions>
|
||||
<template #footer>
|
||||
<a-space>
|
||||
<a-button key="cancel" @click="handleCancel">取消</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</basic-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { $ref } from 'vue/macros'
|
||||
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
||||
import { FormInstance } from 'ant-design-vue/lib/form'
|
||||
import { BasicModal } from '/@/components/Modal'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import { get, ReconcileDiff, ReconcileRecord } from './ReconcileDiff.api'
|
||||
const {
|
||||
initFormEditType,
|
||||
handleCancel,
|
||||
search,
|
||||
labelCol,
|
||||
wrapperCol,
|
||||
modalWidth,
|
||||
title,
|
||||
confirmLoading,
|
||||
visible,
|
||||
editable,
|
||||
showable,
|
||||
formEditType,
|
||||
} = useFormEdit()
|
||||
const { dictConvert } = useDict()
|
||||
// 表单
|
||||
const formRef = $ref<FormInstance>()
|
||||
let form = $ref<ReconcileOrder>({})
|
||||
|
||||
// 事件
|
||||
const emits = defineEmits(['ok'])
|
||||
// 入口
|
||||
function init(record) {
|
||||
visible.value = true
|
||||
confirmLoading.value = true
|
||||
get(record.id).then(({ data }) => {
|
||||
form = data
|
||||
confirmLoading.value = false
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
init,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
119
src/views/payment/order/reconcile/diff/ReconcileDiffList.vue
Normal file
119
src/views/payment/order/reconcile/diff/ReconcileDiffList.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :default-item-count="3" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
<vxe-table
|
||||
row-id="id"
|
||||
ref="xTable"
|
||||
:data="pagination.records"
|
||||
:loading="loading"
|
||||
:sort-config="{ remote: true, trigger: 'cell' }"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<vxe-column type="seq" title="序号" width="60" />
|
||||
<vxe-column field="title" title="订单标题" />
|
||||
<vxe-column field="orderType" title="订单类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ReconcileTrade', row.orderType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="diffType" title="差异类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ReconcileDiffType', row.diffType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="orderId" title="本地订单" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单" />
|
||||
<vxe-column field="amount" title="交易金额" />
|
||||
<vxe-column field="orderTime" title="订单时间" />
|
||||
<vxe-column fixed="right" width="80" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<reconcile-diff-info ref="reconcileDiffInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { DATE, LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { page } from './ReconcileDiff.api'
|
||||
import ReconcileDiffInfo from './ReconcileDiffInfo.vue'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, sortChange, sortParam, pagination, pages, model, loading } =
|
||||
useTablePage(queryPage)
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
let payChannelList = $ref<LabeledValue[]>([])
|
||||
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: DATE, name: '订单标题', placeholder: '请输入订单标题' },
|
||||
] as QueryField[]
|
||||
})
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
const reconcileDiffInfo = $ref<any>()
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
vxeBind()
|
||||
queryPage()
|
||||
})
|
||||
function vxeBind() {
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
payChannelList = await dictDropDown('AsyncPayChannel')
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
...sortParam,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
return Promise.resolve()
|
||||
}
|
||||
/**
|
||||
* 查看详情
|
||||
*/
|
||||
function show(record) {
|
||||
reconcileDiffInfo.init(record)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<basic-drawer forceRender v-bind="$attrs" title="差异明细列表" width="60%" :visible="visible" @close="visible = false">
|
||||
<b-query :query-params="model.queryParam" :default-item-count="3" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }" />
|
||||
<vxe-table
|
||||
row-id="id"
|
||||
ref="xTable"
|
||||
:data="pagination.records"
|
||||
:loading="loading"
|
||||
:sort-config="{ remote: true, trigger: 'cell' }"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<vxe-column type="seq" title="序号" width="60" />
|
||||
<vxe-column field="title" title="订单标题" />
|
||||
<vxe-column field="orderType" title="订单类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ReconcileTrade', row.orderType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="diffType" title="差异类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ReconcileDiffType', row.diffType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="orderId" title="本地订单" />
|
||||
<vxe-column field="gatewayOrderNo" title="网关订单" />
|
||||
<vxe-column field="amount" title="交易金额" sortable />
|
||||
<vxe-column field="orderTime" title="订单时间" sortable />
|
||||
<vxe-column fixed="right" width="80" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<reconcile-diff-info ref="reconcileDiffInfo" />
|
||||
</basic-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { page } from './ReconcileDiff.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import ReconcileDiffInfo from './ReconcileDiffInfo.vue'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import BasicDrawer from '/@/components/Drawer/src/BasicDrawer.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
import { useDict } from '/@/hooks/bootx/useDict'
|
||||
import { ReconcileDetail } from '/@/views/payment/order/reconcile/detail/ReconcileDetail.api'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, sortChange, pagination, pages, sortParam, model, loading } =
|
||||
useTablePage(queryPage)
|
||||
const { notification, createMessage } = useMessage()
|
||||
const { dictDropDown, dictConvert } = useDict()
|
||||
|
||||
let orderTypeList = $ref<LabeledValue[]>([])
|
||||
let diffTypeList = $ref<LabeledValue[]>([])
|
||||
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'title', type: STRING, name: '订单名称', placeholder: '请输入订单名称' },
|
||||
{ field: 'orderType', type: LIST, name: '订单类型', placeholder: '请选择订单类型', selectList: orderTypeList },
|
||||
{ field: 'diffType', type: LIST, name: '差异类型', placeholder: '请选择差异类型', selectList: diffTypeList },
|
||||
{ field: 'orderId', type: STRING, name: '本地定单', placeholder: '请输入本地定单ID' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入网关订单号' },
|
||||
] as QueryField[]
|
||||
})
|
||||
let visible = $ref(false)
|
||||
let reconcileDetail = $ref<ReconcileDetail>()
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
const xToolbar = $ref<VxeToolbarInstance>()
|
||||
const reconcileDiffInfo = $ref<any>()
|
||||
|
||||
nextTick(() => {
|
||||
xTable?.connect(xToolbar as VxeToolbarInstance)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化基础数据
|
||||
*/
|
||||
async function initData() {
|
||||
orderTypeList = await dictDropDown('ReconcileTrade')
|
||||
diffTypeList = await dictDropDown('ReconcileDiffType')
|
||||
}
|
||||
/**
|
||||
* 入口
|
||||
*/
|
||||
function init(record: ReconcileDetail) {
|
||||
visible = true
|
||||
reconcileDetail = record
|
||||
model.queryParam = {}
|
||||
xTable?.clearSort()
|
||||
queryPage()
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
...sortParam,
|
||||
recordId: reconcileDetail?.id,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
function show(record) {
|
||||
reconcileDiffInfo.init(record)
|
||||
}
|
||||
defineExpose({
|
||||
init,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
@@ -32,26 +32,6 @@ export function get(id: string) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 明细分页
|
||||
*/
|
||||
export function pageDetail(params) {
|
||||
return defHttp.get<Result<PageResult<ReconcileDetail>>>({
|
||||
url: '/order/reconcile/pageDetail',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 明细详情
|
||||
*/
|
||||
export function getDetail(id: string) {
|
||||
return defHttp.get<Result<ReconcileDetail>>({
|
||||
url: '/order/reconcile/findDetailById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*/
|
||||
@@ -62,6 +42,16 @@ export function downAndSave(id: any) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 对账单比对
|
||||
*/
|
||||
export function compare(id: any) {
|
||||
return defHttp.post<any>({
|
||||
url: '/order/reconcile/compare',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付对账订单
|
||||
*/
|
||||
@@ -79,23 +69,3 @@ export interface ReconcileOrder extends BaseEntity {
|
||||
// 错误信息
|
||||
errorMsg?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用支付对账记录
|
||||
*/
|
||||
export interface ReconcileDetail extends BaseEntity {
|
||||
// 关联对账订单ID
|
||||
recordOrderId?: string
|
||||
// 交易类型
|
||||
type?: string
|
||||
// 订单id
|
||||
paymentId?: string
|
||||
// 订单id
|
||||
refundId?: string
|
||||
// 网关订单号
|
||||
gatewayOrderNo?: string
|
||||
// 交易金额
|
||||
amount?: string
|
||||
// 商品名称
|
||||
title?: string
|
||||
}
|
@@ -29,6 +29,9 @@
|
||||
<a-descriptions-item label="错误信息">
|
||||
{{ form.errorMsg }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ form.createTime }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<template #footer>
|
||||
<a-space>
|
@@ -36,15 +36,28 @@
|
||||
<vxe-column field="compare" title="对账单比对">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.compare" color="green">已比对</a-tag>
|
||||
<a-link v-else :disabled="!row.down" color="red" @click="compare(row)">比对</a-link>
|
||||
<a-link v-else :disabled="!row.down" color="red" @click="compareOrder(row)">比对</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="errorMsg" title="错误信息" />
|
||||
<vxe-column fixed="right" width="140" :showOverflow="false" title="操作">
|
||||
<vxe-column field="createTime" title="创建时间" />
|
||||
<vxe-column fixed="right" width="120" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
<a-divider type="vertical" />
|
||||
<a-link @click="showDetailPage(row)">对账明细</a-link>
|
||||
<a-dropdown>
|
||||
<a> 更多 <icon icon="ant-design:down-outlined" :size="12" /></a>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<a-link @click="showDetailPage(row)">对账明细</a-link>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-link @click="showDiffPage(row)">差异明细</a-link>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
@@ -60,6 +73,7 @@
|
||||
<reconcile-order-create ref="reconcileOrderCreate" @ok="queryPage" />
|
||||
<reconcile-detail-list ref="reconcileDetailList" />
|
||||
<reconcile-order-info ref="reconcileOrderInfo" />
|
||||
<reconcile-diff-list-model ref="reconcileDiffListModel" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -71,13 +85,16 @@
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { DATE, LIST, QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import { downAndSave, page } from './ReconcileOrder.api'
|
||||
import { compare, downAndSave, page } from './ReconcileOrder.api'
|
||||
import ReconcileOrderInfo from './ReconcileOrderInfo.vue'
|
||||
import ReconcileDetailList from './ReconcileDetailList.vue'
|
||||
import ReconcileOrderCreate from '/@/views/payment/order/reconcile/ReconcileOrderCreate.vue'
|
||||
import ReconcileDetailList from '../detail/ReconcileDetailList.vue'
|
||||
import ReconcileOrderCreate from './ReconcileOrderCreate.vue'
|
||||
import ALink from '/@/components/Link/Link.vue'
|
||||
import ReconcileDiffListModel from '/@/views/payment/order/reconcile/diff/ReconcileDiffListModel.vue'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, sortChange, sortParam, pagination, pages, model, loading } = useTablePage(queryPage)
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, sortChange, sortParam, pagination, pages, model, loading } =
|
||||
useTablePage(queryPage)
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert, dictDropDown } = useDict()
|
||||
|
||||
@@ -103,6 +120,7 @@
|
||||
const reconcileOrderCreate = $ref<any>()
|
||||
const reconcileOrderInfo = $ref<any>()
|
||||
const reconcileDetailList = $ref<any>()
|
||||
const reconcileDiffListModel = $ref<any>()
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
@@ -151,10 +169,13 @@
|
||||
content: '确定要下载对账单吗?',
|
||||
onOk: () => {
|
||||
createMessage.info('对账单下载保存中.....')
|
||||
downAndSave(record.id).then(() => {
|
||||
createMessage.info('对账单下载完成')
|
||||
queryPage()
|
||||
})
|
||||
downAndSave(record.id)
|
||||
.then(() => {
|
||||
createMessage.info('对账单下载完成')
|
||||
})
|
||||
.finally(() => {
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -162,8 +183,22 @@
|
||||
/**
|
||||
* 对账明显比对
|
||||
*/
|
||||
function compare(record) {
|
||||
createMessage.warn('下个版本支持...')
|
||||
function compareOrder(record) {
|
||||
createConfirm({
|
||||
iconType: 'info',
|
||||
title: '提示',
|
||||
content: '确定要进行比对吗?',
|
||||
onOk: () => {
|
||||
createMessage.info('对账单比对中.....')
|
||||
compare(record.id)
|
||||
.then(() => {
|
||||
createMessage.info('对账单比对完成')
|
||||
})
|
||||
.finally(() => {
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,6 +214,13 @@
|
||||
function showDetailPage(record) {
|
||||
reconcileDetailList.init(record)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看差异单
|
||||
*/
|
||||
function showDiffPage(record) {
|
||||
reconcileDiffListModel.init(record)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
@@ -62,6 +62,16 @@ export function syncById(id) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款重试
|
||||
*/
|
||||
export function resetRefund(id){
|
||||
return defHttp.post<Result<void>>({
|
||||
url: '/order/refund/resetRefund',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款记录
|
||||
*/
|
||||
|
@@ -46,14 +46,17 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="reason" title="原因" />
|
||||
<vxe-column fixed="right" width="180" :showOverflow="false" title="操作">
|
||||
<vxe-column fixed="right" width="220" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<a-link @click="show(row)">查看</a-link>
|
||||
<a-divider type="vertical" />
|
||||
<a-link @click="showChannel(row)">通道订单</a-link>
|
||||
<a-divider type="vertical" />
|
||||
<!-- 只有退款中的异步订单才可以同步 -->
|
||||
<a-link :disabled="!(row.asyncPay && row.status === 'progress')" @click="sync(row)">同步</a-link>
|
||||
<!-- 只有异步订单才可以同步 -->
|
||||
<a-link :disabled="!row.asyncPay" @click="sync(row)">同步</a-link>
|
||||
<a-divider type="vertical" />
|
||||
<!-- 只有退款失败的异步订单才可以重新退款 -->
|
||||
<a-link :disabled="!(row.asyncPay && row.status === 'fail')" @click="reset(row)">重试</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
@@ -75,7 +78,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { page, syncById } from './RefundOrder.api'
|
||||
import { page, resetRefund, syncById } from './RefundOrder.api'
|
||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||
import RefundOrderInfo from './RefundOrderInfo.vue'
|
||||
import { VxeTable, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
@@ -99,8 +102,9 @@
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'id', type: STRING, name: '退款号', placeholder: '请输入完整退款号' },
|
||||
{ field: 'paymentId', type: STRING, name: '原支付单号', placeholder: '请输入完整支付ID' },
|
||||
{ field: 'id', type: STRING, name: '退款ID', placeholder: '请输入完整退款ID' },
|
||||
{ field: 'refundNo', type: STRING, name: '退款号', placeholder: '请输入完整退款号' },
|
||||
{ field: 'paymentId', type: STRING, name: '原支付ID', placeholder: '请输入完整支付ID' },
|
||||
{ field: 'businessNo', type: STRING, name: '原业务号', placeholder: '请输入业务号' },
|
||||
{ field: 'gatewayOrderNo', type: STRING, name: '网关订单号', placeholder: '请输入完整网关订单号' },
|
||||
{ field: 'title', type: STRING, name: '原支付标题', placeholder: '请输入原支付标题' },
|
||||
@@ -171,6 +175,24 @@
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款重试
|
||||
*/
|
||||
function reset(record) {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '警告',
|
||||
content: '是否同步退款信息',
|
||||
onOk: () => {
|
||||
loading.value = true
|
||||
resetRefund(record.id).then(() => {
|
||||
createMessage.success('提交成功')
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
|
@@ -14,10 +14,10 @@
|
||||
{{ info.id }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求次数">
|
||||
{{ info.reqCount }}
|
||||
{{ info.reqCount || '空' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="发送类型">
|
||||
<a-tag>{{ dictConvert('ClientNoticeSendType', info.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ClientNoticeSendType', info.sendType) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="是否发送成功">
|
||||
<a-tag v-if="info.success" color="green">是</a-tag>
|
||||
|
@@ -10,16 +10,20 @@
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="reqCount" title="请求次数" />
|
||||
<vxe-column field="reqCount" title="请求次数">
|
||||
<template #default="{ row }">
|
||||
<a-tag color="green">{{ row.reqCount || '空' }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="channel" title="是否成功">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.success" color="green">是</a-tag>
|
||||
<a-tag v-else color="red">否</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="type" title="发送类型">
|
||||
<vxe-column field="sendType" title="发送类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ClientNoticeSendType', row.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ClientNoticeSendType', row.sendType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="errorMsg" title="错误信息" max-width="200" />
|
||||
|
@@ -61,8 +61,8 @@ export function getRecord(id) {
|
||||
export interface ClientNoticeTask extends BaseEntity {
|
||||
// 本地订单ID
|
||||
orderId?: number
|
||||
// 回调类型
|
||||
type?: string
|
||||
// 消息类型
|
||||
noticeType?: string
|
||||
// 消息内容
|
||||
content?: string
|
||||
// 是否发送成功
|
||||
@@ -83,6 +83,8 @@ export interface ClientNoticeRecord extends BaseEntity {
|
||||
taskId?: string
|
||||
// 请求次数
|
||||
reqCount?: number
|
||||
// 发送类型
|
||||
sendType?: boolean
|
||||
// 发送是否成功
|
||||
success?: boolean
|
||||
// 错误信息
|
||||
|
@@ -17,7 +17,11 @@
|
||||
<a-tag>{{ task.orderId }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="回调类型">
|
||||
<a-tag>{{ dictConvert('ClientNoticeType', task.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ClientNoticeType', task.noticeType) }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单状态">
|
||||
<a-tag v-if="task.noticeType === 'pay'">{{ dictConvert('PayStatus', task.orderStatus) || '未知' }}</a-tag>
|
||||
<a-tag v-else>{{ dictConvert('RefundStatus', task.orderStatus) || '未知' }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="消息内容">
|
||||
<json-preview :data="JSON.parse(task.content || '{}')" />
|
||||
|
@@ -21,9 +21,15 @@
|
||||
</a-link>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="type" title="消息类型">
|
||||
<vxe-column field="noticeType" title="消息类型">
|
||||
<template #default="{ row }">
|
||||
<a-tag>{{ dictConvert('ClientNoticeType', row.type) }}</a-tag>
|
||||
<a-tag>{{ dictConvert('ClientNoticeType', row.noticeType) }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="success" title="订单状态">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.noticeType === 'pay'">{{ dictConvert('PayStatus', row.orderStatus) || '未知' }}</a-tag>
|
||||
<a-tag v-else>{{ dictConvert('RefundStatus', row.orderStatus) || '未知' }}</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="success" title="发送成功">
|
||||
@@ -151,9 +157,8 @@
|
||||
/**
|
||||
* 查看订单信息
|
||||
*/
|
||||
function showOrder(record) {
|
||||
console.log(record)
|
||||
if (record.type === 'pay') {
|
||||
function showOrder(record: ClientNoticeTask) {
|
||||
if (record.noticeType === 'pay') {
|
||||
payOrderInfo.init(record.orderId)
|
||||
} else {
|
||||
refundOrderInfo.init(record.orderId)
|
||||
|
@@ -3,9 +3,8 @@
|
||||
<template #headerContent>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="flex-1">
|
||||
<a :href="GITHUB_URL" target="_blank">Bootx-Platform </a>
|
||||
是一个基于Spring Boot、Vue、Ant-Design-Vue
|
||||
、TypeScript的后台管理脚手架,包含支付收单(支付宝、微信、聚合、组合支付)、工作流(Flowable)、三方对接(微信、钉钉、企微、短信)等功能。
|
||||
<a :href="GITHUB_URL" target="_blank">dax-pay </a>
|
||||
是一款免费开源的支付网关,独立部署通过HTTP方式进行调用,不与其他系统产生耦合关联,可以快速集成到各种系统中,提供可视化界面进行管理,便于实现统一的支付信息管理。
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
57
用户授权使用协议.txt
Normal file
57
用户授权使用协议.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
感谢您选择DaxPay支付系统(以下简称DaxPay),DaxPay是一款支付系统,基于 Java 的技术开发,全部源码开放。
|
||||
|
||||
为了使您正确并合法地使用本软件,请您在使用前务必阅读清楚下面的协议条款:
|
||||
|
||||
一、本授权协议适用且仅适用于 DaxPay 2.X.X 版本,如果不同意该协议,请不要进行使用
|
||||
|
||||
二、 产品介绍和产品模式
|
||||
1. DaxPay支付系统是由济南易杯光年软件技术有限公司研发的支付产品,版权归济南易杯光年软件技术有限公司所有
|
||||
|
||||
2. DaxPay旨在解决需要支付交易流的开发者、个体户、公司等提供便捷的支付产品
|
||||
|
||||
3. DaxPay只是一个应用软件,用户部署后只负责信息流的传递,不负责资金流,支付资金全部由用户选择的支付平台直接结算
|
||||
|
||||
4. DaxPay不会私自上传任何数据到外部,但无法保证所系统中三方SDK和依赖是否会对外传输数据
|
||||
|
||||
三、协议许可的权利
|
||||
|
||||
1. 您可以在完全遵守本最终用户授权使用协议的基础上,将本软件应用于商业用途,而不必支付软件版权授权费用
|
||||
|
||||
2. 您可以在协议规定的约束和限制范围内修改 DaxPay 源代码或界面风格以适应您的要求
|
||||
|
||||
3. 您拥有使用本软件构建的网站全部内容所有权,并独立承担与这些内容的相关法律义务
|
||||
|
||||
四、有限担保和免责声明
|
||||
1. 本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。
|
||||
|
||||
2. 用户出于自愿而使用本软件,您必须了解使用本软件的风险,我们不承诺对用户提供任何形式的技术支持、使用担保,也不承担任何因使用本软件而产生问题的相关责任。
|
||||
|
||||
3. 电子文本形式的授权协议如同双方书面签署的协议一样,具有完全的和等同的法律效力。您一旦开始确认本协议并使用DaxPay,即被视为完全理解并接受本协议的各项条款,在享有上述条款授予的权力的同时,受到相关的约束和限制。协议许可范围以外的行为,将直接违反本授权协议并构成侵权,我们有权随时终止授权,责令停止损害,并保留追究相关责任的权力。
|
||||
|
||||
4. DaxPay系统由用户自行部署使用,不提供在线服务、服务托管等服务,用户对外提供服务时,请保证已经根据国家相关法律法规获取到相应的许可
|
||||
|
||||
5. 如果本软件带有其它软件的整合API示范例子包,这些文件版权不属于本软件官方,并且这些文件是没经过授权发布的,请参考相关软件的使用许可合法的使用。
|
||||
|
||||
6. 客户不得利用DaxPay产品从事非法行为,客户应当合法合规的使用产品,DaxPay不承担客户因非法行为造成的任何法律责任。
|
||||
|
||||
7. 如发现客户在使用产品时有任何的非法行为,有权解除授权停止技术支持,并配合有关机关进行调查或向政府部门举报。
|
||||
|
||||
8. 本软件由济南易杯光年软件技术有限公司进行分发,没有授权分销商,也没有任何分公司、代理商、办事处、经销商等销售和分发本产品
|
||||
|
||||
|
||||
五、禁止接入的内容包括但不限于以下内容
|
||||
|
||||
1. 诈骗、BC严禁接入、赛车、V盘、X资金盘、贷款、P2P、汇兑、ICO、二清支付严禁接入
|
||||
|
||||
2. 1元购类、高额返利类 、多级分销类、盲盒类、单纯形式抽奖类、发卡平台严禁接入
|
||||
|
||||
3. 恋爱话术类、数字藏品、色情、政治相关、影视小说、电子书、游戏平台严禁接入
|
||||
|
||||
4. 付费入群、帐号销售、刷单、卡盟平台、刷粉、VPN、售卖假货严禁接入
|
||||
|
||||
5. 未取得相关资质的游戏、私服等禁止接入
|
||||
|
||||
6. 微信/支付宝/银联官方要求禁止接入的、其他支付通道禁止接入的、以及所有国家法规规定禁止的一切情景
|
||||
|
||||
协议日期:2023年01月01日
|
||||
济南易杯光年软件技术有限公司
|
Reference in New Issue
Block a user