Repository: GeeTeam/gt-php-sdk
Branch: master
Commit: 83f25bee5e5e
Files: 9
Total size: 30.8 KB
Directory structure:
gitextract_rznw79nl/
├── .gitignore
├── README.rst
├── composer.json
├── config/
│ └── config.php
├── lib/
│ └── class.geetestlib.php
├── static/
│ ├── gt.js
│ └── login.html
└── web/
├── StartCaptchaServlet.php
└── VerifyLoginServlet.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.project
.buildpath
.settings
================================================
FILE: README.rst
================================================
Gt Php SDK
===============
使用 3.1 之前版本SDK的用户如果想更新到3.1以及以后版本请先联系极验客服,因为为了兼容老用户,新的特性需要修改验证设置
本项目是面向服务器端的,具体使用可以参考我们的 `文档 <http://www.geetest.com/install/sections/idx-server-sdk.html>`_ ,客户端相关开发请参考我们的 `前端文档 <http://www.geetest.com/install/>`_.
开发环境
----------------
- php5.2
部署架构
---------------
详见 `部署架构 <http://www.geetest.com/install/sections/idx-basic-introduction.html#id7>`__
前端接口
-------------------
详见 `前端接口 <http://www.geetest.com/install/sections/idx-client-sdk.html#config-para>`__
宕机回滚
--------------
详见 `宕机回滚 <http://www.geetest.com/install/sections/idx-basic-introduction.html#id8>`__
文件说明
---------------
- config/config.php 极验ID和KEY配置文件,请在 `极验后台 <http://account.geetest.com>`__ 申请,进行替换
- lib/class.geetestlib.php 极验库文件(请不要随意改动)
- static/login.php 前端展示页面,根据您的需求进行自定义
- web/StartCaptchaServlet.php 根据自己的私钥初始化验证
- web/VerifyLoginServlet.php 根据post参数进行二次验证
- static/gt.js 静态js文件,之前是直接引用http://static.geetest.com/static/tools/gt.js的
常见问题
--------------
1. 3.1.0之前的老版本SDK,不兼容现在的id和key
发布日志
-----------------
+ 3.2.0
- 添加用户标识接口
+ 3.1.1
- 统一接口
+ 3.1.0
- 添加challenge加密特性,使验证更安全, 老版本更新请先联系管理员
================================================
FILE: composer.json
================================================
{
"name": "gee-team/gt-php-sdk",
"description": "GtWeb Php Demo",
"authors": [
{
"name": "tanxu1993",
"email": "tanxu1993@gmail.com"
}
],
"require": {
"php": ">=5.0.0"
},
"autoload": {
"classmap": [
"lib"
]
},
"license": "MIT"
}
================================================
FILE: config/config.php
================================================
<?php
/**
* Geetest配置文件
* @author Tanxu
*/
define("CAPTCHA_ID", "b46d1900d0a894591916ea94ea91bd2c");
define("PRIVATE_KEY", "36fc3fe98530eea08dfc6ce76e3d24c4");
define("MOBILE_CAPTCHA_ID", "7c25da6fe21944cfe507d2f9876775a9");
define("MOBILE_PRIVATE_KEY", "f5883f4ee3bd4fa8caec67941de1b903");
?>
================================================
FILE: lib/class.geetestlib.php
================================================
<?php
/**
* 极验行为式验证安全平台,php 网站主后台包含的库文件
*
* @author Tanxu
*/
class GeetestLib {
const GT_SDK_VERSION = 'php_3.2.0';
public static $connectTimeout = 1;
public static $socketTimeout = 1;
private $response;
public function __construct($captcha_id, $private_key) {
$this->captcha_id = $captcha_id;
$this->private_key = $private_key;
}
/**
* 判断极验服务器是否down机
*
* @param null $user_id
* @return int
*/
public function pre_process($user_id = null) {
$url = "http://api.geetest.com/register.php?gt=" . $this->captcha_id;
if (($user_id != null) and (is_string($user_id))) {
$url = $url . "&user_id=" . $user_id;
}
$challenge = $this->send_request($url);
if (strlen($challenge) != 32) {
$this->failback_process();
return 0;
}
$this->success_process($challenge);
return 1;
}
/**
* @param $challenge
*/
private function success_process($challenge) {
$challenge = md5($challenge . $this->private_key);
$result = array(
'success' => 1,
'gt' => $this->captcha_id,
'challenge' => $challenge
);
$this->response = $result;
}
/**
*
*/
private function failback_process() {
$rnd1 = md5(rand(0, 100));
$rnd2 = md5(rand(0, 100));
$challenge = $rnd1 . substr($rnd2, 0, 2);
$result = array(
'success' => 0,
'gt' => $this->captcha_id,
'challenge' => $challenge
);
$this->response = $result;
}
/**
* @return mixed
*/
public function get_response_str() {
return json_encode($this->response);
}
/**
* 返回数组方便扩展
*
* @return mixed
*/
public function get_response() {
return $this->response;
}
/**
* 正常模式获取验证结果
*
* @param $challenge
* @param $validate
* @param $seccode
* @param null $user_id
* @return int
*/
public function success_validate($challenge, $validate, $seccode, $user_id = null) {
if (!$this->check_validate($challenge, $validate)) {
return 0;
}
$data = array(
"seccode" => $seccode,
"sdk" => self::GT_SDK_VERSION,
);
if (($user_id != null) and (is_string($user_id))) {
$data["user_id"] = $user_id;
}
$url = "http://api.geetest.com/validate.php";
$codevalidate = $this->post_request($url, $data);
if ($codevalidate == md5($seccode)) {
return 1;
} else {
if ($codevalidate == "false") {
return 0;
} else {
return 0;
}
}
}
/**
* 宕机模式获取验证结果
*
* @param $challenge
* @param $validate
* @param $seccode
* @return int
*/
public function fail_validate($challenge, $validate, $seccode) {
if ($validate) {
$value = explode("_", $validate);
$ans = $this->decode_response($challenge, $value['0']);
$bg_idx = $this->decode_response($challenge, $value['1']);
$grp_idx = $this->decode_response($challenge, $value['2']);
$x_pos = $this->get_failback_pic_ans($bg_idx, $grp_idx);
$answer = abs($ans - $x_pos);
if ($answer < 4) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
/**
* @param $challenge
* @param $validate
* @return bool
*/
private function check_validate($challenge, $validate) {
if (strlen($validate) != 32) {
return false;
}
if (md5($this->private_key . 'geetest' . $challenge) != $validate) {
return false;
}
return true;
}
/**
* GET 请求
*
* @param $url
* @return mixed|string
*/
private function send_request($url) {
if (function_exists('curl_exec')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::$connectTimeout);
curl_setopt($ch, CURLOPT_TIMEOUT, self::$socketTimeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
if (curl_errno($ch)) {
$err = sprintf("curl[%s] error[%s]", $url, curl_errno($ch) . ':' . curl_error($ch));
$this->triggerError($err);
}
curl_close($ch);
} else {
$opts = array(
'http' => array(
'method' => "GET",
'timeout' => self::$connectTimeout + self::$socketTimeout,
)
);
$context = stream_context_create($opts);
$data = file_get_contents($url, false, $context);
}
return $data;
}
/**
*
* @param $url
* @param array $postdata
* @return mixed|string
*/
private function post_request($url, $postdata = '') {
if (!$postdata) {
return false;
}
$data = http_build_query($postdata);
if (function_exists('curl_exec')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::$connectTimeout);
curl_setopt($ch, CURLOPT_TIMEOUT, self::$socketTimeout);
//不可能执行到的代码
if (!$postdata) {
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
} else {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$data = curl_exec($ch);
if (curl_errno($ch)) {
$err = sprintf("curl[%s] error[%s]", $url, curl_errno($ch) . ':' . curl_error($ch));
$this->triggerError($err);
}
curl_close($ch);
} else {
if ($postdata) {
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
'content' => $data,
'timeout' => self::$connectTimeout + self::$socketTimeout
)
);
$context = stream_context_create($opts);
$data = file_get_contents($url, false, $context);
}
}
return $data;
}
/**
* 解码随机参数
*
* @param $challenge
* @param $string
* @return int
*/
private function decode_response($challenge, $string) {
if (strlen($string) > 100) {
return 0;
}
$key = array();
$chongfu = array();
$shuzi = array("0" => 1, "1" => 2, "2" => 5, "3" => 10, "4" => 50);
$count = 0;
$res = 0;
$array_challenge = str_split($challenge);
$array_value = str_split($string);
for ($i = 0; $i < strlen($challenge); $i++) {
$item = $array_challenge[$i];
if (in_array($item, $chongfu)) {
continue;
} else {
$value = $shuzi[$count % 5];
array_push($chongfu, $item);
$count++;
$key[$item] = $value;
}
}
for ($j = 0; $j < strlen($string); $j++) {
$res += $key[$array_value[$j]];
}
$res = $res - $this->decodeRandBase($challenge);
return $res;
}
/**
* @param $x_str
* @return int
*/
private function get_x_pos_from_str($x_str) {
if (strlen($x_str) != 5) {
return 0;
}
$sum_val = 0;
$x_pos_sup = 200;
$sum_val = base_convert($x_str, 16, 10);
$result = $sum_val % $x_pos_sup;
$result = ($result < 40) ? 40 : $result;
return $result;
}
/**
* @param $full_bg_index
* @param $img_grp_index
* @return int
*/
private function get_failback_pic_ans($full_bg_index, $img_grp_index) {
$full_bg_name = substr(md5($full_bg_index), 0, 9);
$bg_name = substr(md5($img_grp_index), 10, 9);
$answer_decode = "";
// 通过两个字符串奇数和偶数位拼接产生答案位
for ($i = 0; $i < 9; $i++) {
if ($i % 2 == 0) {
$answer_decode = $answer_decode . $full_bg_name[$i];
} elseif ($i % 2 == 1) {
$answer_decode = $answer_decode . $bg_name[$i];
}
}
$x_decode = substr($answer_decode, 4, 5);
$x_pos = $this->get_x_pos_from_str($x_decode);
return $x_pos;
}
/**
* 输入的两位的随机数字,解码出偏移量
*
* @param $challenge
* @return mixed
*/
private function decodeRandBase($challenge) {
$base = substr($challenge, 32, 2);
$tempArray = array();
for ($i = 0; $i < strlen($base); $i++) {
$tempAscii = ord($base[$i]);
$result = ($tempAscii > 57) ? ($tempAscii - 87) : ($tempAscii - 48);
array_push($tempArray, $result);
}
$decodeRes = $tempArray['0'] * 36 + $tempArray['1'];
return $decodeRes;
}
/**
* @param $err
*/
private function triggerError($err) {
trigger_error($err);
}
}
================================================
FILE: static/gt.js
================================================
/* initGeetest 1.0.0
* 用于加载id对应的验证码库,并支持宕机模式
* 暴露 initGeetest 进行验证码的初始化
* 一般不需要用户进行修改
*/
(function (global, factory) {
"use strict";
if (typeof module === "object" && typeof module.exports === "object") {
// CommonJS
module.exports = global.document ?
factory(global, true) :
function (w) {
if (!w.document) {
throw new Error("Geetest requires a window with a document");
}
return factory(w);
};
} else {
factory(global);
}
})(typeof window !== "undefined" ? window : this, function (window, noGlobal) {
"use strict";
if (typeof window === 'undefined') {
throw new Error('Geetest requires browser environment');
}
var document = window.document;
var Math = window.Math;
var head = document.getElementsByTagName("head")[0];
function _Object(obj) {
this._obj = obj;
}
_Object.prototype = {
_each: function (process) {
var _obj = this._obj;
for (var k in _obj) {
if (_obj.hasOwnProperty(k)) {
process(k, _obj[k]);
}
}
return this;
}
};
function Config(config) {
var self = this;
new _Object(config)._each(function (key, value) {
self[key] = value;
});
}
Config.prototype = {
api_server: 'api.geetest.com',
protocol: 'http://',
type_path: '/gettype.php',
fallback_config: {
slide: {
static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
type: 'slide',
slide: '/static/js/geetest.0.0.0.js'
},
fullpage: {
static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
type: 'fullpage',
fullpage: '/static/js/fullpage.0.0.0.js'
}
},
_get_fallback_config: function () {
var self = this;
if (isString(self.type)) {
return self.fallback_config[self.type];
} else if (self.new_captcha) {
return self.fallback_config.fullpage;
} else {
return self.fallback_config.slide;
}
},
_extend: function (obj) {
var self = this;
new _Object(obj)._each(function (key, value) {
self[key] = value;
})
}
};
var isNumber = function (value) {
return (typeof value === 'number');
};
var isString = function (value) {
return (typeof value === 'string');
};
var isBoolean = function (value) {
return (typeof value === 'boolean');
};
var isObject = function (value) {
return (typeof value === 'object' && value !== null);
};
var isFunction = function (value) {
return (typeof value === 'function');
};
var callbacks = {};
var status = {};
var random = function () {
return parseInt(Math.random() * 10000) + (new Date()).valueOf();
};
var loadScript = function (url, cb) {
var script = document.createElement("script");
script.charset = "UTF-8";
script.async = true;
script.onerror = function () {
cb(true);
};
var loaded = false;
script.onload = script.onreadystatechange = function () {
if (!loaded &&
(!script.readyState ||
"loaded" === script.readyState ||
"complete" === script.readyState)) {
loaded = true;
setTimeout(function () {
cb(false);
}, 0);
}
};
script.src = url;
head.appendChild(script);
};
var normalizeDomain = function (domain) {
return domain.replace(/^https?:\/\/|\/$/g, '');
};
var normalizePath = function (path) {
path = path.replace(/\/+/g, '/');
if (path.indexOf('/') !== 0) {
path = '/' + path;
}
return path;
};
var normalizeQuery = function (query) {
if (!query) {
return '';
}
var q = '?';
new _Object(query)._each(function (key, value) {
if (isString(value) || isNumber(value) || isBoolean(value)) {
q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
}
});
if (q === '?') {
q = '';
}
return q.replace(/&$/, '');
};
var makeURL = function (protocol, domain, path, query) {
domain = normalizeDomain(domain);
var url = normalizePath(path) + normalizeQuery(query);
if (domain) {
url = protocol + domain + url;
}
return url;
};
var load = function (protocol, domains, path, query, cb) {
var tryRequest = function (at) {
var url = makeURL(protocol, domains[at], path, query);
loadScript(url, function (err) {
if (err) {
if (at >= domains.length - 1) {
cb(true);
} else {
tryRequest(at + 1);
}
} else {
cb(false);
}
});
};
tryRequest(0);
};
var jsonp = function (domains, path, config, callback) {
if (isObject(config.getLib)) {
config._extend(config.getLib);
callback(config);
return;
}
if (config.offline) {
callback(config._get_fallback_config());
return;
}
var cb = "geetest_" + random();
window[cb] = function (data) {
if (data.status === 'success') {
callback(data.data);
} else if (!data.status) {
callback(data);
} else {
callback(config._get_fallback_config());
}
window[cb] = undefined;
try {
delete window[cb];
} catch (e) {
}
};
load(config.protocol, domains, path, {
gt: config.gt,
callback: cb
}, function (err) {
if (err) {
callback(config._get_fallback_config());
}
});
};
var throwError = function (errorType, config) {
var errors = {
networkError: '网络错误'
};
if (typeof config.onError === 'function') {
config.onError(errors[errorType]);
} else {
throw new Error(errors[errorType]);
}
};
var detect = function () {
return !!window.Geetest;
};
if (detect()) {
status.slide = "loaded";
}
var initGeetest = function (userConfig, callback) {
var config = new Config(userConfig);
if (userConfig.https) {
config.protocol = 'https://';
} else if (!userConfig.protocol) {
config.protocol = window.location.protocol + '//';
}
jsonp([config.api_server || config.apiserver], config.type_path, config, function (newConfig) {
var type = newConfig.type;
var init = function () {
config._extend(newConfig);
callback(new window.Geetest(config));
};
callbacks[type] = callbacks[type] || [];
var s = status[type] || 'init';
if (s === 'init') {
status[type] = 'loading';
callbacks[type].push(init);
load(config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
if (err) {
status[type] = 'fail';
throwError('networkError', config);
} else {
status[type] = 'loaded';
var cbs = callbacks[type];
for (var i = 0, len = cbs.length; i < len; i = i + 1) {
var cb = cbs[i];
if (isFunction(cb)) {
cb();
}
}
callbacks[type] = [];
}
});
} else if (s === "loaded") {
init();
} else if (s === "fail") {
throwError('networkError', config);
} else if (s === "loading") {
callbacks[type].push(init);
}
});
};
window.initGeetest = initGeetest;
return initGeetest;
});
================================================
FILE: static/login.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gt-php-sdk-demo</title>
<style>
body {
margin: 50px 0;
text-align: center;
}
.inp {
border: 1px solid gray;
padding: 0 10px;
width: 200px;
height: 30px;
font-size: 18px;
}
.btn {
border: 1px solid gray;
width: 100px;
height: 30px;
font-size: 18px;
cursor: pointer;
}
#embed-captcha {
width: 300px;
margin: 0 auto;
}
.show {
display: block;
}
.hide {
display: none;
}
#notice {
color: red;
}
/* 以下遮罩层为demo.用户可自行设计实现 */
#mask {
display: none;
position: fixed;
text-align: center;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
overflow: auto;
}
/* 可自行设计实现captcha的位置大小 */
.popup-mobile {
position: relative;
}
#popup-captcha-mobile {
position: fixed;
display: none;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
z-index: 9999;
}
</style>
</head>
<body>
<h1>极验验证SDKDemo</h1>
<br><br>
<hr>
<br><br>
<!-- 为使用方便,直接使用jquery.js库,如您代码中不需要,可以去掉 -->
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
<!-- 引入封装了failback的接口--initGeetest -->
<script src="./gt.js"></script>
<!-- 若是https,使用以下接口 -->
<!-- <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script> -->
<!-- <script src="https://static.geetest.com/static/tools/gt.js"></script> -->
<div class="popup">
<h2>弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值</h2>
<br>
<p>
<labe>用户名:</labe>
<input id="username1" class="inp" type="text" value="极验验证">
</p>
<br>
<p>
<label>密 码:</label>
<input id="password1" class="inp" type="password" value="123456">
</p>
<br>
<input class="btn" id="popup-submit" type="submit" value="提交">
<div id="popup-captcha"></div>
</div>
<script>
var handlerPopup = function (captchaObj) {
// 成功的回调
captchaObj.onSuccess(function () {
var validate = captchaObj.getValidate();
$.ajax({
url: "../web/VerifyLoginServlet.php", // 进行二次验证
type: "post",
dataType: "json",
data: {
type: "pc",
username: $('#username1').val(),
password: $('#password1').val(),
geetest_challenge: validate.geetest_challenge,
geetest_validate: validate.geetest_validate,
geetest_seccode: validate.geetest_seccode
},
success: function (data) {
if (data && (data.status === "success")) {
$(document.body).html('<h1>登录成功</h1>');
} else {
$(document.body).html('<h1>登录失败</h1>');
}
}
});
});
$("#popup-submit").click(function () {
captchaObj.show();
});
// 将验证码加到id为captcha的元素里
captchaObj.appendTo("#popup-captcha");
// 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
};
// 验证开始需要向网站主后台获取id,challenge,success(是否启用failback)
$.ajax({
url: "../web/StartCaptchaServlet.php?type=pc&t=" + (new Date()).getTime(), // 加随机数防止缓存
type: "get",
dataType: "json",
success: function (data) {
// 使用initGeetest接口
// 参数1:配置参数
// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
initGeetest({
gt: data.gt,
challenge: data.challenge,
product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
// 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerPopup);
}
});
</script>
<br><br>
<hr>
<br><br>
<form class="popup" action="../web/VerifyLoginServlet.php" method="post">
<h2>嵌入式Demo,使用表单形式提交二次验证所需的验证结果值</h2>
<input class="inp" name="type" type="hidden" value="pc">
<br>
<p>
<label for="username2">用户名:</label>
<input class="inp" id="username2" type="text" value="极验验证">
</p>
<br>
<p>
<label for="password2">密 码:</label>
<input class="inp" id="password2" type="password" value="123456">
</p>
<div id="embed-captcha"></div>
<p id="wait" class="show">正在加载验证码......</p>
<p id="notice" class="hide">请先拖动验证码到相应位置</p>
<br>
<input class="btn" id="embed-submit" type="submit" value="提交">
</form>
<script>
var handlerEmbed = function (captchaObj) {
$("#embed-submit").click(function (e) {
var validate = captchaObj.getValidate();
if (!validate) {
$("#notice")[0].className = "show";
setTimeout(function () {
$("#notice")[0].className = "hide";
}, 2000);
e.preventDefault();
}
});
// 将验证码加到id为captcha的元素里,同时会有三个input的值:geetest_challenge, geetest_validate, geetest_seccode
captchaObj.appendTo("#embed-captcha");
captchaObj.onReady(function () {
$("#wait")[0].className = "hide";
});
// 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
};
$.ajax({
// 获取id,challenge,success(是否启用failback)
url: "../web/StartCaptchaServlet.php?type=pc&t=" + (new Date()).getTime(), // 加随机数防止缓存
type: "get",
dataType: "json",
success: function (data) {
// 使用initGeetest接口
// 参数1:配置参数
// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
initGeetest({
gt: data.gt,
challenge: data.challenge,
product: "embed", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
// 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerEmbed);
}
});
</script>
<br><br>
<hr>
<br><br>
<div class="popup-mobile">
<h2>移动端手动实现弹出式Demo</h2>
<br>
<p>
<labe for="username3">用户名:</labe>
<input id="username3" class="inp" type="text" value="极验验证">
</p>
<br>
<p>
<label for="password3">密 码:</label>
<input id="password3" class="inp" type="password" value="123456">
</p>
<br>
<input class="btn" id="popup-submit-mobile" type="submit" value="提交">
<div id="mask"></div>
<div id="popup-captcha-mobile"></div>
</div>
<script>
$("#mask").click(function () {
$("#mask, #popup-captcha-mobile").hide();
});
$("#popup-submit-mobile").click(function () {
$("#mask, #popup-captcha-mobile").show();
});
var handlerPopupMobile = function (captchaObj) {
// 将验证码加到id为captcha的元素里
captchaObj.appendTo("#popup-captcha-mobile");
//拖动验证成功后两秒(可自行设置时间)自动发生跳转等行为
captchaObj.onSuccess(function () {
var validate = captchaObj.getValidate();
$.ajax({
url: "../web/VerifyLoginServlet.php", // 进行二次验证
type: "post",
dataType: "json",
data: {
// 二次验证所需的三个值
type: "mobile",
username: $('#username3').val(),
password: $('#password3').val(),
geetest_challenge: validate.geetest_challenge,
geetest_validate: validate.geetest_validate,
geetest_seccode: validate.geetest_seccode
},
success: function (data) {
if (data && (data.status === "success")) {
$(document.body).html('<h1>登录成功</h1>');
} else {
$(document.body).html('<h1>登录失败</h1>');
}
}
});
});
// 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
};
$.ajax({
// 获取id,challenge,success(是否启用failback)
url: "../web/StartCaptchaServlet.php?type=mobile&t=" + (new Date()).getTime(), // 加随机数防止缓存
type: "get",
dataType: "json",
success: function (data) {
// 使用initGeetest接口
// 参数1:配置参数
// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
initGeetest({
gt: data.gt,
challenge: data.challenge,
offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
// 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerPopupMobile);
}
});
</script>
</body>
</html>
================================================
FILE: web/StartCaptchaServlet.php
================================================
<?php
/**
* 使用Get的方式返回:challenge和capthca_id 此方式以实现前后端完全分离的开发模式 专门实现failback
* @author Tanxu
*/
//error_reporting(0);
require_once dirname(dirname(__FILE__)) . '/lib/class.geetestlib.php';
require_once dirname(dirname(__FILE__)) . '/config/config.php';
if($_GET['type'] == 'pc'){
$GtSdk = new GeetestLib(CAPTCHA_ID, PRIVATE_KEY);
}elseif ($_GET['type'] == 'mobile') {
$GtSdk = new GeetestLib(MOBILE_CAPTCHA_ID, MOBILE_PRIVATE_KEY);
}
session_start();
$user_id = "test";
$status = $GtSdk->pre_process($user_id);
$_SESSION['gtserver'] = $status;
$_SESSION['user_id'] = $user_id;
echo $GtSdk->get_response_str();
?>
================================================
FILE: web/VerifyLoginServlet.php
================================================
<?php
/**
* 输出二次验证结果,本文件示例只是简单的输出 Yes or No
*/
// error_reporting(0);
require_once dirname(dirname(__FILE__)) . '/lib/class.geetestlib.php';
require_once dirname(dirname(__FILE__)) . '/config/config.php';
session_start();
if($_POST['type'] == 'pc'){
$GtSdk = new GeetestLib(CAPTCHA_ID, PRIVATE_KEY);
}elseif ($_POST['type'] == 'mobile') {
$GtSdk = new GeetestLib(MOBILE_CAPTCHA_ID, MOBILE_PRIVATE_KEY);
}
$user_id = $_SESSION['user_id'];
if ($_SESSION['gtserver'] == 1) { //服务器正常
$result = $GtSdk->success_validate($_POST['geetest_challenge'], $_POST['geetest_validate'], $_POST['geetest_seccode'], $user_id);
if ($result) {
echo '{"status":"success"}';
} else{
echo '{"status":"fail"}';
}
}else{ //服务器宕机,走failback模式
if ($GtSdk->fail_validate($_POST['geetest_challenge'],$_POST['geetest_validate'],$_POST['geetest_seccode'])) {
echo '{"status":"success"}';
}else{
echo '{"status":"fail"}';
}
}
?>
gitextract_rznw79nl/
├── .gitignore
├── README.rst
├── composer.json
├── config/
│ └── config.php
├── lib/
│ └── class.geetestlib.php
├── static/
│ ├── gt.js
│ └── login.html
└── web/
├── StartCaptchaServlet.php
└── VerifyLoginServlet.php
SYMBOL INDEX (19 symbols across 2 files)
FILE: lib/class.geetestlib.php
class GeetestLib (line 8) | class GeetestLib {
method __construct (line 16) | public function __construct($captcha_id, $private_key) {
method pre_process (line 27) | public function pre_process($user_id = null) {
method success_process (line 47) | private function success_process($challenge) {
method failback_process (line 60) | private function failback_process() {
method get_response_str (line 75) | public function get_response_str() {
method get_response (line 84) | public function get_response() {
method success_validate (line 97) | public function success_validate($challenge, $validate, $seccode, $use...
method fail_validate (line 129) | public function fail_validate($challenge, $validate, $seccode) {
method check_validate (line 153) | private function check_validate($challenge, $validate) {
method send_request (line 170) | private function send_request($url) {
method post_request (line 208) | private function post_request($url, $postdata = '') {
method decode_response (line 262) | private function decode_response($challenge, $string) {
method get_x_pos_from_str (line 298) | private function get_x_pos_from_str($x_str) {
method get_failback_pic_ans (line 316) | private function get_failback_pic_ans($full_bg_index, $img_grp_index) {
method decodeRandBase (line 341) | private function decodeRandBase($challenge) {
method triggerError (line 357) | private function triggerError($err) {
FILE: static/gt.js
function _Object (line 30) | function _Object(obj) {
function Config (line 45) | function Config(config) {
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (36K chars).
[
{
"path": ".gitignore",
"chars": 33,
"preview": ".project\r\n.buildpath\r\n.settings\r\n"
},
{
"path": "README.rst",
"chars": 1127,
"preview": "Gt Php SDK\n===============\n使用 3.1 之前版本SDK的用户如果想更新到3.1以及以后版本请先联系极验客服,因为为了兼容老用户,新的特性需要修改验证设置\n本项目是面向服务器端的,具体使用可以参考我们的 `文档 <"
},
{
"path": "composer.json",
"chars": 340,
"preview": "{\n \"name\": \"gee-team/gt-php-sdk\",\n \"description\": \"GtWeb Php Demo\",\n \"authors\": [\n {\n \"name\":"
},
{
"path": "config/config.php",
"chars": 299,
"preview": "<?php \n/**\n* Geetest配置文件\n* @author Tanxu\n*/\ndefine(\"CAPTCHA_ID\", \"b46d1900d0a894591916ea94ea91bd2c\");\ndefine(\"PRIVATE_K"
},
{
"path": "lib/class.geetestlib.php",
"chars": 9883,
"preview": "<?php\n\n/**\n * 极验行为式验证安全平台,php 网站主后台包含的库文件\n *\n * @author Tanxu\n */\nclass GeetestLib {\n const GT_SDK_VERSION = 'php_3.2"
},
{
"path": "static/gt.js",
"chars": 8833,
"preview": "/* initGeetest 1.0.0\n * 用于加载id对应的验证码库,并支持宕机模式\n * 暴露 initGeetest 进行验证码的初始化\n * 一般不需要用户进行修改\n */\n(function (global, factory)"
},
{
"path": "static/login.html",
"chars": 9395,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-"
},
{
"path": "web/StartCaptchaServlet.php",
"chars": 618,
"preview": "<?php \n/**\n * 使用Get的方式返回:challenge和capthca_id 此方式以实现前后端完全分离的开发模式 专门实现failback\n * @author Tanxu\n */\n//error_reporting(0);"
},
{
"path": "web/VerifyLoginServlet.php",
"chars": 972,
"preview": "<?php \n/**\n * 输出二次验证结果,本文件示例只是简单的输出 Yes or No\n */\n// error_reporting(0);\nrequire_once dirname(dirname(__FILE__)) . '/lib"
}
]
About this extraction
This page contains the full source code of the GeeTeam/gt-php-sdk GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (30.8 KB), approximately 8.4k tokens, and a symbol index with 19 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.