完成50%

This commit is contained in:
2026-07-23 08:23:59 +08:00
parent 9b0ad62df4
commit f1edc6b533
218 changed files with 24318 additions and 5514 deletions
+7
View File
@@ -0,0 +1,7 @@
#tianai-captcha-parent{box-shadow:0 0 11px 0 #999;width:318px;height:318px;overflow:hidden;position:relative;z-index:997;box-sizing:border-box;border-radius:5px;padding:8px}#tianai-captcha-parent #tianai-captcha-box{height:260px;width:100%;position:relative;overflow:hidden}#tianai-captcha-parent #tianai-captcha-box .loading{width:120px;height:20px;-webkit-mask:linear-gradient(90deg, #000 70%, rgba(0, 0, 0, 0) 0) 0/20%;background:linear-gradient(#f7b645 0 0) 0/0% no-repeat rgba(221,221,221,.4196078431);animation:cartoon 1s infinite steps(6);margin:120px auto}@keyframes cartoon{100%{background-size:120%}}#tianai-captcha-parent #tianai-captcha-box #tianai-captcha{transform-style:preserve-3d;will-change:transform;transition-duration:.45s;transform:translateX(-300px)}#tianai-captcha-parent #tianai-captcha-bg-img{background-color:#fff;background-position:top;background-size:cover;z-index:-1;width:100%;height:100%;top:0;left:0;position:absolute;border-radius:6px}#tianai-captcha-parent .slider-bottom{height:19px;width:100%}#tianai-captcha-parent .slider-bottom .close-btn{width:20px;height:20px;background-image:url(../../tac/images/icon.png);background-repeat:no-repeat;background-position:0 -14px;float:right;margin-right:2px;cursor:pointer}#tianai-captcha-parent .slider-bottom .refresh-btn{width:20px;height:20px;background-image:url(../../tac/images/icon.png);background-position:0 -167px;background-repeat:no-repeat;float:right;margin-right:10px;cursor:pointer}#tianai-captcha-parent .slider-bottom .logo{height:30px;float:left}#tianai-captcha-parent .slider-move-shadow{animation:myanimation 2s infinite;height:100%;width:5px;background-color:#fff;position:absolute;top:0;left:0;filter:opacity(0.5);box-shadow:1px 1px 1px #fff;border-radius:50%}#tianai-captcha-parent #tianai-captcha-slider-move-track-mask{border-width:1px;border-style:solid;border-color:#00f4ab;width:0;height:32px;background-color:#a9ffe5;opacity:.5;position:absolute;top:-1px;left:-1px;border-radius:5px}
#tianai-captcha{text-align:left;box-sizing:content-box;width:300px;height:260px;z-index:999}#tianai-captcha .slider-bottom .logo{height:30px}#tianai-captcha .slider-bottom{height:19px;width:100%}#tianai-captcha .content .tianai-captcha-tips{height:25px;width:100%;position:absolute;bottom:-25px;left:0;z-index:999;font-size:15px;line-height:25px;color:#fff;text-align:center;transition:bottom .3s ease-in-out}#tianai-captcha .content .tianai-captcha-tips.tianai-captcha-tips-error{background-color:#ff5d39}#tianai-captcha .content .tianai-captcha-tips.tianai-captcha-tips-success{background-color:#39c522}#tianai-captcha .content .tianai-captcha-tips.tianai-captcha-tips-on{bottom:0}#tianai-captcha .content #tianai-captcha-loading{z-index:9999;background-color:#f5f5f5;text-align:center;height:100%;overflow:hidden;position:relative;display:flex;justify-content:center;align-items:center}#tianai-captcha .content #tianai-captcha-loading img{display:block;width:45px;height:45px}#tianai-captcha #tianai-captcha-slider-bg-canvas{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:5px}#tianai-captcha #tianai-captcha-slider-bg-div{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:5px}#tianai-captcha #tianai-captcha-slider-bg-div .tianai-captcha-slider-bg-div-slice{position:absolute}@keyframes myanimation{from{left:0}to{left:289px}}
#tianai-captcha.tianai-captcha-slider{z-index:999;position:absolute;left:0;top:0;user-select:none}#tianai-captcha.tianai-captcha-slider .content{width:100%;height:180px;position:relative;overflow:hidden}#tianai-captcha.tianai-captcha-slider .bg-img-div{width:100%;height:100%;position:absolute;transform:translate(0px, 0px)}#tianai-captcha.tianai-captcha-slider .bg-img-div img{height:100%;width:100%;border-radius:5px}#tianai-captcha.tianai-captcha-slider .slider-img-div{height:100%;position:absolute;left:0;transform:translate(0px, 0px)}#tianai-captcha.tianai-captcha-slider .slider-img-div #tianai-captcha-slider-move-img{height:100%}#tianai-captcha.tianai-captcha-slider .slider-move{height:34px;width:100%;margin:11px 0;position:relative}#tianai-captcha.tianai-captcha-slider .slider-move-track{position:relative;height:32px;line-height:32px;text-align:center;background:#f5f5f5;color:#999;transition:0s;font-size:14px;box-sizing:content-box;border:1px solid #f5f5f5;border-radius:4px}#tianai-captcha.tianai-captcha-slider .refresh-btn,#tianai-captcha.tianai-captcha-slider .close-btn{display:inline-block}#tianai-captcha.tianai-captcha-slider .slider-move{line-height:38px;font-size:14px;text-align:center;white-space:nowrap;color:#88949d;-moz-user-select:none;-webkit-user-select:none;user-select:none;filter:opacity(0.8)}#tianai-captcha.tianai-captcha-slider .slider-move .slider-move-btn{transform:translate(0px, 0px);position:absolute;top:-6px;left:0;width:63px;height:45px;background-color:#fff;background-repeat:no-repeat;background-size:contain;border-radius:5px}#tianai-captcha.tianai-captcha-slider .slider-tip{margin-bottom:5px;font-weight:bold;font-size:15px;line-height:normal;color:#000}#tianai-captcha.tianai-captcha-slider .slider-move-btn:hover{cursor:pointer}
#tianai-captcha.tianai-captcha-rotate .rotate-img-div{height:100%;text-align:center}#tianai-captcha.tianai-captcha-rotate .rotate-img-div img{height:100%;transform:rotate(0deg);display:inline-block}
#tianai-captcha.tianai-captcha-concat .tianai-captcha-slider-concat-img-div{background-size:100% 180px;position:absolute;transform:translate(0px, 0px);z-index:1;width:100%}#tianai-captcha.tianai-captcha-concat .tianai-captcha-slider-concat-bg-img{width:100%;height:100%;position:absolute;transform:translate(0px, 0px);background-size:100% 180px}
#tianai-captcha.tianai-captcha-disable{z-index:999;position:absolute;left:0;top:0}#tianai-captcha.tianai-captcha-disable .content{width:100%;height:180px;position:relative;overflow:hidden}#tianai-captcha.tianai-captcha-disable .content .bg-img-div{background-image:url(../../tac/images/dun.jpeg);width:100%;height:100%;overflow:hidden}#tianai-captcha.tianai-captcha-disable .content .bg-img-div #content-span{color:#fff;overflow:hidden;margin-top:132px;display:block;text-align:center}
#tianai-captcha.tianai-captcha-word-click{box-sizing:border-box}#tianai-captcha.tianai-captcha-word-click .click-tip{position:relative;height:40px;width:100%}#tianai-captcha.tianai-captcha-word-click .click-tip .tip-img{height:35px;position:absolute;right:15px}#tianai-captcha.tianai-captcha-word-click .click-tip #tianai-captcha-click-track-font{font-size:18px;display:inline-block;height:40px;line-height:40px;position:absolute}#tianai-captcha.tianai-captcha-word-click .slider-bottom{position:relative;top:6px}#tianai-captcha.tianai-captcha-word-click .content #bg-img-click-mask{width:100%;height:100%;position:absolute;left:0;top:0}#tianai-captcha.tianai-captcha-word-click .content #bg-img-click-mask .click-span{position:absolute;left:0;top:0;border-radius:50px;background-color:#409eff;width:20px;height:20px;text-align:center;line-height:20px;color:#fff;border:2px solid #fff;box-sizing:content-box}#tianai-captcha.tianai-captcha-word-click .click-confirm-btn{width:100%;height:35px;border-radius:4px;background-image:linear-gradient(173deg, hsl(38.09, 91%, 57.89%) 0%, hsl(38.09, 89.38%, 71.74%) 100%);font-size:15px;text-align:center;box-sizing:border-box;line-height:35px;color:#fff;margin-top:3px}#tianai-captcha.tianai-captcha-word-click .click-confirm-btn:hover{cursor:pointer}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

