From 29d61beb1113605a6890844ae40fc14e77ca233a Mon Sep 17 00:00:00 2001
From: YunaiV <zhijiantianya@gmail.com>
Date: Fri, 21 Jul 2023 13:49:42 +0800
Subject: [PATCH 1/2] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E7=AE=80?=
 =?UTF-8?q?=E5=8C=96=E6=94=AF=E4=BB=98=E5=AE=9D=E6=94=AF=E4=BB=98=E7=9A=84?=
 =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=95=8C=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../pay/app/components/aliPayChannelForm.vue  | 289 ------------------
 .../pay/app/components/alipayChannelForm.vue  | 268 ++++++++++++++++
 yudao-ui-admin/src/views/pay/app/index.vue    |  25 +-
 3 files changed, 276 insertions(+), 306 deletions(-)
 delete mode 100644 yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue
 create mode 100644 yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue

diff --git a/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue
deleted file mode 100644
index 76b047490..000000000
--- a/yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue
+++ /dev/null
@@ -1,289 +0,0 @@
-<template>
-  <div>
-    <el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px">
-      <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px"
-               v-loading="transferParam.loading">
-        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
-          <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
-            <template slot="append">%</template>
-          </el-input>
-        </el-form-item>
-        <el-form-item label-width="180px" label="开放平台 APPID" prop="aliPayConfig.appId">
-          <el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}">
-          </el-input>
-        </el-form-item>
-        <el-form-item label-width="180px" label="渠道状态" prop="status">
-          <el-radio-group v-model="form.status" size="medium">
-            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
-              {{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl">
-          <el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium">
-            <el-radio label="https://openapi.alipay.com/gateway.do">线上环境</el-radio>
-            <el-radio label="https://openapi-sandbox.dl.alipaydev.com/gateway.do">沙箱环境</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType">
-          <el-radio-group v-model="form.aliPayConfig.signType" size="medium">
-            <el-radio key="RSA2" label="RSA2">RSA2</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode">
-          <el-radio-group v-model="form.aliPayConfig.mode" size="medium">
-            <el-radio  key="公钥模式" :label="1">公钥模式</el-radio>
-            <el-radio  key="证书模式" :label="2">证书模式</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <div v-if="form.aliPayConfig.mode === 1">
-          <el-form-item label-width="180px" label="应用私钥" prop="aliPayConfig.privateKey">
-            <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
-                      placeholder="请输入应用私钥" clearable :style="{width: '100%'}">
-            </el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="支付宝公钥" prop="aliPayConfig.alipayPublicKey">
-            <el-input
-              type="textarea"
-              :autosize="{minRows: 8, maxRows: 8}"
-              v-model="form.aliPayConfig.alipayPublicKey"
-              placeholder="请输入支付宝公钥" clearable
-              :style="{width: '100%'}">
-            </el-input>
-          </el-form-item>
-        </div>
-        <div v-if="form.aliPayConfig.mode === 2">
-          <el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent">
-            <el-input v-model="form.aliPayConfig.appCertContent" type="textarea"
-                      placeholder="请上传商户公钥应用证书"
-                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="">
-            <el-upload
-              action=""
-              ref="privateKeyContentFile"
-              :limit="1"
-              :accept="fileAccept"
-              :http-request="appCertUpload"
-              :before-upload="fileBeforeUpload">
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-          <el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent">
-            <el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea"
-                      placeholder="请上传支付宝公钥证书"
-                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="">
-            <el-upload
-              ref="privateCertContentFile"
-              action=""
-              :limit="1"
-              :accept="fileAccept"
-              :before-upload="fileBeforeUpload"
-              :http-request="alipayPublicCertUpload">
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-          <el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent">
-            <el-input
-              v-model="form.aliPayConfig.rootCertContent"
-              type="textarea"
-              placeholder="请上传根证书"
-              readonly :autosize="{minRows: 8, maxRows: 8}"
-              :style="{width: '100%'}">
-            </el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="">
-            <el-upload
-              ref="privateCertContentFile"
-              :limit="1"
-              :accept="fileAccept"
-              action=""
-              :before-upload="fileBeforeUpload"
-              :http-request="rootCertUpload">
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-        </div>
-        <el-form-item label-width="180px" label="备注" prop="remark">
-          <el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button @click="close">取消</el-button>
-        <el-button type="primary" @click="handleConfirm">确定</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-<script>
-import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
-
-const defaultForm = {
-  code: '',
-  status: null,
-  remark: '',
-  feeRate: null,
-  appId: '',
-  aliPayConfig: {
-    appId: '',
-    serverUrl: null,
-    signType: '',
-    mode: null,
-    privateKey: '',
-    alipayPublicKey: '',
-    appCertContent: '',
-    alipayPublicCertContent: '',
-    rootCertContent: ''
-  }
-};
-
-export default {
-  name: "aliPayChannelForm",
-  components: {},
-  props: {
-    // 传输的参数
-    transferParam: {
-      // 加载动画
-      "loading": false,
-      // 是否修改
-      "edit": false,
-      // 是否显示
-      "aliPayOpen": false,
-      // 应用ID
-      "appId": null,
-      // 渠道编码
-      "payCode": null,
-    }
-  },
-  data() {
-    return {
-      title:'',
-      form: JSON.parse(JSON.stringify(defaultForm)),
-      rules: {
-        feeRate: [{ required: true,  message: '请输入渠道费率', trigger: 'blur' }],
-        status: [{ required: true,  message: '渠道状态不能为空',  trigger: 'blur' }],
-        'aliPayConfig.appId': [{ required: true, message: '请输入开放平台上创建的应用的 ID', trigger: 'blur' }],
-        'aliPayConfig.serverUrl': [{ required: true, message: '请传入网关地址', trigger: 'blur' }],
-        'aliPayConfig.signType': [{ required: true, message: '请传入签名算法类型', trigger: 'blur' }],
-        'aliPayConfig.mode': [{ required: true, message: '公钥类型不能为空', trigger: 'blur'}],
-        'aliPayConfig.privateKey': [{ required: true, message: '请输入商户私钥', trigger: 'blur' }],
-        'aliPayConfig.alipayPublicKey': [{ required: true, message: '请输入支付宝公钥字符串', trigger: 'blur' }],
-        'aliPayConfig.appCertContent': [{ required: true,  message: '请上传商户公钥应用证书', trigger: 'blur' }],
-        'aliPayConfig.alipayPublicCertContent': [{ required: true, message: '请上传支付宝公钥证书', trigger: 'blur'}],
-        'aliPayConfig.rootCertContent': [{ required: true, message: '请上传指定根证书', trigger: 'blur' }],
-      },
-      fileAccept: ".crt",
-    }
-  },
-  watch: {
-    transferParam: {
-      deep: true,  // 深度监听
-      handler(newVal) {
-        if (newVal.aliPayOpen) {
-          this.form.code = newVal.payCode;
-          this.form.appId = newVal.appId;
-          // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
-          if (newVal.edit === true && newVal.loading) {
-            this.title = "编辑支付渠道";
-            this.init();
-          } else {
-            this.title = "创建支付渠道";
-          }
-        }
-      }
-    }
-  },
-  methods: {
-    init() {
-      getChannel(this.transferParam.appId, this.transferParam.payCode)
-        .then(response => {
-          this.form.id = response.data.id;
-          this.form.feeRate = response.data.feeRate;
-          this.form.status = response.data.status;
-          this.form.remark = response.data.remark;
-
-          let config = JSON.parse(response.data.config);
-          this.form.aliPayConfig.appId = config.appId;
-          this.form.aliPayConfig.serverUrl = config.serverUrl;
-          this.form.aliPayConfig.signType = config.signType;
-          this.form.aliPayConfig.mode = config.mode;
-          this.form.aliPayConfig.privateKey = config.privateKey;
-          this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey;
-          this.form.aliPayConfig.appCertContent = config.appCertContent;
-          this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent;
-          this.form.aliPayConfig.rootCertContent = config.rootCertContent;
-          this.transferParam.loading = false;
-        })
-    },
-    close() {
-      this.transferParam.aliPayOpen = false;
-      this.form = JSON.parse(JSON.stringify(defaultForm));
-    },
-    handleConfirm() {
-      this.$refs['aliPayForm'].validate(valid => {
-        if (!valid) {
-          return
-        }
-        let data = this.form;
-        data.config = JSON.stringify(this.form.aliPayConfig);
-        if (this.transferParam.edit) {
-          updateChannel(data).then(response => {
-            if (response.code === 0) {
-              this.$modal.msgSuccess("修改成功");
-              this.close();
-            }
-          })
-        } else {
-          createChannel(data).then(response => {
-            if (response.code === 0) {
-              this.$modal.msgSuccess("新增成功");
-              this.$parent.refreshTable();
-              this.close();
-            }
-          });
-        }
-      });
-    },
-    fileBeforeUpload(file) {
-      let format = '.' + file.name.split(".")[1];
-      if (format !== this.fileAccept) {
-        this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
-        return false;
-      }
-      let isRightSize = file.size / 1024 / 1024 < 2
-      if (!isRightSize) {
-        this.$message.error('文件大小超过 2MB')
-      }
-      return isRightSize
-    },
-    appCertUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.aliPayConfig.appCertContent = e.target.result
-      }
-      readFile.readAsText(event.file);
-    },
-    alipayPublicCertUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.aliPayConfig.alipayPublicCertContent = e.target.result
-      }
-      readFile.readAsText(event.file);
-    },
-    rootCertUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.aliPayConfig.rootCertContent = e.target.result
-      }
-      readFile.readAsText(event.file);
-    },
-
-  }
-}
-
-</script>
-<style scoped>
-
-</style>
diff --git a/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
new file mode 100644
index 000000000..1043c414a
--- /dev/null
+++ b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
@@ -0,0 +1,268 @@
+<template>
+  <div>
+    <el-dialog :visible.sync="dialogVisible" :title="title" @closed="close" append-to-body width="800px">
+      <el-form ref="form" :model="formData" :rules="rules" size="medium" label-width="100px" v-loading="formLoading">
+        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
+          <el-input v-model="formData.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
+            <template slot="append">%</template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label-width="180px" label="开放平台 APPID" prop="config.appId">
+          <el-input v-model="formData.config.appId" placeholder="请输入开放平台 APPID" clearable :style="{width: '100%'}">
+          </el-input>
+        </el-form-item>
+        <el-form-item label-width="180px" label="渠道状态" prop="status">
+          <el-radio-group v-model="formData.status" size="medium">
+            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)"
+                      :label="parseInt(dict.value)">
+              {{ dict.label }}
+            </el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label-width="180px" label="网关地址" prop="config.serverUrl">
+          <el-radio-group v-model="formData.config.serverUrl" size="medium">
+            <el-radio label="https://openapi.alipay.com/gateway.do">线上环境</el-radio>
+            <el-radio label="https://openapi-sandbox.dl.alipaydev.com/gateway.do">沙箱环境</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label-width="180px" label="算法类型" prop="config.signType">
+          <el-radio-group v-model="formData.config.signType" size="medium">
+            <el-radio key="RSA2" label="RSA2">RSA2</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label-width="180px" label="公钥类型" prop="config.mode">
+          <el-radio-group v-model="formData.config.mode" size="medium">
+            <el-radio  key="公钥模式" :label="1">公钥模式</el-radio>
+            <el-radio  key="证书模式" :label="2">证书模式</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <div v-if="formData.config.mode === 1">
+          <el-form-item label-width="180px" label="应用私钥" prop="config.privateKey">
+            <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="formData.config.privateKey"
+                      placeholder="请输入应用私钥" clearable :style="{width: '100%'}">
+            </el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="支付宝公钥" prop="config.alipayPublicKey">
+            <el-input
+              type="textarea"
+              :autosize="{minRows: 8, maxRows: 8}"
+              v-model="formData.config.alipayPublicKey"
+              placeholder="请输入支付宝公钥" clearable
+              :style="{width: '100%'}">
+            </el-input>
+          </el-form-item>
+        </div>
+        <div v-if="formData.config.mode === 2">
+          <el-form-item label-width="180px" label="商户公钥应用证书" prop="config.appCertContent">
+            <el-input v-model="formData.config.appCertContent" type="textarea"
+                      placeholder="请上传商户公钥应用证书"
+                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="">
+            <el-upload
+              action=""
+              ref="privateKeyContentFile"
+              :limit="1"
+              :accept="fileAccept"
+              :http-request="appCertUpload"
+              :before-upload="fileBeforeUpload">
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label-width="180px" label="支付宝公钥证书" prop="config.alipayPublicCertContent">
+            <el-input v-model="formData.config.alipayPublicCertContent" type="textarea"
+                      placeholder="请上传支付宝公钥证书"
+                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="">
+            <el-upload
+              ref="privateCertContentFile"
+              action=""
+              :limit="1"
+              :accept="fileAccept"
+              :before-upload="fileBeforeUpload"
+              :http-request="alipayPublicCertUpload">
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label-width="180px" label="根证书" prop="config.rootCertContent">
+            <el-input
+              v-model="formData.config.rootCertContent"
+              type="textarea"
+              placeholder="请上传根证书"
+              readonly :autosize="{minRows: 8, maxRows: 8}"
+              :style="{width: '100%'}">
+            </el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="">
+            <el-upload
+              ref="privateCertContentFile"
+              :limit="1"
+              :accept="fileAccept"
+              action=""
+              :before-upload="fileBeforeUpload"
+              :http-request="rootCertUpload">
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+        </div>
+        <el-form-item label-width="180px" label="备注" prop="remark">
+          <el-input v-model="formData.remark" :style="{width: '100%'}"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取消</el-button>
+        <el-button type="primary" @click="submitForm">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { createChannel, getChannel, updateChannel } from "@/api/pay/channel";
+import { CommonStatusEnum } from "@/utils/constants";
+
+export default {
+  name: "alipayChannelForm",
+  data() {
+    return {
+      dialogVisible: false,
+      formLoading: false,
+      title:'',
+      formData: {
+        appId: '',
+        code: '',
+        status: undefined,
+        feeRate: undefined,
+        remark: '',
+        config: {
+          appId: '',
+          serverUrl: null,
+          signType: '',
+          mode: null,
+          privateKey: '',
+          alipayPublicKey: '',
+          appCertContent: '',
+          alipayPublicCertContent: '',
+          rootCertContent: ''
+        }
+      },
+      rules: {
+        feeRate: [{ required: true,  message: '请输入渠道费率', trigger: 'blur' }],
+        status: [{ required: true,  message: '渠道状态不能为空',  trigger: 'blur' }],
+        'config.appId': [{ required: true, message: '请输入开放平台上创建的应用的 ID', trigger: 'blur' }],
+        'config.serverUrl': [{ required: true, message: '请传入网关地址', trigger: 'blur' }],
+        'config.signType': [{ required: true, message: '请传入签名算法类型', trigger: 'blur' }],
+        'config.mode': [{ required: true, message: '公钥类型不能为空', trigger: 'blur'}],
+        'config.privateKey': [{ required: true, message: '请输入商户私钥', trigger: 'blur' }],
+        'config.alipayPublicKey': [{ required: true, message: '请输入支付宝公钥字符串', trigger: 'blur' }],
+        'config.appCertContent': [{ required: true,  message: '请上传商户公钥应用证书', trigger: 'blur' }],
+        'config.alipayPublicCertContent': [{ required: true, message: '请上传支付宝公钥证书', trigger: 'blur'}],
+        'config.rootCertContent': [{ required: true, message: '请上传指定根证书', trigger: 'blur' }],
+      },
+      fileAccept: ".crt",
+    }
+  },
+  methods: {
+    open(appId, code) {
+      this.dialogVisible = true;
+      this.formLoading = true;
+      this.reset(appId, code);
+      getChannel(appId, code).then(response => {
+        if (response.data && response.data.id) {
+          this.formData = response.data;
+          this.formData.config = JSON.parse(response.data.config);
+        }
+        this.title = this.formData.id ? '创建支付渠道' : '编辑支付渠道'
+      }).finally(() => {
+        this.formLoading = false;
+      });
+    },
+    close() {
+      this.dialogVisible = false;
+      this.reset(undefined, undefined);
+    },
+    submitForm() {
+      this.$refs['form'].validate(valid => {
+        if (!valid) {
+          return
+        }
+        const data = { ...this.formData };
+        data.config = JSON.stringify(this.formData.config);
+        if (!data.id) {
+          createChannel(data).then(response => {
+            this.$modal.msgSuccess("新增成功");
+            this.$emit('success')
+            this.close();
+          });
+        } else {
+          updateChannel(data).then(response => {
+            this.$modal.msgSuccess("修改成功");
+            this.$emit('success')
+            this.close();
+          })
+        }
+      });
+    },
+    /** 重置表单 */
+    reset(appId, code) {
+      this.formData = {
+        appId: appId,
+        code: code,
+        status: CommonStatusEnum.ENABLE,
+        remark: '',
+        feeRate: null,
+        config: {
+          appId: '',
+          serverUrl: null,
+          signType: 'RSA2',
+          mode: null,
+          privateKey: '',
+          alipayPublicKey: '',
+          appCertContent: '',
+          alipayPublicCertContent: '',
+          rootCertContent: ''
+        }
+      }
+      this.resetForm('form')
+    },
+    fileBeforeUpload(file) {
+      let format = '.' + file.name.split(".")[1];
+      if (format !== this.fileAccept) {
+        this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
+        return false;
+      }
+      let isRightSize = file.size / 1024 / 1024 < 2
+      if (!isRightSize) {
+        this.$message.error('文件大小超过 2MB')
+      }
+      return isRightSize
+    },
+    appCertUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.appCertContent = e.target.result
+      }
+      readFile.readAsText(event.file);
+    },
+    alipayPublicCertUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.alipayPublicCertContent = e.target.result
+      }
+      readFile.readAsText(event.file);
+    },
+    rootCertUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.rootCertContent = e.target.result
+      }
+      readFile.readAsText(event.file);
+    },
+
+  }
+}
+
+</script>
+<style scoped>
+
+</style>
diff --git a/yudao-ui-admin/src/views/pay/app/index.vue b/yudao-ui-admin/src/views/pay/app/index.vue
index d280321a3..3a038f8be 100644
--- a/yudao-ui-admin/src/views/pay/app/index.vue
+++ b/yudao-ui-admin/src/views/pay/app/index.vue
@@ -216,7 +216,7 @@
 
     <!-- 弹窗 -->
     <wechat-channel-form :transferParam="channelParam" />
