滑块验证码-备份
<p>[TOC]</p>
<h3>概述</h3>
<p>滑块验证码包括客户端(浏览器)接入和服务端接入。</p>
<p>业务流程:
1、客户端完成滑块动作,滑块正确则返回ticket;
2、客户端完成验证之后,再用客户端返回的ticket,调用服务端校验ticket接口完成验证。</p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=6a69f275600392d27d13f374ec8c77b3&amp;file=file.png" alt="" /></p>
<p>客户端演示:<a href="https://api-js.jumdata.com/slider-captcha/demo.html">https://api-js.jumdata.com/slider-captcha/demo.html</a></p>
<hr />
<h3>客户端接入</h3>
<h4>准备工作</h4>
<p>Web 页面需引入滑块验证码的js,在业务需要验证时,唤起验证码进行验证。</p>
<pre><code class="language-html">&lt;script type=&quot;text/javascript&quot; src=&quot;https://api-js.jumdata.com/slider-captcha/slider-captcha.min.js&quot;&gt;&lt;/script&gt;</code></pre>
<p>> 必须动态引入验证码 JS。如使用本地缓存,或通过其他手段规避动态加载,会导致验证码无法正常更新,对抗能力无法保证,甚至引起误拦截。</p>
<h4>示例代码</h4>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;title&gt;滑块验证码示例 - 聚美智数&lt;/title&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;!-- 验证码程序依赖(必须)。请勿修改以下程序依赖,如使用本地缓存,或通过其他手段规避加载,会导致验证码无法正常更新,对抗能力无法保证,甚至引起误拦截。 --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://api-js.jumdata.com/slider-captcha/slider-captcha.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;button id=&quot;btnCaptcha&quot; type=&quot;button&quot;&gt;验证&lt;/button&gt;
&lt;/body&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
/**
* 回调函数, 在滑块停止时触发
*/
function callback(captchaRes) {
// captchaRes属性如下:
// ret Int 验证结果,0:验证成功。2:用户主动关闭验证码。
// ticket String 验证成功的票据,当且仅当 ret = 0 时 ticket 有值。
// bizState Any 自定义透传参数。
// randstr String 本次验证的随机串,后续票据校验时需传递该参数。
console.log('callback:', captchaRes)
if(captchaRes.ret === 0){
console.log('客户端验证成功')
// todo 此处需要调用接入者的服务端接口,完成验证,详见服务端接入说明
} else {
console.log('验证失败')
}
}
var captcha = new JumeiSliderCaptcha('您的验证码CaptchaAppId(联系服务商开通)', callback, {})
// 定义验证码触发事件
document.getElementById('btnCaptcha').onclick = function () {
captcha.show()
}
&lt;/script&gt;
&lt;/html&gt;</code></pre>
<p>如采用Vue开发,则可以动态引入滑块验证码的js</p>
<pre><code class="language-html">&lt;template&gt;
&lt;div&gt;
&lt;button type=&quot;button&quot; @click=&quot;open&quot;&gt;验证&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
const CAPTCHA_APP_ID = '您的验证码CaptchaAppId(联系服务商开通)';
const SLIDER_CAPTCHA_JS = 'https://api-js.jumdata.com/slider-captcha/slider-captcha.min.js'
export default {
data() {
return {
captcha: null
}
},
created() {
},
mounted() {
// 动态引入滑块验证码的js
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = location.protocol + '//' + location.host + rootPath + SLIDER_CAPTCHA_JS;
let head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(script)
},
methods: {
open() {
if (!this.captcha) {
// 因为mounted的时候滑块验证码的js还没加载,因此JumeiSliderCaptcha实例必须在open的时候创建
this.captcha = new JumeiSliderCaptcha(CAPTCHA_APP_ID, this.callback, {})
}
this.captcha.show()
},
callback(captchaRes) {
// 属性如下:
// ret Int 验证结果,0:验证成功。2:用户主动关闭验证码。
// ticket String 验证成功的票据,当且仅当 ret = 0 时 ticket 有值。
// bizState Any 自定义透传参数。
// randstr String 本次验证的随机串,后续票据校验时需传递该参数。
console.log('callback:', captchaRes)
if(captchaRes.ret === 0){
console.log('客户端验证成功')
// todo 此处需要调用接入者的服务端接口,完成验证,详见服务端接入说明
} else {
console.log('验证失败')
}
}
}
}
&lt;/script&gt;</code></pre>
<h4>JumeiSliderCaptcha 使用说明</h4>
<h5>参数说明</h5>
<table>
<thead>
<tr>
<th>参数名</th>
<th>值类型</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>captchaAppId</td>
<td>String</td>
<td>验证码 CaptchaAppId (联系服务商开通)。 注意:不可使用客户端类型为小程序的 captchaAppId,会导致数据统计错误。</td>
</tr>
<tr>
<td>callback</td>
<td>Function</td>
<td>验证码回调函数,详见 callback 回调函数。</td>
</tr>
<tr>
<td>options</td>
<td>Object</td>
<td>验证码外观配置参数, 详见 options 外观配置参数。</td>
</tr>
</tbody>
</table>
<h5>callback 回调函数</h5>
<p>验证结束后,会调用业务传入的回调函数,并在第一个参数中传入回调结果。回调结果字段说明如下:</p>
<h6>回调函数字段说明</h6>
<table>
<thead>
<tr>
<th>字段名</th>
<th>值类型</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>ret</td>
<td>Int</td>
<td>验证结果,0:验证成功。2:用户主动关闭验证码。</td>
</tr>
<tr>
<td>ticket</td>
<td>String</td>
<td>验证成功的票据,当且仅当 ret = 0 时 ticket 有值。</td>
</tr>
<tr>
<td>bizState</td>
<td>Any</td>
<td>自定义透传参数。</td>
</tr>
<tr>
<td>randstr</td>
<td>String</td>
<td>本次验证的随机串,后续票据校验时需传递该参数。</td>
</tr>
<tr>
<td>errorCode</td>
<td>String</td>
<td>错误 code ,详情请参见 回调函数 errorCode 说明。</td>
</tr>
<tr>
<td>errorMessage</td>
<td>String</td>
<td>错误信息。</td>
</tr>
</tbody>
</table>
<h6>回调函数 errorCode 说明</h6>
<table>
<thead>
<tr>
<th>errorCode</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>1001</td>
<td>加载错误</td>
</tr>
<tr>
<td>1002</td>
<td>调用 show 方法超时</td>
</tr>
<tr>
<td>1003</td>
<td>中间 js 加载超时</td>
</tr>
<tr>
<td>1004</td>
<td>中间 js 加载错误</td>
</tr>
<tr>
<td>1005</td>
<td>中间 js 运行错误</td>
</tr>
<tr>
<td>1006</td>
<td>拉取验证码配置错误/超时</td>
</tr>
<tr>
<td>1007</td>
<td>iframe 加载超时</td>
</tr>
<tr>
<td>1008</td>
<td>iframe 加载错误</td>
</tr>
<tr>
<td>1009</td>
<td>jquery 加载错误</td>
</tr>
<tr>
<td>1010</td>
<td>滑块 js 加载错误</td>
</tr>
<tr>
<td>1011</td>
<td>滑块 js 运行错误</td>
</tr>
<tr>
<td>1012</td>
<td>刷新连续错误 3 次</td>
</tr>
<tr>
<td>1013</td>
<td>验证网络连续错误 3 次</td>
</tr>
</tbody>
</table>
<h5>options 外观配置参数</h5>
<p>options 参数用于对验证码进行定制外观设置,默认可以设置为空。</p>
<p>> 1、验证码弹窗内部不支持调整样式大小,如果需要调整,可在弹窗最外层用 class=tcaptcha-transform 的元素设置 transform:scale();。验证码更新可能会改变元素的 id,class 等属性,请勿依赖其他验证码元素属性值覆盖样式。
> 2、如果手机原生端有设置左右滑动手势,需在调用验证码 show 方法前禁用,验证完成后再打开,防止与验证码滑动事件冲突。</p>
<table>
<thead>
<tr>
<th>配置名</th>
<th>值类型</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>bizState</td>
<td>Any</td>
<td>自定义透传参数,业务可用该字段传递少量数据,该字段的内容会被带入 callback 回调的对象中。</td>
</tr>
<tr>
<td>enableDarkMode</td>
<td>Boolean/String</td>
<td>开启自适应深夜模式: {"enableDarkMode": true} 强制深夜模式: {"enableDarkMode": 'force'}</td>
</tr>
<tr>
<td>sdkOpts</td>
<td>Object</td>
<td>示例 {"width": 140, "height": 140} 仅支持移动端原生 webview 调用时传入,用来设置验证码 loading 加载弹窗的大小(<strong>注意,并非验证码弹窗大小</strong>)。</td>
</tr>
<tr>
<td>ready</td>
<td>Function</td>
<td>验证码加载完成的回调,回调参数为验证码实际的宽高: {"sdkView": { "width": number, "height": number }} 该参数仅为查看验证码宽高使用,<strong>请勿使用此参数直接设定宽高</strong>。</td>
</tr>
<tr>
<td>needFeedBack</td>
<td>Boolean/String</td>
<td>隐藏帮助按钮或自定义帮助按钮链接。 隐藏帮助按钮: {"needFeedBack": false } 自定义帮助链接: {"needFeedBack": 'url 地址' }</td>
</tr>
<tr>
<td>userLanguage</td>
<td>String</td>
<td>指定验证码提示文案的语言,优先级高于控制台配置。 支持传入值同 navigator.language 用户首选语言,大小写不敏感。 详情参见 userLanguage 配置参数。</td>
</tr>
<tr>
<td>type</td>
<td>String</td>
<td>定义验证码展示方式。popup(默认)弹出式,以浮层形式居中弹出展示验证码。embed 嵌入式,以嵌入指定容器元素中的方式展示验证码。</td>
</tr>
</tbody>
</table>
<h5>userLanguage 配置参数</h5>
<table>
<thead>
<tr>
<th>参数名</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>zh-cn</td>
<td>简体中文</td>
</tr>
<tr>
<td>zh-hk</td>
<td>繁体中文(中国香港)</td>
</tr>
<tr>
<td>zh-tw</td>
<td>繁体中文(中国台湾)</td>
</tr>
<tr>
<td>en</td>
<td>英文</td>
</tr>
<tr>
<td>ar</td>
<td>阿拉伯语</td>
</tr>
<tr>
<td>my</td>
<td>缅甸语</td>
</tr>
<tr>
<td>fr</td>
<td>法语</td>
</tr>
<tr>
<td>de</td>
<td>德语</td>
</tr>
<tr>
<td>he</td>
<td>希伯来语</td>
</tr>
<tr>
<td>hi</td>
<td>印地语</td>
</tr>
<tr>
<td>id</td>
<td>印尼语</td>
</tr>
<tr>
<td>it</td>
<td>意大利语</td>
</tr>
<tr>
<td>ja</td>
<td>日语</td>
</tr>
<tr>
<td>ko</td>
<td>朝鲜语</td>
</tr>
<tr>
<td>lo</td>
<td>老挝语</td>
</tr>
<tr>
<td>ms</td>
<td>马来语</td>
</tr>
<tr>
<td>pl</td>
<td>波兰语</td>
</tr>
<tr>
<td>pt</td>
<td>葡萄牙语</td>
</tr>
<tr>
<td>ru</td>
<td>俄语</td>
</tr>
<tr>
<td>es</td>
<td>西班牙语</td>
</tr>
<tr>
<td>th</td>
<td>泰语</td>
</tr>
<tr>
<td>tr</td>
<td>土耳其语</td>
</tr>
<tr>
<td>vi</td>
<td>越南语</td>
</tr>
</tbody>
</table>
<hr />
<h3>服务端接入</h3>
<p>客户端验证成功之后,需要由接入者的服务端再调用服务商的服务端接口完成校验,本接口即完成该功能
> 服务端接口需要采用appId、appSecret生成并且传入sign,请不要在客户端直接调用服务商的服务端接口,以免暴露appSecret。应该由接入者的客户端调用接入者的服务端,再由接入者的服务端调用服务商的服务端接口</p>
<h4>请求方式</h4>
<ul>
<li>POST</li>
</ul>
<h4>请求格式</h4>
<ul>
<li>application/x-www-form-urlencoded</li>
</ul>
<h4>请求参数</h4>
<table>
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>必须</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>appId</td>
<td>String</td>
<td>是</td>
<td>服务商分配的唯一标识</td>
</tr>
<tr>
<td>timestamp</td>
<td>Long</td>
<td>是</td>
<td>当前时间戳(毫秒)</td>
</tr>
<tr>
<td>sign</td>
<td>String</td>
<td>是</td>
<td>签名,详见<a href="#签名算法">签名算法说明</a></td>
</tr>
<tr>
<td>captchaAppId</td>
<td>String</td>
<td>是</td>
<td>验证码 captchaAppId ,和客户端一致</td>
</tr>
<tr>
<td>ticket</td>
<td>String</td>
<td>是</td>
<td>验证码返回给用户的票据</td>
</tr>
<tr>
<td>randstr</td>
<td>String</td>
<td>是</td>
<td>验证票据需要的随机字符串</td>
</tr>
<tr>
<td>ip</td>
<td>String</td>
<td>是</td>
<td>用户操作来源的外网 IP</td>
</tr>
</tbody>
</table>
<p><a name="签名算法"></a></p>
<h4>签名算法说明</h4>
<pre><code>sign = sha256(appId + appSecret + timestamp)</code></pre>
<p>用服务商分配的 <strong>appId</strong>、服务商分配的 <strong>appSecret</strong>,当前时间戳(毫秒) <strong>timestamp</strong>,按上述顺序拼接成字符串,再进行 <strong>sha256</strong> 哈希得到。如下:</p>
<pre><code class="language-java">String appId = &quot;xyzxy2121zxyz&quot;;
String timestamp = &quot;1555378976238&quot;;
String appSecret = &quot;efcefcef1121cefcefc1212121&quot;;
String str = appId + appSecret + timestamp;
String sign = sha256(str);</code></pre>
<h4>验证成功返回样例</h4>
<pre><code class="language-json">{
&quot;code&quot;: 200,
&quot;msg&quot;: &quot;成功&quot;,
&quot;taskNo&quot;: &quot;987272522132093927999832&quot;,
&quot;charge&quot;: true
}</code></pre>
<h4>验证失败返回样例</h4>
<pre><code class="language-json">{
&quot;code&quot;: 301,
&quot;msg&quot;: &quot;验证码不正确&quot;,
&quot;taskNo&quot;: &quot;987272522132093927999832&quot;,
&quot;charge&quot;: true
}</code></pre>
<h4>错误返回</h4>
<pre><code class="language-json">{
&quot;code&quot;: 400,
&quot;msg&quot;: &quot;ticket不能为空&quot;,
&quot;charge&quot;: false
}</code></pre>
<h4>返回字段说明</h4>
<table>
<thead>
<tr>
<th>字段名</th>
<th><div style="width:420px">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>code</td>
<td>返回码,详见:code返回码说明</td>
</tr>
<tr>
<td>msg</td>
<td>code对应的描述</td>
</tr>
<tr>
<td>charge</td>
<td>计费标志 true为计费,false为不计费</td>
</tr>
<tr>
<td>taskNo</td>
<td>本次请求号</td>
</tr>
<tr>
<td>data</td>
<td>返回具体结果,object类型,详见data返回字段描述</td>
</tr>
</tbody>
</table>
<h4>code返回码说明</h4>
<table>
<thead>
<tr>
<th>code</th>
<th><div style="width:420px;">说明</div></th>
</tr>
</thead>
<tbody>
<tr>
<td>200</td>
<td>成功(计费)</td>
</tr>
<tr>
<td>301</td>
<td>验证码不正确(计费)</td>
</tr>
<tr>
<td>302</td>
<td>验证码超时,需要重新获取(计费)</td>
</tr>
<tr>
<td>303</td>
<td>用户来源 ip不匹配(计费)</td>
</tr>
<tr>
<td>400</td>
<td>参数错误</td>
</tr>
<tr>
<td>404</td>
<td>接口地址不正确</td>
</tr>
<tr>
<td>500</td>
<td>系统维护,请稍候再试</td>
</tr>
<tr>
<td>601</td>
<td>接口未开通</td>
</tr>
<tr>
<td>602</td>
<td>账号停用</td>
</tr>
<tr>
<td>604</td>
<td>接口停用</td>
</tr>
<tr>
<td>606</td>
<td>调用超限,请稍候再试</td>
</tr>
<tr>
<td>607</td>
<td>ip不在白名单</td>
</tr>
<tr>
<td>609</td>
<td>请求过于频繁,请稍候再试</td>
</tr>
<tr>
<td>610</td>
<td>请求超时</td>
</tr>
<tr>
<td>999</td>
<td>其他,以实际返回为准</td>
</tr>
</tbody>
</table>