如对接入流程存在疑问,参见快速开始

名词解释

术语描述
验证码业务idcaptchaId(appId), 验证码唯一标识,公开可见,用于区分不同的验证码使用场景,如登录、投票、发帖等。可在云片用户后台验证服务产品管理页面进行创建管理。
密钥对idSecret Id, 请求密钥id,与Secret Key配对使用,用于对二次校验接口参数进行签名计算。
密钥对KeySecret Key, 请求密钥Key, 与密钥id配对使用,用于对二次校验接口参数进行签名计算。
验证用户拖动/点击一次验证码拼图即视为一次“验证”,不论拖动/点击是否正确。
二次校验验证数据随表单提交到产品后台后,产品后台需要将验证数据发送到云片验证服务后台做二次校验,目的是核实验证数据的有效性。
验证码类型滑动拼图、文字点选等,在云片用户后台产品管理页面可以创建并修改

前端接入

web端

兼容性

支持Chrome、IE9+、360、腾讯、搜狗、Safari、Firefox、Opera;主流手机浏览器

引入初始化SDK JS

  1. <script src="https://www.yunpian.com/static/official/js/libs/riddler-sdk-0.2.2.js"></script>

注:IE9+需要在SDK之前额外引入polyfill,示例如下

  1. <script src="https://cdn.bootcss.com/babel-polyfill/7.4.3/polyfill.min.js"></script>

配置验证对象

new YpRiddler(options)options对象为配置对象,以下为配置参数:

参数类型必填备注
onSuccessfunction(validInfo:object, close:function)Y监听验证成功事件。validInfo:验证成功返回参数(token,authenticate);close:关闭验证窗口
appIdstringY应用标识。captchaId
versionstringY接口版本号
containerHTMLElementY验证逻辑绑定的元素
noButtonbooleanF是否在container内渲染按钮,当mode不为flat时有效
modestringFUI接入方式。flat-直接嵌入,float-浮动,dialog-对话框,external-外置滑动(拖动滑块时才浮现验证图片,仅适用于滑动拼图验证) 默认dialog
onErrorfunctionF验证异常处理器。即当云片验证服务出现异常时,可以在此回调上处理,比如,不使用验证,或者,使用图片验证服务等。
onFailfunction(code:int, msg:string, retry:function)F用户验证失败处理器, code: 错误码,msg: 错误信息,retry: 重试验证逻辑。默认实现为重新验证一次。
beforeStartfunction(next:function)F进入验证逻辑前的勾子。next: 继续执行后续逻辑
expiredintF请求过期时限。单位秒,默认30
jsonpFieldstringFjsonp处理器名。默认为ypjsonp
rsaPublicKeystringF加密公钥。如非异常情况则无需设置
hostsstringF验证服务器地址。如非异常情况则无需设置
winWidthnumber/stringF窗口宽度。宽度最小230px: 两种方式:1. 纯数字格式,单位px. 默认500; 2. 百分比格式, 比如80%,表示相对当前浏览器可视区域宽度的百分比。不小于230px
langstringF支持语言,默认简体中文。zh-cn(简体中文)、en(英文)
langPackobjectF外部导入所需设置语言文案。需按指定格式设置对象导入,当外部导入语言包时,lang设置会自动失效

winWidth窗口宽度配置

  1. // 设置窗口宽度为固定值(px)
  2. new YpRiddler({
  3. ...
  4. winWidth: '500'
  5. ...
  6. })
  7. // 设置窗口宽度为屏幕宽度的百分比(窗口宽度winWidth = 屏幕宽度 * %)
  8. new YpRiddler({
  9. ...
  10. winWidth: '30%'
  11. ...
  12. })

lang配置(可选)

系统默认支持中文,如需要替换其他语言请进行如下配置。目前支持的语言有:简体中文、英文。如果需要设置文案的语言,可通过外部文件,按指定格式设置文案内容,然后在options配置项中通过langPack传入语言对象(object)即可。

  1. // 语言模版
  2. const LANG_OTHER = {
  3. 'YPcaptcha_01': '请点击按钮开始验证',
  4. 'YPcaptcha_02': '请按顺序点击:',
  5. 'YPcaptcha_03': '向右拖动滑块填充拼图',
  6. 'YPcaptcha_04': '验证失败,请重试',
  7. 'YPcaptcha_05': '验证成功',
  8. 'YPcaptcha_06': '验证失败'
  9. }
  10. new YpRiddler({
  11. ...
  12. langPack: LANG_OTHER
  13. ...
  14. })

