实例介绍
【实例简介】亲测可用,仅供参考学习交流使用
操作步骤:
1. 打开软件 扫描二维码登陆(实际上登陆的是微信网页版)
2. 在你的微信>>钱包>>收付款>>二维码收款>>保存收款码
3. 让客户扫描你的收款码 填写付款备注>> 付款
4. 付款完毕后 该工具会收到 付款金额以及付款备注(如下图)
通过付款备注 区分是谁付款的,从而实现自动发货功能
【实例截图】
【核心代码】
package bin.mt;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static bin.mt.Util.*;
@SuppressWarnings("WeakerAccess")
public class WeChat {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static final Logger logger = LoggerFactory.getLogger(WeChat.class);
static {
System.setProperty("jsse.enableSNIExtension", "false");
}
private static final String UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36";
private String uuid;
private String loginUrl;
private String domainName;
private String pushDomainName;
private String skey;
private String wxsid;
private String wxuin;
private String pass_ticket;
private String syncKey;
private JSONObject syncKeyJson;
private WeChatListener listener;
private CookieJar cookieJar = new CookieJar() {
HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(@Nonnull HttpUrl url, @Nonnull List<Cookie> cookies) {
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(@Nonnull HttpUrl url) {
List<Cookie> cookies = new ArrayList<>();
String host = url.host();
// 没有对path进行匹配
for (Map.Entry<String, List<Cookie>> entry : cookieStore.entrySet()) {
if (host.endsWith(entry.getKey())) {
cookies.addAll(entry.getValue());
}
}
return cookies;
}
};
private OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.cookieJar(cookieJar).build();
// 禁止重定向
private OkHttpClient client2 = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.cookieJar(cookieJar).followRedirects(false).build();
public WeChat(WeChatListener listener) {
this.listener = listener;
}
private byte[] getLoginQRCode() throws IOException {
String url = "https://wx2.qq.com/?&lang=zh_CN";
Request request = new Request.Builder().url(url)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.build();
Response response = client.newCall(request).execute();
response.close();
url = "https://login.wx2.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx2.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=" System.currentTimeMillis();
request = new Request.Builder().url(url)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.build();
response = client.newCall(request).execute();
checkStatusCode(response);
//noinspection ConstantConditions
String str = response.body().string();
response.close();
uuid = getStringMiddle(str, "window.QRLogin.uuid = \"", "\";");
url = "https://login.weixin.qq.com/qrcode/" uuid;
request = new Request.Builder().url(url)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.build();
response = client.newCall(request).execute();
checkStatusCode(response);
//noinspection ConstantConditions
byte[] data = response.body().bytes();
response.close();
return data;
}
private long lastCheckQRCodeTime;
private boolean checkQRCode() throws IOException {
if (lastCheckQRCodeTime == -1)
lastCheckQRCodeTime = System.currentTimeMillis();
else
lastCheckQRCodeTime ;
int r = (int) (System.currentTimeMillis() & 0xFFFFFFF);
String url = "https://login.wx2.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=" uuid "&tip=0&r=-" r "&_=" lastCheckQRCodeTime;
Request request = new Request.Builder().url(url)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.addHeader("host", "login.wx2.qq.com")
.addHeader("referer", "https://wx2.qq.com/?&lang=zh_CN")
.build();
Response response = client.newCall(request).execute();
checkStatusCode(response);
//noinspection ConstantConditions
String str = response.body().string();
// System.out.println(str);
// response.close();
String code = getStringMiddle(str, "code=", ";");
switch (code) {
case "408":
break;
case "201":
String base64 = getStringMiddle(str, "base64,", "'");
listener.onQRCodeScanned(new BASE64Decoder().decodeBuffer(base64));
break;
case "200":
loginUrl = getStringMiddle(str, "redirect_uri=\"", "\"");
domainName = getStringMiddle(loginUrl, "//", "/");
pushDomainName = "webpush." domainName;
return true;
default:
logger.debug("checkQRCode: unknown code - " str);
return false;
}
return false;
}
private boolean checkIsLogged() throws IOException {
Request request = new Request.Builder().url(loginUrl)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.build();
// System.out.println("loginUrl " loginUrl);
Response response = client2.newCall(request).execute();
//noinspection ConstantConditions
String str = response.body().string();
response.close();
// System.out.println(str);
if (getStringMiddle(str, "<ret>", "</ret>").equals("0")) {
skey = getStringMiddle(str, "<skey>", "</skey>");
wxsid = getStringMiddle(str, "<wxsid>", "</wxsid>");
wxuin = getStringMiddle(str, "<wxuin>", "</wxuin>");
pass_ticket = getStringMiddle(str, "<pass_ticket>", "</pass_ticket>");
// System.out.println(skey);
// System.out.println(wxsid);
// System.out.println(wxuin);
// System.out.println(pass_ticket);
// System.out.println(webwx_data_ticket);
loadSyncKey();
return true;
}
return false;
}
public void login() {
lastCheckQRCodeTime = -1;
listener.onLoadingQRCode();
new Thread(() -> {
try {
byte[] data = getLoginQRCode();
listener.onReceivedQRCode(data);
while (true) {
if (checkQRCode())
break;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean logged = checkIsLogged();
listener.onLoginResult(logged);
if (logged) {
long time = System.currentTimeMillis();
w:
while (true) {
for (int i = 0; i < 5; i ) {
try {
if (syncCheck() < 1000)
continue w;
} catch (Throwable e) {
logger.debug("SyncCheck", e);
continue w;
}
}
// 如果10次都得到错误的返回码,break
break;
}
listener.onDropped(System.currentTimeMillis() - time);
}
} catch (IOException e) {
listener.onException(e);
}
}).start();
}
private void loadSyncKey() throws IOException {
String postData = "{\"BaseRequest\":{\"Uin\":\"" wxuin
"\",\"Sid\":\"" wxsid "\",\"Skey\":\"" skey
"\",\"DeviceID\":\"" get15RandomText() "\"}}";
int r = (int) (System.currentTimeMillis() & 0xFFFFFFF);
String url = "https://" domainName "/cgi-bin/mmwebwx-bin/webwxinit?r=-" r "&lang=zh_CN&pass_ticket=" pass_ticket;
Request request = new Request.Builder().url(url)
.method("POST", RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), postData))
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.addHeader("host", "wx.qq.com")
.addHeader("content-type", "application/json;charset=UTF-8")
.addHeader("referer", "https://" domainName "/")
.build();
Response response = client.newCall(request).execute();
//noinspection ConstantConditions
JSONObject jsonObject = JSONObject.fromObject(response.body().string());
response.close();
jsonObject = syncKeyJson = jsonObject.getJSONObject("SyncKey");
int count = jsonObject.getInt("Count");
JSONArray jsonArray = jsonObject.getJSONArray("List");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i ) {
jsonObject = jsonArray.getJSONObject(i);
sb.append("|").append(jsonObject.getInt("Key")).append("_").append(jsonObject.getInt("Val"));
}
sb.deleteCharAt(0);
syncKey = sb.toString();
// System.out.println(syncKey);
// System.out.println(syncKeyJson.toString());
}
private int syncCheck() throws IOException {
String url = "https://" pushDomainName "/cgi-bin/mmwebwx-bin/synccheck?r=" System.currentTimeMillis()
"&skey=" skey.replace("@", "%40") "&sid=" wxsid "&uin=" wxuin "&deviceid=" get15RandomText()
"&synckey=" syncKey.replace("|", "%7C") "&_=" System.currentTimeMillis();
// System.out.println("正在等待消息..");
Request request = new Request.Builder().url(url)
.addHeader("accept", "*/*")
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", UA)
.addHeader("referer", "https://" domainName "/")
.addHeader("host", pushDomainName)
.build();
Response response;
try {
response = client.newCall(request).execute();
} catch (Exception e) {
return 1100;
}
if (!response.isSuccessful()) {
response.close();
return 1100;
}
//noinspection ConstantConditions
String str = response.body().string();
response.close();
String retCode = getStringMiddle(str, "retcode:\"", "\"");
String selector = getStringMiddle(str, "selector:\"", "\"");
// 1101 1100 1102掉线
if (retCode.length() == 4 && retCode.startsWith("1")) {
logger.warn(str);
return Integer.parseInt(retCode);
}
if (selector.equals("0"))
return 0;
// 有消息
try {
getMessage();
} catch (Throwable e) {
return 1000;
}
return 1;
}
private void getMessage() throws IOException {
JSONObject json = new JSONObject();
JSONObject baseRequest = new JSONObject();
baseRequest.put("Uin", wxuin);
baseRequest.put("Sid", wxsid);
baseRequest.put("Skey", skey);
baseRequest.put("DeviceID", get15RandomText());
json.put("BaseRequest", baseRequest);
json.put("SyncKey", syncKeyJson);
StringBuilder sb = new StringBuilder("-1728");
for (int i = 0; i < 6; i ) {
sb.append(RANDOM.nextInt(10));
}
json.put("rr", Integer.valueOf(sb.toString()));
String content = json.toString();
// System.out.println(content);
String url = "https://" domainName "/cgi-bin/mmwebwx-bin/webwxsync?sid=" wxsid "&skey=" skey.replace("@", "%40") "&pass_ticket=" pass_ticket;
Request request = new Request.Builder().url(url)
.method("POST", RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), content))
.addHeader("connection", "keep-alive")
.addHeader("accept", "application/json, text/plain, */*")
.addHeader("user-agent", UA)
.addHeader("content-type", "application/json;charset=UTF-8")
.build();
Response response;
try {
response = client.newCall(request).execute();
} catch (Exception e) {
return;
}
if (!response.isSuccessful()) {
response.close();
return;
}
//noinspection ConstantConditions
content = response.body().string();
response.close();
// System.out.println(content);
JSONObject jsonObject = JSONObject.fromObject(content);
JSONObject syncKeyJson = this.syncKeyJson = jsonObject.getJSONObject("SyncKey");
int count = syncKeyJson.getInt("Count");
JSONArray jsonArray = syncKeyJson.getJSONArray("List");
sb = new StringBuilder();
for (int i = 0; i < count; i ) {
syncKeyJson = jsonArray.getJSONObject(i);
sb.append("|").append(syncKeyJson.getInt("Key")).append("_").append(syncKeyJson.getInt("Val"));
}
sb.deleteCharAt(0);
syncKey = sb.toString();
jsonArray = jsonObject.getJSONArray("AddMsgList");
int size = jsonArray.size();
for (int i = 0; i < size; i ) {
jsonObject = jsonArray.getJSONObject(i);
// String fromUserName = jsonObject.getString("FromUserName");
// String toUserName = jsonObject.getString("ToUserName");
int msgType = jsonObject.getInt("MsgType");
String con = jsonObject.getString("Content");
if (msgType == 49) {
checkPay(con);
}
}
}
private void checkPay(String con) throws IOException {
// System.out.println(con);
if (!con.contains("CDATA[微信支付]") || !con.contains("CDATA[收款到账通知") || !con.contains("收款成功"))
return;
String money = getStringMiddle(con, "收款金额:¥", "<br/>");
if (money.isEmpty())
return;
try {
//noinspection ResultOfMethodCallIgnored
Float.parseFloat(money);
} catch (NumberFormatException e) {
return;
}
String mark = getStringMiddle(con, "付款方备注:", "<br/>");
String all = getStringMiddle(con, "汇总:", "<br/>");
String count = getStringMiddle(all, "第", "笔");
String allMoney = getStringRight(all, "¥").replace(".", "");
all = DATE_FORMAT.format(System.currentTimeMillis()) "-" count "-" allMoney;
listener.onReceivedMoney(money, mark, all);
}
private static void checkStatusCode(Response response) throws IOException {
if (!response.isSuccessful()) {
throw new IOException("Http status code = " response.code());
}
}
interface WeChatListener {
void onLoadingQRCode();
/**
* 得到登录二维码
*
* @param jpgData 二维码图片
*/
void onReceivedQRCode(byte[] jpgData);
/**
* 二维码被扫描
*
* @param jpgData 头像
*/
void onQRCodeScanned(byte[] jpgData);
void onLoginResult(boolean loginSucceed);
void onReceivedMoney(String money, String mark, String id) throws IOException;
/**
* 登录成功后掉线
*
* @param onlineTime 掉线之前保持在线到时长
*/
void onDropped(long onlineTime);
void onException(IOException e);
}
}
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论