1+ package me .biezhi .wechat ;
2+
3+ import java .awt .EventQueue ;
4+ import java .io .File ;
5+ import java .net .MalformedURLException ;
6+ import java .net .URL ;
7+
8+ import javax .swing .UIManager ;
9+
10+ import org .slf4j .Logger ;
11+ import org .slf4j .LoggerFactory ;
12+
13+ import com .blade .kit .DateKit ;
14+ import com .blade .kit .StringKit ;
15+ import com .blade .kit .http .HttpRequest ;
16+ import com .blade .kit .json .JSONObject ;
17+
18+ import me .biezhi .wechat .exception .WechatException ;
19+ import me .biezhi .wechat .listener .WechatListener ;
20+ import me .biezhi .wechat .model .WechatContact ;
21+ import me .biezhi .wechat .model .WechatMeta ;
22+ import me .biezhi .wechat .model .WechatRequest ;
23+ import me .biezhi .wechat .service .WechatService ;
24+ import me .biezhi .wechat .service .WechatServiceImpl ;
25+ import me .biezhi .wechat .ui .QRCodeFrame ;
26+ import me .biezhi .wechat .util .CookieUtil ;
27+ import me .biezhi .wechat .util .JSUtil ;
28+ import me .biezhi .wechat .util .Matchers ;
29+
30+ /**
31+ * Hello world!
32+ *
33+ */
34+ public class WechatRobot {
35+
36+ private static final Logger LOGGER = LoggerFactory .getLogger (WechatRobot .class );
37+
38+ private WechatListener wechatListener = new WechatListener ();
39+ private WechatService wechatService = new WechatServiceImpl ();
40+
41+ private int tip = 0 ;
42+ private String base_uri , redirect_uri , webpush_url = Constant .BASE_URL ;
43+
44+ private WechatMeta wechatMeta = new WechatMeta ();
45+ private WechatRequest wechatRequest ;
46+ private WechatContact wechatContact ;
47+
48+ private QRCodeFrame qrCodeFrame ;
49+
50+ public WechatRobot () {
51+ System .setProperty ("https.protocols" , "TLSv1" );
52+ System .setProperty ("jsse.enableSNIExtension" , "false" );
53+ }
54+
55+ /**
56+ * 显示二维码
57+ *
58+ * @return
59+ */
60+ public void showQrCode () throws WechatException {
61+
62+ String uuid = wechatService .getUUID ();
63+ wechatMeta .setUuid (uuid );
64+
65+ LOGGER .info ("[*] 获取到uuid为 [{}]" , uuid );
66+ String url = Constant .QRCODE_URL + uuid ;
67+ final File output = new File ("temp.jpg" );
68+ HttpRequest .post (url , true , "t" , "webwx" , "_" , DateKit .getCurrentUnixTime ()).receive (output );
69+
70+ if (null != output && output .exists () && output .isFile ()) {
71+ EventQueue .invokeLater (new Runnable () {
72+ public void run () {
73+ try {
74+ UIManager .setLookAndFeel ("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel" );
75+ qrCodeFrame = new QRCodeFrame (output .getPath ());
76+ } catch (Exception e ) {
77+ e .printStackTrace ();
78+ }
79+ }
80+ });
81+ }
82+ }
83+
84+ /**
85+ * 等待登录
86+ */
87+ public String waitForLogin () throws WechatException {
88+ this .tip = 1 ;
89+ String url = "https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login" ;
90+ HttpRequest request = HttpRequest .get (url , true , "tip" , this .tip , "uuid" , wechatMeta .getUuid (), "_" ,
91+ DateKit .getCurrentUnixTime ());
92+
93+ LOGGER .info ("[*] " + request .toString ());
94+
95+ String res = request .body ();
96+ request .disconnect ();
97+
98+ if (null == res ) {
99+ throw new WechatException ("扫描二维码验证失败" );
100+ }
101+ String code = Matchers .match ("window.code=(\\ d+);" , res );
102+ if (null == code ) {
103+ throw new WechatException ("扫描二维码验证失败" );
104+ } else {
105+ if (code .equals ("201" )) {
106+ LOGGER .info ("[*] 成功扫描,请在手机上点击确认以登录" );
107+ tip = 0 ;
108+ } else if (code .equals ("200" )) {
109+ LOGGER .info ("[*] 正在登录..." );
110+ String pm = Matchers .match ("window.redirect_uri=\" (\\ S+?)\" ;" , res );
111+ String redirectHost = "wx.qq.com" ;
112+ try {
113+ URL pmURL = new URL (pm );
114+ redirectHost = pmURL .getHost ();
115+ } catch (MalformedURLException e ) {
116+ throw new WechatException (e );
117+ }
118+ String pushServer = JSUtil .getPushServer (redirectHost );
119+ this .webpush_url = "https://" + pushServer + "/cgi-bin/mmwebwx-bin" ;
120+ this .redirect_uri = pm + "&fun=new" ;
121+
122+ LOGGER .info ("[*] redirect_uri={}" , this .redirect_uri );
123+
124+ this .base_uri = this .redirect_uri .substring (0 , this .redirect_uri .lastIndexOf ("/" ));
125+
126+ LOGGER .info ("[*] base_uri={}" , this .base_uri );
127+ } else if (code .equals ("408" )) {
128+ throw new WechatException ("登录超时" );
129+ } else {
130+ LOGGER .info ("[*] 扫描code={}" , code );
131+ }
132+ }
133+ return code ;
134+ }
135+
136+ public void closeQrWindow () {
137+ qrCodeFrame .dispose ();
138+ }
139+
140+ /**
141+ * 登录
142+ */
143+ public void login () throws WechatException {
144+
145+ HttpRequest request = HttpRequest .get (this .redirect_uri );
146+
147+ LOGGER .info ("[*] " + request );
148+
149+ String res = request .body ();
150+ wechatMeta .setCookie (CookieUtil .getCookie (request ));
151+ request .disconnect ();
152+
153+ if (StringKit .isBlank (res )) {
154+ throw new WechatException ("登录失败" );
155+ }
156+
157+ wechatMeta .setSkey (Matchers .match ("<skey>(\\ S+)</skey>" , res ));
158+ wechatMeta .setWxsid (Matchers .match ("<wxsid>(\\ S+)</wxsid>" , res ));
159+ wechatMeta .setWxuin (Matchers .match ("<wxuin>(\\ S+)</wxuin>" , res ));
160+ wechatMeta .setPass_ticket (Matchers .match ("<pass_ticket>(\\ S+)</pass_ticket>" , res ));
161+
162+ JSONObject baseRequest = new JSONObject ();
163+ baseRequest .put ("Uin" , wechatMeta .getWxuin ());
164+ baseRequest .put ("Sid" , wechatMeta .getWxsid ());
165+ baseRequest .put ("Skey" , wechatMeta .getSkey ());
166+ baseRequest .put ("DeviceID" , wechatMeta .getDeviceId ());
167+ wechatMeta .setBaseRequest (baseRequest );
168+
169+ LOGGER .info ("[*] skey[{}]" , wechatMeta .getSkey ());
170+ LOGGER .info ("[*] wxsid[{}]" , wechatMeta .getWxsid ());
171+ LOGGER .info ("[*] wxuin[{}]" , wechatMeta .getWxuin ());
172+ LOGGER .info ("[*] pass_ticket[{}]" , wechatMeta .getPass_ticket ());
173+ LOGGER .info ("[*] 微信登录成功" );
174+ }
175+
176+ /**
177+ * 微信初始化
178+ */
179+ public void wxInit () throws WechatException {
180+ this .wechatRequest = wechatService .wxInit (wechatMeta );
181+ LOGGER .info ("[*] 微信初始化成功" );
182+ }
183+
184+ /**
185+ * 微信状态通知
186+ */
187+ public void wxStatusNotify () throws WechatException {
188+ wechatService .openStatusNotify (wechatMeta , wechatRequest );
189+ LOGGER .info ("[*] 开启状态通知成功" );
190+ }
191+
192+ /**
193+ * 获取联系人
194+ */
195+ public boolean getContact () {
196+ this .wechatContact = wechatService .getContact (wechatMeta , wechatRequest );
197+ LOGGER .info ("[*] 获取联系人成功" );
198+ LOGGER .info ("[*] 共有 %d 位联系人" , wechatContact .getContactList ().size ());
199+ return false ;
200+ }
201+
202+ public void listenMsgMode () {
203+ wechatListener .start (this );
204+ }
205+
206+ public WechatService getWechatService () {
207+ return wechatService ;
208+ }
209+
210+ public void setWechatService (WechatService wechatService ) {
211+ this .wechatService = wechatService ;
212+ }
213+
214+ public WechatMeta getWechatMeta () {
215+ return wechatMeta ;
216+ }
217+
218+ public void setWechatMeta (WechatMeta wechatMeta ) {
219+ this .wechatMeta = wechatMeta ;
220+ }
221+
222+ public WechatRequest getWechatRequest () {
223+ return wechatRequest ;
224+ }
225+
226+ public void setWechatRequest (WechatRequest wechatRequest ) {
227+ this .wechatRequest = wechatRequest ;
228+ }
229+
230+ public WechatContact getWechatContact () {
231+ return wechatContact ;
232+ }
233+
234+ public void setWechatContact (WechatContact wechatContact ) {
235+ this .wechatContact = wechatContact ;
236+ }
237+
238+ public String getWebpush_url () {
239+ return webpush_url ;
240+ }
241+
242+ public void setWebpush_url (String webpush_url ) {
243+ this .webpush_url = webpush_url ;
244+ }
245+
246+ public void start () throws WechatException {
247+ this .login ();
248+ this .wxInit ();
249+ this .wxStatusNotify ();
250+ this .getContact ();
251+ // 监听消息
252+ this .listenMsgMode ();
253+ }
254+
255+ }
0 commit comments