+164
View File
@@ -0,0 +1,164 @@
(function attachJiapuTacAdapter(global) {
"use strict";
var SUPPORTED_TYPES = ["SLIDER", "ROTATE", "CONCAT", "WORD_IMAGE_CLICK"];
function fail(message, code) {
var error = new Error(message);
error.code = code || "TAC_PROTOCOL_INVALID";
throw error;
}
function text(value, label) {
if (typeof value !== "string" || !value.trim()) fail(label + "不能为空");
return value.trim();
}
function positiveInteger(value, label) {
var number = Number(value);
if (!Number.isInteger(number) || number < 1) fail(label + "必须是正整数");
return number;
}
function assertContext(context) {
if (!context || typeof context !== "object") fail("TAC 请求上下文无效");
return {
tenantId: text(context.tenantId, "租户标识"),
clientId: text(context.clientId, "客户端标识"),
sceneCode: text(context.sceneCode, "验证场景"),
subject: text(context.subject, "验证主体"),
providerCode: text(context.providerCode, "验证服务商").toUpperCase(),
captchaType: text(context.captchaType, "验证码类型").toUpperCase(),
};
}
function assertChallengePayload(type, payload) {
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
fail("行为验证挑战缺少渲染载荷");
}
if (type === "CONCAT") {
text(payload.backgroundImage, "拼图背景图片");
positiveInteger(payload.backgroundImageHeight, "拼图背景高度");
if (!payload.data || !Number.isFinite(Number(payload.data.randomY))) {
fail("拼图挑战缺少 randomY");
}
return;
}
text(payload.backgroundImage, "行为验证背景图片");
text(payload.templateImage, "行为验证模板图片");
}
function normalizeChallengeResponse(response, expectedContext) {
var context = assertContext(expectedContext);
if (!response || typeof response !== "object" || Number(response.code) !== 200) {
fail((response && response.msg) || "行为验证挑战请求失败", "TAC_CHALLENGE_FAILED");
}
var data = response.data;
if (!data || typeof data !== "object" || data.required !== true) {
fail("行为验证挑战未处于强制验证状态", "TAC_CHALLENGE_NOT_REQUIRED");
}
var providerCode = text(data.providerCode, "挑战服务商").toUpperCase();
var captchaType = text(data.captchaType, "挑战验证码类型").toUpperCase();
if (providerCode !== "TIANAI" || providerCode !== context.providerCode) {
fail("行为验证挑战服务商不匹配", "TAC_PROVIDER_MISMATCH");
}
if (SUPPORTED_TYPES.indexOf(captchaType) < 0 || captchaType !== context.captchaType) {
fail("行为验证挑战类型不匹配", "TAC_TYPE_MISMATCH");
}
var challengeId = text(data.challengeId, "行为验证挑战标识");
var expireSeconds = positiveInteger(data.expireSeconds, "行为验证挑战有效期");
assertChallengePayload(captchaType, data.payload);
return {
challenge: {
required: true,
providerCode: providerCode,
captchaType: captchaType,
challengeId: challengeId,
expireSeconds: expireSeconds,
},
sdkResponse: {
code: 200,
msg: typeof response.msg === "string" ? response.msg : "操作成功",
data: Object.assign({}, data.payload, {
type: captchaType,
id: challengeId,
}),
},
};
}
function assertTrack(track) {
if (!track || typeof track !== "object" || Array.isArray(track)) fail("行为验证轨迹无效");
positiveInteger(track.bgImageWidth, "轨迹背景宽度");
positiveInteger(track.bgImageHeight, "轨迹背景高度");
var startTime = Number(track.startTime);
var stopTime = Number(track.stopTime);
if (!Number.isFinite(startTime) || !Number.isFinite(stopTime) || stopTime < startTime) {
fail("行为验证轨迹时间无效");
}
if (!Array.isArray(track.trackList) || track.trackList.length < 1) {
fail("行为验证轨迹不能为空");
}
track.trackList.forEach(function validatePoint(point) {
if (!point || !Number.isFinite(Number(point.x)) || !Number.isFinite(Number(point.y)) ||
!Number.isFinite(Number(point.t)) || typeof point.type !== "string" || !point.type) {
fail("行为验证轨迹点无效");
}
});
return track;
}
function buildVerifyBody(libraryRequest, expectedContext, challenge) {
var context = assertContext(expectedContext);
if (!challenge || typeof challenge !== "object") fail("行为验证挑战上下文缺失");
var challengeId = text(challenge.challengeId, "行为验证挑战标识");
if (!libraryRequest || libraryRequest.id !== challengeId) {
fail("行为验证 challenge 标识与当前挑战不匹配", "TAC_CHALLENGE_MISMATCH");
}
if (challenge.providerCode !== context.providerCode || challenge.captchaType !== context.captchaType) {
fail("行为验证挑战上下文已变化", "TAC_CONTEXT_MISMATCH");
}
return {
tenantId: context.tenantId,
clientId: context.clientId,
sceneCode: context.sceneCode,
subject: context.subject,
challengeId: challengeId,
providerCode: challenge.providerCode,
captchaType: challenge.captchaType,
// 受保护 OpenAPI 的唯一合同是 payload.trackSDK 回调 id 已提升为 challengeId
// 不得再次混入 payload,也不得退回“直接传 track”的兼容分支。
payload: { track: assertTrack(libraryRequest.data) },
};
}
function normalizeVerifyResponse(response) {
if (!response || typeof response !== "object" || Number(response.code) !== 200) {
fail((response && response.msg) || "行为验证请求失败", "TAC_VERIFY_REQUEST_FAILED");
}
var data = response.data;
if (!data || data.passed !== true) {
fail((data && data.message) || "行为验证未通过", "TAC_VERIFY_REJECTED");
}
var validToken = text(data.validToken, "行为验证票据");
var expireSeconds = positiveInteger(data.expireSeconds, "行为验证票据有效期");
return {
code: 200,
data: { passed: true, validToken: validToken, expireSeconds: expireSeconds },
};
}
function toSdkFailure(error) {
return {
code: 4001,
msg: error && error.message ? error.message : "行为验证失败,请重试",
};
}
global.JiapuTacAdapter = Object.freeze({
normalizeChallengeResponse: normalizeChallengeResponse,
buildVerifyBody: buildVerifyBody,
normalizeVerifyResponse: normalizeVerifyResponse,
toSdkFailure: toSdkFailure,
});
})(typeof window !== "undefined" ? window : globalThis);
+1
View File
File diff suppressed because one or more lines are too long