代码拉取完成,页面将自动刷新
unit webapp;
interface
uses SysUtils, Variants,Classes,idhttp,StdCtrls,DateUtils,Controls, IdIOHandler,IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL,IDCookieManager,superObject,Hashtable,log4me;
const webpush_url :string = 'https://webpush.weixin.qq.com' ;
type Pcookie = ^Tcookie;
Tcookie = record // cookies key
wxuin:string; // wxuin
skey:string; // skey
wxsid:string; // sid
pass_ticket:string; // pass_ticket
end;
type TBaseRequest =record
Uin:string;
Sid:string;
Skey:String;
DeviceID:string;
end;
type PwxMessage = ^ TwxMessage;
TwxMessage =record
fromUser:string;
toUser:string;
MsgType:String;
Content:string;
Status: string;
ImgStatus: string;
end;
type TWxWeb = class (TObject)
private
uuid:string; // UUID
tip:string; // tip
baseUri :string; //取得域名
redirectUri:string; //跳转URL
returnMessage:string; // 返回消息
keyCookie: Tcookie; // 关键cookies
syncKeyObj: ISuperObject; //syncKey json 结构体
baseReqeust:TBaseRequest;
cookies:string; // cookies 字符串
syncKey:string; // 消息轮询 的syncKey
idHttp: TIdHttp;
sslHandler:TIdSSLIOHandlerSocketOpenSSL;
function getCookies():boolean;
public
imagestream:TMemoryStream; //二维码图片流
userName:string; // 当前用户名称 序列 每次登录都会变化
userNikeName:string ;
retcode :string; // 同步返回码
selector :string; // 事件代码
MemberCount:integer; // 联系人数量
wxAddMessageList:Tlist;
wxMessageList:Tlist;
wxActiveContactList:THashTable; //存储最近活动的联系人 (自行实现)
wxContactList:THashTable; //存储所有联系人 (自行实现)
wxGroupList:THashTable; //微信群 联系人 (自行实现)
wxAllContactList:THashTable ; // 所有联系人 (认证联系人+ 群组联系人)
constructor Create;
function getUUID:boolean;
function showQRImage():boolean;
function waitForLogin():boolean;
function login():boolean;
function wxInit():boolean;
function wxStatusNotify():boolean;
function wxgetContact() :boolean;
function syncMessageCheck():boolean;
function syncMessageGet():boolean;
end;
function GetRandomName(num:integer):string;
function GetTimeString():string;
implementation
uses main,RegExpr,StrUtils;
constructor TWxWeb.Create;
begin
idHttp:=TIdHttp.Create(nil);
sslHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
idhttp.AllowCookies:=false;
idhttp.IOHandler:= sslHandler;
idhttp.Request.Accept := 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*';
idhttp.Request.AcceptLanguage := 'zh-cn';
idhttp.Request.ContentType := 'application/x-www-form-urlencoded';
idhttp.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)';
{ 存储联系人
wxActiveContactList:= THashTable.create(1000);
wxContactList:=THashTable.create(1000);
wxGroupList:=THashTable.create(1000);
wxAllContactList:=THashTable.create(1000);
}
end;
function TWxWeb.getUUID():boolean;
var url :String;
t:Longword ;
s:string;
reg: TRegExpr;
begin
t:=DateTimeToUnix(now());
url:='https://login.weixin.qq.com/jslogin?appid=%s&fun=%s&lang=%s&_=%s';
url:=format(url,['wx782c26e4c19acffb','new','zh_CN',inttoStr(DateTimeToUnix(t))]);
try
if idhttp.Connected = false then
s:= idhttp.get(url);
except
result:=false;
end;
//s:='window.QRLogin.code = 200; window.QRLogin.uuid = "QfzdEMz5uA=="';
reg := TRegExpr.Create; //建立
reg.Expression:='(\d+)';
reg.Exec(s);
if reg.SubExprMatchCount = 1 then
begin
if reg.Match[1] = '200' then
begin
reg.Expression:='"(\S+?)"';
reg.Exec(s);
if reg.SubExprMatchCount = 1 then
begin
uuid:=reg.Match[1];
result:=true;
end;
end
else
begin
result:=false;
exit;
end;
FreeAndNil(reg);
end
else
begin
result:=false;
exit;
end;
end;
function TWxWeb.showQRImage():boolean;
var url:string;
begin
imagestream := TMemoryStream.Create();
url := 'https://login.weixin.qq.com/qrcode/' + uuid+'?t=webwx';
try
idhttp.get(url,imagestream) ;
tip:='1';
result:=true;
except
result:=false;
end;
end;
function TWxWeb.waitForLogin():boolean;
var url:string;
s:string;
reg:TRegExpr;
recode:string;
begin
url:='https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s';
url:=Format(url,[tip,uuid,gettimestring()]);
try
s:= idhttp.get(url) ;
except
result:=false;
end;
if s = '' then
result:=false;
reg:= TRegExpr.Create; //建立
reg.Expression:='(\d+)';
reg.Exec(s);
if reg.SubExprMatchCount = 1 then
begin
recode:=reg.Match[1];
if recode = '201' then
begin
returnMessage:='成功扫描,请在手机上点击确认以登录';
tip :='0' ;
result:=false;
exit;
end
else if recode = '408' then
begin
returnMessage:='登录超时 ,请重试';
tip :='0' ;
result:=false;
exit;
end
else if recode = '200' then
begin
returnMessage:='正在登录,稍等.....';
reg.Expression:='"(\S+?)"' ;
reg.Exec(s);
if reg.SubExprMatchCount = 1 then
begin
redirectUri:= reg.Match[1] + '&fun=new' ;
reg.Expression:='//(\S+?)/' ;
reg.Exec(redirectUri);
if reg.SubExprMatchCount = 1 then
begin
baseUri:='http://'+reg.Match[1];
end;
FreeAndNil(reg);
result:=true;
end;
end;
end
else
begin
result:=false;
exit;
end;
end;
function TWxWeb.login():boolean;
var
resString:string;
reg: TRegExpr;
begin
try
resString:= idhttp.get(redirectUri);
getCookies();
except
result:=false;
exit;
end;
if resString <>'' then
begin
reg:= TRegExpr.Create;
reg.Expression:='<ret>(\d+)</ret>';
reg.Exec(resString);
if reg.SubExprMatchCount = 1 then
begin
if reg.Match[1] = '0' then
begin
reg.Expression:='<skey>(\S+?)</skey><wxsid>(\S+?)</wxsid><wxuin>(\S+?)</wxuin><pass_ticket>(\S+?)</pass_ticket>';
reg.Exec(resString);
keyCookie.skey:=reg.Match[1];
keyCookie.wxsid:=reg.Match[2];
keyCookie.wxuin:= reg.Match[3];
keyCookie.pass_ticket:= reg.Match[4];
baseReqeust.Uin:= keyCookie.wxuin;
baseReqeust.Sid:= keyCookie.wxsid;
baseReqeust.Skey:=keyCookie.skey;
baseReqeust.DeviceID:='e'+GetRandomName(16);
FreeAndNil(reg);
result:=true;
end
end;
end
else
begin
result:=false;
exit;
end;
end;
function TWxWeb.wxInit():boolean;
var url:string;
parmas:TstringList;
root, superObject:ISuperObject;
requestJson:string;
responseJson:string;
resObject,syncKeyList,contactList: ISuperObject;
item: ISuperObject;
reCode:string;
syncKeyString:string;
ResponseStream: TStringstream;
begin
ResponseStream:=TStringstream.Create('',TEncoding.UTF8);
superObject:= SO([]);
root:= SO([]);
parmas:=TstringList.Create;
url := baseURI + '/cgi-bin/mmwebwx-bin/webwxinit?r=%s&pass_ticket=%s&skey=%s' ;
url:=Format(url,[gettimeString(),keyCookie.pass_ticket,keyCookie.skey]);
superObject.s['Uin']:= baseReqeust.Uin;
superObject.s['Sid']:= baseReqeust.Sid;
superObject.S['Skey']:= baseReqeust.Skey;
superObject.S['DeviceID']:= baseReqeust.DeviceID;
root.O['BaseRequest']:= superObject;
requestJson:=root.AsJSon();
parmas.Add(requestJson);
try
idhttp.Request.CustomHeaders.Values['Cookie']:=Cookies;
idhttp.Post(url,parmas,ResponseStream);
except
result:=false;
exit;
end;
responseJson:= ResponseStream.DataString;
if responseJson = '' then
begin
result:=false;
exit;
end;
ResponseStream.Free;
parmas.Free;
resObject:= so(responseJson);
reCode:= resObject['BaseResponse.Ret'].AsString();
if reCode = '0' then
begin
syncKeyObj := resObject['SyncKey'];
syncKeyList:= resObject['SyncKey.List'];
syncKeyString:='';
for item in syncKeyList do
begin
syncKeyString:= syncKeyString+'|'+item.S['Key']+ '_'+item.s['Val'];
end;
syncKey:=midstr(syncKeyString,2,length(syncKey)-1);
userName:= resObject['User.UserName'].AsString();
contactList := resObject['ContactList'];
for item in contactList do
begin
if pos(item.S['UserName'] , '@@') <> -1 then
begin
log4info(item.S['NickName']+':'+item.S['UserName']);
wxActiveContactList.put(item.S['NickName'],item.S['UserName']);
end;
end;
result:=true;
end
else
begin
result:=false;
end;
end;
function TWxWeb.wxStatusNotify():boolean;
var url:string;
parmas:TstringList;
root, superObject,resObject:ISuperObject;
requestJson,responseJson:string ;
reCode:string;
begin
//headers:=Tstringlist.Create;
parmas:=TstringList.Create;
url := baseURI + '/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=%s&pass_ticket=%s' ;
url:=Format(url,['zh_CN',keyCookie.pass_ticket]);
idhttp.Request.RawHeaders.AddValue('Content-type','application/json; charset=UTF-8');
idhttp.Request.CustomHeaders.Values['Cookie']:=Cookies;
superObject:= SO([]);
superObject.s['Uin']:= baseReqeust.Uin;
superObject.s['Sid']:= baseReqeust.Sid;
superObject.S['Skey']:= baseReqeust.Skey;
superObject.S['DeviceID']:= baseReqeust.DeviceID;
root:= SO([]);
root.O['BaseRequest']:= superObject;
root.s['Code']:='3';
root.s['FromUserName']:=userName;
root.s['ToUserName']:=userName;
root.s['ClientMsgId']:=GetRandomName(14);
requestJson:=root.AsJSon();
parmas.Add(requestJson);
try
responseJson:=idhttp.post(url,parmas);
except
result:=false;
end;
parmas.Free;
if responseJson = '' then
begin
result:=false;
exit;
end;
resObject:=SO(responseJson);
reCode:= resObject['BaseResponse.Ret'].AsString();
if reCode ='0' then
result:=true
else
result:=false;
end;
function TWxWeb.wxgetContact() :boolean;
var url:string;
responseJson:string;
resObject:ISuperObject;
reCode:string;
begin
url := baseURI + '/cgi-bin/mmwebwx-bin/webwxgetcontact?pass_ticket=%s&skey=%s&t=%s' ;
url:= format(url,[keyCookie.pass_ticket,keyCookie.skey,Gettimestring()]) ;
try
idhttp.Request.CustomHeaders.Values['Cookie']:=Cookies;
responseJson:=idhttp.get(url);
except
result:=false;
exit;
end;
if responseJson = '' then
begin
result:=false;
exit;
end;
begin
resObject:=SO(responseJson);
reCode:= resObject['BaseResponse.Ret'].AsString();
if reCode ='0' then
begin
MemberCount:=resObject['MemberCount'].AsInteger();
result:=true
end
else
result:=false;
exit;
end;
end;
{ function TWxWeb.wxgetContact() :boolean;
var url:string;
headers:TstringList;
parmas:TstringList;
responseJson:string;
resObject:ISuperObject;
reCode:string;
begin
headers:=TstringList.Create;
parmas:=TstringList.Create;
url := baseURI + '/cgi-bin/mmwebwx-bin/webwxgetcontact' ;
parmas.Add('pass_ticket='+keyCookie.pass_ticket);
parmas.Add('skey='+keyCookie.skey);
parmas.Add('r='+Gettimestring());
try
// idhttp.Request.ContentType; //最重要的初始化。
idhttp.Request.CustomHeaders.Values['Cookie']:=Cookies;
responseJson:=idhttp.post(url,parmas);
if responseJson <> '' then
begin
resObject:=SO(responseJson);
reCode:= resObject['BaseResponse.Ret'].AsString();
if reCode ='0' then
begin
MemberCount:=resObject['MemberCount'].AsInteger();
result:=true
end
else
result:=false;
end;
except
result:=false;
end;
end;
}
function TWxWeb.syncMessageCheck():boolean;
var url:string;
resStr:string ;
reg:TRegExpr;
begin
url := webpush_url + '/cgi-bin/mmwebwx-bin/synccheck?skey=%s&sid=%s&uin=%s&deviceid=%s&synckey=%s&r=%s&_=%s' ;
url:=Format(url,[keyCookie.skey,keyCookie.wxsid,baseReqeust.Uin,baseReqeust.DeviceID,Utf8Encode(synckey),GetTimeString()+leftstr('00000',5),GetTimeString()]);
try
idhttp.request.customheaders.text:='cookie:' + Cookies;
resStr:=idhttp.get(url);
if resStr <> '' then
begin
reg := TRegExpr.Create; //建立
reg.Expression:='retcode:"(\d+)",selector:"(\d+)"';
reg.Exec(resStr);
if reg.SubExprMatchCount > 1 then
begin
retcode:=reg.Match[1];
selector:=reg.Match[2];
end;
freeandnil(reg);
if retcode ='0' then
result:=true
else
result:=false;
end;
except
result:=false;
end;
end;
function TWxWeb.syncMessageGet():boolean;
var url:string;
parmas:TstringList;
root, superObject,resObject,syncKeys,item:ISuperObject;
addMsgList :ISuperObject;
requestJson,responseJson:string ;
reCode:string;
syncKeyString:string;
t:string;
ResponseStream: TStringstream;
begin
ResponseStream:=TStringstream.Create('',TEncoding.UTF8);
t:=GetTimeString();
parmas:=TstringList.Create;
url := baseURI + '/cgi-bin/mmwebwx-bin/webwxsync?lang=%s&pass_ticket=%s&skey=%s&sid=%s&r=%s&_=%s' ;
url:=Format(url,['zh_CN',keyCookie.pass_ticket,keyCookie.skey,keyCookie.wxsid,t,t]);
idhttp.Request.ContentType:= 'application/json;charset=utf-8';
idhttp.request.customheaders.text:='Cookie:' + Cookies;
superObject:= SO([]);
superObject.s['Uin']:= baseReqeust.Uin;
superObject.s['Sid']:= baseReqeust.Sid;
superObject.S['Skey']:= baseReqeust.Skey;
superObject.S['DeviceID']:= baseReqeust.DeviceID;
root:= SO([]);
root.O['BaseRequest']:= superObject;
root.o['SyncKey']:=syncKeyObj;
root.s['rr']:=t;
requestJson:=root.AsJSon();
parmas.Add(requestJson);
try
idhttp.post(url,parmas,ResponseStream);
except
result:=false;
end;
responseJson:=ResponseStream.DataString;
if responseJson = '' then
begin
result:=false;
end;
resObject:=SO(responseJson);
reCode:= resObject['BaseResponse.Ret'].AsString();
if reCode ='0' then
begin
syncKeys:= resObject['SyncKey.List'];
syncKeyString:='';
for item in syncKeys do
begin
syncKeyString:= syncKeyString+'|'+item.S['Key']+ '_'+item.s['Val'];
end;
syncKey:=midstr( syncKeyString,2,length(syncKeyString)-1);
addMsgList:=resObject['AddMsgList'];
wxAddMessageList:=Tlist.Create;
for item in addMsgList do
begin
if item.S['FromUserName'] = userName then
begin
continue;
end;
{
获取消息信息
wxMessage.fromUser:=item.S['FromUserName'];
wxMessage.toUser:=item.S['toUserName'];
wxMessage.MsgType:=item.S['MsgType'];
wxMessage.Content:=item.S['Content'];
wxMessage.Status:=item.S['Status'];
wxMessage.ImgStatus:=item.S['ImgStatus'];
wxAddMessageList.Add(@wxMessage);
}
end;
result:=true ;
end
else
result:=false;
end;
function TWxWeb.getCookies():boolean;
var tmp,cookie:string;
i:integer;
begin
for i := 0 to idhttp.Response.RawHeaders.Count - 1 do
begin
tmp := idhttp.Response.RawHeaders[i];
if pos('set-cookie: ', LowerCase(tmp)) = 0 then Continue;
tmp := Trim(Copy(tmp, Pos('Set-cookie: ', tmp) + Length('Set-cookie: '), Length(tmp)));
tmp := Trim(Copy(tmp, 0, Pos(';', tmp) - 1));
if cookie = '' then
cookie := tmp else cookie := cookie + '; ' + tmp;
end;
cookies:=cookie;
result :=true;
end;
function GetRandomName(num:integer):string;
var SourceStr,str:string;
i:integer;
begin
SourceStr:='1234567890';
for i:=1 to num do
str:=str+sourcestr[Random(10)+1];
Result:=str;
end;
function GetTimeString( ):string;
begin
Result:=inttostr(DateTimeToUnix(now()));
end;
end.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。