-    <ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form>
+    <alipay-channel-form ref="alipayChannelFormRef" @success="getList" />
   </div>
 </template>
 
@@ -225,13 +225,13 @@ import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage }
 import { DICT_TYPE, getDictDatas } from "@/utils/dict";
 import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants";
 import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
-import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm";
+import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm";
 
 export default {
   name: "PayApp",
   components: {
     "wechatChannelForm": wechatChannelForm,
-    "aliPayChannelForm": aliPayChannelForm
+    "alipayChannelForm": alipayChannelForm
   },
   data() {
     return {
@@ -285,13 +285,6 @@ export default {
         "appId": null,
         // 渠道编码
         "payCode": null,
-        // 商户对象
-        "payMerchant": {
-          // 编号
-          "id": null,
-          // 名称
-          "name": null
-        },
       }
     };
   },
@@ -426,14 +419,12 @@ export default {
         this.channelParam.aliPayOpen = false;
       }
       if (type === PayType.ALIPAY) {
-        this.channelParam.aliPayOpen = true;
-        this.channelParam.wechatOpen = false;
+        console.log(this.$refs['alipayChannelFormRef'])
+        this.$refs['alipayChannelFormRef'].open(row.id, payCode);
+        return;
+        // this.channelParam.aliPayOpen = true;
+        // this.channelParam.wechatOpen = false;
       }
-      this.channelParam.edit = false;
-      this.channelParam.loading = false;
-      this.channelParam.appId = row.id;
-      this.channelParam.payCode = payCode;
-      this.channelParam.payMerchant = row.payMerchant;
     },
     /**
      * 根据渠道编码判断渠道列表中是否存在

From f92a5899f3bb9e7ee53cc002a10909467b31f5e8 Mon Sep 17 00:00:00 2001
From: YunaiV <zhijiantianya@gmail.com>
Date: Fri, 21 Jul 2023 21:50:05 +0800
Subject: [PATCH 2/2] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E7=AE=80?=
 =?UTF-8?q?=E5=8C=96=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98=E7=9A=84=E9=85=8D?=
 =?UTF-8?q?=E7=BD=AE=E7=95=8C=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 yudao-ui-admin/src/utils/constants.js         |   8 -
 .../pay/app/components/alipayChannelForm.vue  |   9 +-
 .../pay/app/components/wechatChannelForm.vue  | 328 ------------------
 .../pay/app/components/weixinChannelForm.vue  | 257 ++++++++++++++
 yudao-ui-admin/src/views/pay/app/index.vue    | 167 ++++-----
 5 files changed, 318 insertions(+), 451 deletions(-)
 delete mode 100644 yudao-ui-admin/src/views/pay/app/components/wechatChannelForm.vue
 create mode 100644 yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue

diff --git a/yudao-ui-admin/src/utils/constants.js b/yudao-ui-admin/src/utils/constants.js
index 70e0f5a02..a4805096d 100644
--- a/yudao-ui-admin/src/utils/constants.js
+++ b/yudao-ui-admin/src/utils/constants.js
@@ -180,14 +180,6 @@ export const PayDisplayModeEnum = {
   }
 }
 
-/**
- * 支付类型枚举
- */
-export const PayType = {
-  WECHAT: "WECHAT",
-  ALIPAY: "ALIPAY"
-}
-
 /**
  * 支付订单状态枚举
  */
