mirror of
https://github.com/34892002/edgeKey.git
synced 2026-05-06 23:33:10 +08:00
fix: payment
This commit is contained in:
@@ -300,5 +300,8 @@ bun dev
|
|||||||
4. 在搜索框输入关键词过滤日志,例如:
|
4. 在搜索框输入关键词过滤日志,例如:
|
||||||
- `email.notify_order_paid.config_failed` — 支付后邮件配置获取失败
|
- `email.notify_order_paid.config_failed` — 支付后邮件配置获取失败
|
||||||
- `email.send.failed` — 邮件发送失败
|
- `email.send.failed` — 邮件发送失败
|
||||||
|
- `email.order_paid.failed` — 支付成功后发送邮件通知失败
|
||||||
- `payment.notify.route_exception` — 支付回调路由异常
|
- `payment.notify.route_exception` — 支付回调路由异常
|
||||||
- `payment.notify.context_missing` — 支付回调缺少数据库上下文
|
- `payment.notify.context_missing` — 支付回调缺少数据库上下文
|
||||||
|
- `payment.notify.diagnostic` — 支付回调校验异常诊断(签名错误、金额不匹配等)
|
||||||
|
- `bepusdt.verify_notify` — BEpusdt 回调原始 payload(debug 级别)
|
||||||
34
components/SecretInput.vue
Normal file
34
components/SecretInput.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div class="relative">
|
||||||
|
<input
|
||||||
|
:type="visible ? 'text' : 'password'"
|
||||||
|
:value="modelValue"
|
||||||
|
class="input input-bordered w-full pr-10"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="absolute right-3 top-1/2 -translate-y-1/2 text-base-content/40 hover:text-base-content"
|
||||||
|
@click="visible = !visible"
|
||||||
|
>
|
||||||
|
<svg v-if="visible" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z" /><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd" />
|
||||||
|
<path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.064 7 9.542 7 .847 0 1.669-.105 2.454-.303z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
defineProps<{ modelValue: string }>();
|
||||||
|
defineEmits<{ "update:modelValue": [value: string] }>();
|
||||||
|
defineOptions({ inheritAttrs: false });
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,24 @@
|
|||||||
# 公共组件文档
|
# 公共组件文档
|
||||||
|
|
||||||
|
## SecretInput
|
||||||
|
|
||||||
|
带显示/隐藏切换的密钥输入框,用于密码、API Secret 等敏感字段。
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 属性 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `modelValue` | `string` | 输入值(v-model) |
|
||||||
|
|
||||||
|
支持透传所有原生 `input` 属性(如 `placeholder`、`disabled` 等)。
|
||||||
|
|
||||||
|
### 基本用法
|
||||||
|
|
||||||
|
```components/SecretInput.vue#L1-3
|
||||||
|
<SecretInput v-model="form.appSecret" placeholder="请输入 App Secret" />
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## DataTable
|
## DataTable
|
||||||
|
|
||||||
通用带翻页的表格组件,基于 daisyUI `table` 样式。
|
通用带翻页的表格组件,基于 daisyUI `table` 样式。
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export function getPaymentProviderLabel(provider: string) {
|
|||||||
case "EPAY":
|
case "EPAY":
|
||||||
return "易支付";
|
return "易支付";
|
||||||
case "BEPUSDT":
|
case "BEPUSDT":
|
||||||
return "USDT";
|
return "BEpusdt";
|
||||||
default:
|
default:
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface AlipayConfig {
|
|||||||
returnUrl?: string;
|
returnUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_GATEWAY = "https://openapi.alipay.com/gateway.do";
|
|
||||||
|
|
||||||
function pemToBase64(pem: string) {
|
function pemToBase64(pem: string) {
|
||||||
return pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, "");
|
return pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, "");
|
||||||
@@ -65,7 +65,7 @@ function buildSignString(params: Record<string, string>) {
|
|||||||
export function createAlipayAdapter(config: AlipayConfig): PaymentProviderAdapter {
|
export function createAlipayAdapter(config: AlipayConfig): PaymentProviderAdapter {
|
||||||
return {
|
return {
|
||||||
async createPayment(input) {
|
async createPayment(input) {
|
||||||
const gateway = config.baseUrl?.trim().replace(/\/+$/, "") || DEFAULT_GATEWAY;
|
const gateway = `${config.baseUrl?.trim().replace(/\/+$/, "")}/gateway.do`;
|
||||||
|
|
||||||
if (!config.alipayAppId || !config.alipayPrivateKey) {
|
if (!config.alipayAppId || !config.alipayPrivateKey) {
|
||||||
throw badRequestError("支付宝配置不完整", "ALIPAY_CONFIG_INCOMPLETE");
|
throw badRequestError("支付宝配置不完整", "ALIPAY_CONFIG_INCOMPLETE");
|
||||||
@@ -136,7 +136,7 @@ export async function queryAlipayTrade(config: AlipayConfig, outTradeNo: string)
|
|||||||
throw badRequestError("支付宝配置不完整", "ALIPAY_CONFIG_INCOMPLETE");
|
throw badRequestError("支付宝配置不完整", "ALIPAY_CONFIG_INCOMPLETE");
|
||||||
}
|
}
|
||||||
|
|
||||||
const gateway = config.baseUrl?.trim().replace(/\/+$/, "") || DEFAULT_GATEWAY;
|
const gateway = `${config.baseUrl?.trim().replace(/\/+$/, "")}/gateway.do`;
|
||||||
const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
|
const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
|
||||||
const params: Record<string, string> = {
|
const params: Record<string, string> = {
|
||||||
app_id: config.alipayAppId,
|
app_id: config.alipayAppId,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
import { badRequestError, externalServiceError } from "../../lib/app-error";
|
import { badRequestError, externalServiceError } from "../../lib/app-error";
|
||||||
|
import { logger } from "../../lib/logger";
|
||||||
import type { PaymentProviderAdapter } from "./provider";
|
import type { PaymentProviderAdapter } from "./provider";
|
||||||
|
|
||||||
interface BepusdtConfig {
|
interface BepusdtConfig {
|
||||||
@@ -40,18 +41,8 @@ export function createBepusdtAdapter(config: BepusdtConfig): PaymentProviderAdap
|
|||||||
};
|
};
|
||||||
|
|
||||||
const signature = signBepusdt(payload, config.appSecret);
|
const signature = signBepusdt(payload, config.appSecret);
|
||||||
const response = await fetch(`${normalizeBaseUrl(config.baseUrl)}/api/v1/order/create-transaction`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
...payload,
|
|
||||||
signature,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const json = (await response.json()) as {
|
type BepusdtResponse = {
|
||||||
status_code?: number;
|
status_code?: number;
|
||||||
message?: string;
|
message?: string;
|
||||||
data?: {
|
data?: {
|
||||||
@@ -60,7 +51,23 @@ export function createBepusdtAdapter(config: BepusdtConfig): PaymentProviderAdap
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!response.ok || json.status_code !== 200 || !json.data?.payment_url) {
|
let json: BepusdtResponse;
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${normalizeBaseUrl(config.baseUrl)}/api/v1/order/create-order`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
body: JSON.stringify({ ...payload, signature }),
|
||||||
|
});
|
||||||
|
const text = (await response.text()).replace(/^\uFEFF/, "");
|
||||||
|
json = JSON.parse(text) as BepusdtResponse;
|
||||||
|
} catch (err) {
|
||||||
|
throw externalServiceError(
|
||||||
|
`BEpusdt 请求失败: ${err instanceof Error ? err.message : String(err)}`,
|
||||||
|
"BEPUSDT_INVALID_RESPONSE"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.status_code !== 200 || !json.data?.payment_url) {
|
||||||
throw externalServiceError(json.message || "BEpusdt 创建支付失败", "BEPUSDT_CREATE_PAYMENT_FAILED");
|
throw externalServiceError(json.message || "BEpusdt 创建支付失败", "BEPUSDT_CREATE_PAYMENT_FAILED");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +87,13 @@ export function createBepusdtAdapter(config: BepusdtConfig): PaymentProviderAdap
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug("bepusdt.verify_notify", { payload });
|
||||||
const signature = payload.signature || "";
|
const signature = payload.signature || "";
|
||||||
const unsignedPayload = { ...payload };
|
const unsignedPayload = { ...payload };
|
||||||
delete unsignedPayload.signature;
|
delete unsignedPayload.signature;
|
||||||
const expected = signBepusdt(unsignedPayload, config.appSecret);
|
const expected = signBepusdt(unsignedPayload, config.appSecret);
|
||||||
const status = payload.status === "2" ? "PAID" : payload.status === "3" ? "FAILED" : "PENDING";
|
const statusVal = String(payload.status);
|
||||||
|
const status = statusVal === "2" ? "PAID" : statusVal === "3" ? "FAILED" : "PENDING";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isValid: signature === expected,
|
isValid: signature === expected,
|
||||||
@@ -97,4 +106,4 @@ export function createBepusdtAdapter(config: BepusdtConfig): PaymentProviderAdap
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ import { notifyOrderPaid as _notifyOrderPaid } from "../email/service";
|
|||||||
const defaultPaymentConfigs: Record<PaymentProvider, PaymentConfigValue> = {
|
const defaultPaymentConfigs: Record<PaymentProvider, PaymentConfigValue> = {
|
||||||
BEPUSDT: {
|
BEPUSDT: {
|
||||||
provider: "BEPUSDT",
|
provider: "BEPUSDT",
|
||||||
name: "USDT",
|
name: "BEpusdt",
|
||||||
isEnabled: false,
|
isEnabled: false,
|
||||||
baseUrl: "",
|
baseUrl: "",
|
||||||
appId: "",
|
appId: "",
|
||||||
@@ -41,7 +41,7 @@ const defaultPaymentConfigs: Record<PaymentProvider, PaymentConfigValue> = {
|
|||||||
provider: "ALIPAY",
|
provider: "ALIPAY",
|
||||||
name: "支付宝",
|
name: "支付宝",
|
||||||
isEnabled: false,
|
isEnabled: false,
|
||||||
baseUrl: "",
|
baseUrl: "https://openapi.alipay.com",
|
||||||
alipayAppId: "",
|
alipayAppId: "",
|
||||||
alipayPrivateKey: "",
|
alipayPrivateKey: "",
|
||||||
alipayPublicKey: "",
|
alipayPublicKey: "",
|
||||||
|
|||||||
@@ -212,11 +212,11 @@
|
|||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">API Key</span>
|
<span class="label-text font-medium">API Key</span>
|
||||||
<input v-model="configForm.apiKey" class="input input-bordered w-full" />
|
<SecretInput v-model="configForm.apiKey" />
|
||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">Secret Key</span>
|
<span class="label-text font-medium">Secret Key</span>
|
||||||
<input v-model="configForm.secretKey" class="input input-bordered w-full" :disabled="configForm.apiProvider !== 'MAILJET'" :placeholder="configForm.apiProvider === 'MAILJET' ? 'Mailjet Secret Key' : 'Brevo 不需要该字段'" />
|
<SecretInput v-model="configForm.secretKey" :disabled="configForm.apiProvider !== 'MAILJET'" :placeholder="configForm.apiProvider === 'MAILJET' ? 'Mailjet Secret Key' : 'Brevo 不需要该字段'" />
|
||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">超时(ms)</span>
|
<span class="label-text font-medium">超时(ms)</span>
|
||||||
@@ -253,7 +253,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">SMTP 密码</span>
|
<span class="label-text font-medium">SMTP 密码</span>
|
||||||
<input v-model="configForm.smtpPassword" class="input input-bordered w-full" />
|
<SecretInput v-model="configForm.smtpPassword" />
|
||||||
</label><label class="flex flex-col gap-1.5">
|
</label><label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">认证方式</span>
|
<span class="label-text font-medium">认证方式</span>
|
||||||
<select v-model="configForm.smtpAuthType" class="select select-bordered w-full">
|
<select v-model="configForm.smtpAuthType" class="select select-bordered w-full">
|
||||||
@@ -480,6 +480,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import SecretInput from "../../../components/SecretInput.vue";
|
||||||
import { normalizeTelefuncError } from "../../../lib/app-error";
|
import { normalizeTelefuncError } from "../../../lib/app-error";
|
||||||
import { reactive, ref, computed } from "vue";
|
import { reactive, ref, computed } from "vue";
|
||||||
import { useData } from "vike-vue/useData";
|
import { useData } from "vike-vue/useData";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<option value="">全部支付方式</option>
|
<option value="">全部支付方式</option>
|
||||||
<option value="EPAY">易支付</option>
|
<option value="EPAY">易支付</option>
|
||||||
<option value="ALIPAY">支付宝</option>
|
<option value="ALIPAY">支付宝</option>
|
||||||
<option value="BEPUSDT">USDT</option>
|
<option value="BEPUSDT">BEpusdt</option>
|
||||||
</select>
|
</select>
|
||||||
<select v-model="filter.status" class="select select-sm select-bordered w-32">
|
<select v-model="filter.status" class="select select-sm select-bordered w-32">
|
||||||
<option value="">全部状态</option>
|
<option value="">全部状态</option>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div role="tablist" class="tabs tabs-border">
|
<div role="tablist" class="tabs tabs-border">
|
||||||
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'BEPUSDT' }" @click="activeTab = 'BEPUSDT'">
|
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'BEPUSDT' }" @click="activeTab = 'BEPUSDT'">
|
||||||
BEpusdt / USDT
|
BEpusdt
|
||||||
<span v-if="localConfigs.BEPUSDT?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
<span v-if="localConfigs.BEPUSDT?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
||||||
</a>
|
</a>
|
||||||
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'EPAY' }" @click="activeTab = 'EPAY'">
|
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'EPAY' }" @click="activeTab = 'EPAY'">
|
||||||
Epay / 聚合支付
|
Epay
|
||||||
<span v-if="localConfigs.EPAY?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
<span v-if="localConfigs.EPAY?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
||||||
</a>
|
</a>
|
||||||
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'ALIPAY' }" @click="activeTab = 'ALIPAY'">
|
<a role="tab" class="tab" :class="{ 'tab-active': activeTab === 'ALIPAY' }" @click="activeTab = 'ALIPAY'">
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
<span v-if="localConfigs.ALIPAY?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
<span v-if="localConfigs.ALIPAY?.isEnabled" class="ml-1.5 inline-block w-2 h-2 rounded-full bg-success"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<PaymentConfigCard v-if="activeTab === 'BEPUSDT'" provider="BEPUSDT" title="BEpusdt / USDT" :initial-value="localConfigs.BEPUSDT" @saved="localConfigs.BEPUSDT = $event" />
|
<PaymentConfigCard v-if="activeTab === 'BEPUSDT'" provider="BEPUSDT" title="Usdt/Usdc(数字货币)" :initial-value="localConfigs.BEPUSDT" @saved="localConfigs.BEPUSDT = $event" />
|
||||||
<PaymentConfigCard v-if="activeTab === 'EPAY'" provider="EPAY" title="Epay / 聚合支付" :initial-value="localConfigs.EPAY" @saved="localConfigs.EPAY = $event" />
|
<PaymentConfigCard v-if="activeTab === 'EPAY'" provider="EPAY" title="易支付(聚合支付)" :initial-value="localConfigs.EPAY" @saved="localConfigs.EPAY = $event" />
|
||||||
<PaymentConfigCard v-if="activeTab === 'ALIPAY'" provider="ALIPAY" title="支付宝" :initial-value="localConfigs.ALIPAY" @saved="localConfigs.ALIPAY = $event" />
|
<PaymentConfigCard v-if="activeTab === 'ALIPAY'" provider="ALIPAY" title="支付宝(官方)" :initial-value="localConfigs.ALIPAY" @saved="localConfigs.ALIPAY = $event" />
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
<input v-model="form.name" class="input input-bordered w-full" />
|
<input v-model="form.name" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">网关地址</span>
|
<span class="label-text font-medium">网关地址(仅需填写主域名,系统处理接口)</span>
|
||||||
<input v-model="form.baseUrl" class="input input-bordered w-full" placeholder="https://example.com" />
|
<input v-model="form.baseUrl" class="input input-bordered w-full" placeholder="https://pay.example.com (末尾请勿加斜杠)" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ const props = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
name: props.initialValue?.name ?? (props.provider === 'BEPUSDT' ? 'USDT' : '聚合支付'),
|
name: props.initialValue?.name ?? (props.provider === 'BEPUSDT' ? 'BEpusdt' : '聚合支付'),
|
||||||
isEnabled: props.initialValue?.isEnabled ?? false,
|
isEnabled: props.initialValue?.isEnabled ?? false,
|
||||||
baseUrl: props.initialValue?.baseUrl ?? '',
|
baseUrl: props.initialValue?.baseUrl ?? '',
|
||||||
notifyUrl: props.initialValue?.notifyUrl ?? '',
|
notifyUrl: props.initialValue?.notifyUrl ?? '',
|
||||||
|
|||||||
@@ -8,16 +8,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">应用私钥(PKCS#8,去掉头尾和换行)</span>
|
<span class="label-text font-medium">应用私钥(PKCS#8,去掉头尾和换行)</span>
|
||||||
<textarea v-model="modelValue.alipayPrivateKey" class="textarea textarea-bordered w-full font-mono text-xs" rows="4" placeholder="MIIEvgIBADANBgkq..." />
|
<SecretInput v-model="modelValue.alipayPrivateKey" placeholder="MIIEvgIBADANBgkq..." />
|
||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">支付宝公钥(用于验签,去掉头尾和换行)</span>
|
<span class="label-text font-medium">支付宝公钥(用于验签,去掉头尾和换行)</span>
|
||||||
<textarea v-model="modelValue.alipayPublicKey" class="textarea textarea-bordered w-full font-mono text-xs" rows="3" placeholder="MIIBIjANBgkq..." />
|
<SecretInput v-model="modelValue.alipayPublicKey" placeholder="MIIBIjANBgkq..." />
|
||||||
</label>
|
</label>
|
||||||
<p class="text-xs text-base-content/60">密钥生成工具:<a href="https://opendocs.alipay.com/common/02kipl" target="_blank" class="link">支付宝密钥工具</a></p>
|
<p class="text-xs text-base-content/60">密钥生成工具:<a href="https://opendocs.alipay.com/common/02kipl" target="_blank" class="link">支付宝密钥工具</a></p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import SecretInput from "../../../../components/SecretInput.vue";
|
||||||
defineProps<{ modelValue: Record<string, any> }>();
|
defineProps<{ modelValue: Record<string, any> }>();
|
||||||
</script>
|
</script>
|
||||||
@@ -6,11 +6,12 @@
|
|||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">App Secret</span>
|
<span class="label-text font-medium">App Secret</span>
|
||||||
<input v-model="modelValue.appSecret" class="input input-bordered w-full" />
|
<SecretInput v-model="modelValue.appSecret" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import SecretInput from "../../../../components/SecretInput.vue";
|
||||||
defineProps<{ modelValue: Record<string, any> }>();
|
defineProps<{ modelValue: Record<string, any> }>();
|
||||||
</script>
|
</script>
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<label class="flex flex-col gap-1.5">
|
<label class="flex flex-col gap-1.5">
|
||||||
<span class="label-text font-medium">Key</span>
|
<span class="label-text font-medium">Key</span>
|
||||||
<input v-model="modelValue.key" class="input input-bordered w-full" />
|
<SecretInput v-model="modelValue.key" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-base-content/60">
|
<p class="text-xs text-base-content/60">
|
||||||
@@ -15,5 +15,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import SecretInput from "../../../../components/SecretInput.vue";
|
||||||
defineProps<{ modelValue: Record<string, any> }>();
|
defineProps<{ modelValue: Record<string, any> }>();
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user