Using wechat web brower to register.

This commit is contained in:
Sola
2015-12-02 04:18:49 +08:00
parent 21d7c44e7e
commit 8d9b8da42f
22 changed files with 1049 additions and 236 deletions

58
docs/Authorize.html Normal file
View File

@@ -0,0 +1,58 @@
<!DOCTYPE html><html><head><title>Authorize</title><meta charset='utf-8'><link href='https://dn-maxiang.qbox.me/res-min/themes/marxico.css' rel='stylesheet'></head><body><div id='preview-contents' class='note-content'>
<div id="wmd-preview" class="preview-content"></div>
<div id="wmd-preview-section-1791" class="wmd-preview-section preview-content">
</div><div id="wmd-preview-section-1806" class="wmd-preview-section preview-content">
<h1 id="authorize">Authorize</h1>
<div><div class="toc"><div class="toc">
<ul>
<li><a href="#authorize">Authorize</a><ul>
<li><a href="#url">URL</a></li>
<li><a href="#method">Method</a></li>
<li><a href="#parameters">Parameters</a></li>
<li><a href="#response-code">Response Code</a></li>
</ul>
</li>
<li><a href="#signature">Signature</a></li>
</ul>
</div>
</div>
</div></div><div id="wmd-preview-section-1793" class="wmd-preview-section preview-content">
<h2 id="url">URL</h2>
<p><a href="http://sola.love/ww/api/authorize" target="_blank">http://sola.love/ww/api/authorize</a></p>
</div><div id="wmd-preview-section-1794" class="wmd-preview-section preview-content">
<h2 id="method">Method</h2>
<p>POST</p>
</div><div id="wmd-preview-section-1795" class="wmd-preview-section preview-content">
<h2 id="parameters">Parameters</h2>
<ul><li><code>wechat</code> Wechat ID</li>
</ul>
</div><div id="wmd-preview-section-1838" class="wmd-preview-section preview-content">
<h2 id="response-code">Response Code</h2>
<ul><li>Success <br>
<ul>
<li><code>0</code> OK</li></ul></li>
<li>Error <br>
<ul>
<li><code>-1</code> PARAMETER_REQUIRED</li>
<li><code>-9</code> AUTHORIZE_FAILED</li></ul></li>
</ul>
<hr></div><div id="wmd-preview-section-1797" class="wmd-preview-section preview-content">
<h1 id="signature">Signature</h1>
<p>Created by Sola on 2/15/2015</p></div><div id="wmd-preview-section-footnotes" class="preview-content"></div></div></body></html>

View File

@@ -0,0 +1,82 @@
<!DOCTYPE html><html><head><title>绑定微信请求</title><meta charset='utf-8'><link href='https://dn-maxiang.qbox.me/res-min/themes/marxico.css' rel='stylesheet'></head><body><div id='preview-contents' class='note-content'>
<div id="wmd-preview" class="preview-content"></div>
<div id="wmd-preview-section-5" class="wmd-preview-section preview-content">
</div><div id="wmd-preview-section-27" class="wmd-preview-section preview-content">
<h1 id="绑定微信请求">绑定微信请求</h1>
</div><div id="wmd-preview-section-58" class="wmd-preview-section preview-content">
<h2 id="url">URL</h2>
<p><a href="http://sola.love" target="_blank">http://sola.love</a></p></div><div id="wmd-preview-section-94" class="wmd-preview-section preview-content">
<h2 id="method">Method</h2>
<p>POST</p>
</div><div id="wmd-preview-section-633" class="wmd-preview-section preview-content">
<h2 id="params">Params</h2>
<ul><li><code>wechatid</code> <strong>string</strong> 用户微信ID</li>
<li><code>name</code> <strong>string</strong> 姓名</li>
<li><code>sid</code> <strong>string</strong> 学号</li>
<li><code>isp</code> <strong>integer</strong> ISP的代码</li>
<li><code>username</code> <strong>string</strong> 宽带帐号</li>
<li><code>block</code> <strong>integer</strong> 片区代码</li>
<li><code>room</code> <strong>integer</strong> 宿舍房号 </li>
<li><code>phone</code> <strong>string</strong> 手机号码</li>
</ul></div><div id="wmd-preview-section-657" class="wmd-preview-section preview-content">
<h2 id="more">More</h2></div><div id="wmd-preview-section-2016" class="wmd-preview-section preview-content">
<h3 id="片区代码">片区代码</h3>
<ul><li>岐头生活区 <br>
<ul>
<li>18栋 <code>10</code></li>
<li>19栋 <code>11</code></li>
<li>16栋 <code>12</code></li>
<li>17栋 <code>13</code></li></ul></li>
<li>北门生活区 <br>
<ul>
<li>7栋 <code>20</code></li>
<li>8栋 <code>21</code></li>
<li>9栋 <code>22</code></li>
<li>10栋 <code>23</code></li>
<li>11栋 <code>24</code></li></ul></li>
<li>东门生活区 <br>
<ul>
<li>12栋 <code>30</code></li>
<li>13栋 <code>31</code></li>
<li>14栋 <code>32</code></li>
<li>15栋 <code>33</code></li></ul></li>
<li>香晖苑 <br>
<ul>
<li>A <code>40</code></li>
<li>B <code>41</code></li>
<li>C <code>42</code></li>
<li>D <code>43</code></li></ul></li>
<li>凤翔生活区 <br>
<ul>
<li>1栋 <code>50</code></li>
<li>2栋 <code>51</code></li>
<li>3栋 <code>52</code></li>
<li>4栋 <code>53</code></li>
<li>5栋 <code>54</code></li>
<li>6栋 <code>55</code></li></ul></li>
<li>东门区 <br>
<ul>
<li>20栋 <code>60</code></li>
<li>21栋 <code>61</code></li></ul></li>
</ul></div><div id="wmd-preview-section-2112" class="wmd-preview-section preview-content">
<h2 id="author">Author</h2>
<p>LiuYue(hangxingliu)</p></div><div id="wmd-preview-section-2175" class="wmd-preview-section preview-content">
<h2 id="date">Date</h2>
<p>2015/11/28</p></div><div id="wmd-preview-section-footnotes" class="preview-content"></div></div></body></html>

