From 5748e5c2b6d1de68455fb1c33e9acfb47fdb1edb Mon Sep 17 00:00:00 2001 From: DaxPay Dev Date: Fri, 24 Jul 2026 20:10:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(easypay):=20=E5=95=86=E6=88=B7RSA=E5=AF=86?= =?UTF-8?q?=E9=92=A5=E5=AF=B9=E5=9C=A8=E7=BA=BF=E7=94=9F=E6=88=90=E4=B8=8E?= =?UTF-8?q?=E5=85=AC=E7=A7=81=E9=92=A5=E7=BA=AFBase64=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 两端 EasyPayConfig 商户公钥区新增"生成密钥对"按钮与私钥弹窗 - 生成/保存时去除PEM头尾与换行,公私钥均以纯Base64存储(易支付要求) - easypay 节点新增5个i18n key,两端10语种同步 --- .../langs/en-US/payment/merchant/app.json | 7 +- .../langs/id-ID/payment/merchant/app.json | 7 +- .../langs/ja-JP/payment/merchant/app.json | 7 +- .../langs/ko-KR/payment/merchant/app.json | 7 +- .../langs/ms-MY/payment/merchant/app.json | 7 +- .../langs/th-TH/payment/merchant/app.json | 7 +- .../langs/vi-VN/payment/merchant/app.json | 7 +- .../langs/zh-CN/payment/merchant/app.json | 7 +- .../langs/zh-HK/payment/merchant/app.json | 7 +- .../langs/zh-TW/payment/merchant/app.json | 7 +- .../merchant/easypay/EasyPayConfig.vue | 145 +++++++++++++----- .../langs/en-US/payment/merchant/app.json | 7 +- .../langs/id-ID/payment/merchant/app.json | 7 +- .../langs/ja-JP/payment/merchant/app.json | 7 +- .../langs/ko-KR/payment/merchant/app.json | 7 +- .../langs/ms-MY/payment/merchant/app.json | 7 +- .../langs/th-TH/payment/merchant/app.json | 7 +- .../langs/vi-VN/payment/merchant/app.json | 7 +- .../langs/zh-CN/payment/merchant/app.json | 7 +- .../langs/zh-HK/payment/merchant/app.json | 7 +- .../langs/zh-TW/payment/merchant/app.json | 7 +- .../merchant/easypay/EasyPayConfig.vue | 98 +++++++++++- 22 files changed, 325 insertions(+), 58 deletions(-) diff --git a/apps/daxpay-admin/src/locales/langs/en-US/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/en-US/payment/merchant/app.json index c5cde5626..d0b640713 100644 --- a/apps/daxpay-admin/src/locales/langs/en-US/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/en-US/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "MD5 key used for V1 request signing", "useSystemKeyDesc": "Use the platform key pair so merchant public key is not required", "publicKeyDesc": "Merchant RSA public key when using a custom key pair", - "platformPublicKeyDesc": "Platform public key for integrator signature verification" + "platformPublicKeyDesc": "Platform public key for integrator signature verification", + "genRsaKeyPair": "Generate Key Pair", + "confirmGenPublicKey": "The public key already exists. Regenerating will overwrite it. Continue?", + "genKeyPairTitle": "RSA Key Pair", + "privateKey": "Private Key", + "privateKeyWarning": "The private key is shown only once. Keep it safe — it cannot be recovered if lost." } } diff --git a/apps/daxpay-admin/src/locales/langs/id-ID/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/id-ID/payment/merchant/app.json index adde1f197..c5397d853 100644 --- a/apps/daxpay-admin/src/locales/langs/id-ID/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/id-ID/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "Kunci MD5 untuk penandatanganan permintaan V1", "useSystemKeyDesc": "Gunakan pasangan kunci platform sehingga kunci publik merchant tidak diperlukan", "publicKeyDesc": "Kunci publik RSA merchant saat menggunakan pasangan kunci kustom", - "platformPublicKeyDesc": "Kunci publik platform untuk verifikasi tanda tangan integrator" + "platformPublicKeyDesc": "Kunci publik platform untuk verifikasi tanda tangan integrator", + "genRsaKeyPair": "Buat Pasangan Kunci", + "confirmGenPublicKey": "Kunci publik sudah ada. Membuat ulang akan menimpa kunci yang ada. Lanjutkan?", + "genKeyPairTitle": "Pasangan Kunci RSA", + "privateKey": "Kunci Privat", + "privateKeyWarning": "Kunci privat hanya ditampilkan sekali di sini. Simpan dengan aman — tidak dapat dipulihkan jika hilang." } } diff --git a/apps/daxpay-admin/src/locales/langs/ja-JP/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/ja-JP/payment/merchant/app.json index e80847232..be92b15bc 100644 --- a/apps/daxpay-admin/src/locales/langs/ja-JP/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/ja-JP/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "V1 署名用の MD5 鍵", "useSystemKeyDesc": "プラットフォーム鍵ペアを使う場合、加盟店公開鍵の入力は不要です", "publicKeyDesc": "独自鍵ペア利用時の加盟店 RSA 公開鍵", - "platformPublicKeyDesc": "連携側の署名検証用プラットフォーム公開鍵" + "platformPublicKeyDesc": "連携側の署名検証用プラットフォーム公開鍵", + "genRsaKeyPair": "鍵ペアを生成", + "confirmGenPublicKey": "公開鍵が既に存在します。再生成すると元の公開鍵が上書きされます。再生成しますか?", + "genKeyPairTitle": "RSA鍵ペア", + "privateKey": "秘密鍵", + "privateKeyWarning": "秘密鍵はここに一度だけ表示されます。確実に保管してください。紛失すると復元できません。" } } diff --git a/apps/daxpay-admin/src/locales/langs/ko-KR/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/ko-KR/payment/merchant/app.json index 649be7669..bc2f544b7 100644 --- a/apps/daxpay-admin/src/locales/langs/ko-KR/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/ko-KR/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "V1 서명용 MD5 키", "useSystemKeyDesc": "플랫폼 키 쌍을 사용하면 가맹점 공개키를 입력할 필요가 없습니다", "publicKeyDesc": "자체 키 쌍 사용 시 가맹점 RSA 공개키", - "platformPublicKeyDesc": "연동측 서명 검증용 플랫폼 공개키" + "platformPublicKeyDesc": "연동측 서명 검증용 플랫폼 공개키", + "genRsaKeyPair": "키 쌍 생성", + "confirmGenPublicKey": "공개 키가 이미 존재합니다. 다시 생성하면 기존 공개 키를 덮어씁니다. 다시 생성하시겠습니까?", + "genKeyPairTitle": "RSA 키 쌍", + "privateKey": "개인 키", + "privateKeyWarning": "개인 키는 여기에 한 번만 표시됩니다. 안전하게 보관하세요. 분실 시 복구할 수 없습니다." } } diff --git a/apps/daxpay-admin/src/locales/langs/ms-MY/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/ms-MY/payment/merchant/app.json index b287f7309..cf82bfc10 100644 --- a/apps/daxpay-admin/src/locales/langs/ms-MY/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/ms-MY/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "Kunci MD5 untuk penandatanganan permintaan V1", "useSystemKeyDesc": "Gunakan pasangan kunci platform supaya kunci awam pedagang tidak diperlukan", "publicKeyDesc": "Kunci awam RSA pedagang apabila menggunakan pasangan kunci tersuai", - "platformPublicKeyDesc": "Kunci awam platform untuk pengesahan tandatangan pengintegrasi" + "platformPublicKeyDesc": "Kunci awam platform untuk pengesahan tandatangan pengintegrasi", + "genRsaKeyPair": "Jana Pasangan Kunci", + "confirmGenPublicKey": "Kunci awam telah wujud. Menjana semula akan menulis ganti kunci sedia ada. Teruskan?", + "genKeyPairTitle": "Pasangan Kunci RSA", + "privateKey": "Kunci Peribadi", + "privateKeyWarning": "Kunci peribadi hanya dipaparkan sekali di sini. Simpan dengan selamat — tidak boleh dipulihkan jika hilang." } } diff --git a/apps/daxpay-admin/src/locales/langs/th-TH/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/th-TH/payment/merchant/app.json index 9395b46dc..f01a7bd94 100644 --- a/apps/daxpay-admin/src/locales/langs/th-TH/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/th-TH/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "คีย์ MD5 สำหรับการเซ็นคำขอ V1", "useSystemKeyDesc": "ใช้คู่คีย์ของแพลตฟอร์มจึงไม่ต้องกรอกรหัสสาธารณะผู้ค้า", "publicKeyDesc": "รหัสสาธารณะ RSA ของผู้ค้า เมื่อใช้คู่คีย์ที่กำหนดเอง", - "platformPublicKeyDesc": "รหัสสาธารณะของแพลตฟอร์มสำหรับการตรวจสอบลายเซ็นผู้เชื่อมต่อ" + "platformPublicKeyDesc": "รหัสสาธารณะของแพลตฟอร์มสำหรับการตรวจสอบลายเซ็นผู้เชื่อมต่อ", + "genRsaKeyPair": "สร้างคู่คีย์", + "confirmGenPublicKey": "มีคีย์สาธารณะอยู่แล้ว การสร้างใหม่จะเขียนทับคีย์เดิม ต้องการสร้างใหม่หรือไม่?", + "genKeyPairTitle": "คู่คีย์ RSA", + "privateKey": "คีย์ส่วนตัว", + "privateKeyWarning": "คีย์ส่วนตัวจะแสดงที่นี่เพียงครั้งเดียว โปรดเก็บรักษาให้ดี หากสูญหายจะกู้คืนไม่ได้" } } diff --git a/apps/daxpay-admin/src/locales/langs/vi-VN/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/vi-VN/payment/merchant/app.json index dbf43d464..1e589e4db 100644 --- a/apps/daxpay-admin/src/locales/langs/vi-VN/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/vi-VN/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "Khóa MD5 dùng để ký yêu cầu V1", "useSystemKeyDesc": "Dùng cặp khóa nền tảng nên không cần khóa công khai merchant", "publicKeyDesc": "Khóa công khai RSA merchant khi dùng cặp khóa tùy chỉnh", - "platformPublicKeyDesc": "Khóa công khai nền tảng để bên tích hợp xác minh chữ ký" + "platformPublicKeyDesc": "Khóa công khai nền tảng để bên tích hợp xác minh chữ ký", + "genRsaKeyPair": "Tạo cặp khóa", + "confirmGenPublicKey": "Khóa công khai đã tồn tại. Tạo lại sẽ ghi đè khóa hiện có. Tiếp tục?", + "genKeyPairTitle": "Cặp khóa RSA", + "privateKey": "Khóa riêng", + "privateKeyWarning": "Khóa riêng chỉ hiển thị một lần tại đây. Vui lòng lưu giữ an toàn — không thể khôi phục nếu mất." } } diff --git a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/zh-CN/payment/merchant/app.json index 1159e3490..4cfd78326 100644 --- a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/zh-CN/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "V1 签名用 MD5 密钥", "useSystemKeyDesc": "使用平台密钥对时无需填写商户公钥", "publicKeyDesc": "商户侧 RSA 公钥(自签时填写)", - "platformPublicKeyDesc": "平台公钥,对接方验签使用" + "platformPublicKeyDesc": "平台公钥,对接方验签使用", + "genRsaKeyPair": "生成密钥对", + "confirmGenPublicKey": "公钥已存在,重新生成将覆盖原有公钥,确定要重新生成吗?", + "genKeyPairTitle": "RSA密钥对", + "privateKey": "私钥", + "privateKeyWarning": "私钥仅在此处展示一次,请务必妥善保管,丢失无法找回" } } diff --git a/apps/daxpay-admin/src/locales/langs/zh-HK/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/zh-HK/payment/merchant/app.json index 9dc49f5b5..d0c0c4bc3 100644 --- a/apps/daxpay-admin/src/locales/langs/zh-HK/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/zh-HK/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "V1 簽名用 MD5 密鑰", "useSystemKeyDesc": "使用平台密鑰對時無需填寫商戶公鑰", "publicKeyDesc": "商戶側 RSA 公鑰(自簽時填寫)", - "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用" + "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用", + "genRsaKeyPair": "產生金鑰對", + "confirmGenPublicKey": "公鑰已存在,重新產生將覆蓋原有公鑰,確定要重新產生嗎?", + "genKeyPairTitle": "RSA金鑰對", + "privateKey": "私鑰", + "privateKeyWarning": "私鑰僅在此處顯示一次,請務必妥善保管,遺失無法找回" } } diff --git a/apps/daxpay-admin/src/locales/langs/zh-TW/payment/merchant/app.json b/apps/daxpay-admin/src/locales/langs/zh-TW/payment/merchant/app.json index f780384a8..c59302003 100644 --- a/apps/daxpay-admin/src/locales/langs/zh-TW/payment/merchant/app.json +++ b/apps/daxpay-admin/src/locales/langs/zh-TW/payment/merchant/app.json @@ -82,6 +82,11 @@ "md5KeyDesc": "V1 簽名用 MD5 密鑰", "useSystemKeyDesc": "使用平台密鑰對時無需填寫商戶公鑰", "publicKeyDesc": "商戶側 RSA 公鑰(自簽時填寫)", - "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用" + "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用", + "genRsaKeyPair": "產生金鑰對", + "confirmGenPublicKey": "公鑰已存在,重新產生將覆蓋原有公鑰,確定要重新產生嗎?", + "genKeyPairTitle": "RSA金鑰對", + "privateKey": "私鑰", + "privateKeyWarning": "私鑰僅在此處顯示一次,請務必妥善保管,遺失無法找回" } } diff --git a/apps/daxpay-admin/src/views/payment/merchant/easypay/EasyPayConfig.vue b/apps/daxpay-admin/src/views/payment/merchant/easypay/EasyPayConfig.vue index ad58c8e1b..91a66b9dd 100644 --- a/apps/daxpay-admin/src/views/payment/merchant/easypay/EasyPayConfig.vue +++ b/apps/daxpay-admin/src/views/payment/merchant/easypay/EasyPayConfig.vue @@ -13,6 +13,7 @@ type EasyPayCredentialParam, type EasyPayCredentialResult, } from '#/api/payment/merchant/easypay-credential.api'; + import { KeyGenApi } from '#/api/payment/merchant/key-gen.api'; import { MchAppInfoApi, type MchAppInfoResult } from '#/api/payment/merchant/mch-app-info.api'; import RouteQueryMissingState from '#/components/route/RouteQueryMissingState.vue'; import { PermCodes } from '#/constants/perm-codes'; @@ -64,18 +65,36 @@ }); // 原始脱敏数据,用于 diffForm 比对 const originalForm = ref({}); + // RSA 密钥对弹窗 + const keyPairVisible = ref(false); + const privateKeyContent = ref(''); /** - * 平台公钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64 + * 公钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64 */ function normalizePublicKey(pem?: string) { if (!pem) { return pem; } return pem - .replace(/-----BEGIN PUBLIC KEY-----/g, '') - .replace(/-----END PUBLIC KEY-----/g, '') - .replace(/\s+/g, ''); + .replaceAll('-----BEGIN PUBLIC KEY-----', '') + .replaceAll('-----END PUBLIC KEY-----', '') + .replaceAll(/\s+/g, ''); + } + + /** + * 私钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64(易支付要求) + */ + function normalizePrivateKey(pem?: string) { + if (!pem) { + return pem; + } + return pem + .replaceAll('-----BEGIN PRIVATE KEY-----', '') + .replaceAll('-----END PRIVATE KEY-----', '') + .replaceAll('-----BEGIN RSA PRIVATE KEY-----', '') + .replaceAll('-----END RSA PRIVATE KEY-----', '') + .replaceAll(/\s+/g, ''); } /** @@ -173,7 +192,7 @@ /** * 复制文本 */ - function handleCopy(text?: string | number | null) { + function handleCopy(text?: null | number | string) { if (text === undefined || text === null || text === '') { return; } @@ -181,6 +200,39 @@ message.success($t('common.operationSuccess')); } + /** + * 生成 RSA 密钥对(公钥已存在时二次确认) + */ + async function handleGenRsaKeyPair() { + if (form.publicKey) { + confirm({ + title: $t('common.confirm'), + content: $t('payment.merchant.app.easypay.confirmGenPublicKey'), + okText: $t('common.okText'), + cancelText: $t('common.cancelText'), + onOk: async () => { + await doGenRsaKeyPair(); + }, + }); + } else { + await doGenRsaKeyPair(); + } + } + + /** + * 执行生成 RSA 密钥对:公钥去 PEM 头尾后填入表单,私钥弹窗展示 + */ + async function doGenRsaKeyPair() { + const { data } = await KeyGenApi.genRsaKeyPair(); + if (data) { + // 公钥去注释与换行(纯 Base64 存储),前端处理 + form.publicKey = normalizePublicKey(data.publicKey); + // 私钥同样去 PEM 头尾与换行(易支付要求纯 Base64),弹窗展示 + privateKeyContent.value = normalizePrivateKey(data.privateKey) ?? ''; + keyPairVisible.value = true; + } + } + /** * 保存配置 */ @@ -196,6 +248,10 @@ onOk: async () => { saving.value = true; try { + // 商户公钥去 PEM 头尾与换行(纯 Base64 存储),保存时兜底处理 + if (form.publicKey) { + form.publicKey = normalizePublicKey(form.publicKey); + } // 敏感字段未修改时不提交 const sensitiveData = diffForm(originalForm, form, 'md5Key', 'publicKey'); const submitData: EasyPayCredentialParam = { @@ -263,9 +319,7 @@ {{ $t('menu.payment.merchant.easypay') }} - - ({{ appInfo.appName }}) - + ({{ appInfo.appName }}) diff --git a/apps/daxpay-merchant/src/locales/langs/en-US/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/en-US/payment/merchant/app.json index 3679e0129..09a6e5752 100644 --- a/apps/daxpay-merchant/src/locales/langs/en-US/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/en-US/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "MD5 key used for V1 request signing", "useSystemKeyDesc": "Use the platform key pair so merchant public key is not required", "publicKeyDesc": "Merchant RSA public key when using a custom key pair", - "platformPublicKeyDesc": "Platform public key for integrator signature verification" + "platformPublicKeyDesc": "Platform public key for integrator signature verification", + "genRsaKeyPair": "Generate Key Pair", + "confirmGenPublicKey": "The public key already exists. Regenerating will overwrite it. Continue?", + "genKeyPairTitle": "RSA Key Pair", + "privateKey": "Private Key", + "privateKeyWarning": "The private key is shown only once. Keep it safe — it cannot be recovered if lost." } } diff --git a/apps/daxpay-merchant/src/locales/langs/id-ID/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/id-ID/payment/merchant/app.json index 96ed9ce0c..b949eac0f 100644 --- a/apps/daxpay-merchant/src/locales/langs/id-ID/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/id-ID/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "Kunci MD5 untuk penandatanganan permintaan V1", "useSystemKeyDesc": "Gunakan pasangan kunci platform sehingga kunci publik merchant tidak diperlukan", "publicKeyDesc": "Kunci publik RSA merchant saat menggunakan pasangan kunci kustom", - "platformPublicKeyDesc": "Kunci publik platform untuk verifikasi tanda tangan integrator" + "platformPublicKeyDesc": "Kunci publik platform untuk verifikasi tanda tangan integrator", + "genRsaKeyPair": "Buat Pasangan Kunci", + "confirmGenPublicKey": "Kunci publik sudah ada. Membuat ulang akan menimpa kunci yang ada. Lanjutkan?", + "genKeyPairTitle": "Pasangan Kunci RSA", + "privateKey": "Kunci Privat", + "privateKeyWarning": "Kunci privat hanya ditampilkan sekali di sini. Simpan dengan aman — tidak dapat dipulihkan jika hilang." } } diff --git a/apps/daxpay-merchant/src/locales/langs/ja-JP/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/ja-JP/payment/merchant/app.json index 9d46bf8e5..d05c91c98 100644 --- a/apps/daxpay-merchant/src/locales/langs/ja-JP/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/ja-JP/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "V1 署名用の MD5 鍵", "useSystemKeyDesc": "プラットフォーム鍵ペアを使う場合、加盟店公開鍵の入力は不要です", "publicKeyDesc": "独自鍵ペア利用時の加盟店 RSA 公開鍵", - "platformPublicKeyDesc": "連携側の署名検証用プラットフォーム公開鍵" + "platformPublicKeyDesc": "連携側の署名検証用プラットフォーム公開鍵", + "genRsaKeyPair": "鍵ペアを生成", + "confirmGenPublicKey": "公開鍵が既に存在します。再生成すると元の公開鍵が上書きされます。再生成しますか?", + "genKeyPairTitle": "RSA鍵ペア", + "privateKey": "秘密鍵", + "privateKeyWarning": "秘密鍵はここに一度だけ表示されます。確実に保管してください。紛失すると復元できません。" } } diff --git a/apps/daxpay-merchant/src/locales/langs/ko-KR/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/ko-KR/payment/merchant/app.json index 853dc57dd..29f616f51 100644 --- a/apps/daxpay-merchant/src/locales/langs/ko-KR/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/ko-KR/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "V1 서명용 MD5 키", "useSystemKeyDesc": "플랫폼 키 쌍을 사용하면 가맹점 공개키를 입력할 필요가 없습니다", "publicKeyDesc": "자체 키 쌍 사용 시 가맹점 RSA 공개키", - "platformPublicKeyDesc": "연동측 서명 검증용 플랫폼 공개키" + "platformPublicKeyDesc": "연동측 서명 검증용 플랫폼 공개키", + "genRsaKeyPair": "키 쌍 생성", + "confirmGenPublicKey": "공개 키가 이미 존재합니다. 다시 생성하면 기존 공개 키를 덮어씁니다. 다시 생성하시겠습니까?", + "genKeyPairTitle": "RSA 키 쌍", + "privateKey": "개인 키", + "privateKeyWarning": "개인 키는 여기에 한 번만 표시됩니다. 안전하게 보관하세요. 분실 시 복구할 수 없습니다." } } diff --git a/apps/daxpay-merchant/src/locales/langs/ms-MY/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/ms-MY/payment/merchant/app.json index 69e022ad5..d3d79ccaa 100644 --- a/apps/daxpay-merchant/src/locales/langs/ms-MY/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/ms-MY/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "Kunci MD5 untuk penandatanganan permintaan V1", "useSystemKeyDesc": "Gunakan pasangan kunci platform supaya kunci awam pedagang tidak diperlukan", "publicKeyDesc": "Kunci awam RSA pedagang apabila menggunakan pasangan kunci tersuai", - "platformPublicKeyDesc": "Kunci awam platform untuk pengesahan tandatangan pengintegrasi" + "platformPublicKeyDesc": "Kunci awam platform untuk pengesahan tandatangan pengintegrasi", + "genRsaKeyPair": "Jana Pasangan Kunci", + "confirmGenPublicKey": "Kunci awam telah wujud. Menjana semula akan menulis ganti kunci sedia ada. Teruskan?", + "genKeyPairTitle": "Pasangan Kunci RSA", + "privateKey": "Kunci Peribadi", + "privateKeyWarning": "Kunci peribadi hanya dipaparkan sekali di sini. Simpan dengan selamat — tidak boleh dipulihkan jika hilang." } } diff --git a/apps/daxpay-merchant/src/locales/langs/th-TH/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/th-TH/payment/merchant/app.json index b3f932ad3..69a24cb09 100644 --- a/apps/daxpay-merchant/src/locales/langs/th-TH/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/th-TH/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "คีย์ MD5 สำหรับการเซ็นคำขอ V1", "useSystemKeyDesc": "ใช้คู่คีย์ของแพลตฟอร์มจึงไม่ต้องกรอกรหัสสาธารณะผู้ค้า", "publicKeyDesc": "รหัสสาธารณะ RSA ของผู้ค้า เมื่อใช้คู่คีย์ที่กำหนดเอง", - "platformPublicKeyDesc": "รหัสสาธารณะของแพลตฟอร์มสำหรับการตรวจสอบลายเซ็นผู้เชื่อมต่อ" + "platformPublicKeyDesc": "รหัสสาธารณะของแพลตฟอร์มสำหรับการตรวจสอบลายเซ็นผู้เชื่อมต่อ", + "genRsaKeyPair": "สร้างคู่คีย์", + "confirmGenPublicKey": "มีคีย์สาธารณะอยู่แล้ว การสร้างใหม่จะเขียนทับคีย์เดิม ต้องการสร้างใหม่หรือไม่?", + "genKeyPairTitle": "คู่คีย์ RSA", + "privateKey": "คีย์ส่วนตัว", + "privateKeyWarning": "คีย์ส่วนตัวจะแสดงที่นี่เพียงครั้งเดียว โปรดเก็บรักษาให้ดี หากสูญหายจะกู้คืนไม่ได้" } } diff --git a/apps/daxpay-merchant/src/locales/langs/vi-VN/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/vi-VN/payment/merchant/app.json index 19ac7d31d..eb0f79f37 100644 --- a/apps/daxpay-merchant/src/locales/langs/vi-VN/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/vi-VN/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "Khóa MD5 dùng để ký yêu cầu V1", "useSystemKeyDesc": "Dùng cặp khóa nền tảng nên không cần khóa công khai merchant", "publicKeyDesc": "Khóa công khai RSA merchant khi dùng cặp khóa tùy chỉnh", - "platformPublicKeyDesc": "Khóa công khai nền tảng để bên tích hợp xác minh chữ ký" + "platformPublicKeyDesc": "Khóa công khai nền tảng để bên tích hợp xác minh chữ ký", + "genRsaKeyPair": "Tạo cặp khóa", + "confirmGenPublicKey": "Khóa công khai đã tồn tại. Tạo lại sẽ ghi đè khóa hiện có. Tiếp tục?", + "genKeyPairTitle": "Cặp khóa RSA", + "privateKey": "Khóa riêng", + "privateKeyWarning": "Khóa riêng chỉ hiển thị một lần tại đây. Vui lòng lưu giữ an toàn — không thể khôi phục nếu mất." } } diff --git a/apps/daxpay-merchant/src/locales/langs/zh-CN/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/zh-CN/payment/merchant/app.json index 011e6a629..e21c037fa 100644 --- a/apps/daxpay-merchant/src/locales/langs/zh-CN/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/zh-CN/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "V1 签名用 MD5 密钥", "useSystemKeyDesc": "使用平台密钥对时无需填写商户公钥", "publicKeyDesc": "商户侧 RSA 公钥(自签时填写)", - "platformPublicKeyDesc": "平台公钥,对接方验签使用" + "platformPublicKeyDesc": "平台公钥,对接方验签使用", + "genRsaKeyPair": "生成密钥对", + "confirmGenPublicKey": "公钥已存在,重新生成将覆盖原有公钥,确定要重新生成吗?", + "genKeyPairTitle": "RSA密钥对", + "privateKey": "私钥", + "privateKeyWarning": "私钥仅在此处展示一次,请务必妥善保管,丢失无法找回" } } diff --git a/apps/daxpay-merchant/src/locales/langs/zh-HK/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/zh-HK/payment/merchant/app.json index a8ee57507..294280855 100644 --- a/apps/daxpay-merchant/src/locales/langs/zh-HK/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/zh-HK/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "V1 簽名用 MD5 密鑰", "useSystemKeyDesc": "使用平台密鑰對時無需填寫商戶公鑰", "publicKeyDesc": "商戶側 RSA 公鑰(自簽時填寫)", - "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用" + "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用", + "genRsaKeyPair": "產生金鑰對", + "confirmGenPublicKey": "公鑰已存在,重新產生將覆蓋原有公鑰,確定要重新產生嗎?", + "genKeyPairTitle": "RSA金鑰對", + "privateKey": "私鑰", + "privateKeyWarning": "私鑰僅在此處顯示一次,請務必妥善保管,遺失無法找回" } } diff --git a/apps/daxpay-merchant/src/locales/langs/zh-TW/payment/merchant/app.json b/apps/daxpay-merchant/src/locales/langs/zh-TW/payment/merchant/app.json index bf2f5105a..454d40bdb 100644 --- a/apps/daxpay-merchant/src/locales/langs/zh-TW/payment/merchant/app.json +++ b/apps/daxpay-merchant/src/locales/langs/zh-TW/payment/merchant/app.json @@ -86,6 +86,11 @@ "md5KeyDesc": "V1 簽名用 MD5 密鑰", "useSystemKeyDesc": "使用平台密鑰對時無需填寫商戶公鑰", "publicKeyDesc": "商戶側 RSA 公鑰(自簽時填寫)", - "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用" + "platformPublicKeyDesc": "平台公鑰,對接方驗簽使用", + "genRsaKeyPair": "產生金鑰對", + "confirmGenPublicKey": "公鑰已存在,重新產生將覆蓋原有公鑰,確定要重新產生嗎?", + "genKeyPairTitle": "RSA金鑰對", + "privateKey": "私鑰", + "privateKeyWarning": "私鑰僅在此處顯示一次,請務必妥善保管,遺失無法找回" } } diff --git a/apps/daxpay-merchant/src/views/payment/merchant/easypay/EasyPayConfig.vue b/apps/daxpay-merchant/src/views/payment/merchant/easypay/EasyPayConfig.vue index 76026ec37..8fb6cd221 100644 --- a/apps/daxpay-merchant/src/views/payment/merchant/easypay/EasyPayConfig.vue +++ b/apps/daxpay-merchant/src/views/payment/merchant/easypay/EasyPayConfig.vue @@ -13,6 +13,7 @@ type EasyPayCredentialParam, type EasyPayCredentialResult, } from '#/api/payment/merchant/easypay-credential.api'; + import { KeyGenApi } from '#/api/payment/merchant/key-gen.api'; import { MchAppInfoApi, type MchAppInfoResult } from '#/api/payment/merchant/mch-app-info.api'; import RouteQueryMissingState from '#/components/route/RouteQueryMissingState.vue'; import { PermCodes } from '#/constants/perm-codes'; @@ -54,9 +55,12 @@ }); // 原始脱敏数据,用于 diffForm 比对 const originalForm = ref({}); + // RSA 密钥对弹窗 + const keyPairVisible = ref(false); + const privateKeyContent = ref(''); /** - * 平台公钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64 + * 公钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64 */ function normalizePublicKey(pem?: string) { if (!pem) { @@ -68,6 +72,21 @@ .replaceAll(/\s+/g, ''); } + /** + * 私钥规范化:去掉 PEM 头尾与空白,得到可直接复制的纯 Base64(易支付要求) + */ + function normalizePrivateKey(pem?: string) { + if (!pem) { + return pem; + } + return pem + .replaceAll('-----BEGIN PRIVATE KEY-----', '') + .replaceAll('-----END PRIVATE KEY-----', '') + .replaceAll('-----BEGIN RSA PRIVATE KEY-----', '') + .replaceAll('-----END RSA PRIVATE KEY-----', '') + .replaceAll(/\s+/g, ''); + } + /** * 重置表单默认值后合并服务端数据 */ @@ -163,6 +182,39 @@ message.success($t('common.operationSuccess')); } + /** + * 生成 RSA 密钥对(公钥已存在时二次确认) + */ + async function handleGenRsaKeyPair() { + if (form.publicKey) { + confirm({ + title: $t('common.confirm'), + content: $t('payment.merchant.app.easypay.confirmGenPublicKey'), + okText: $t('common.okText'), + cancelText: $t('common.cancelText'), + onOk: async () => { + await doGenRsaKeyPair(); + }, + }); + } else { + await doGenRsaKeyPair(); + } + } + + /** + * 执行生成 RSA 密钥对:公钥去 PEM 头尾后填入表单,私钥弹窗展示 + */ + async function doGenRsaKeyPair() { + const { data } = await KeyGenApi.genRsaKeyPair(); + if (data) { + // 公钥去注释与换行(纯 Base64 存储),前端处理 + form.publicKey = normalizePublicKey(data.publicKey); + // 私钥同样去 PEM 头尾与换行(易支付要求纯 Base64),弹窗展示 + privateKeyContent.value = normalizePrivateKey(data.privateKey) ?? ''; + keyPairVisible.value = true; + } + } + /** * 保存配置 */ @@ -178,6 +230,10 @@ onOk: async () => { saving.value = true; try { + // 商户公钥去 PEM 头尾与换行(纯 Base64 存储),保存时兜底处理 + if (form.publicKey) { + form.publicKey = normalizePublicKey(form.publicKey); + } // 敏感字段未修改时不提交 const sensitiveData = diffForm(originalForm.value, form, 'md5Key', 'publicKey'); const submitData: EasyPayCredentialParam = { @@ -481,6 +537,14 @@ allow-clear class="font-mono text-sm" /> +
+ + + {{ $t('payment.merchant.app.easypay.genRsaKeyPair') }} + +
@@ -489,6 +553,38 @@ + + + +
+
+ + {{ $t('payment.merchant.app.easypay.privateKeyWarning') }} +
+
+
+ + {{ $t('payment.merchant.app.easypay.privateKey') }} + + + + {{ $t('common.copy') }} + +
+
+ +
+
+
+