Demo

  1. <html>
  2. <head>
  3. <!--依赖-->
  4. <script src="https://www.yunpian.com/static/official/js/libs/riddler-sdk-0.2.2.js"></script>
  5. <script>
  6. window.onload = function () {
  7. // 初始化
  8. new YpRiddler({
  9. expired: 10,
  10. mode: 'dialog',
  11. winWidth: 500,
  12. lang: 'zh-cn', // 界面语言, 目前支持: 中文简体 zh-cn, 英语 en
  13. // langPack: LANG_OTHER, // 你可以通过该参数自定义语言包, 其优先级高于lang
  14. container: document.getElementById('cbox'),
  15. appId: 'your-app-id',
  16. version: 'v1',
  17. onError: function (param) {
  18. if (param.code == 429) {
  19. alert('请求过于频繁,请稍后再试!')
  20. return
  21. }
  22. // 异常回调
  23. console.error('验证服务异常')
  24. },
  25. onSuccess: function (validInfo, close) {
  26. // 成功回调
  27. alert(`验证通过!token=${validInfo.token}, authenticate=${validInfo.authenticate}`)
  28. close()
  29. },
  30. onFail: function (code, msg, retry) {
  31. // 失败回调
  32. alert('出错啦:' + msg + ' code: ' + code)
  33. retry()
  34. },
  35. beforeStart: function (next) {
  36. console.log('验证马上开始')
  37. next()
  38. },
  39. onExit: function () {
  40. // 退出验证 (仅限dialog模式有效)
  41. console.log('退出验证')
  42. }
  43. })
  44. }
  45. </script>
  46. </head>
  47. <body>
  48. <div id="cbox"></div>
  49. </body>
  50. </html>

接入成功样例

前端接入完成后,通过谷歌浏览器的Network查看请求记录,verify请求会返回两个参数:authenticatetoken图片

后端接入

接口名称

二次验证接口

接口地址

https://captcha.yunpian.com/v1/api/authenticate

请求

  • 请求方式:POST
  • 请求类型:application/x-www-form-urlencoded

请求参数

参数类型必填备注
captchaIdstringY验证产品 id
tokenstringY前端从verfiy接口获取的token,token 作为一次验证的标志。
authenticatestringY前端从verfiy接口验证通过后,返回的参数
secretIdstringY验证产品密钥 id
versionstringY版本,固定值1.0
userstringF可选值,接入方用户标志,如担心信息泄露,可采用摘要方式给出。
timestampstringY当前时间戳的毫秒值,如1541064141441
noncestringY随机正整数, 在 1-99999 之间,与 timestamp 配合可以防止消息重放
signaturestringY签名信息,见签名计算方法

支持的语言及请求示例

Java请求示例

  1. import java.io.IOException;
  2. import java.net.URISyntaxException;
  3. import java.util.Arrays;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.Random;
  7. import org.apache.commons.codec.digest.DigestUtils;
  8. import org.apache.commons.httpclient.HttpClient;
  9. import org.apache.commons.httpclient.methods.PostMethod;
  10. /**
  11. * A demo for YunPian CAPTCHA authenticate API
  12. */
  13. public class AuthenticateDemo {
  14. private static String AUTH_URL = "https://captcha.yunpian.com/v1/api/authenticate";
  15. public static void main(String[] args) throws IOException, URISyntaxException {
  16. Map<String, String> paramMap = new HashMap<>();
  17. // replace the following "{example}"s with actual values
  18. paramMap.put("captchaId", "{captchaId}");
  19. paramMap.put("secretId", "{secretId}");
  20. paramMap.put("token", "{token}");
  21. paramMap.put("authenticate", "{authenticate}");
  22. paramMap.put("version", "1.0");
  23. paramMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
  24. paramMap.put("nonce", String.valueOf(new Random().nextInt(99999)));
  25. paramMap.put("user", "{user}"); // user is optional
  26. String signature = genSignature("{secretKey}", paramMap);
  27. paramMap.put("signature", signature);
  28. StringBuilder sb = new StringBuilder();
  29. PostMethod postMethod = new PostMethod(AUTH_URL);
  30. postMethod.addRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  31. paramMap.forEach((k, v) -> {
  32. postMethod.addParameter(k, v);
  33. });
  34. HttpClient httpClient = new HttpClient();
  35. int status = httpClient.executeMethod(postMethod);
  36. String responseBodyAsString = postMethod.getResponseBodyAsString();
  37. System.out.println(responseBodyAsString);
  38. }
  39. // generate signature
  40. private static String genSignature(String secretKey, Map<String, String> params) {
  41. String[] keys = params.keySet().toArray(new String[0]);
  42. Arrays.sort(keys);
  43. StringBuilder sb = new StringBuilder();
  44. for (String key : keys) {
  45. sb.append(key).append(params.get(key));
  46. }
  47. sb.append(secretKey);
  48. return DigestUtils.md5Hex(sb.toString());
  49. }
  50. }