View File

@@ -0,0 +1,77 @@
package love.sola.netsupport.api;
import com.google.gson.Gson;
import love.sola.netsupport.config.Settings;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.wechat.Command;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
* Created by Sola on 2015/12/2.
* Don't modify this source without my agreement
* ***********************************************
*/
@WebServlet(name = "Authorize", urlPatterns = "/api/authorize", loadOnStartup = 21)
public class Authorize extends HttpServlet {
private Gson gson = SQLCore.gson;
public static Map<String, Long> fetchedTime = new ConcurrentHashMap<>();
public static Map<String, Command> fetchedCommand = new ConcurrentHashMap<>();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-type", "text/json;charset=utf-8");
PrintWriter out = response.getWriter();
String wechat = request.getParameter("wechat");
out.println(gson.toJson(authorize(wechat)));
out.close();
}
private Response authorize(String wechat) {
if (wechat == null) {
return new Response(Response.ResponseCode.PARAMETER_REQUIRED);
}
Long l = fetchedTime.remove(wechat);
Command c = fetchedCommand.remove(wechat);
if (l == null || c == null) {
return new Response(Response.ResponseCode.AUTHORIZE_FAILED);
}
if (l < System.currentTimeMillis() - Settings.I.User_Command_Timeout) {
return new Response(Response.ResponseCode.AUTHORIZE_FAILED);
}
switch (c) {
case REGISTER:
Register.authorized.put(wechat, System.currentTimeMillis());
break;
default:
return new Response(Response.ResponseCode.AUTHORIZE_FAILED);
}
return new Response(Response.ResponseCode.OK);
}
@SuppressWarnings("Duplicates")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-type", "text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
out.println(lang("Illegal_Request"));
out.close();
}
}

View File

