This commit is contained in:
2025-10-24 15:05:27 +08:00
parent 767af75aad
commit a4ae06ea52
6 changed files with 25 additions and 25 deletions

View File

@@ -9,7 +9,11 @@
<template v-if="!licenseDisplayInfo.isPaid">
<button class="action-btn" @click="refreshLicenseStatus" :disabled="checking" ref="checkButton">{{ $t('license.button.checkLicense.label') }}</button>
<kuc-tooltip :title="$t('license.button.checkLicense.desc')" :container="checkButton"></kuc-tooltip>
<button class="action-btn main" @click="purchaseLicense" ref="buyButton">{{ $t('license.button.purchase.label') }}</button>
<button class="action-btn main" @click="purchaseLicense" ref="buyButton">{{ $t('license.button.purchase.label') }}
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="open-icon">
<path d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<kuc-tooltip :title="$t('license.button.purchase.desc')" :container="buyButton"></kuc-tooltip>
</template>
<button v-else class="action-btn" @click="hidePaidMsg">{{ $t('license.button.hide') }}</button>
@@ -134,9 +138,10 @@ async function refreshLicenseStatus() {
}
function purchaseLicense() {
alert(
`请联系管理员或访问官方网站购买许可证。\nDomain: ${licenseInfo.value?.domain}\nPlugin: ${licenseInfo.value?.pluginId}`,
);
const { name, email } = kintone.getLoginUser();
const domain = licenseInfo.value?.domain;
const pluginId = licenseInfo.value?.pluginId;
window.open(`https://alisurvey.alicorns.co.jp/s/Iuc5RxZv?input1761283180784=${domain}&input1761283200616=${pluginId}&input1761283314263=${name}&input1761283275767=${email}`);
}
function hidePaidMsg() {

View File

@@ -70,14 +70,19 @@
border-color: #33691E;
}
.license-status-info .action-btn .open-icon {
margin-left: 2px;
vertical-align: middle;
}
.notification-link {
color: #fff;
opacity: 0.8;
text-decoration: underline;
}
.notification-link:hover {
opacity: 1;
color: #fff;
opacity: 0.8;
}
.text-red {

View File

@@ -54,7 +54,8 @@ export default {
},
error: {
fetchFailed: 'Remote license check failed: {e}',
checkFailed: 'License check failed, plugin disabled: {e}'
checkFailed: 'License check failed, plugin disabled: {e}',
jwtFailed: 'JWT verification or parsing failed: {e}',
}
},
};

View File

@@ -42,7 +42,7 @@ export default {
},
notification: {
days: '今日 | 明日 | {count}日後',
gotoLink: 'ご利用には<a class="notification-link" href="{link}">プラグインの設定</a>をご確認ください。',
gotoLink: 'ご利用には<a class="notification-link" href="{link}">プラグインの設定</a>をご確認ください。',
expired: 'プラグイン「{plugin}」の有効期限が切れました。',
warning: 'プラグイン「{plugin}」の試用期間が{days}で終了します。'
},
@@ -57,7 +57,8 @@ export default {
},
error: {
fetchFailed: 'リモートライセンスチェックに失敗しました: {e}',
checkFailed: 'ライセンスチェックに失敗しました。プラグイン機能が無効になりました: {e}'
checkFailed: 'ライセンスチェックに失敗しました。プラグイン機能が無効になりました: {e}',
jwtFailed: 'JWTの検証または解析に失敗しました: {e}',
}
},
};

View File

@@ -51,11 +51,11 @@ export class LicenseService {
// 验证完整的JWT
const result = KJUR.jws.JWS.verifyJWT(savedLicense.jwt, rsaPublicKey.trim(), {alg: ['RS256']});
if (!result) {
console.warn('JWT signature verification failed');
console.warn($t('license.error.jwtFailed', { e : '' }));
return false;
}
} catch (error) {
console.error('JWT verification or parsing failed:', error);
console.warn($t('license.error.jwtFailed', { e : error }));
return false;
}

View File

@@ -1,24 +1,12 @@
// 本地存储加密工具类
import { LicenseService } from '@/services/license-service';
import type { LicenseInfo, LicenseJWSResult, LicenseSetting, SavedLicense } from '@/types/license';
import type { LicenseJWSResult, LicenseSetting, SavedLicense } from '@/types/license';
import { KJUR } from 'jsrsasign';
export class LicenseStorage {
private static readonly STORAGE_KEY_PREFIX = 'alicorns_plugin_';
private static readonly STORAGE_SETTING_KEY_PREFIX = this.STORAGE_KEY_PREFIX + 'setting_';
/**
* 解码JWT不验证
*/
private static parseJWT(jwt: string) {
try {
return KJUR.jws.JWS.parse(jwt);
} catch (error) {
console.error('JWT parsing failed:', error);
return null;
}
}
/**
* 生成存储key
*/
@@ -89,7 +77,7 @@ export class LicenseStorage {
// decode
let decodedJWT: LicenseJWSResult;
try {
decodedJWT = this.parseJWT(storedJWT) as LicenseJWSResult;
decodedJWT = KJUR.jws.JWS.parse(storedJWT) as LicenseJWSResult;
if (!decodedJWT) {
return null;
}