C#请求示例

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8. using System.Web;
  9. namespace ConsoleApp1
  10. {
  11. /// A demo for YunPian CAPTCHA authenticate API
  12. class AuthenticateDemo
  13. {
  14. protected const string AUTH_URL = "https://captcha.yunpian.com/v1/api/authenticate";
  15. protected const string VERSION = "1.0";
  16. protected const int MAX_NONCE = 99999;
  17. static void Main(string[] args)
  18. {
  19. Dictionary<string, string> parameters = new Dictionary<string, string>();
  20. // replace the following "{example}"s with actual values!!!
  21. parameters.Add("captchaId", "{captchaId}");
  22. parameters.Add("secretId", "{secretId}");
  23. parameters.Add("token", "{token}");
  24. parameters.Add("authenticate", "{authenticate}");
  25. parameters.Add("version", VERSION);
  26. parameters.Add("timestamp", GetCurrentTimeMillis());
  27. parameters.Add("nonce", GetNonce().ToString());
  28. //parameters.Add("user", "{user}"); // user is optional
  29. // generate signature
  30. string sign = GenSignature("{secretKey}", parameters);
  31. parameters.Add("signature", sign);
  32. // authenticate
  33. string retString = PostAuthData(parameters);
  34. Console.WriteLine(retString);
  35. }
  36. // post authenticate data
  37. public static string PostAuthData(Dictionary<string, string> parameters)
  38. {
  39. StringBuilder sb = new StringBuilder();
  40. foreach (var item in parameters)
  41. {
  42. if (sb.Length > 0)
  43. sb.Append("&");
  44. sb.Append(item.Key + "=" + HttpUtility.UrlEncode(item.Value, System.Text.Encoding.UTF8));
  45. }
  46. string data = sb.ToString();
  47. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AUTH_URL);
  48. request.Timeout = 30 * 1000;
  49. request.Method = "POST";
  50. request.ContentType = "application/x-www-form-urlencoded";
  51. request.ContentLength = Encoding.UTF8.GetByteCount(data);
  52. Stream myRequestStream = request.GetRequestStream();
  53. byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(data);
  54. myRequestStream.Write(requestBytes, 0, requestBytes.Length);
  55. myRequestStream.Close();
  56. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  57. Stream myResponseStream = response.GetResponseStream();
  58. StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
  59. string retString = myStreamReader.ReadToEnd();
  60. myStreamReader.Close();
  61. myResponseStream.Close();
  62. return retString;
  63. }
  64. // generate signature
  65. public static String GenSignature(String secretKey, Dictionary<String, String> parameters)
  66. {
  67. parameters = parameters.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value);
  68. StringBuilder builder = new StringBuilder();
  69. foreach (KeyValuePair<String, String> kv in parameters)
  70. {
  71. builder.Append(kv.Key).Append(kv.Value);
  72. }
  73. builder.Append(secretKey);
  74. String tmp = builder.ToString();
  75. MD5 md5 = new MD5CryptoServiceProvider();
  76. byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(tmp));
  77. builder.Clear();
  78. foreach (byte b in result)
  79. {
  80. builder.Append(b.ToString("x2"));
  81. }
  82. return builder.ToString();
  83. }
  84. private static int GetNonce()
  85. {
  86. Random r = new Random();
  87. int n = r.Next(1, MAX_NONCE);
  88. return n;
  89. }
  90. private static String GetCurrentTimeMillis()
  91. {
  92. TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  93. return Convert.ToInt64(ts.TotalMilliseconds).ToString();
  94. }
  95. }
  96. }

PHP请求示例

  1. <?php
  2. $params = array();
  3. $params["authenticate"] ="{authenticate}";//用户验证通过后,返回的参数
  4. $params["token"] ="{token}";//前端返回的 token
  5. $params["captchaId"] ="{captchaId}";//验证产品 id
  6. $params["secretId"] ="{secretId}";//验证产品 secretId
  7. $secretKey = "{secretKey}";//验证产品 secretKey
  8. $params["version"] = "1.0";//版本,固定值1.0
  9. $params["timestamp"] = sprintf("%d", round(microtime(true)*1000));// 当前时间戳的毫秒值,如1541064141441
  10. $params["nonce"] = sprintf("%d", rand(1,99999)); //随机正整数, 在 1-99999 之间
  11. ksort($params); // 参数排序
  12. $buff="";
  13. foreach($params as $key=>$value){
  14. $buff .=$key;
  15. $buff .=$value;
  16. }
  17. $buff .= $secretKey;
  18. //print_r($buff);
  19. $signature=md5($buff);
  20. $params["signature"] =$signature ;//签名信息,见签名计算方法
  21. $url="https://captcha.yunpian.com/v1/api/authenticate";
  22. $ch = curl_init();
  23. curl_setopt($ch, CURLOPT_URL, $url);
  24. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  25. /* 设置返回结果为流 */
  26. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  27. /* 设置超时时间*/
  28. curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  29. /* 设置通信方式 */
  30. curl_setopt($ch, CURLOPT_POST, 1);
  31. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  32. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/x-www-form-urlencoded'));
  33. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
  34. $result = curl_exec($ch);
  35. var_dump($result);

