楼主菜鸡一枚,最近有在学习thinkphp,看到有个图形验证码的类库captcha,故想尝试用在小程序中。
小程序wxml代码如下:
<!--pages/test/test.wxml-->
<form bindsubmit="formsubmit">
<input name="code" placeholder="请输入验证码" style="border:1px solid black"/>
<image onload="imageload" src="{{captchaImage}}" style="width:200px;height:88px;" ></image>
<button form-type="submit">提交</button>
</form >
js代码如下:
// pages/test/test.js
Page({
data: {
captchaImage:'https://www.st1207.com/captcha' //验证码图片地址
},
formsubmit: function (e) {
console.log(e.detail.value);
var that=this;
wx.request({
url: "https://www.st1207.com/api/v3.captcha/index", //服务器验证地址
method:"GET",
data:e.detail.value,
success: function (res) {
console.log(res.data);
},
fail: function (err) {
console.log(err);
}
})
},
})
服务器代码如下
<?php
namespace app\api\controller\v3;
use think\Controller;
use think\captcha\Captcha as Cap;
class Captcha extends Controller{
public function index($code=''){
$captcha=new Cap;
if(!$captcha->check($code)){
return '验证失败'.$code;
}else{
return '验证成功'.$code;
}
}
}
?>
代码完成,开始测试,虽然验证码可以正常显示,但是提交表单进行验证的时候总是提示验证失败。
各种网络搜索查找资料,才发现thinkphp是用Session来储存验证码的。而小程序不支持主动保存cookie,更不会在request header中发送cookie。导致小程序每次向服务器发送请求的时候,SESSIONID都会发生变化,所以永远都不会验证成功。
思考解决办法:手动保存服务器response header中的sessionid,再向服务器发送验证请求的时候,在wx.request中手动添加header:{'cookie':'PHPSESSID=...' }.
查看以上代码,小程序第一次向服务器发送请求是在<image>组件加载服务器验证码图片的时候,此时没有办法获得response header。所以也就不能手动保存。
再想办法 :<image>组件的src 不直接使用服务器的图形验证码地址,先在onload事件中通过wx,request或者wx.downloadFile请求服务器https://www.st1207.com/captcha, 获得response header和图片信息再通过js的data 让小程序来显示。
查看wx.request 的回调函数success:function(res){ }
有response header,可以获得sessionID 为 res.header['Set-Cookie'],但是返回的res.data确是一堆乱码,无法来让<image>组件进行显示
查看wx.downloadFile 的回调函数虽然可以把图片下载下来进行显示,但是并不能获得response header。
作为一名菜鸟,不知道有没有表达的清楚,请各位大神帮忙看看还有没有其他办法。
已经真机测试通过,可以加qq讨论:974353437
const app = getApp()
Page({
data: {
imgUrl:
''
,
result:
''
},
onLoad() {
this
.initCaptcha();
},
initCaptcha() {
let url =
'http://192.168.0.119:15539/Captcha/Index'
;
wx.request({
header: app.globalData.header,
url,
data:{},
success: (res) => {
this
.setSessionId(res);
this
.downloadCaptcha();
}
})
},
downloadCaptcha(){
let url =
'http://192.168.0.119:15539/Captcha/Generate?'
+
new
Date().getTime();
wx.downloadFile({
header: app.globalData.header,
url,
success: (res) => {
console.log(res);
this
.setData({
imgUrl:res.tempFilePath
});
}
})
},
refreshCaptcha() {
this
.initCaptcha();
},
setSessionId(res) {
let cookieStr = res.header[
'Set-Cookie'
];
// app.globalData.header.Cookie = cookieStr;
if
(cookieStr){
let cookies = cookieStr.split(
'; '
)
if
(!cookies || cookies.length <= 0)
return
;
cookies.forEach(
(v) => {
const str = v.split(
'='
);
if
(str[0] && str[0] ==
'ASP.NET_SessionId'
) {
let sessionId = decodeURI(str[1]);
app.globalData.header.Cookie = `ASP.NET_SessionId=${sessionId}`;
}
}
);
}
},
onSubmit(e){
let { code } = e.detail.value;
let url =
'http://192.168.0.119:15539/Captcha/Validate'
;
wx.request({
header: app.globalData.header,
url,
data: {code},
success: (res) => {
console.log(res);
this
.initCaptcha();
this
.setData({
result:res.data.message
})
}
})
}
})
wxml
<!--index.wxml-->
<
form
bind:submit
=
"onSubmit"
class
=
"form"
>
<
input
placeholder
=
'请输入验证码'
name
=
"code"
/>
<
image
bindtap
=
"refreshCaptcha"
src
=
"{{imgUrl}}"
mode
=
"cover"
style
=
"width:100px;height:50px"
></
image
>
<
button
formType
=
"submit"
>验证</
button
>
<
view
>操作结果:{{result}}</
view
>
</
form
>
app.globalData.header.Cookie 这儿的 Cookie 显示未定义
项目入口文件 app.js 增加下面代码.
globalData: {
userInfo:
null
,
header: {
'Cookie'
:
''
}
},
如果是PHP程序, 将上面的 ASP.NET_SessionId 替换成 PHPSESSID
uni.request({ url: this.urlTimestamp, // 加上时间戳的验证码地址 responseType: 'arraybuffer' }) .then(res => { const [, { data, cookies, header }] = res; const base64Url = 'data:image/png;base64,' + uni.arrayBufferToBase64(data); console.log(data, cookies, header); // cookies/header 中都可以取到SESSIONID this.captchaUrl = base64Url; // base64用于展示 });
前面一切正常,提交审核时候https请求验证码图片和token,tempFilePath返回的http的图片地址无法显示.
恩,不嫌麻烦的话可以多写一次请求。
第一次请求用wx.request,把返回的sessionid存起来,返回的二进制流图片数据不要管它(我目前不知道怎么放到image里)。
第二次请求用过wx.downloadFile,在请求header里面加上你之前存起来的sessionid,把返回的tempFilePath临时文件地址放到image里显示。
第三次用wx.request,header带上你的sessionid,进行验证。
将验证码的sessionid和openid绑定,判断时读取当前openid绑定的sessionid的session