|
|
@@ -0,0 +1,232 @@
|
|
|
+<template>
|
|
|
+ <div class="p-2">
|
|
|
+ <el-card shadow="hover">
|
|
|
+ <template #header>
|
|
|
+ <div class="card-header">
|
|
|
+ <span>微信小程序支付配置</span>
|
|
|
+ <el-button type="primary" @click="handleSave" :loading="saving">保存配置</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-form :model="form" label-width="140px" v-loading="loading">
|
|
|
+ <el-form-item label="商户号ID">
|
|
|
+ <el-input v-model="form.mchId" placeholder="请输入微信支付商户号(MCHID)" style="width: 400px" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="商户号API密钥">
|
|
|
+ <el-input v-model="form.apiV3Key" placeholder="请输入微信支付商户API密钥(APIv3密钥)"
|
|
|
+ type="password" show-password style="width: 400px" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="支付证书">
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ action="#"
|
|
|
+ :auto-upload="false"
|
|
|
+ :show-file-list="false"
|
|
|
+ accept=".pem"
|
|
|
+ :on-change="handleCertChange"
|
|
|
+ >
|
|
|
+ <el-button type="primary">上传证书文件</el-button>
|
|
|
+ </el-upload>
|
|
|
+ <div class="tip-text">微信支付证书(apiclient_cert.pem),前往微信商家平台下载</div>
|
|
|
+ <div v-if="form.certUploaded" class="success-text">✓ 证书已上传</div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="商户私钥">
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ action="#"
|
|
|
+ :auto-upload="false"
|
|
|
+ :show-file-list="false"
|
|
|
+ accept=".pem"
|
|
|
+ :on-change="handlePrivateKeyChange"
|
|
|
+ >
|
|
|
+ <el-button type="primary">上传私钥文件</el-button>
|
|
|
+ </el-upload>
|
|
|
+ <div class="tip-text">微信支付证书私钥(apiclient_key.pem),前往微信商家平台下载</div>
|
|
|
+ <div v-if="form.privateKeyUploaded" class="success-text">✓ 私钥已上传</div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-divider content-position="left">微信支付公钥配置(新商户必填)</el-divider>
|
|
|
+
|
|
|
+ <el-form-item label="公钥ID">
|
|
|
+ <el-input v-model="form.publicKeyId" placeholder="请输入微信支付公钥ID,如:PUB_KEY_ID_xxx" style="width: 400px" />
|
|
|
+ <div class="tip-text">从微信商户平台 → API安全 → 申请微信支付公钥 获取</div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="微信支付公钥">
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ action="#"
|
|
|
+ :auto-upload="false"
|
|
|
+ :show-file-list="false"
|
|
|
+ accept=".pem"
|
|
|
+ :on-change="handlePublicKeyChange"
|
|
|
+ >
|
|
|
+ <el-button type="primary">上传公钥文件</el-button>
|
|
|
+ </el-upload>
|
|
|
+ <div class="tip-text">微信支付公钥(pub_key.pem),从微信商户平台 → API安全 下载</div>
|
|
|
+ <div v-if="form.publicKeyUploaded" class="success-text">✓ 公钥已上传</div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-divider content-position="left">回调配置</el-divider>
|
|
|
+
|
|
|
+ <el-form-item label="API回调地址">
|
|
|
+ <el-input v-model="form.notifyUrl" placeholder="请输入支付回调地址,如:https://域名/v1/order/notify" style="width: 400px" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import request from '@/utils/request'
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
+const saving = ref(false)
|
|
|
+const privateKeyFile = ref<File | null>(null)
|
|
|
+const certFile = ref<File | null>(null)
|
|
|
+const publicKeyFile = ref<File | null>(null)
|
|
|
+
|
|
|
+const form = ref({
|
|
|
+ mchId: '',
|
|
|
+ apiV3Key: '',
|
|
|
+ notifyUrl: '',
|
|
|
+ privateKeyUploaded: false,
|
|
|
+ certUploaded: false,
|
|
|
+ publicKeyId: '',
|
|
|
+ publicKeyUploaded: false
|
|
|
+})
|
|
|
+
|
|
|
+const handlePrivateKeyChange = (file: any) => {
|
|
|
+ privateKeyFile.value = file.raw
|
|
|
+ ElMessage.success('私钥文件已选择,保存时将一并上传')
|
|
|
+}
|
|
|
+
|
|
|
+const handleCertChange = (file: any) => {
|
|
|
+ certFile.value = file.raw
|
|
|
+ ElMessage.success('证书文件已选择,保存时将一并上传')
|
|
|
+}
|
|
|
+
|
|
|
+const handlePublicKeyChange = (file: any) => {
|
|
|
+ publicKeyFile.value = file.raw
|
|
|
+ ElMessage.success('公钥文件已选择,保存时将一并上传')
|
|
|
+}
|
|
|
+
|
|
|
+const getConfig = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await request.get('/miniapp/paymentConfig/list')
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ form.value.mchId = res.data.mchId || ''
|
|
|
+ form.value.apiV3Key = res.data.apiV3Key || ''
|
|
|
+ form.value.notifyUrl = res.data.notifyUrl || ''
|
|
|
+ form.value.privateKeyUploaded = res.data.privateKeyUploaded || false
|
|
|
+ form.value.certUploaded = res.data.certUploaded || false
|
|
|
+ form.value.publicKeyId = res.data.publicKeyId || ''
|
|
|
+ form.value.publicKeyUploaded = res.data.publicKeyUploaded || false
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取配置失败', e)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleSave = async () => {
|
|
|
+ saving.value = true
|
|
|
+ try {
|
|
|
+ // 上传私钥
|
|
|
+ if (privateKeyFile.value) {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('file', privateKeyFile.value)
|
|
|
+ const uploadRes = await request.post('/miniapp/paymentConfig/uploadPrivateKey', formData, {
|
|
|
+ headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
+ })
|
|
|
+ if (uploadRes.code !== 200) {
|
|
|
+ ElMessage.error('私钥上传失败:' + uploadRes.msg)
|
|
|
+ saving.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+ form.value.privateKeyUploaded = true
|
|
|
+ privateKeyFile.value = null
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上传证书
|
|
|
+ if (certFile.value) {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('file', certFile.value)
|
|
|
+ const uploadRes = await request.post('/miniapp/paymentConfig/uploadCert', formData, {
|
|
|
+ headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
+ })
|
|
|
+ if (uploadRes.code !== 200) {
|
|
|
+ ElMessage.error('证书上传失败:' + uploadRes.msg)
|
|
|
+ saving.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+ form.value.certUploaded = true
|
|
|
+ certFile.value = null
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上传公钥
|
|
|
+ if (publicKeyFile.value) {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('file', publicKeyFile.value)
|
|
|
+ const uploadRes = await request.post('/miniapp/paymentConfig/uploadPublicKey', formData, {
|
|
|
+ headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
+ })
|
|
|
+ if (uploadRes.code !== 200) {
|
|
|
+ ElMessage.error('公钥上传失败:' + uploadRes.msg)
|
|
|
+ saving.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+ form.value.publicKeyUploaded = true
|
|
|
+ publicKeyFile.value = null
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await request.put('/miniapp/paymentConfig/wxpay', {
|
|
|
+ mchId: form.value.mchId,
|
|
|
+ apiV3Key: form.value.apiV3Key,
|
|
|
+ notifyUrl: form.value.notifyUrl,
|
|
|
+ publicKeyId: form.value.publicKeyId
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ ElMessage.success('保存成功')
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.msg || '保存失败')
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ ElMessage.error('保存失败')
|
|
|
+ } finally {
|
|
|
+ saving.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getConfig()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.tip-text {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: 4px;
|
|
|
+}
|
|
|
+.success-text {
|
|
|
+ color: #67c23a;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: 4px;
|
|
|
+}
|
|
|
+</style>
|