Python请求示例

  1. import random
  2. import time
  3. import hashlib
  4. import requests
  5. authenticate = '{authenticate}'
  6. secretKey = '{secretKey}'
  7. token = '{token}'
  8. captchaId = '{captchaId}'
  9. secretId = '{secretId}'
  10. data = {
  11. 'authenticate': authenticate,
  12. 'captchaId': captchaId,
  13. 'nonce': str(random.randint(10000, 99999)),
  14. 'secretId': secretId,
  15. 'timestamp': str(time.time()).split('.')[0],
  16. 'token': token,
  17. 'version': '1.0'
  18. }
  19. print '%s: %s' % ('data', data)
  20. sign_str = ''
  21. items = sorted(data.items(), key=lambda d:d[0])
  22. for item in items:
  23. sign_str += '%s%s' % (item[0],item[1])
  24. sign_str += secretKey
  25. print '%s: %s' % ('sign_str', sign_str)
  26. signature = hashlib.md5(sign_str).hexdigest().lower()
  27. data['signature'] = signature
  28. print '%s: %s' % ('data', data)
  29. url = 'https://captcha.yunpian.com/v1/api/authenticate'
  30. headers = {'Content-Type': 'application/x-www-form-urlencoded'}
  31. r = requests.post(url, data=data, headers=headers)
  32. print r.text

补充说明:

1、签名计算方法

  • 第一步:对所有请求参数(不包括 signature 参数),按照参数名ASCII码表升序顺序排序。如:foo=1, bar=2, foo_bar=3, baz=4 排序后的顺序是 bar=2, baz=4, foo=1, foo_bar=3 。
  • 第二步:将排序好的参数名和参数值构造成字符串,格式为:key1+value1+key2+value2… 。根据上面的示例得到的构造结果为:bar2baz4foo1foo_bar3 。
  • 第三步:选择与 secretId 配对的 secretKey ,加到上一步构造好的参数字符串之后,如 secretKey=e3da918313c14ea8b25db31f01263f80 ,则最后的参数字符串为 bar2barz4foo1foo_bar3e3da918313c14ea8b25db31f01263f80。
  • 第四步:把3步骤拼装好的字符串采用 utf-8 编码,使用 MD5 算法对字符串进行摘要,计算得到 signature 参数值,将其加入到接口请求参数中即可。MD5 是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32位十六进制字符。上述签名的结果为:59db908f26fb997c30b32ddb911485c2。
  1. /**
  2. * 生成签名信息
  3. * @param secretKey 产品私钥
  4. * @param params 接口请求参数名和参数值map,不包括signature参数名
  5. * @return
  6. */
  7. public static String genSignature(String secretKey, Map<String, String> params){
  8. // 1. 参数名按照ASCII码表升序排序
  9. String[] keys = params.keySet().toArray(new String[0]);
  10. Arrays.sort(keys);
  11. // 2. 按照排序拼接参数名与参数值
  12. StringBuilder sb = new StringBuilder();
  13. for (String key : keys) {
  14. sb.append(key).append(params.get(key));
  15. }
  16. // 3. 将secretKey拼接到最后
  17. sb.append(secretKey);
  18. // 4. MD5是128位长度的摘要算法,转换为十六进制之后长度为32字符
  19. return DigestUtils.md5Hex(sb.toString().getBytes("UTF-8"));
  20. }

2、响应码释义

前端相关响应码

verify接口响应码释义

响应码错误信息具体描述
0ok验证通过
1bad request验证请求数据缺失或格式有误
2verify fail验证不通过
400param_invalid请求参数错误,检查i k参数
400captcha_id_invalidcaptchaId不存在
429too many requests请求过于频繁,请稍后再试
500server_error服务异常

get接口响应码释义

响应码错误信息具体描述
0ok获取验证图片成功
400param_invalid请求参数错误,检查i k参数
400captcha_id_invalidcaptchaId不存在
429too many requests请求过于频繁,请稍后再试
500server_error服务异常

后端相关响应码

响应参数

参数类型必填备注
codeintY成功为0,非0为异常信息,详见下方“二次验证接口响应码释义”
msgstringY错误描述信息

二次验证接口响应码释义

响应码错误信息具体描述
0ok二次验证通过
400validate_fail二次验证不通过
400signature_invalid签名校验失败
400param_invalid请求参数错误,检查i k参数
400captcha_id_invalidcaptchaId不存在
429too many requests请求过于频繁,请稍后再试
500server_error服务异常