diff --git a/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
index 1043c414a..cb67b9d76 100644
--- a/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
+++ b/yudao-ui-admin/src/views/pay/app/components/alipayChannelForm.vue
@@ -172,7 +172,7 @@ export default {
           this.formData = response.data;
           this.formData.config = JSON.parse(response.data.config);
         }
-        this.title = this.formData.id ? '创建支付渠道' : '编辑支付渠道'
+        this.title = !this.formData.id ? '创建支付渠道' : '编辑支付渠道'
       }).finally(() => {
         this.formLoading = false;
       });
@@ -257,12 +257,7 @@ export default {
         this.formData.config.rootCertContent = e.target.result
       }
       readFile.readAsText(event.file);
-    },
-
+    }
   }
 }
-
 </script>
-<style scoped>
-
-</style>
diff --git a/yudao-ui-admin/src/views/pay/app/components/wechatChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/wechatChannelForm.vue
deleted file mode 100644
index c3e691f9f..000000000
--- a/yudao-ui-admin/src/views/pay/app/components/wechatChannelForm.vue
+++ /dev/null
@@ -1,328 +0,0 @@
-<template>
-  <div>
-    <el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
-      <el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="120px"
-               v-loading="transferParam.loading">
-        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
-          <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
-            <template slot="append">%</template>
-          </el-input>
-        </el-form-item>
-        <el-form-item label-width="180px" label="公众号 APPID" prop="weChatConfig.appId">
-          <el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号 APPID" clearable :style="{width: '100%'}">
-          </el-input>
-        </el-form-item>
-        <el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId">
-          <el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input>
-        </el-form-item>
-        <el-form-item label-width="180px" label="渠道状态" prop="status">
-          <el-radio-group v-model="form.status" size="medium">
-            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
-              {{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
-          <el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
-            <el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
-              {{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <div v-if="form.weChatConfig.apiVersion === 'v2'">
-          <el-form-item label-width="180px" label="商户密钥" prop="weChatConfig.mchKey">
-            <el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户密钥" clearable
-                      :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="apiclient_cert.p12 证书" prop="weChatConfig.keyContent">
-            <el-input v-model="form.weChatConfig.keyContent" type="textarea"
-                      placeholder="请上传 apiclient_cert.p12 证书"
-                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="">
-            <el-upload :limit="1" accept=".p12" action=""
-                       :before-upload="p12FileBeforeUpload"
-                       :http-request="keyContentUpload">
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-        </div>
-        <div v-if="form.weChatConfig.apiVersion === 'v3'">
-          <el-form-item label-width="180px" label="API V3 密钥" prop="weChatConfig.apiV3Key">
-            <el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入 API V3 密钥" clearable
-                      :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="apiclient_key.perm 证书" prop="weChatConfig.privateKeyContent">
-            <el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
-                      placeholder="请上传 apiclient_key.perm 证书"
-                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="" prop="privateKeyContentFile">
-            <el-upload ref="privateKeyContentFile"
-                       :limit="1"
-                       accept=".pem"
-                       action=""
-                       :before-upload="pemFileBeforeUpload"
-                       :http-request="privateKeyContentUpload"
-            >
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-          <el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent">
-            <el-input v-model="form.weChatConfig.privateCertContent" type="textarea"
-                      placeholder="请上传apiclient_cert.perm证书"
-                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
-          </el-form-item>
-          <el-form-item label-width="180px" label="" prop="privateCertContentFile">
-            <el-upload ref="privateCertContentFile"
-                       :limit="1"
-                       accept=".pem"
-                       action=""
-                       :before-upload="pemFileBeforeUpload"
-                       :http-request="privateCertContentUpload"
-            >
-              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
-            </el-upload>
-          </el-form-item>
-        </div>
-        <el-form-item label-width="180px" label="备注" prop="remark">
-          <el-input v-model="form.remark" :style="{width: '100%'}" />
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button @click="close">取消</el-button>
-        <el-button type="primary" @click="handleConfirm">确定</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-<script>
-import {DICT_TYPE, getDictDatas} from "@/utils/dict";
-import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
-
-const defaultForm = {
-  code: '',
-  status: null,
-  remark: '',
-  feeRate: null,
-  appId: '',
-  weChatConfig: {
-    appId: '',
-    mchId: '',
-    apiVersion: '',
-    mchKey: '',
-    keyContent: '',
-    privateKeyContent: '',
-    privateCertContent: '',
-    apiV3Key:'',
-  }
-}
-
-export default {
-  name: "wechatChannelForm",
-  components: {},
-  props: {
-    // 传输的参数
-    transferParam: {
-      // 加载动画
-      "loading": false,
-      // 是否修改
-      "edit": false,
-      // 是否显示
-      "wechatOpen": false,
-      // 应用ID
-      "appId": null,
-      // 渠道编码
-      "payCode": null,
-    }
-  },
-  data() {
-    return {
-      title:'',
-      form: JSON.parse(JSON.stringify(defaultForm)),
-      rules: {
-        feeRate: [{
-          required: true,
-          message: '请输入渠道费率',
-          trigger: 'blur'
-        }],
-        'weChatConfig.mchId': [{
-          required: true,
-          message: '请传入商户号',
-          trigger: 'blur'
-        }],
-        'weChatConfig.appId': [{
-          required: true,
-          message: '请输入公众号APPID',
-          trigger: 'blur'
-        }],
-        status: [{
-          required: true,
-          message: '渠道状态不能为空',
-          trigger: 'blur'
-        }],
-        'weChatConfig.apiVersion': [{
-          required: true,
-          message: 'API版本不能为空',
-          trigger: 'blur'
-        }],
-        'weChatConfig.mchKey': [{
-          required: true,
-          message: '请输入商户密钥',
-          trigger: 'blur'
-        }],
-        'weChatConfig.keyContent': [{
-          required: true,
-          message: '请上传 apiclient_cert.p12 证书',
-          trigger: 'blur'
-        }],
-        'weChatConfig.privateKeyContent': [{
-          required: true,
-          message: '请上传 apiclient_key.perm 证书',
-          trigger: 'blur'
-        }],
-        'weChatConfig.privateCertContent': [{
-          required: true,
-          message: '请上传 apiclient_cert.perm证 书',
-          trigger: 'blur'
-        }],
-        'weChatConfig.apiV3Key': [{
-          required: true,
-          message: '请上传 api V3 密钥值',
-          trigger: 'blur'
-        }],
-      },
-      // 渠道状态 数据字典
-      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
-      versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
-    }
-  },
-  watch: {
-    transferParam: {
-      deep: true,  // 深度监听
-      handler(newVal) {
-        if (newVal.wechatOpen) {
-          this.form.code = newVal.payCode;
-          this.form.appId = newVal.appId;
-          // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
-          if (newVal.edit && newVal.loading) {
-            this.title = "编辑支付渠道";
-            this.init();
-          } else {
-            this.title = "创建支付渠道";
-          }
-        }
-      }
-    }
-  },
-  methods: {
-    init() {
-      getChannel(this.transferParam.appId, this.transferParam.payCode)
-        .then(response => {
-          this.form.id = response.data.id;
-          this.form.feeRate = response.data.feeRate;
-          this.form.appId = response.data.appId;
-          this.form.status = response.data.status;
-          this.form.remark = response.data.remark;
-
-          let config = JSON.parse(response.data.config);
-          this.form.weChatConfig.appId = config.appId;
-          this.form.weChatConfig.apiVersion = config.apiVersion;
-          this.form.weChatConfig.mchId = config.mchId;
-          this.form.weChatConfig.mchKey = config.mchKey;
-          this.form.weChatConfig.keyContent = config.keyContent;
-          this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
-          this.form.weChatConfig.privateCertContent = config.privateCertContent;
-          this.form.weChatConfig.apiV3Key = config.apiV3Key;
-          this.transferParam.loading = false;
-        })
-    },
-    close() {
-      this.transferParam.wechatOpen = false;
-      this.form = JSON.parse(JSON.stringify(defaultForm));
-    },
-    handleConfirm() {
-      this.$refs['wechatJsApiForm'].validate(valid => {
-        if (!valid) {
-          return
-        }
-        let data = this.form;
-        data.config = JSON.stringify(this.form.weChatConfig);
-        if (this.transferParam.edit) {
-          updateChannel(data).then(response => {
-            if (response.code === 0) {
-              this.$modal.msgSuccess("修改成功");
-              this.close();
-            }
-          })
-        } else {
-
-          createChannel(data).then(response => {
-            if (response.code === 0) {
-              this.$modal.msgSuccess("新增成功");
-              this.$parent.refreshTable();
-              this.close();
-            }
-          });
-        }
-      });
-    },
-    /**
-     * apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
-     */
-    fileBeforeUpload(file, fileAccept) {
-      let format = '.' + file.name.split(".")[1];
-      if (format !== fileAccept) {
-        debugger
-        this.$message.error('请上传指定格式"' + fileAccept + '"文件');
-        return false;
-      }
-      let isRightSize = file.size / 1024 / 1024 < 2
-      if (!isRightSize) {
-        this.$message.error('文件大小超过 2MB')
-      }
-      return isRightSize
-    },
-    p12FileBeforeUpload(file) {
-      this.fileBeforeUpload(file, '.p12')
-    },
-    pemFileBeforeUpload(file) {
-      this.fileBeforeUpload(file, '.pem')
-    },
-    /**
-     * 读取 apiclient_key.pem 到 privateKeyContent 字段
-     */
-    privateKeyContentUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.weChatConfig.privateKeyContent = e.target.result
-      }
-      readFile.readAsText(event.file);
-    },
-    /**
-     * 读取 apiclient_cert.pem 到 privateCertContent 字段
-     */
-    privateCertContentUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.weChatConfig.privateCertContent = e.target.result
-      }
-      readFile.readAsText(event.file);
-    },
-    /**
-     * 读取 apiclient_cert.p12 到 keyContent 字段
-     */
-    keyContentUpload(event) {
-      const readFile = new FileReader()
-      readFile.onload = (e) => {
-        this.form.weChatConfig.keyContent = e.target.result.split(',')[1]
-      }
-      readFile.readAsDataURL(event.file); // 读成 base64
-    }
-  }
-}
-
-</script>
-<style scoped>
-
-</style>
diff --git a/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue
new file mode 100644
index 000000000..00e0773b5
--- /dev/null
+++ b/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue
@@ -0,0 +1,257 @@
+<template>
+  <div>
+    <el-dialog :visible.sync="dialogVisible" :title="title" @close="close" append-to-body width="800px">
+      <el-form ref="form" :model="formData" :rules="rules" size="medium" label-width="120px"
+               v-loading="formLoading">
+        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
+          <el-input v-model="formData.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
+            <template slot="append">%</template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label-width="180px" label="公众号 APPID" prop="config.appId">
+          <el-input v-model="formData.config.appId" placeholder="请输入公众号 APPID" clearable :style="{width: '100%'}">
+          </el-input>
+        </el-form-item>
+        <el-form-item label-width="180px" label="商户号" prop="config.mchId">
+          <el-input v-model="formData.config.mchId" :style="{width: '100%'}"></el-input>
+        </el-form-item>
+        <el-form-item label-width="180px" label="渠道状态" prop="status">
+          <el-radio-group v-model="formData.status" size="medium">
+            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)"
+                      :label="parseInt(dict.value)">
+              {{ dict.label }}
+            </el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label-width="180px" label="API 版本" prop="config.apiVersion">
+          <el-radio-group v-model="formData.config.apiVersion" size="medium">
+            <el-radio label="v2">v2</el-radio>
+            <el-radio label="v3">v3</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <div v-if="formData.config.apiVersion === 'v2'">
+          <el-form-item label-width="180px" label="商户密钥" prop="config.mchKey">
+            <el-input v-model="formData.config.mchKey" placeholder="请输入商户密钥" clearable
+                      :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="apiclient_cert.p12 证书" prop="config.keyContent">
+            <el-input v-model="formData.config.keyContent" type="textarea"
+                      placeholder="请上传 apiclient_cert.p12 证书"
+                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="">
+            <el-upload :limit="1" accept=".p12" action=""
+                       :before-upload="p12FileBeforeUpload"
+                       :http-request="keyContentUpload">
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+        </div>
+        <div v-if="formData.config.apiVersion === 'v3'">
+          <el-form-item label-width="180px" label="API V3 密钥" prop="config.apiV3Key">
+            <el-input v-model="formData.config.apiV3Key" placeholder="请输入 API V3 密钥" clearable
+                      :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="apiclient_key.perm 证书" prop="config.privateKeyContent">
+            <el-input v-model="formData.config.privateKeyContent" type="textarea"
+                      placeholder="请上传 apiclient_key.perm 证书"
+                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="" prop="privateKeyContentFile">
+            <el-upload ref="privateKeyContentFile"
+                       :limit="1"
+                       accept=".pem"
+                       action=""
+                       :before-upload="pemFileBeforeUpload"
+                       :http-request="privateKeyContentUpload"
+            >
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="config.privateCertContent">
+            <el-input v-model="formData.config.privateCertContent" type="textarea"
+                      placeholder="请上传apiclient_cert.perm证书"
+                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
+          </el-form-item>
+          <el-form-item label-width="180px" label="" prop="privateCertContentFile">
+            <el-upload ref="privateCertContentFile"
+                       :limit="1"
+                       accept=".pem"
+                       action=""
+                       :before-upload="pemFileBeforeUpload"
+                       :http-request="privateCertContentUpload"
+            >
+              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
+            </el-upload>
+          </el-form-item>
+        </div>
+        <el-form-item label-width="180px" label="备注" prop="remark">
+          <el-input v-model="formData.remark" :style="{width: '100%'}" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取消</el-button>
+        <el-button type="primary" @click="submitForm">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { createChannel, getChannel, updateChannel } from "@/api/pay/channel";
+import { CommonStatusEnum } from "@/utils/constants";
+
+export default {
+  name: "weixinChannelForm",
+  data() {
+    return {
+      dialogVisible: false,
+      formLoading: false,
+      title:'',
+      formData: {
+        appId: '',
+        code: '',
+        status: undefined,
+        feeRate: undefined,
+        remark: '',
+        config: {
+          appId: '',
+          mchId: '',
+          apiVersion: '',
+          mchKey: '',
+          keyContent: '',
+          privateKeyContent: '',
+          privateCertContent: '',
+          apiV3Key:'',
+        }
+      },
+      rules: {
+        feeRate: [{ required: true, message: '请输入渠道费率', trigger: 'blur' }],
+        status: [{ required: true, message: '渠道状态不能为空', trigger: 'blur'}],
+        'config.mchId': [{ required: true, message: '请传入商户号', trigger: 'blur'}],
+        'config.appId': [{ required: true, message: '请输入公众号APPID', trigger: 'blur'}],
+        'config.apiVersion': [{ required: true, message: 'API版本不能为空', trigger: 'blur'}],
+        'config.mchKey': [{ required: true, message: '请输入商户密钥', trigger: 'blur' }],
+        'config.keyContent': [{ required: true, message: '请上传 apiclient_cert.p12 证书', trigger: 'blur' }],
+        'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.perm 证书', trigger: 'blur' }],
+        'config.privateCertContent': [{ required: true, message: '请上传 apiclient_cert.perm证 书', trigger: 'blur' }],
+        'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }],
+      },
+    }
+  },
+  methods: {
+    open(appId, code) {
+      this.dialogVisible = true;
+      this.formLoading = true;
+      this.reset(appId, code);
+      getChannel(appId, code).then(response => {
+        if (response.data && response.data.id) {
+          this.formData = response.data;
+          this.formData.config = JSON.parse(response.data.config);
+        }
+        this.title = !this.formData.id ? '创建支付渠道' : '编辑支付渠道'
+      }).finally(() => {
+        this.formLoading = false;
+      });
+    },
+    close() {
+      this.dialogVisible = false;
+      this.reset(undefined, undefined);
+    },
+    submitForm() {
+      this.$refs['form'].validate(valid => {
+        if (!valid) {
+          return
+        }
+        const data = { ...this.formData };
+        data.config = JSON.stringify(this.formData.config);
+        if (!data.id) {
+          createChannel(data).then(response => {
+            this.$modal.msgSuccess("新增成功");
+            this.$emit('success')
+            this.close();
+          });
+        } else {
+          updateChannel(data).then(response => {
+            this.$modal.msgSuccess("修改成功");
+            this.$emit('success')
+            this.close();
+          })
+        }
+      });
+    },
+    /** 重置表单 */
+    reset(appId, code) {
+      this.formData = {
+        appId: appId,
+        code: code,
+        status: CommonStatusEnum.ENABLE,
+        feeRate: undefined,
+        remark: '',
+        config: {
+          appId: '',
+          mchId: '',
+          apiVersion: '',
+          mchKey: '',
+          keyContent: '',
+          privateKeyContent: '',
+          privateCertContent: '',
+          apiV3Key:'',
+        }
+      }
+      this.resetForm('form')
+    },
+    /**
+     * apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
+     */
+    fileBeforeUpload(file, fileAccept) {
+      let format = '.' + file.name.split(".")[1];
+      if (format !== fileAccept) {
+        debugger
+        this.$message.error('请上传指定格式"' + fileAccept + '"文件');
+        return false;
+      }
+      let isRightSize = file.size / 1024 / 1024 < 2
+      if (!isRightSize) {
+        this.$message.error('文件大小超过 2MB')
+      }
+      return isRightSize
+    },
+    p12FileBeforeUpload(file) {
+      this.fileBeforeUpload(file, '.p12')
+    },
+    pemFileBeforeUpload(file) {
+      this.fileBeforeUpload(file, '.pem')
+    },
+    /**
+     * 读取 apiclient_key.pem 到 privateKeyContent 字段
+     */
+    privateKeyContentUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.privateKeyContent = e.target.result
+      }
+      readFile.readAsText(event.file);
+    },
+    /**
+     * 读取 apiclient_cert.pem 到 privateCertContent 字段
+     */
+    privateCertContentUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.privateCertContent = e.target.result
+      }
+      readFile.readAsText(event.file);
+    },
+    /**
+     * 读取 apiclient_cert.p12 到 keyContent 字段
+     */
+    keyContentUpload(event) {
+      const readFile = new FileReader()
+      readFile.onload = (e) => {
+        this.formData.config.keyContent = e.target.result.split(',')[1]
+      }
+      readFile.readAsDataURL(event.file); // 读成 base64
+    }
+  }
+}
+</script>
diff --git a/yudao-ui-admin/src/views/pay/app/index.vue b/yudao-ui-admin/src/views/pay/app/index.vue
index 3a038f8be..be92e0dae 100644
--- a/yudao-ui-admin/src/views/pay/app/index.vue
+++ b/yudao-ui-admin/src/views/pay/app/index.vue
@@ -9,7 +9,7 @@
       </el-form-item>
       <el-form-item label="开启状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