@@ -2,6 +2,7 @@ package love.sola.netsupport.api;
import com.google.gson.Gson;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.sql.TableUser;
import javax.servlet.ServletConfig;
@@ -22,12 +23,11 @@ import java.io.PrintWriter;
@WebServlet(name = "GetUser",urlPatterns = "/api/getuser",loadOnStartup = 1)
public class GetUser extends HttpServlet {
private Gson gson = null;
private Gson gson = SQLCore.gson;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
gson = new Gson();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

View File

@@ -0,0 +1,156 @@
package love.sola.netsupport.api;
import love.sola.netsupport.config.Settings;
import love.sola.netsupport.enums.Block;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.sql.TableUser;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
* Created by Sola on 2015/11/29.
* Don't modify this source without my agreement
* ***********************************************
*/
@WebServlet(name = "Register", urlPatterns = "/api/register", loadOnStartup = 22)
public class Register extends HttpServlet {
public static Map<String, Long> authorized = new ConcurrentHashMap<>();
public static final String STUDENT_ID_REGEX = "^(2010|2012|2013|2014|2015)[0-9]{9}$";
public static final String PHONE_NUMBER_REGEX = "^1[34578][0-9]{9}$";
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-type", "text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
ISP isp = checkISP(request.getParameter("isp"));
Block block = checkBlock(request.getParameter("block"));
out.println(
register(
checkStudentId(request.getParameter("sid")),
request.getParameter("name"),
isp,
checkNetAccount(request.getParameter("username"), isp),
block,
checkRoom(request.getParameter("room"), block),
checkPhoneNumber(request.getParameter("phone")),
checkWechat(request.getParameter("wechatid"))
)
);
out.close();
}
@SuppressWarnings("Duplicates")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-type", "text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
out.println(lang("Illegal_Request"));
out.close();
}
private String register(long sid, String name, ISP isp, String netAccount, Block block, int room, long phone, String wechat) {
if (wechat == null) return lang("Illegal_Request");
if (sid == -1) return lang("Invalid_Student_Id");
if (name == null) return lang("Invalid_Name");
if (isp == null) return lang("Invalid_ISP");
if (netAccount == null) return lang("Invalid_Account");
if (block == null) return lang("Invalid_Block");
if (room == -1) return lang("Invalid_Room");
if (phone == -1) return lang("Invalid_Phone_Number");
User user = TableUser.getUserById(sid);
if (user == null) return lang("Invalid_Student_Id");
if (!user.getName().equals(name)) return lang("Invalid_Name");
if (user.getWechatId() != null) return lang("User_Already_Registered");
user.setIsp(isp);
user.setNetAccount(netAccount);
user.setBlock(block);
user.setRoom(room);
user.setPhone(phone);
user.setWechatId(wechat);
return lang("Register_Success");
}
private long checkStudentId(String studentId) {
if (studentId == null) return -1;
if (studentId.matches(STUDENT_ID_REGEX)) {
try {
return Long.parseLong(studentId);
} catch (NumberFormatException ignored) {
}
}
return -1;
}
private long checkPhoneNumber(String phone) {
if (phone == null) return -1;
if (phone.matches(PHONE_NUMBER_REGEX)) {
try {
return Long.parseLong(phone);
} catch (NumberFormatException ignored) {
}
}
return -1;
}
private ISP checkISP(String isp) {
if (isp == null) return null;
try {
return ISP.fromId(Integer.parseInt(isp));
} catch (NumberFormatException ignored) {
}
return null;
}
private String checkNetAccount(String account, ISP isp) {
if (isp == null) return null;
if (account == null) return null;
if (!account.matches(isp.accountRegex)) return null;
return account;
}
private Block checkBlock(String block) {
if (block == null) return null;
try {
return Block.fromId(Integer.parseInt(block));
} catch (NumberFormatException ignored) {
}
return null;
}
private int checkRoom(String room, Block block) {
if (block == null) return -1;
if (room == null) return -1;
try {
Integer i = Integer.parseInt(room);
if (i <= 100 || i >= 1300) return -1;
return i;
} catch (NumberFormatException ignored) {
}
return -1;
}
private String checkWechat(String wechat) {
if (wechat == null) return null;
Long l = authorized.remove(wechat);
return l == null ? null : l < System.currentTimeMillis() - Settings.I.User_Register_Timeout ? null : wechat;
}
}

View File

@@ -5,6 +5,8 @@ import lombok.AllArgsConstructor;
import java.util.HashMap;
import java.util.Map;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
* Created by Sola on 2015/11/5.
@@ -31,27 +33,26 @@ public class Response {
public enum ResponseCode {
OK(0, "OK"),
PARAMETER_REQUIRED(-1, "Parameter Required"),
ILLEGAL_PARAMETER(-2, "Illegal parameter"),
USER_NOT_FOUND(-11, "User not found"),
OK(0),
PARAMETER_REQUIRED(-1),
ILLEGAL_PARAMETER(-2),
AUTHORIZE_FAILED(-9),
USER_NOT_FOUND(-11),
;
private static final Map<Integer, ResponseCode> ID_MAP = new HashMap<>();
static {
for (ResponseCode type : values()) {
if (type.id > 0) {
ID_MAP.put(type.id, type);
}
ID_MAP.put(type.id, type);
}
}
public final String info;
public final int id;
ResponseCode(int id, String info) {
this.info = info;
ResponseCode(int id) {
this.info = lang("RC_" + name());
this.id = id;
}

View File

@@ -0,0 +1,44 @@
package love.sola.netsupport.api;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Map;
/**
* ***********************************************
* Created by Sola on 2014/8/20.
* Don't modify this source without my agreement
* ***********************************************
*/
@WebServlet(name = "TestPost",urlPatterns = "/api/testpost",loadOnStartup = 10)
public class TestPost extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-type", "text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("Parameters:");
for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
out.println(entry.getKey() + ": " + Arrays.toString(entry.getValue()));
}
out.close();
}
}

View File

@@ -0,0 +1,41 @@
package love.sola.netsupport.config;
import love.sola.netsupport.sql.TableLang;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
/**
* ***********************************************
* Created by Sola on 2015/11/30.
* Don't modify this source without my agreement
* ***********************************************
*/
public class Lang {
public static Map<String, String> messages;
public static Map<String, MessageFormat> format_cache = new HashMap<>(32);
static {
messages = new HashMap<>();
TableLang.getLang(messages);
}
public static String lang(String key) {
String value = messages.get(key);
return value == null ? "!!" + key + "!!" : value;
}
public static String format(String key, Object... args) {
MessageFormat cache = format_cache.get(key);
if (cache != null) {
return cache.format(args);
} else {
cache = new MessageFormat(lang(key));
format_cache.put(key, cache);
return cache.format(args);
}
}
}

