package foundation.icall.wx;
|
|
import java.io.OutputStream;
|
import java.util.Arrays;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import foundation.dao.DataPackage;
|
import foundation.data.entity.Entity;
|
import foundation.data.entity.EntitySet;
|
import foundation.data.entity.Filter;
|
import foundation.data.object.DataObject;
|
import foundation.handler.DataPool;
|
import foundation.handler.ResultPool;
|
import foundation.icall.ICall;
|
import foundation.icall.callout.ICallRequest;
|
import foundation.icall.callout.JSONResponse;
|
import foundation.icall.connector.HttpServerConn;
|
import foundation.io.template.SendTemplate;
|
import foundation.json.JObjectReader;
|
import foundation.persist.NamedSQL;
|
import foundation.persist.SQLRunner;
|
import foundation.server.config.SecretMap;
|
import foundation.util.EncipherUtil;
|
import foundation.util.ID;
|
import foundation.util.Util;
|
import foundation.workflow.WorkStep;
|
import okhttp3.MediaType;
|
import okhttp3.OkHttpClient;
|
import okhttp3.Request;
|
import okhttp3.RequestBody;
|
import okhttp3.Response;
|
|
|
public class WXConn extends HttpServerConn {
|
|
private static WXConn instance;
|
private static int TimeOutHour = 2;
|
private static String monitorId = "WechatConn";
|
public Map<String, Date> serverLastTime;
|
private HashMap<String, String> tokens;
|
|
private WXConn() {
|
serverLastTime = new HashMap<String, Date>();
|
}
|
|
public static synchronized WXConn getInstance() {
|
if (instance == null) {
|
instance = new WXConn();
|
}
|
|
return instance;
|
}
|
|
@Override
|
public ResultPool echoSignature(ResultPool resultPool, DataPool dataPool) throws Exception{
|
//1. 响应微信请求
|
String signature = dataPool.getParam("signature");
|
String timestamp = dataPool.getParam("timestamp");
|
String nonce = dataPool.getParam("nonce");
|
String echostr = dataPool.getParam("echostr");
|
String serverName = dataPool.getParam("server");
|
|
String token = SecretMap.getSecret("WeChatPlatform");
|
String[] signatureList = new String[] {nonce, timestamp, token};
|
Arrays.sort(signatureList);
|
StringBuffer signatureBuffer = new StringBuffer();
|
|
for (String element : signatureList) {
|
signatureBuffer.append(element);
|
}
|
|
String compareSignature = EncipherUtil.sha1Decode(signatureBuffer.toString());
|
if (!signature.equals(compareSignature)) {
|
return resultPool;
|
}
|
resultPool.setFireReplay(false);
|
|
HttpServletResponse response = resultPool.getResponse();
|
if (!Util.isEmpty(echostr)) {
|
OutputStream outputStream = response.getOutputStream();
|
outputStream.write(echostr.getBytes());
|
}
|
response.setCharacterEncoding("UTF-8");
|
|
return resultPool;
|
}
|
|
public ResultPool echo(ResultPool resultPool, DataPool dataPool) throws Exception{
|
JObjectReader dataReader = dataPool.getJObjectReader();
|
String platformOpenId = dataReader.getString("fromusername");
|
String sceneId = dataReader.getString("eventkey");
|
String msgType = dataReader.getString("msgtype");
|
String eventType = dataReader.getString("event");
|
String accountId = null, content = "";
|
// 关注事件
|
if(MessageType.Event == MessageType.parse(msgType) && EventType.Subscribe == EventType.parse(eventType)){
|
// 1. 获取unionid
|
login(null, null);
|
String token = tokens.get(meta.getName());
|
Request request = new Request.Builder()
|
.url("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + token +"&openid=" + platformOpenId + "&lang=zh_CN")
|
.get()
|
.build();
|
OkHttpClient httpClient = new OkHttpClient();
|
Response response = httpClient.newCall(request).execute();
|
JSONResponse result = new JSONResponse(response);
|
String unionId = result.getString("unionid");
|
|
DataObject accountbject = DataObject.getInstance("md_hcp_account");
|
|
// 2.1 不存在场景ID(搜索关注), 则根据用户Id新建绑定关系
|
if (Util.isEmpty(sceneId)) {
|
Filter filter = new Filter();
|
filter.add("union_id", unionId);
|
EntitySet accountSet = accountbject.getTableEntitySet(filter);
|
|
if (accountSet.size() < 1) {
|
Entity account = createNewAccount(unionId, platformOpenId, null);
|
accountbject.saveEntity(account);
|
accountId = account.getId();
|
}
|
else {
|
// 2.2 搜索关注并已绑定小程序, 更新户公众号唯一标识
|
for (Entity account : accountSet) {
|
if (Util.isEmpty(account.getString("wx_openid_platform"))) {
|
account.set("wx_openid_platform", platformOpenId);
|
accountbject.updateEntity(account);
|
}
|
|
accountId = account.getId();
|
}
|
}
|
}
|
else {
|
EntitySet accountSet = accountbject.getTableEntitySet(new Filter("scene_id", sceneId));
|
|
// 2.3 存在场景ID(扫码关注), 则根据场景Id更新用户ID
|
for (Entity account : accountSet) {
|
account.set("wx_openid_platform", platformOpenId);
|
account.set("union_id", unionId);
|
accountbject.updateEntity(account);
|
|
accountId = account.getId();
|
}
|
}
|
|
DataPackage dataPackage = DataPackage.getInstance("md_hcp_account");
|
dataPackage.setMasterId(accountId);
|
dataPackage.loadOneDataFromDB();
|
|
SendTemplate sendTemplate = new SendTemplate("request/wx_subscribe_reply.txt");
|
content = sendTemplate.generateFill(dataPackage) ;
|
}
|
|
return resultPool;
|
}
|
|
private Entity createNewAccount(String unionId, String platformOpenId, String programOpenId) throws Exception {
|
DataObject accountbject = DataObject.getInstance("md_hcp_account");
|
Entity account = accountbject.createTableEntity(true);
|
|
if (!Util.isEmpty(platformOpenId)) {
|
logger.info("set wx_openid_platform :{}", platformOpenId);
|
account.set("wx_openid_platform", platformOpenId);
|
}
|
|
if (!Util.isEmpty(programOpenId)) {
|
logger.info("set wx_open_id :{}", programOpenId);
|
account.set("wx_open_id", programOpenId);
|
}
|
account.set("union_id", unionId);
|
|
String appid = meta.getString("appid");
|
DataObject platformObject = DataObject.getInstance("md_platform");
|
Entity platform = platformObject.getTableEntity(new Filter("wx_open_id", appid));
|
|
if (platform != null) {
|
String platformId = platform.getId();
|
String platformName = platform.getString("name");
|
account.set("company_id", platformId);
|
account.set("company_name", platformName);
|
account.set("platform_id", platformId);
|
account.set("platform_name", platformName);
|
}
|
|
account.set("scene_id", ID.newValue());
|
return account;
|
}
|
|
@Override
|
public Entity systemLogin(DataPool dataPool) throws Exception {
|
String code = dataPool.getParam("code");
|
String appid = meta.getString("appid");
|
String secret = meta.getString("secret");
|
String getUserUrl = meta.getString("user_url")
|
+ "?appid=" + appid
|
+ "&secret=" + secret
|
+ "&js_code=" + code
|
+ "&grant_type=authorization_code";
|
Request request = new Request.Builder()
|
.url(getUserUrl)
|
.get()
|
.build();
|
OkHttpClient httpClient = new OkHttpClient();
|
Response response = httpClient.newCall(request).execute();
|
JSONResponse result = new JSONResponse(response);
|
|
logger.info(result.toString());
|
String programOpenId = result.getString("openid");
|
String unionId = result.getString("unionid");
|
|
Filter filter = new Filter();
|
filter.add("union_id", unionId);
|
|
Entity account = getExistsUser(filter);
|
|
if (account == null) {
|
logger.info("create wx_open_id:{}", programOpenId);
|
account = createNewAccount(unionId, null, programOpenId);
|
logger.info("after wx_open_id:{}", account.getString("wx_open_id"));
|
}
|
else {
|
logger.info("update wx_open_id:{}", programOpenId);
|
account.set("wx_open_id", programOpenId);
|
logger.info("after wx_open_id:{}", account.getString("wx_open_id"));
|
}
|
|
return account;
|
}
|
|
private Entity getExistsUser(Filter filter) throws Exception {
|
NamedSQL namedSQL = NamedSQL.getInstance("getAccountUser");
|
namedSQL.setFilter(filter);
|
|
Entity entity = SQLRunner.getEntity(namedSQL);
|
return entity;
|
}
|
|
@Override
|
public void login(WorkStep step, ICall iCall) throws Exception {
|
if (!tokenExpired()) {
|
return;
|
}
|
|
//1. 获取 token
|
getToken();
|
}
|
|
@Override
|
public void logout(WorkStep step, ICall iCall) throws Exception {
|
|
}
|
|
@Override
|
public ICallRequest createRequest(String url) {
|
String requestUrl = meta.getString("base_url");
|
String token = tokens.get(meta.getName());
|
ICallRequest request = new ICallRequest(requestUrl + url + "?access_token=" + token);
|
// request.addFormData("token", token);
|
return request;
|
}
|
|
private boolean tokenExpired() {
|
Date lastTime = serverLastTime.get(meta.getName());
|
if (tokens == null) {
|
tokens = new HashMap<String, String>();
|
}
|
String token = tokens.get(meta.getName());
|
|
if (Util.isEmpty(token) || lastTime == null) {
|
return true;
|
}
|
|
Date now = new Date();
|
boolean result = now.getTime() - lastTime.getTime() >= TimeOutHour * 60 * 60 * 1000;
|
logger.info("是否重新获取token:{}, 上次获取token时间:{}, 本次获取token时间:{}", result, lastTime, now);
|
|
return result;
|
}
|
|
private void getToken() throws Exception {
|
String appid = meta.getString("appid");
|
String secret = meta.getString("secret");
|
String grantType = meta.getString("grant_type");
|
String url = meta.getString("base_url") + meta.getString("token_url");
|
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("grant_type", grantType);
|
jsonObject.put("appid", appid);
|
jsonObject.put("secret", secret);
|
jsonObject.put("force_refresh", false);
|
|
String jsonBody = jsonObject.toJSONString();
|
|
Request request = new Request.Builder()
|
.url(url)
|
.post(RequestBody.create(MediaType.get("application/json"), jsonBody))
|
.build();
|
|
OkHttpClient httpClient = new OkHttpClient();
|
Response response = httpClient.newCall(request).execute();
|
JSONResponse result = new JSONResponse(response);
|
|
String token = result.getString("access_token");
|
|
tokens.put(meta.getName(), token);
|
|
if(Util.isEmpty(token)) {
|
token = "85_xybVvwSH7Gu_x0C9WOEeV7uuAaF9XPMMI9Xox2usfOVmuS65RBDVbxT7Rltc4JJSQvxQ0nmltAqmrmBLQWnE3haNhFEosEb5Bhuaj7xFae1BHYvAX5SPLD3GKLQQIEiACABTP";
|
}
|
logger.info("token:{}", token);
|
|
serverLastTime.put(meta.getName(), new Date());
|
}
|
|
public String getName() {
|
return meta.getName();
|
}
|
|
@Override
|
public String getAccessToken() {
|
return tokens.get(meta.getName());
|
}
|
}
|