-          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label"
+          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" :label="dict.label"
                      :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
@@ -48,60 +48,55 @@
         <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_APP.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_APP.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_APP.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_PC.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_PC.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_PC.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_WAP.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_WAP.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_WAP.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_QR.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_QR.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_QR.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_BAR.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_BAR.code)"
+                       @click="handleChannel(scope.row,payChannelEnum.ALIPAY_BAR.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.ALIPAY_BAR.code)">
             </el-button>
           </template>
         </el-table-column>
@@ -110,60 +105,55 @@
         <el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_LITE.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.WX_LITE.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.WX_LITE.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_PUB.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.WX_PUB.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.WX_PUB.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.WX_APP.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_APP.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.WX_APP.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.WX_APP.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.WX_NATIVE.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_NATIVE.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_NATIVE.code,payType.WECHAT)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_NATIVE.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.WX_NATIVE.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_NATIVE.code,payType.WECHAT)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.WX_NATIVE.code)">
             </el-button>
           </template>
         </el-table-column>
         <el-table-column :label="payChannelEnum.WX_BAR.name" align="center">
           <template v-slot="scope">
             <el-button type="success" icon="el-icon-check" circle
-                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_BAR.code)"
-                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_BAR.code,payType.WECHAT)">
+                       v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_BAR.code)"
+                       @click="handleChannel(scope.row, payChannelEnum.WX_BAR.code)">
             </el-button>