View File

@@ -29,6 +29,11 @@ public class Settings {
public int Check_Spam_Cache_Expire_Time;
public int Check_Spam_Interval;
public int User_Caching_Time;
public int User_Register_Timeout;
public int User_Command_Timeout;
//No arg constructor for Yaml.loadAs
public Settings() { I = this; }

View File

@@ -0,0 +1,106 @@
package love.sola.netsupport.enums;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
* Created by Sola on 2015/11/30.
* Don't modify this source without my agreement
* ***********************************************
*/
public enum Block {
@SerializedName("10")
QT_18(10),
@SerializedName("11")
QT_19(11),
@SerializedName("12")
QT_16(12),
@SerializedName("13")
QT_17(13),
@SerializedName("20")
BM_7(20),
@SerializedName("21")
BM_8(21),
@SerializedName("22")
BM_9(22),
@SerializedName("23")
BM_10(23),
@SerializedName("24")
BM_11(24),
@SerializedName("30")
DM_12(30),
@SerializedName("31")
DM_13(31),
@SerializedName("32")
DM_14(32),
@SerializedName("33")
DM_15(33),
@SerializedName("40")
XH_A(40),
@SerializedName("41")
XH_B(41),
@SerializedName("42")
XH_C(42),
@SerializedName("43")
XH_D(43),
@SerializedName("50")
FX_1(50),
@SerializedName("51")
FX_2(51),
@SerializedName("52")
FX_3(52),
@SerializedName("53")
FX_4(53),
@SerializedName("54")
FX_5(54),
@SerializedName("55")
FX_6(55),
@SerializedName("60")
DM_20(60),
@SerializedName("61")
DM_21(61),
;
private static final Map<String, Block> NAME_MAP = new HashMap<>();
private static final Map<Integer, Block> ID_MAP = new HashMap<>();
static {
for (Block type : values()) {
if (type.name != null) {
NAME_MAP.put(type.name.toLowerCase(), type);
}
if (type.id > 0) {
ID_MAP.put(type.id, type);
}
}
}
public final String name;
public final int id;
Block(int id) {
this.name = lang("BLOCK_" + name());
this.id = id;
}
public static Block fromName(String name) {
if (name == null) {
return null;
}
return NAME_MAP.get(name.toLowerCase());
}
public static Block fromId(int id) {
return ID_MAP.get(id);
}
@Override
public String toString() { return name; }
}

View File

@@ -0,0 +1,63 @@
package love.sola.netsupport.enums;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
* Created by Sola on 2014/8/20.
* Don't modify this source without my agreement
* ***********************************************
*/
public enum ISP {
@SerializedName("1")
TELECOM(1, "^1[3|4|5|7|8][0-9]{9}$"),
@SerializedName("2")
UNICOM(2, "ZSZJLAN[0-9]{10}@16900\\.gd"),
@SerializedName("3")
CHINAMOBILE(3, "^1[3|4|5|7|8][0-9]{9}@139\\.gd$"),;
private static final Map<String, ISP> NAME_MAP = new HashMap<>();
private static final Map<Integer, ISP> ID_MAP = new HashMap<>();
static {
for (ISP type : values()) {
if (type.name != null) {
NAME_MAP.put(type.name.toLowerCase(), type);
}
if (type.id > 0) {
ID_MAP.put(type.id, type);
}
}
}
public final int id;
public final String name;
public final String accountRegex;
ISP(int id, String accountRegex) {
this.id = id;
this.name = lang("ISP_" + name());
this.accountRegex = accountRegex;
}
public static ISP fromName(String name) {
if (name == null) {
return null;
}
return NAME_MAP.get(name.toLowerCase());
}
public static ISP fromId(int id) {
return ID_MAP.get(id);
}
@Override
public String toString() { return name; }
}

View File

@@ -1,56 +0,0 @@
package love.sola.netsupport.enums;
import java.util.HashMap;
import java.util.Map;
/**
* ***********************************************
* Created by Sola on 2014/8/20.
* Don't modify this source without my agreement
* ***********************************************
*/
public enum ISPType {
TELECOM("Telecom", 1),
UNICOM("Unicom", 2),
CHINAMOBILE("ChinaMobile", 3),;
private static final Map<String, ISPType> NAME_MAP = new HashMap<>();
private static final Map<Integer, ISPType> ID_MAP = new HashMap<>();
static {
for (ISPType type : values()) {
if (type.name != null) {
NAME_MAP.put(type.name.toLowerCase(), type);
}
if (type.id > 0) {
ID_MAP.put(type.id, type);
}
}
}
public final String name;
public final int id;
ISPType(String name, int id) {
this.name = name;
this.id = id;
}
public static ISPType fromName(String name) {
if (name == null) {
return null;
}
return NAME_MAP.get(name.toLowerCase());
}
public static ISPType fromId(int id) {
return ID_MAP.get(id);
}
@Override
public String toString() {
return name;
}
}

View File

@@ -2,7 +2,8 @@ package love.sola.netsupport.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import love.sola.netsupport.enums.ISPType;
import love.sola.netsupport.enums.Block;
import love.sola.netsupport.enums.ISP;
/**
* ***********************************************
@@ -16,8 +17,11 @@ public class User {
private final long id;
private final String name;
private ISP isp;
private String netAccount;
private ISPType isp;
private String wechatId;
private Block block;
private int room;
private long phone;
}

View File

@@ -0,0 +1,28 @@
package love.sola.netsupport.sql;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
/**
* ***********************************************
* Created by Sola on 2015/11/30.
* Don't modify this source without my agreement
* ***********************************************
*/
public class TableLang extends SQLCore {
public static void getLang(Map<String, String> lang) {
try (Connection conn = ds.getConnection()) {
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM lang;");
while (rs.next()) {
lang.put(rs.getString("lkey"), rs.getString("lvalue"));
}
} catch (SQLException e) {
}
}
}

View File

@@ -1,12 +1,19 @@
package love.sola.netsupport.sql;
import love.sola.netsupport.enums.ISPType;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import love.sola.netsupport.config.Settings;
import love.sola.netsupport.enums.Block;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.pojo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* ***********************************************
@@ -14,43 +21,101 @@ import java.sql.SQLException;
* Don't modify this source without my agreement
* ***********************************************
*/
@SuppressWarnings("Duplicates")
public class TableUser extends SQLCore {
public static final String COLUMN_ID = "id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_NET_ACCOUNT = "netaccount";
public static final String COLUMN_ISP = "isp";
public static final String COLUMN_NET_ACCOUNT = "netaccount";
public static final String COLUMN_WECHAT = "wechat";
public static final String COLUMN_BLOCK = "block";
public static final String COLUMN_ROOM = "room";
public static final String COLUMN_PHONE = "phone";
public static User getUserByName(String name) {
try (Connection conn = ds.getConnection()) {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user_info WHERE name=?");
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return new User(rs.getLong(COLUMN_ID),
rs.getString(COLUMN_NAME),
rs.getString(COLUMN_NET_ACCOUNT),
ISPType.fromId(rs.getInt(COLUMN_ISP)),
rs.getString(COLUMN_WECHAT));
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static User getUserById(long id) {
if (id < 0) return null;
try {
return cache_id.get(id);
} catch (ExecutionException e) {
return null;
}
}
public static User getUserByWechat(String wechat) {
if (wechat == null) return null;
try {
return cache_wechat.get(wechat);
} catch (ExecutionException e) {
return null;
}
}
public static User getUserByName(String name) {
if (name == null) return null;
User u = getUserByName0(name);
if (u != null) {
cache_id.put(u.getId(), u);
if (u.getWechatId()!=null) cache_wechat.put(u.getWechatId(), u);
}
return u;
}
public static int updateUser(User user) {
int r = updateUser0(user);
if (r > 0) {
cache_id.put(user.getId(), user);
if (user.getWechatId() != null) cache_wechat.put(user.getWechatId(), user);
}
return r;
}
private static LoadingCache<Long, User> cache_id = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.maximumSize(2048)
.expireAfterAccess(Settings.I.User_Caching_Time, TimeUnit.SECONDS)
.build(new IdLoader());
private static LoadingCache<String, User> cache_wechat = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.maximumSize(2048)
.expireAfterAccess(Settings.I.User_Caching_Time, TimeUnit.SECONDS)
.build(new WechatLoader());
private static class IdLoader extends CacheLoader<Long, User> {
@Override
public User load(Long key) throws Exception {
User u = getUserById0(key);
System.out.println("Queried user: " + u);
if (u == null) throw new UserNotFoundException();
if (u.getWechatId() != null) cache_wechat.put(u.getWechatId(), u);
return u;
}
}
private static class WechatLoader extends CacheLoader<String, User> {
@Override
public User load(String key) throws Exception {
User u = getUserByWechat0(key);
System.out.println("Queried user: " + u);
if (u == null) throw new UserNotFoundException();
cache_id.put(u.getId(), u);
return u;
}
}
public static class UserNotFoundException extends Exception { }
private static User getUserById0(long id) {
try (Connection conn = ds.getConnection()) {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user_info WHERE id=?");
ps.setLong(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return new User(rs.getLong(COLUMN_ID),
rs.getString(COLUMN_NAME),
rs.getString(COLUMN_NET_ACCOUNT),
ISPType.fromId(rs.getInt(COLUMN_ISP)),
rs.getString(COLUMN_WECHAT));
return constructUser(rs);
}
} catch (SQLException e) {
e.printStackTrace();
@@ -58,21 +123,70 @@ public class TableUser extends SQLCore {
return null;
}
public static int updateUser(User user) {
private static User getUserByWechat0(String wechat) {
try (Connection conn = ds.getConnection()) {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user_info WHERE wechat=?");
ps.setString(1, wechat);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return constructUser(rs);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private static User getUserByName0(String name) {
try (Connection conn = ds.getConnection()) {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user_info WHERE name=?");
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return constructUser(rs);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private static int updateUser0(User user) {
try (Connection conn = ds.getConnection()) {
PreparedStatement ps = conn.prepareStatement("UPDATE user_info SET " +
COLUMN_WECHAT + "=?," +
COLUMN_ISP + "=?," +
COLUMN_NET_ACCOUNT + "=?," +
COLUMN_ISP + "=? " +
COLUMN_BLOCK + "=?," +
COLUMN_ROOM + "=?," +
COLUMN_PHONE + "=? " +
"WHERE id=?");
ps.setString(1, user.getWechatId());
ps.setString(2, user.getNetAccount());
ps.setInt(3, user.getIsp().id);
ps.setLong(4, user.getId());
ps.setInt(2, user.getIsp().id);
ps.setString(3, user.getNetAccount());
ps.setInt(4, user.getBlock().id);
ps.setInt(5, user.getRoom());
ps.setLong(6, user.getPhone());
ps.setLong(7, user.getId());
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
}
private static User constructUser(ResultSet rs) throws SQLException {
return new User(
rs.getLong(COLUMN_ID),
rs.getString(COLUMN_NAME),
ISP.fromId(rs.getInt(COLUMN_ISP)),
rs.getString(COLUMN_NET_ACCOUNT),
rs.getString(COLUMN_WECHAT),
Block.fromId(rs.getInt(COLUMN_BLOCK)),
rs.getInt(COLUMN_ROOM),
rs.getInt(COLUMN_PHONE)
);
}
}

View File

@@ -1,7 +1,5 @@
package love.sola.netsupport.wechat;
import lombok.Getter;
import java.util.HashMap;
import java.util.Map;
@@ -13,7 +11,7 @@ import java.util.Map;
*/
public enum Command {
REGISTER(0, "Register", "(?i)^Register$"),
REGISTER(0, "Register", ".*"),
;
private static final Map<Integer, Command> ID_MAP = new HashMap<>();
@@ -26,12 +24,9 @@ public enum Command {
}
}
@Getter
private final String name;
@Getter
private final String regex;
@Getter
private final int id;
public final String name;
public final String regex;
public final int id;
Command(int id, String name, String regex) {
this.name = name;

View File

@@ -3,12 +3,11 @@ package love.sola.netsupport.wechat;
import love.sola.netsupport.config.Settings;
import love.sola.netsupport.wechat.handler.RegisterHandler;
import love.sola.netsupport.wechat.intercepter.CheckSpamInterceptor;
import love.sola.netsupport.wechat.matcher.CommandMatcher;
import love.sola.netsupport.wechat.matcher.RegisterMatcher;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.api.*;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
@@ -18,6 +17,9 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import static love.sola.netsupport.config.Lang.lang;
/**
* ***********************************************
@@ -25,7 +27,7 @@ import java.io.IOException;
* Don't modify this source without my agreement
* ***********************************************
*/
@WebServlet(name = "WxMpServlet", urlPatterns = "/wechattest", loadOnStartup = 2)
@WebServlet(name = "WxMpServlet", urlPatterns = "/wechattest", loadOnStartup = 99)
public class WxMpServlet extends HttpServlet {
public static WxMpServlet instance;
@@ -56,10 +58,24 @@ public class WxMpServlet extends HttpServlet {
wxMpMessageRouter.rule()
.async(false)
.msgType("text")
.matcher(new CommandMatcher(Command.REGISTER))
.matcher(new RegisterMatcher())
.handler(new RegisterHandler())
.interceptor(checkSpamInterceptor)
.end();
wxMpMessageRouter.rule()
.async(false)
.msgType("event")
.event("subscribe")
.handler(new WxMpMessageHandler() {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
return WxMpXmlOutMessage.TEXT()
.fromUser(wxMessage.getToUserName())
.toUser(wxMessage.getFromUserName())
.content(lang("Event_Subscribe")).build();
}
})
.end();
}
@Override
@@ -75,7 +91,7 @@ public class WxMpServlet extends HttpServlet {
if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
// Signature fail
response.getWriter().println("Access Denied");
response.getWriter().println(lang("Access_Denied"));
return;
}
@@ -95,7 +111,7 @@ public class WxMpServlet extends HttpServlet {
outMessage = WxMpXmlOutMessage.TEXT()
.fromUser(inMessage.getToUserName())
.toUser(inMessage.getFromUserName())
.content("Invalid Operation.")
.content(lang("Invalid_Operation"))
.build();
}
response.getWriter().write(outMessage.toXml());
@@ -110,14 +126,14 @@ public class WxMpServlet extends HttpServlet {
outMessage = WxMpXmlOutMessage.TEXT()
.fromUser(inMessage.getToUserName())
.toUser(inMessage.getFromUserName())
.content("Invalid Operation.")
.content(lang("Invalid_Operation"))
.build();
}
response.getWriter().write(outMessage.toEncryptedXml(config));
return;
}
response.getWriter().println("Unknown encrypt-type");
response.getWriter().println(lang("Unknown_Encrypt_Type"));
return;
}

View File

@@ -1,10 +1,7 @@
package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.ISPType;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.api.Authorize;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.matcher.CommandMatcher;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
@@ -13,9 +10,10 @@ import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
import java.util.HashMap;
import java.util.Map;
import static love.sola.netsupport.config.Lang.format;
/**
* ***********************************************
* Created by Sola on 2015/11/4.
@@ -24,123 +22,14 @@ import java.util.Map;
*/
public class RegisterHandler implements WxMpMessageHandler {
public static final String STUDENT_ID_REGEX = "^(2010|2012|2013|2014|2015)[0-9]{9}";
Map<String, User> confirmed = new HashMap<>();
Map<String, RegisterStep> steps = new HashMap<>();
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager)
throws WxErrorException {
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
handle(wxMessage.getContent(), wxMessage.getFromUserName(), out);
out.content(format("User_Register_Link", wxMessage.getFromUserName()));
Authorize.fetchedTime.put(wxMessage.getFromUserName(), System.currentTimeMillis());
Authorize.fetchedCommand.put(wxMessage.getFromUserName(), Command.REGISTER);
return out.build();
}
private void handle(String in, String userName, TextBuilder out) {
if (in.equalsIgnoreCase("q")) {
CommandMatcher.inCmdUsers.remove(userName);
confirmed.remove(userName);
steps.remove(userName);
out.content("Operation canceled.");
return;
}
if (!steps.containsKey(userName)) {
out.content("Welcome, please type your student identification number.");
CommandMatcher.inCmdUsers.put(userName, Command.REGISTER);
steps.put(userName, RegisterStep.STUDENT_ID);
return;
}
RegisterStep step = steps.get(userName);
if (step == RegisterStep.STUDENT_ID) {
Long sid = checkStudentId(in);
User user;
if (sid == null || (user = TableUser.getUserById(sid)) == null) {
out.content("Invalid student identification number. Type 'q' to cancel this operation.");
return;
}
out.content("Please type your real name to validate.");
confirmed.put(userName, user);
steps.put(userName, RegisterStep.NAME);
return;
}
User user = confirmed.get(userName);
if (step == RegisterStep.NAME) {
if (in.trim().equals(user.getName())) {
out.content("Confirmed success.\n" +
"Please enter your ISP.\n" +
"1-Telecom 2-Unicom 3-ChinaMobile");
steps.put(userName, RegisterStep.ISP);
} else {
out.content("Validate failed.\n" +
"If you have any issue, please contact administrator.\n" +
"Type 'q' to cancel this operation.");
}
return;
}
if (step == RegisterStep.ISP) {
ISPType type = checkISP(in);
if (type == null) {
out.content("Invalid ISP. Please retype your ISP.");
} else {
user.setIsp(type);
out.content("Success.\n" +
"Please enter your net account.");
steps.put(userName, RegisterStep.NET_ACCOUNT);
}
return;
}
if (step == RegisterStep.NET_ACCOUNT) {
String account = checkNetAccount(in);
if (account == null) {
out.content("Invalid account. Please retype your net account.");
} else {
user.setNetAccount(account);
steps.put(userName, RegisterStep.COMPLETE);
}
}
if (step == RegisterStep.COMPLETE) {
user.setWechatId(userName);
TableUser.updateUser(user);
CommandMatcher.inCmdUsers.remove(userName);
confirmed.remove(userName);
steps.remove(userName);
out.content("Congratulations!\n" +
"You has successful registered!\n" +
"Please enjoy our service.");
}
}
private Long checkStudentId(String studentId) {
if (studentId.matches(STUDENT_ID_REGEX)) {
try {
return Long.parseLong(studentId);
} catch (NumberFormatException ignored) {
}
}
return null;
}
private ISPType checkISP(String isp) {
try {
return ISPType.fromId(Integer.parseInt(isp));
} catch (NumberFormatException ignored) {
}
return null;
}
private String checkNetAccount(String account) {
return account;
}
enum RegisterStep {
STUDENT_ID,
NAME,
ISP,
NET_ACCOUNT,
COMPLETE,
;
}
}

View File

@@ -0,0 +1,146 @@
package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.matcher.CommandMatcher;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
import java.util.HashMap;
import java.util.Map;
/**
* ***********************************************
* Created by Sola on 2015/11/4.
* Don't modify this source without my agreement
* ***********************************************
*/
public class __INVALID__RegisterHandler implements WxMpMessageHandler {
public static final String STUDENT_ID_REGEX = "^(2010|2012|2013|2014|2015)[0-9]{9}";
Map<String, User> confirmed = new HashMap<>();
Map<String, RegisterStep> steps = new HashMap<>();
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager)
throws WxErrorException {
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
handle(wxMessage.getContent(), wxMessage.getFromUserName(), out);
return out.build();
}
private void handle(String in, String userName, TextBuilder out) {
if (in.equalsIgnoreCase("q")) {
CommandMatcher.inCmdUsers.remove(userName);
confirmed.remove(userName);
steps.remove(userName);
out.content("Operation canceled.");
return;
}
if (!steps.containsKey(userName)) {
out.content("Welcome, please type your student identification number.");
CommandMatcher.inCmdUsers.put(userName, Command.REGISTER);
steps.put(userName, RegisterStep.STUDENT_ID);
return;
}
RegisterStep step = steps.get(userName);
if (step == RegisterStep.STUDENT_ID) {
Long sid = checkStudentId(in);
User user;
if (sid == null || (user = TableUser.getUserById(sid)) == null) {
out.content("Invalid student identification number. Type 'q' to cancel this operation.");
return;
}
out.content("Please type your real name to validate.");
confirmed.put(userName, user);
steps.put(userName, RegisterStep.NAME);
return;
}
User user = confirmed.get(userName);
if (step == RegisterStep.NAME) {
if (in.trim().equals(user.getName())) {
out.content("Confirmed success.\n" +
"Please enter your ISP.\n" +
"1-Telecom 2-Unicom 3-ChinaMobile");
steps.put(userName, RegisterStep.ISP);
} else {
out.content("Validate failed.\n" +
"If you have any issue, please contact administrator.\n" +
"Type 'q' to cancel this operation.");
}
return;
}
if (step == RegisterStep.ISP) {
ISP type = checkISP(in);
if (type == null) {
out.content("Invalid ISP. Please retype your ISP.");
} else {
user.setIsp(type);
out.content("Success.\n" +
"Please enter your net account.");
steps.put(userName, RegisterStep.NET_ACCOUNT);
}
return;
}
if (step == RegisterStep.NET_ACCOUNT) {
String account = checkNetAccount(in);
if (account == null) {
out.content("Invalid account. Please retype your net account.");
} else {
user.setNetAccount(account);
steps.put(userName, step = RegisterStep.COMPLETE);
}
}
if (step == RegisterStep.COMPLETE) {
user.setWechatId(userName);
TableUser.updateUser(user);
CommandMatcher.inCmdUsers.remove(userName);
confirmed.remove(userName);
steps.remove(userName);
out.content("Congratulations!\n" +
"You has successful registered!\n" +
"Please enjoy our service.");
}
}
private Long checkStudentId(String studentId) {
if (studentId.matches(STUDENT_ID_REGEX)) {
try {
return Long.parseLong(studentId);
} catch (NumberFormatException ignored) {
}
}
return null;
}
private ISP checkISP(String isp) {
try {
return ISP.fromId(Integer.parseInt(isp));
} catch (NumberFormatException ignored) {
}
return null;
}
private String checkNetAccount(String account) {
return account;
}
enum RegisterStep {
STUDENT_ID,
NAME,
ISP,
NET_ACCOUNT,
COMPLETE,
;
}
}

View File

@@ -29,7 +29,7 @@ public class CommandMatcher implements WxMpMessageMatcher {
if (inCmdUsers.containsKey(fromUser)) {
return command == inCmdUsers.get(fromUser);
} else {
return message.getContent().matches(command.getRegex());
return message.getContent().matches(command.regex);
}
}

View File

@@ -0,0 +1,23 @@
package love.sola.netsupport.wechat.matcher;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.sql.TableUser;
import me.chanjar.weixin.mp.api.WxMpMessageMatcher;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
/**
* ***********************************************
* Created by Sola on 2015/11/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public class RegisterMatcher implements WxMpMessageMatcher {
@Override
public boolean match(WxMpXmlMessage message) {
String fromUser = message.getFromUserName();
User u = TableUser.getUserByWechat(fromUser);
return u == null;
}
}

View File

@@ -0,0 +1,21 @@
package love.sola.netsupport.wechat;
import org.junit.Test;
import java.text.MessageFormat;
/**
* ***********************************************
* Created by Sola on 2015/12/2.
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestMessageFormat {
@Test
public void test() {
MessageFormat format = new MessageFormat("You''ve not registered, please <a href=\"http://topaz.sinaapp.com/nm/reg.php?wechat={0}\">CLICK HERE</a> to register.");
System.out.println(format.format(new Object[]{"wechatid"}));
}
}