$mobile = $_GET['mobile'];
$captcha = new SimpleCaptcha(array(),$mobile);
$captcha->maxWordLength=4;
$captcha->minWordLength=4;
$captcha->maxRotation=2;
$captcha->height=45;
$captcha->fonts=array(
'Duality' => array('spacing' => 5, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
'Heineken' => array('spacing' => 5, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
'Jura' => array('spacing' => 5, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
);
$captcha->CreateImage();
class SimpleCaptcha {
public $width = 150;
public $height = 60;
public $mobile = '';
public $wordsFile = 'words/en.php';
public $resourcesPath = '../../com/chungda/util/captcha/resources';
public $minWordLength = 6;
public $maxWordLength = 6;
public $redis_var = 'vcode';
public $backgroundColor = array(255, 255, 255);
public $colors = array(
array(27,78,181), // blue
array(22,163,35), // green
array(214,36,7), // red
);
public $shadowColor = array(0, 0, 0);
public $lineWidth = 2;
public $noisePoint=130;
public $fonts = array(
'Antykwa' => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
'Candice' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
'Duality' => array('spacing' => 0, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
'Heineken' => array('spacing' => 0, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
'Jura' => array('spacing' => 0, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
'Times' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
);
public $Yperiod = 12;
public $Yamplitude = 14;
public $Xperiod = 11;
public $Xamplitude = 5;
public $maxRotation = 8;
public $scale = 2;
public $blur = true;
public $debug = false;
public $imageFormat = 'jpeg';
public $im;
public function __construct($config = array(),$mobile) {//传入mobile参数
$this->mobile = $mobile;
}
public function CreateImage() {
$ini = microtime(true);
$this->ImageAllocate();
$text = $this->GetCaptchaText();
$fontcfg = $this->fonts[array_rand($this->fonts)];
$this->WriteText($text, $fontcfg);
//存redis key:mobile => value:text
require_once("../../include.php");
$CRedis = new Redis();
$CRedis->connect(REDIS_SERVER_SESSION,REDIS_PORT,3);
$codeKey = "EX:".DOMAIN.":api:appPicAuth:cache:$this->mobile";
$CRedis->setex($codeKey, 60, strtolower($text));
$CRedis->close();
if (!empty($this->lineWidth)) {
$this->WriteLine();
}
if ($this->blur && function_exists('imagefilter')) {
imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
}
$this->ReduceImage();
$this->createNoisePoint();
if ($this->debug) {
imagestring($this->im, 1, 1, $this->height-8,
"$text {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms",
$this->GdFgColor
);
}
$this->WriteImage();
$this->Cleanup();
}
protected function ImageAllocate() {
if (!empty($this->im)) {
imagedestroy($this->im);
}
$this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale);
$this->GdBgColor = imagecolorallocate($this->im,
$this->backgroundColor[0],
$this->backgroundColor[1],
$this->backgroundColor[2]
);
imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor);
$color = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
$this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);
if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) {
$this->GdShadowColor = imagecolorallocate($this->im,
$this->shadowColor[0],
$this->shadowColor[1],
$this->shadowColor[2]
);
}
}
protected function GetCaptchaText() {
$text = $this->GetDictionaryCaptchaText();
if (!$text) {
$text = $this->GetRandomCaptchaText();
}
return $text;
}
protected function GetRandomCaptchaText($length = null) {
if (empty($length)) {
$length = rand($this->minWordLength, $this->maxWordLength);
}
$words = "abcdefghijlmnopqrstvwyz";
$vocals = "aeiou";
$text = "";
$vocal = rand(0, 1);
for ($i=0; $i<$length; $i++) {
if ($vocal) {
$text .= substr($vocals, mt_rand(0, 4), 1);
} else {
$text .= substr($words, mt_rand(0, 22), 1);
}
$vocal = !$vocal;
}
return $text;
}
function GetDictionaryCaptchaText($extended = false) {
if (empty($this->wordsFile)) {
return false;
}
if (substr($this->wordsFile, 0, 1) == '/') {
$wordsfile = $this->wordsFile;
} else {
$wordsfile = $this->resourcesPath.'/'.$this->wordsFile;
}
if (!file_exists($wordsfile)) {
return false;
}
$fp = fopen($wordsfile, "r");
$length = strlen(fgets($fp));
if (!$length) {
return false;
}
$line = rand(1, (filesize($wordsfile)/$length)-2);
if (fseek($fp, $length*$line) == -1) {
return false;
}
$text = trim(fgets($fp));
fclose($fp);
if ($extended) {
$text = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY);
$vocals = array('a', 'e', 'i', 'o', 'u');
foreach ($text as $i => $char) {
if (mt_rand(0, 1) && in_array($char, $vocals)) {
$text[$i] = $vocals[mt_rand(0, 4)];
}
}
$text = implode('', $text);
}
return $text;
}
protected function WriteLine() {
$x1 = $this->width*$this->scale*.15;
$x2 = $this->textFinalX;
$y1 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
$y2 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
$width = $this->lineWidth/2*$this->scale;
for ($i = $width*-1; $i <= $width; $i++) {
imageline($this->im, $x1, $y1+$i, $x2, $y2+$i, $this->GdFgColor);
}
}
protected function WriteText($text, $fontcfg = array()) {
if (empty($fontcfg)) {
$fontcfg = $this->fonts[array_rand($this->fonts)];
}
$fontfile = $this->resourcesPath.'/fonts/'.$fontcfg['font'];
$lettersMissing = $this->maxWordLength-strlen($text);
$fontSizefactor = 1+($lettersMissing*0.09);
$x = 20*$this->scale;
$y = round(($this->height*27/40)*$this->scale);
$length = strlen($text);
for ($i=0; $i<$length; $i++) {
$degree = rand($this->maxRotation*-1, $this->maxRotation);
$fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor;
$letter = substr($text, $i, 1);
if ($this->shadowColor) {
$coords = imagettftext($this->im, $fontsize, $degree,
$x+$this->scale, $y+$this->scale,
$this->GdShadowColor, $fontfile, $letter);
}
$coords = imagettftext($this->im, $fontsize, $degree,
$x, $y,
$this->GdFgColor, $fontfile, $letter);
$x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale);
}
$this->textFinalX = 0;//$x;
}
protected function WaveImage() {
// X-axis wave generation
$xp = $this->scale*$this->Xperiod*rand(1,3);
$k = rand(0, 100);
for ($i = 0; $i < ($this->width*$this->scale); $i++) {
imagecopy($this->im, $this->im,
$i-1, sin($k+$i/$xp) * ($this->scale*$this->Xamplitude),
$i, 0, 1, $this->height*$this->scale);
}
$k = rand(0, 100);
$yp = $this->scale*$this->Yperiod*rand(1,2);
for ($i = 0; $i < ($this->height*$this->scale); $i++) {
imagecopy($this->im, $this->im,
sin($k+$i/$yp) * ($this->scale*$this->Yamplitude), $i-1,
0, $i, $this->width*$this->scale, 1);
}
}
protected function ReduceImage() {
// Reduzco el tamaño de la imagen
$imResampled = imagecreatetruecolor($this->width, $this->height);
imagecopyresampled($imResampled, $this->im,
0, 0, 0, 0,
$this->width, $this->height,
$this->width*$this->scale, $this->height*$this->scale
);
imagedestroy($this->im);
$this->im = $imResampled;
}
public function createNoisePoint(){
for($i=0;$i<$this->noisePoint;$i++){
$pointColor=imagecolorallocate($this->im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imagesetpixel($this->im,mt_rand(0,$this->width),mt_rand(0,$this->height),$pointColor);
}
}
protected function WriteImage() {
if ($this->imageFormat == 'png' && function_exists('imagepng')) {
header("Content-type: image/png");
imagepng($this->im);
} else {
header("Content-type: image/jpeg");
imagejpeg($this->im, null, 80);
}
}
protected function Cleanup() {
imagedestroy($this->im);
}
}
效果:访问这个url就可以获取图形验证码并在redis中存储
url => http://www.”.DOMAIN.”/member/authCodeApp.php?mobile=”.mobile."&time=".time;
url最后的时间是为了防止重复访问,app端的图形验证码不变的情况发生
//读取redis key:mobile => value:text
$CRedis = new Redis();
$CRedis->connect(REDIS_SERVER_SESSION,REDIS_PORT,3);
$codeKey = "EX:".DOMAIN.":api:appPicAuth:cache:".$mobile;
$mobilePicCode = $CRedis->get($codeKey);
$CRedis->close();
$code = self::random(6);
if(strtolower($picCode) === $mobilePicCode)
{
return self::xsqJsonEncode($resultArr);
}
else
{
$resultArr = array("code" => "205", "msg" => "图形验证码错误");
return self::xsqJsonEncode($resultArr);
}
}
至此图形验证码的生成和验证已经完成
这里主要使用redis存储的目的是为了解决app端的session问题