-            <el-button v-else
-                       type="danger" icon="el-icon-close" circle
-                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_BAR.code,payType.WECHAT)">
+            <el-button v-else type="danger" icon="el-icon-close" circle
+                       @click="handleChannel(scope.row, payChannelEnum.WX_BAR.code)">
             </el-button>
           </template>
         </el-table-column>
@@ -191,7 +181,7 @@
         </el-form-item>
         <el-form-item label="开启状态" prop="status">
           <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
+            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
               {{ dict.label }}
             </el-radio>
           </el-radio-group>
@@ -214,24 +204,23 @@
       </div>
     </el-dialog>
 
-    <!-- 弹窗 -->
-    <wechat-channel-form :transferParam="channelParam" />
+    <!-- 对话框(支付应用的配置) -->
+    <weixin-channel-form ref="weixinChannelFormRef" @success="getList" />
     <alipay-channel-form ref="alipayChannelFormRef" @success="getList" />
   </div>
 </template>
 
 <script>
 import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } from "@/api/pay/app";
-import { DICT_TYPE, getDictDatas } from "@/utils/dict";
-import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants";
-import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
+import { PayChannelEnum, CommonStatusEnum } from "@/utils/constants";
+import weixinChannelForm from "@/views/pay/app/components/weixinChannelForm";
 import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm";
 
 export default {
   name: "PayApp",
   components: {
-    "wechatChannelForm": wechatChannelForm,
-    "alipayChannelForm": alipayChannelForm
+    weixinChannelForm,
+    alipayChannelForm
   },
   data() {
     return {
@@ -264,28 +253,8 @@ export default {
         orderNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}],
         refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}],
       },
-      // 数据字典
-      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
-      sysCommonStatusEnum: CommonStatusEnum,
       // 支付渠道枚举
       payChannelEnum: PayChannelEnum,
-      // 支付类型
-      payType: PayType,
-      // 是否显示支付窗口
-      payOpen: false,
-      // 微信组件传参参数
-      channelParam: {
-        // 是否修改
-        "edit": false,
-        // 微信是否显示
-        "wechatOpen": false,
-        // 支付宝是否显示
-        "aliPayOpen": false,
-        // 应用ID
-        "appId": null,
-        // 渠道编码
-        "payCode": null,
-      }
     };
   },
   created() {
@@ -312,7 +281,7 @@ export default {
       this.form = {
         id: undefined,
         name: undefined,
-        status: undefined,
+        status: CommonStatusEnum.ENABLE,
         remark: undefined,
         orderNotifyUrl: undefined,
         refundNotifyUrl: undefined,
@@ -397,43 +366,25 @@ export default {
     /**
      * 修改支付渠道信息
      */
-    handleUpdateChannel(row, payCode, type) {
-      this.settingChannelParam(row, payCode, type)
-      this.channelParam.edit = true;
-      this.channelParam.loading = true;
-    },
-    /**
-     * 新增支付渠道信息
-     */
-    handleCreateChannel(row, payCode, type) {
-      this.settingChannelParam(row, payCode, type)
-      this.channelParam.edit = false;
-      this.channelParam.loading = false;
-    },
-    /**
-     * 设置支付渠道信息
-     */
-    settingChannelParam(row, payCode, type) {
-      if (type === PayType.WECHAT) {
-        this.channelParam.wechatOpen = true;
-        this.channelParam.aliPayOpen = false;
+    handleChannel(row, code) {
+      if (code.indexOf('alipay_') === 0) {
+        this.$refs['alipayChannelFormRef'].open(row.id, code);
+        return
       }
-      if (type === PayType.ALIPAY) {
-        console.log(this.$refs['alipayChannelFormRef'])
-        this.$refs['alipayChannelFormRef'].open(row.id, payCode);
-        return;
-        // this.channelParam.aliPayOpen = true;
-        // this.channelParam.wechatOpen = false;
+      if (code.indexOf('wx_') === 0) {
+        this.$refs['weixinChannelFormRef'].open(row.id, code);
+        return
       }
     },
     /**
      * 根据渠道编码判断渠道列表中是否存在
+     *
      * @param channels 渠道列表
      * @param channelCode 渠道编码
      */
-    judgeChannelExist(channels, channelCode) {
+    isChannelExists(channels, channelCode) {
       return channels.indexOf(channelCode) !== -1;
     }
   }
-};
+}
 </script>