mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-10 10:17:31 +00:00
init v1.0.0
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
<module>ruoyi-common-tenant</module>
|
||||
<module>ruoyi-common-chat</module>
|
||||
<module>ruoyi-common-pay</module>
|
||||
<module>ruoyi-common-wechat</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
|
||||
@@ -166,6 +166,13 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-wechat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 支付模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
|
||||
@@ -70,13 +70,6 @@
|
||||
<version>0.5.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- azure-ai -->
|
||||
<dependency>
|
||||
<groupId>com.azure</groupId>
|
||||
<artifactId>azure-ai-openai</artifactId>
|
||||
<version>1.0.0-beta.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
||||
@@ -12,15 +12,17 @@ public class OpenAIConst {
|
||||
|
||||
public final static int SUCCEED_CODE = 200;
|
||||
|
||||
public final static double GPT3_COST = 0.03;
|
||||
public final static double GPT3_COST = 0.05;
|
||||
|
||||
public final static double GPT4_COST = 0.3;
|
||||
|
||||
public final static double GPT4_ALL_COST = 0.3;
|
||||
|
||||
/** 绘图费用 */
|
||||
public final static double DALL3_COST = 0.3;
|
||||
public final static double DALL3_COST = 0.4;
|
||||
|
||||
/** 绘图费用-高清 */
|
||||
public final static double DALL3_HD_COST = 0.6;
|
||||
public final static double DALL3_HD_COST = 0.8;
|
||||
|
||||
/** mdjourney绘图费用 */
|
||||
public final static double MJ_COST = 0.3;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* mj任务请求实体类
|
||||
*
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class MjTaskRequest {
|
||||
|
||||
private String prompt;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.xmzs.common.chat.entity.Tts;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TextToSpeech {
|
||||
|
||||
@Builder.Default
|
||||
private String model = Model.TTS_1.getName();
|
||||
/**
|
||||
* 音频声音源
|
||||
*
|
||||
* @see TtsVoice
|
||||
*/
|
||||
private String voice;
|
||||
/**
|
||||
* 输入内容
|
||||
*/
|
||||
private String input;
|
||||
/**
|
||||
* 输出音频文件格式
|
||||
*
|
||||
* @see TtsFormat
|
||||
*/
|
||||
@JsonProperty("response_format")
|
||||
private String responseFormat;
|
||||
/**
|
||||
* 速度调节,默认是1,取值范围0.25——4.0
|
||||
*/
|
||||
private Double speed;
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
TTS_1("tts-1"),
|
||||
TTS_1_HD("tts-1-hd"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.xmzs.common.chat.entity.Tts;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TtsFormat {
|
||||
MP3("mp3"),
|
||||
OPUS("opus"),
|
||||
AAC("aac"),
|
||||
FLAC("flac"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xmzs.common.chat.entity.Tts;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 生成不同声音的音频
|
||||
* <p>具体语音效果参考:https://platform.openai.com/docs/guides/text-to-speech</p>
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TtsVoice {
|
||||
|
||||
ALLOY("alloy"),
|
||||
ECHO("echo"),
|
||||
FABLE("fable"),
|
||||
ONYX("onyx"),
|
||||
NOVA("nova"),
|
||||
SHIMMER("shimmer"),
|
||||
;
|
||||
|
||||
private final String name;
|
||||
}
|
||||
@@ -174,6 +174,10 @@ public class BaseChatCompletion implements Serializable {
|
||||
* gpt-3.5-turbo-16k-0613 超长上下文 支持函数
|
||||
*/
|
||||
GPT_3_5_TURBO_16K_0613("gpt-3.5-turbo-16k-0613"),
|
||||
/**
|
||||
* gpt-3.5-turbo-0125 超长上下文 支持函数
|
||||
*/
|
||||
GPT_3_5_TURBO_0125("gpt-3.5-turbo-0125"),
|
||||
/**
|
||||
* GPT4.0
|
||||
*/
|
||||
@@ -209,6 +213,10 @@ public class BaseChatCompletion implements Serializable {
|
||||
* 支持图片
|
||||
*/
|
||||
GPT_4_VISION_PREVIEW("gpt-4-vision-preview"),
|
||||
/**
|
||||
* gpt-4-0613,支持函数
|
||||
*/
|
||||
GPT_4_0125_PREVIEW("gpt-4-0125-preview"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xmzs.common.chat.openai;
|
||||
|
||||
import com.xmzs.common.chat.entity.Tts.TextToSpeech;
|
||||
import com.xmzs.common.chat.entity.chat.ChatCompletionWithPicture;
|
||||
import io.reactivex.Single;
|
||||
import okhttp3.MultipartBody;
|
||||
@@ -33,6 +34,7 @@ import com.xmzs.common.chat.entity.models.ModelResponse;
|
||||
import com.xmzs.common.chat.entity.moderations.Moderation;
|
||||
import com.xmzs.common.chat.entity.moderations.ModerationResponse;
|
||||
import com.xmzs.common.chat.entity.whisper.WhisperResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@@ -340,4 +342,15 @@ public interface OpenAiApi {
|
||||
*/
|
||||
@POST("v1/chat/completions")
|
||||
Single<ChatCompletionResponse> chatCompletionWithPicture(@Body ChatCompletionWithPicture chatCompletion);
|
||||
|
||||
/**
|
||||
* 文本转语音
|
||||
*
|
||||
* @param textToSpeech 参数
|
||||
* @return ResponseBody body
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@POST("v1/audio/speech")
|
||||
@Streaming
|
||||
Call<ResponseBody> textToSpeech(@Body TextToSpeech textToSpeech);
|
||||
}
|
||||
|
||||
@@ -668,7 +668,6 @@ public class OpenAiClient {
|
||||
return this.chatCompletion(chatCompletion);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 语音翻译:目前仅支持翻译为英文
|
||||
*
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.xmzs.common.chat.config.LocalCache;
|
||||
import com.xmzs.common.chat.entity.Tts.TextToSpeech;
|
||||
import com.xmzs.common.chat.entity.billing.BillingUsage;
|
||||
import com.xmzs.common.chat.entity.billing.KeyInfo;
|
||||
import com.xmzs.common.chat.entity.billing.Subscription;
|
||||
@@ -37,10 +38,12 @@ import com.xmzs.common.chat.entity.chat.ChatCompletion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
@@ -344,6 +347,67 @@ public class OpenAiStreamClient {
|
||||
Transcriptions transcriptions = Transcriptions.builder().build();
|
||||
return this.speechToTextTranscriptions(file, transcriptions);
|
||||
}
|
||||
/**
|
||||
* 文本转语音(异步)
|
||||
*
|
||||
* @param textToSpeech 参数
|
||||
* @param callback 返回值接收
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public void textToSpeech(TextToSpeech textToSpeech, retrofit2.Callback callback) {
|
||||
retrofit2.Call<ResponseBody> responseBody = this.openAiApi.textToSpeech(textToSpeech);
|
||||
responseBody.enqueue(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本转语音(同步)
|
||||
*
|
||||
* @param textToSpeech 参数
|
||||
* @since 1.1.3
|
||||
*/
|
||||
public ResponseBody textToSpeech(TextToSpeech textToSpeech){
|
||||
Call<ResponseBody> responseBody = this.openAiApi.textToSpeech(textToSpeech);
|
||||
try {
|
||||
return responseBody.execute().body();
|
||||
} catch (IOException e) {
|
||||
throw new BaseException("文本转语音(同步)失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本转语音(克隆)
|
||||
*
|
||||
* @param textToSpeech
|
||||
* @return
|
||||
*/
|
||||
public ResponseBody textToSpeechClone(TextToSpeech textToSpeech) {
|
||||
String baseUrl = "http://localhost:8081";
|
||||
String spk = "三月七";
|
||||
String text = textToSpeech.getInput();
|
||||
String lang = "zh";
|
||||
|
||||
// 创建OkHttpClient实例
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
// 构建请求URL
|
||||
HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl).newBuilder();
|
||||
urlBuilder.addQueryParameter("spk", spk);
|
||||
urlBuilder.addQueryParameter("text", text);
|
||||
urlBuilder.addQueryParameter("lang", lang);
|
||||
String url = urlBuilder.build().toString();
|
||||
|
||||
// 创建请求对象
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
// 发送请求并处理响应
|
||||
try {
|
||||
return client.newCall(request).execute().body();
|
||||
} catch (IOException e) {
|
||||
throw new BaseException("语音克隆失败!{}",e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.knuddels.jtokkit.api.Encoding;
|
||||
import com.knuddels.jtokkit.api.EncodingRegistry;
|
||||
import com.knuddels.jtokkit.api.EncodingType;
|
||||
import com.knuddels.jtokkit.api.ModelType;
|
||||
import com.xmzs.common.chat.entity.chat.BaseChatCompletion;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import com.xmzs.common.chat.entity.chat.ChatCompletion;
|
||||
@@ -39,11 +40,13 @@ public class TikTokensUtil {
|
||||
modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_0613.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
|
||||
modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
|
||||
modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
|
||||
modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_0125.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_32K.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_0613.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_32K_0613.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
modelMap.put(ChatCompletion.Model.GPT_4_0125_PREVIEW.getName(), registry.getEncodingForModel(ModelType.GPT_4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,28 +10,33 @@ public class PayConfig {
|
||||
/**
|
||||
* 商户ID
|
||||
*/
|
||||
public static String pid = "xx";
|
||||
public static String pid = "xxx";
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
*/
|
||||
public static String payUrl = "https://pay-cloud.vip/mapi.php";
|
||||
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
public static String key = "xxx";
|
||||
|
||||
/**
|
||||
* 服务器异步通知地址
|
||||
*/
|
||||
public static String notify_url = "https://www.pandarobot.chat/pay/returnUrl";
|
||||
|
||||
/**
|
||||
* 页面跳转通知地址
|
||||
*/
|
||||
public static String return_url = "https://www.pandarobot.chat/pay/notifyUrl";
|
||||
|
||||
/**
|
||||
* 支付方式
|
||||
*/
|
||||
public static String type = "wxpay";
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
*/
|
||||
public static String payUrl = "https://pay.bluetuo.com/mapi.php";
|
||||
|
||||
/**
|
||||
* 服务器异步通知地址
|
||||
*/
|
||||
public static String notify_url = "http://xx/pay/returnUrl";
|
||||
|
||||
/**
|
||||
* 页面跳转通知地址
|
||||
*/
|
||||
public static String return_url = "http://xx/pay/notifyUrl";
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
@@ -40,12 +45,6 @@ public class PayConfig {
|
||||
/**
|
||||
* 加密方式默认MD5
|
||||
*/
|
||||
|
||||
public static String sign_type = "MD5";
|
||||
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
public static String key = "xx";
|
||||
|
||||
}
|
||||
|
||||
@@ -19,5 +19,4 @@ public interface PayService {
|
||||
* @return String
|
||||
**/
|
||||
String getPayUrl(String orderNo, String name, double money, String clientIp);
|
||||
|
||||
}
|
||||
|
||||
@@ -40,5 +40,4 @@ public class PayServiceImpl implements PayService {
|
||||
JSONObject jsonObject = new JSONObject(body);
|
||||
return (String) jsonObject.get("qrcode");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ public class AllUrlHandler implements InitializingBean {
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
map.keySet().forEach(info -> {
|
||||
// 获取注解上边的 path 替代 path variable 为 *
|
||||
Objects.requireNonNull(info.getPathPatternsCondition().getPatterns())
|
||||
if(info.getPathPatternsCondition()!=null){
|
||||
Objects.requireNonNull(info.getPathPatternsCondition().getPatterns())
|
||||
.forEach(url -> set.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, "*")));
|
||||
}
|
||||
});
|
||||
urls.addAll(set);
|
||||
}
|
||||
|
||||
51
ruoyi-common/ruoyi-common-wechat/pom.xml
Normal file
51
ruoyi-common/ruoyi-common-wechat/pom.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-wechat</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-wechat 微信服务
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- emoji -->
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
<artifactId>emoji-java</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- qq -->
|
||||
<dependency>
|
||||
<groupId>net.mamoe</groupId>
|
||||
<artifactId>mirai-core-jvm</artifactId>
|
||||
<version>2.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xmzs.common.wechat;
|
||||
|
||||
import com.xmzs.common.wechat.controller.LoginController;
|
||||
import com.xmzs.common.wechat.core.MsgCenter;
|
||||
import com.xmzs.common.wechat.face.IMsgHandlerFace;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
|
||||
public class Wechat {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Wechat.class);
|
||||
private IMsgHandlerFace msgHandler;
|
||||
|
||||
public Wechat(IMsgHandlerFace msgHandler, String qrPath) {
|
||||
System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误
|
||||
this.msgHandler = msgHandler;
|
||||
|
||||
// 登陆
|
||||
LoginController login = new LoginController();
|
||||
login.login(qrPath);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++");
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MsgCenter.handleMsg(msgHandler);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.xmzs.common.wechat.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 辅助工具类,该类暂时未用,请忽略
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月22日 下午10:34:46
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class AssistTools {
|
||||
private static OkHttpClient client = new OkHttpClient();
|
||||
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
|
||||
|
||||
public static boolean sendQrPicToServer(String username, String password, String uploadUrl, String localPath)
|
||||
throws IOException {
|
||||
File file = new File(localPath);
|
||||
RequestBody requestBody = new MultipartBody.Builder().addFormDataPart("username", username)
|
||||
.addFormDataPart("password", password)
|
||||
.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file)).build();
|
||||
Request request = new Request.Builder().url(uploadUrl).post(requestBody).build();
|
||||
Call call = client.newCall(request);
|
||||
try {
|
||||
Response response = call.execute();
|
||||
System.out.println(response.body().string());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
package com.xmzs.common.wechat.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.xmzs.common.wechat.beans.BaseMsg;
|
||||
import com.xmzs.common.wechat.beans.RecommendInfo;
|
||||
import com.xmzs.common.wechat.core.Core;
|
||||
import com.xmzs.common.wechat.utils.Config;
|
||||
import com.xmzs.common.wechat.utils.MyHttpClient;
|
||||
import com.xmzs.common.wechat.utils.enums.StorageLoginInfoEnum;
|
||||
import com.xmzs.common.wechat.utils.enums.URLEnum;
|
||||
import com.xmzs.common.wechat.utils.enums.VerifyFriendEnum;
|
||||
|
||||
/**
|
||||
* 消息处理类
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月23日 下午2:30:37
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class MessageTools {
|
||||
private static Logger LOG = LoggerFactory.getLogger(MessageTools.class);
|
||||
private static Core core = Core.getInstance();
|
||||
private static MyHttpClient myHttpClient = core.getMyHttpClient();
|
||||
|
||||
/**
|
||||
* 根据UserName发送文本消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月4日 下午11:17:38
|
||||
* @param msg
|
||||
* @param toUserName
|
||||
*/
|
||||
private static void sendMsg(String text, String toUserName) {
|
||||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
LOG.info(String.format("发送消息 %s: %s", toUserName, text));
|
||||
webWxSendMsg(1, text, toUserName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID发送文本消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月6日 上午11:45:51
|
||||
* @param text
|
||||
* @param id
|
||||
*/
|
||||
public static void sendMsgById(String text, String id) {
|
||||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
sendMsg(text, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据NickName发送文本消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月4日 下午11:17:38
|
||||
* @param text
|
||||
* @param nickName
|
||||
*/
|
||||
public static boolean sendMsgByNickName(String text, String nickName) {
|
||||
if (nickName != null) {
|
||||
String toUserName = WechatTools.getUserNameByNickName(nickName);
|
||||
if (toUserName != null) {
|
||||
webWxSendMsg(1, text, toUserName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息发送
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月23日 下午2:32:02
|
||||
* @param msgType
|
||||
* @param content
|
||||
* @param toUserName
|
||||
*/
|
||||
public static void webWxSendMsg(int msgType, String content, String toUserName) {
|
||||
String url = String.format(URLEnum.WEB_WX_SEND_MSG.getUrl(), core.getLoginInfo().get("url"));
|
||||
Map<String, Object> msgMap = new HashMap<String, Object>();
|
||||
msgMap.put("Type", msgType);
|
||||
msgMap.put("Content", content);
|
||||
msgMap.put("FromUserName", core.getUserName());
|
||||
msgMap.put("ToUserName", toUserName == null ? core.getUserName() : toUserName);
|
||||
msgMap.put("LocalID", new Date().getTime() * 10);
|
||||
msgMap.put("ClientMsgId", new Date().getTime() * 10);
|
||||
Map<String, Object> paramMap = core.getParamMap();
|
||||
paramMap.put("Msg", msgMap);
|
||||
paramMap.put("Scene", 0);
|
||||
try {
|
||||
String paramStr = JSON.toJSONString(paramMap);
|
||||
HttpEntity entity = myHttpClient.doPost(url, paramStr);
|
||||
EntityUtils.toString(entity, Consts.UTF_8);
|
||||
} catch (Exception e) {
|
||||
LOG.error("webWxSendMsg", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传多媒体文件到 微信服务器,目前应该支持3种类型: 1. pic 直接显示,包含图片,表情 2.video 3.doc 显示为文件,包含PDF等
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 上午12:41:13
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
private static JSONObject webWxUploadMedia(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (!file.exists() && file.isFile()) {
|
||||
LOG.info("file is not exist");
|
||||
return null;
|
||||
}
|
||||
String url = String.format(URLEnum.WEB_WX_UPLOAD_MEDIA.getUrl(), core.getLoginInfo().get("fileUrl"));
|
||||
String mimeType = new MimetypesFileTypeMap().getContentType(file);
|
||||
String mediaType = "";
|
||||
if (mimeType == null) {
|
||||
mimeType = "text/plain";
|
||||
} else {
|
||||
mediaType = mimeType.split("/")[0].equals("image") ? "pic" : "doc";
|
||||
}
|
||||
String lastModifieDate = new SimpleDateFormat("yyyy MM dd HH:mm:ss").format(new Date());
|
||||
long fileSize = file.length();
|
||||
String passTicket = (String) core.getLoginInfo().get("pass_ticket");
|
||||
String clientMediaId = new Date().getTime()
|
||||
+ String.valueOf(new Random().nextLong()).substring(0, 4);
|
||||
String webwxDataTicket = MyHttpClient.getCookie("webwx_data_ticket");
|
||||
if (webwxDataTicket == null) {
|
||||
LOG.error("get cookie webwx_data_ticket error");
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Object> paramMap = core.getParamMap();
|
||||
|
||||
paramMap.put("ClientMediaId", clientMediaId);
|
||||
paramMap.put("TotalLen", fileSize);
|
||||
paramMap.put("StartPos", 0);
|
||||
paramMap.put("DataLen", fileSize);
|
||||
paramMap.put("MediaType", 4);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
||||
|
||||
builder.addTextBody("id", "WU_FILE_0", ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("name", filePath, ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("type", mimeType, ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("lastModifieDate", lastModifieDate, ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("size", String.valueOf(fileSize), ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("mediatype", mediaType, ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("uploadmediarequest", JSON.toJSONString(paramMap), ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("webwx_data_ticket", webwxDataTicket, ContentType.TEXT_PLAIN);
|
||||
builder.addTextBody("pass_ticket", passTicket, ContentType.TEXT_PLAIN);
|
||||
builder.addBinaryBody("filename", file, ContentType.create(mimeType), filePath);
|
||||
HttpEntity reqEntity = builder.build();
|
||||
HttpEntity entity = myHttpClient.doPostFile(url, reqEntity);
|
||||
if (entity != null) {
|
||||
try {
|
||||
String result = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
return JSON.parseObject(result);
|
||||
} catch (Exception e) {
|
||||
LOG.error("webWxUploadMedia 错误: ", e);
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据NickName发送图片消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午10:32:45
|
||||
* @param nackName
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendPicMsgByNickName(String nickName, String filePath) {
|
||||
String toUserName = WechatTools.getUserNameByNickName(nickName);
|
||||
if (toUserName != null) {
|
||||
return sendPicMsgByUserId(toUserName, filePath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户id发送图片消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午10:34:24
|
||||
* @param userId
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendPicMsgByUserId(String userId, String filePath) {
|
||||
JSONObject responseObj = webWxUploadMedia(filePath);
|
||||
if (responseObj != null) {
|
||||
String mediaId = responseObj.getString("MediaId");
|
||||
if (mediaId != null) {
|
||||
return webWxSendMsgImg(userId, mediaId);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送图片消息,内部调用
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午10:38:55
|
||||
* @return
|
||||
*/
|
||||
private static boolean webWxSendMsgImg(String userId, String mediaId) {
|
||||
String url = String.format("%s/webwxsendmsgimg?fun=async&f=json&pass_ticket=%s", core.getLoginInfo().get("url"),
|
||||
core.getLoginInfo().get("pass_ticket"));
|
||||
Map<String, Object> msgMap = new HashMap<String, Object>();
|
||||
msgMap.put("Type", 3);
|
||||
msgMap.put("MediaId", mediaId);
|
||||
msgMap.put("FromUserName", core.getUserSelf().getString("UserName"));
|
||||
msgMap.put("ToUserName", userId);
|
||||
String clientMsgId = String.valueOf(new Date().getTime())
|
||||
+ String.valueOf(new Random().nextLong()).substring(1, 5);
|
||||
msgMap.put("LocalID", clientMsgId);
|
||||
msgMap.put("ClientMsgId", clientMsgId);
|
||||
Map<String, Object> paramMap = core.getParamMap();
|
||||
paramMap.put("BaseRequest", core.getParamMap().get("BaseRequest"));
|
||||
paramMap.put("Msg", msgMap);
|
||||
String paramStr = JSON.toJSONString(paramMap);
|
||||
HttpEntity entity = myHttpClient.doPost(url, paramStr);
|
||||
if (entity != null) {
|
||||
try {
|
||||
String result = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0;
|
||||
} catch (Exception e) {
|
||||
LOG.error("webWxSendMsgImg 错误: ", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户id发送文件
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午11:57:36
|
||||
* @param userId
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendFileMsgByUserId(String userId, String filePath) {
|
||||
String title = new File(filePath).getName();
|
||||
Map<String, String> data = new HashMap<String, String>();
|
||||
data.put("appid", Config.API_WXAPPID);
|
||||
data.put("title", title);
|
||||
data.put("totallen", "");
|
||||
data.put("attachid", "");
|
||||
data.put("type", "6"); // APPMSGTYPE_ATTACH
|
||||
data.put("fileext", title.split("\\.")[1]); // 文件后缀
|
||||
JSONObject responseObj = webWxUploadMedia(filePath);
|
||||
if (responseObj != null) {
|
||||
data.put("totallen", responseObj.getString("StartPos"));
|
||||
data.put("attachid", responseObj.getString("MediaId"));
|
||||
} else {
|
||||
LOG.error("sednFileMsgByUserId 错误: ", data);
|
||||
}
|
||||
return webWxSendAppMsg(userId, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户昵称发送文件消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月10日 下午10:59:27
|
||||
* @param nickName
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendFileMsgByNickName(String nickName, String filePath) {
|
||||
String toUserName = WechatTools.getUserNameByNickName(nickName);
|
||||
if (toUserName != null) {
|
||||
return sendFileMsgByUserId(toUserName, filePath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部调用
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月10日 上午12:21:28
|
||||
* @param userId
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
private static boolean webWxSendAppMsg(String userId, Map<String, String> data) {
|
||||
String url = String.format("%s/webwxsendappmsg?fun=async&f=json&pass_ticket=%s", core.getLoginInfo().get("url"),
|
||||
core.getLoginInfo().get("pass_ticket"));
|
||||
String clientMsgId = String.valueOf(new Date().getTime())
|
||||
+ String.valueOf(new Random().nextLong()).substring(1, 5);
|
||||
String content = "<appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>" + data.get("title")
|
||||
+ "</title><des></des><action></action><type>6</type><content></content><url></url><lowurl></lowurl>"
|
||||
+ "<appattach><totallen>" + data.get("totallen") + "</totallen><attachid>" + data.get("attachid")
|
||||
+ "</attachid><fileext>" + data.get("fileext") + "</fileext></appattach><extinfo></extinfo></appmsg>";
|
||||
Map<String, Object> msgMap = new HashMap<String, Object>();
|
||||
msgMap.put("Type", data.get("type"));
|
||||
msgMap.put("Content", content);
|
||||
msgMap.put("FromUserName", core.getUserSelf().getString("UserName"));
|
||||
msgMap.put("ToUserName", userId);
|
||||
msgMap.put("LocalID", clientMsgId);
|
||||
msgMap.put("ClientMsgId", clientMsgId);
|
||||
/*
|
||||
* Map<String, Object> paramMap = new HashMap<String, Object>();
|
||||
*
|
||||
* @SuppressWarnings("unchecked") Map<String, Map<String, String>>
|
||||
* baseRequestMap = (Map<String, Map<String, String>>)
|
||||
* core.getLoginInfo() .get("baseRequest"); paramMap.put("BaseRequest",
|
||||
* baseRequestMap.get("BaseRequest"));
|
||||
*/
|
||||
|
||||
Map<String, Object> paramMap = core.getParamMap();
|
||||
paramMap.put("Msg", msgMap);
|
||||
paramMap.put("Scene", 0);
|
||||
String paramStr = JSON.toJSONString(paramMap);
|
||||
HttpEntity entity = myHttpClient.doPost(url, paramStr);
|
||||
if (entity != null) {
|
||||
try {
|
||||
String result = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0;
|
||||
} catch (Exception e) {
|
||||
LOG.error("错误: ", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 被动添加好友
|
||||
*
|
||||
* @date 2017年6月29日 下午10:08:43
|
||||
* @param msg
|
||||
* @param accept
|
||||
* true 接受 false 拒绝
|
||||
*/
|
||||
public static void addFriend(BaseMsg msg, boolean accept) {
|
||||
if (!accept) { // 不添加
|
||||
return;
|
||||
}
|
||||
int status = VerifyFriendEnum.ACCEPT.getCode(); // 接受好友请求
|
||||
RecommendInfo recommendInfo = msg.getRecommendInfo();
|
||||
String userName = recommendInfo.getUserName();
|
||||
String ticket = recommendInfo.getTicket();
|
||||
// 更新好友列表
|
||||
// TODO 此处需要更新好友列表
|
||||
// core.getContactList().add(msg.getJSONObject("RecommendInfo"));
|
||||
|
||||
String url = String.format(URLEnum.WEB_WX_VERIFYUSER.getUrl(), core.getLoginInfo().get("url"),
|
||||
String.valueOf(System.currentTimeMillis() / 3158L), core.getLoginInfo().get("pass_ticket"));
|
||||
|
||||
List<Map<String, Object>> verifyUserList = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Object> verifyUser = new HashMap<String, Object>();
|
||||
verifyUser.put("Value", userName);
|
||||
verifyUser.put("VerifyUserTicket", ticket);
|
||||
verifyUserList.add(verifyUser);
|
||||
|
||||
List<Integer> sceneList = new ArrayList<Integer>();
|
||||
sceneList.add(33);
|
||||
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("BaseRequest", core.getParamMap().get("BaseRequest"));
|
||||
body.put("Opcode", status);
|
||||
body.put("VerifyUserListSize", 1);
|
||||
body.put("VerifyUserList", verifyUserList);
|
||||
body.put("VerifyContent", "");
|
||||
body.put("SceneListCount", 1);
|
||||
body.put("SceneList", sceneList);
|
||||
body.put("skey", core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey()));
|
||||
|
||||
String result = null;
|
||||
try {
|
||||
String paramStr = JSON.toJSONString(body);
|
||||
HttpEntity entity = myHttpClient.doPost(url, paramStr);
|
||||
result = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
} catch (Exception e) {
|
||||
LOG.error("webWxSendMsg", e);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(result)) {
|
||||
LOG.error("被动添加好友失败");
|
||||
}
|
||||
|
||||
LOG.debug(result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.xmzs.common.wechat.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.xmzs.common.wechat.core.Core;
|
||||
import com.xmzs.common.wechat.utils.enums.StorageLoginInfoEnum;
|
||||
import com.xmzs.common.wechat.utils.enums.URLEnum;
|
||||
|
||||
/**
|
||||
* 微信小工具,如获好友列表等
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月4日 下午10:49:16
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class WechatTools {
|
||||
private static Logger LOG = LoggerFactory.getLogger(WechatTools.class);
|
||||
|
||||
private static Core core = Core.getInstance();
|
||||
|
||||
/**
|
||||
* 根据用户名发送文本消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月4日 下午10:43:14
|
||||
* @param msg
|
||||
* @param toUserName
|
||||
*/
|
||||
public static void sendMsgByUserName(String msg, String toUserName) {
|
||||
MessageTools.sendMsgById(msg, toUserName);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 通过RealName获取本次UserName
|
||||
* </p>
|
||||
* <p>
|
||||
* 如NickName为"yaphone",则获取UserName=
|
||||
* "@1212d3356aea8285e5bbe7b91229936bc183780a8ffa469f2d638bf0d2e4fc63",
|
||||
* 可通过UserName发送消息
|
||||
* </p>
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月4日 下午10:56:31
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String getUserNameByNickName(String nickName) {
|
||||
for (JSONObject o : core.getContactList()) {
|
||||
if (o.getString("NickName").equals(nickName)) {
|
||||
return o.getString("UserName");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回好友昵称列表
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月4日 下午11:37:20
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getContactNickNameList() {
|
||||
List<String> contactNickNameList = new ArrayList<String>();
|
||||
for (JSONObject o : core.getContactList()) {
|
||||
contactNickNameList.add(o.getString("NickName"));
|
||||
}
|
||||
return contactNickNameList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回好友完整信息列表
|
||||
*
|
||||
* @date 2017年6月26日 下午9:45:39
|
||||
* @return
|
||||
*/
|
||||
public static List<JSONObject> getContactList() {
|
||||
return core.getContactList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回群列表
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月5日 下午9:55:21
|
||||
* @return
|
||||
*/
|
||||
public static List<JSONObject> getGroupList() {
|
||||
return core.getGroupList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群ID列表
|
||||
*
|
||||
* @date 2017年6月21日 下午11:42:56
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getGroupIdList() {
|
||||
return core.getGroupIdList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群NickName列表
|
||||
*
|
||||
* @date 2017年6月21日 下午11:43:38
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getGroupNickNameList() {
|
||||
return core.getGroupNickNameList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据groupIdList返回群成员列表
|
||||
*
|
||||
* @date 2017年6月13日 下午11:12:31
|
||||
* @param groupId
|
||||
* @return
|
||||
*/
|
||||
public static JSONArray getMemberListByGroupId(String groupId) {
|
||||
return core.getGroupMemeberMap().get(groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出微信
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月18日 下午11:56:54
|
||||
*/
|
||||
public static void logout() {
|
||||
webWxLogout();
|
||||
}
|
||||
|
||||
private static boolean webWxLogout() {
|
||||
String url = String.format(URLEnum.WEB_WX_LOGOUT.getUrl(),
|
||||
core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey()));
|
||||
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
|
||||
params.add(new BasicNameValuePair("redirect", "1"));
|
||||
params.add(new BasicNameValuePair("type", "1"));
|
||||
params.add(
|
||||
new BasicNameValuePair("skey", (String) core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey())));
|
||||
try {
|
||||
HttpEntity entity = core.getMyHttpClient().doGet(url, params, false, null);
|
||||
String text = EntityUtils.toString(entity, Consts.UTF_8); // 无消息
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOG.debug(e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setUserInfo() {
|
||||
for (JSONObject o : core.getContactList()) {
|
||||
core.getUserInfoMap().put(o.getString("NickName"), o);
|
||||
core.getUserInfoMap().put(o.getString("UserName"), o);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据用户昵称设置备注名称
|
||||
*
|
||||
* @date 2017年5月27日 上午12:21:40
|
||||
* @param userName
|
||||
* @param remName
|
||||
*/
|
||||
public static void remarkNameByNickName(String nickName, String remName) {
|
||||
String url = String.format(URLEnum.WEB_WX_REMARKNAME.getUrl(), core.getLoginInfo().get("url"),
|
||||
core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey()));
|
||||
Map<String, Object> msgMap = new HashMap<String, Object>();
|
||||
Map<String, Object> msgMap_BaseRequest = new HashMap<String, Object>();
|
||||
msgMap.put("CmdId", 2);
|
||||
msgMap.put("RemarkName", remName);
|
||||
msgMap.put("UserName", core.getUserInfoMap().get(nickName).get("UserName"));
|
||||
msgMap_BaseRequest.put("Uin", core.getLoginInfo().get(StorageLoginInfoEnum.wxuin.getKey()));
|
||||
msgMap_BaseRequest.put("Sid", core.getLoginInfo().get(StorageLoginInfoEnum.wxsid.getKey()));
|
||||
msgMap_BaseRequest.put("Skey", core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey()));
|
||||
msgMap_BaseRequest.put("DeviceID", core.getLoginInfo().get(StorageLoginInfoEnum.deviceid.getKey()));
|
||||
msgMap.put("BaseRequest", msgMap_BaseRequest);
|
||||
try {
|
||||
String paramStr = JSON.toJSONString(msgMap);
|
||||
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
|
||||
// String result = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
LOG.info("修改备注" + remName);
|
||||
} catch (Exception e) {
|
||||
LOG.error("remarkNameByUserName", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信在线状态
|
||||
*
|
||||
* @date 2017年6月16日 上午12:47:46
|
||||
* @return
|
||||
*/
|
||||
public static boolean getWechatStatus() {
|
||||
return core.isAlive();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xmzs.common.wechat.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* AppInfo
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年7月3日 下午10:38:14
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class AppInfo implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private int type;
|
||||
private String appId;
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package com.xmzs.common.wechat.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 收到的微信消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年7月3日 下午10:28:06
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class BaseMsg implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private int subMsgType;
|
||||
private int voiceLength;
|
||||
private String fileName;
|
||||
private int imgHeight;
|
||||
private String toUserName;
|
||||
private int hasProductId;
|
||||
private int imgStatus;
|
||||
private String url;
|
||||
private int imgWidth;
|
||||
private int forwardFlag;
|
||||
private int status;
|
||||
private String Ticket;
|
||||
/** 推荐消息报文 **/
|
||||
private RecommendInfo recommendInfo;
|
||||
private long createTime;
|
||||
private String newMsgId;
|
||||
/** 文本消息内容 **/
|
||||
private String text;
|
||||
/** 消息类型 **/
|
||||
private int msgType;
|
||||
/** 是否为群消息 **/
|
||||
private boolean groupMsg;
|
||||
private String msgId;
|
||||
private int statusNotifyCode;
|
||||
private AppInfo appInfo;
|
||||
private int appMsgType;
|
||||
private String Type;
|
||||
private int playLength;
|
||||
private String mediaId;
|
||||
private String content;
|
||||
private String statusNotifyUserName;
|
||||
/** 消息发送者ID **/
|
||||
private String fromUserName;
|
||||
private String oriContent;
|
||||
private String fileSize;
|
||||
|
||||
public int getSubMsgType() {
|
||||
return subMsgType;
|
||||
}
|
||||
|
||||
public void setSubMsgType(int subMsgType) {
|
||||
this.subMsgType = subMsgType;
|
||||
}
|
||||
|
||||
public int getVoiceLength() {
|
||||
return voiceLength;
|
||||
}
|
||||
|
||||
public void setVoiceLength(int voiceLength) {
|
||||
this.voiceLength = voiceLength;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public int getImgHeight() {
|
||||
return imgHeight;
|
||||
}
|
||||
|
||||
public void setImgHeight(int imgHeight) {
|
||||
this.imgHeight = imgHeight;
|
||||
}
|
||||
|
||||
public String getToUserName() {
|
||||
return toUserName;
|
||||
}
|
||||
|
||||
public void setToUserName(String toUserName) {
|
||||
this.toUserName = toUserName;
|
||||
}
|
||||
|
||||
public int getHasProductId() {
|
||||
return hasProductId;
|
||||
}
|
||||
|
||||
public void setHasProductId(int hasProductId) {
|
||||
this.hasProductId = hasProductId;
|
||||
}
|
||||
|
||||
public int getImgStatus() {
|
||||
return imgStatus;
|
||||
}
|
||||
|
||||
public void setImgStatus(int imgStatus) {
|
||||
this.imgStatus = imgStatus;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public int getImgWidth() {
|
||||
return imgWidth;
|
||||
}
|
||||
|
||||
public void setImgWidth(int imgWidth) {
|
||||
this.imgWidth = imgWidth;
|
||||
}
|
||||
|
||||
public int getForwardFlag() {
|
||||
return forwardFlag;
|
||||
}
|
||||
|
||||
public void setForwardFlag(int forwardFlag) {
|
||||
this.forwardFlag = forwardFlag;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return Ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
Ticket = ticket;
|
||||
}
|
||||
|
||||
public RecommendInfo getRecommendInfo() {
|
||||
return recommendInfo;
|
||||
}
|
||||
|
||||
public void setRecommendInfo(RecommendInfo recommendInfo) {
|
||||
this.recommendInfo = recommendInfo;
|
||||
}
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getNewMsgId() {
|
||||
return newMsgId;
|
||||
}
|
||||
|
||||
public void setNewMsgId(String newMsgId) {
|
||||
this.newMsgId = newMsgId;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
public void setMsgType(int msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public boolean isGroupMsg() {
|
||||
return groupMsg;
|
||||
}
|
||||
|
||||
public void setGroupMsg(boolean groupMsg) {
|
||||
this.groupMsg = groupMsg;
|
||||
}
|
||||
|
||||
public String getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
public void setMsgId(String msgId) {
|
||||
this.msgId = msgId;
|
||||
}
|
||||
|
||||
public int getStatusNotifyCode() {
|
||||
return statusNotifyCode;
|
||||
}
|
||||
|
||||
public void setStatusNotifyCode(int statusNotifyCode) {
|
||||
this.statusNotifyCode = statusNotifyCode;
|
||||
}
|
||||
|
||||
public AppInfo getAppInfo() {
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
public void setAppInfo(AppInfo appInfo) {
|
||||
this.appInfo = appInfo;
|
||||
}
|
||||
|
||||
public int getAppMsgType() {
|
||||
return appMsgType;
|
||||
}
|
||||
|
||||
public void setAppMsgType(int appMsgType) {
|
||||
this.appMsgType = appMsgType;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return Type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public int getPlayLength() {
|
||||
return playLength;
|
||||
}
|
||||
|
||||
public void setPlayLength(int playLength) {
|
||||
this.playLength = playLength;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public void setMediaId(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getStatusNotifyUserName() {
|
||||
return statusNotifyUserName;
|
||||
}
|
||||
|
||||
public void setStatusNotifyUserName(String statusNotifyUserName) {
|
||||
this.statusNotifyUserName = statusNotifyUserName;
|
||||
}
|
||||
|
||||
public String getFromUserName() {
|
||||
return fromUserName;
|
||||
}
|
||||
|
||||
public void setFromUserName(String fromUserName) {
|
||||
this.fromUserName = fromUserName;
|
||||
}
|
||||
|
||||
public String getOriContent() {
|
||||
return oriContent;
|
||||
}
|
||||
|
||||
public void setOriContent(String oriContent) {
|
||||
this.oriContent = oriContent;
|
||||
}
|
||||
|
||||
public String getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(String fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.xmzs.common.wechat.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* RecommendInfo
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年7月3日 下午10:35:14
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class RecommendInfo implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String ticket;
|
||||
private String userName;
|
||||
private int sex;
|
||||
private int attrStatus;
|
||||
private String city;
|
||||
private String nickName;
|
||||
private int scene;
|
||||
private String province;
|
||||
private String content;
|
||||
private String alias;
|
||||
private String signature;
|
||||
private int opCode;
|
||||
private int qQNum;
|
||||
private int verifyFlag;
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public int getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(int sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public int getAttrStatus() {
|
||||
return attrStatus;
|
||||
}
|
||||
|
||||
public void setAttrStatus(int attrStatus) {
|
||||
this.attrStatus = attrStatus;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public void setNickName(String nickName) {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public int getScene() {
|
||||
return scene;
|
||||
}
|
||||
|
||||
public void setScene(int scene) {
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public String getProvince() {
|
||||
return province;
|
||||
}
|
||||
|
||||
public void setProvince(String province) {
|
||||
this.province = province;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
public void setAlias(String alias) {
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public int getOpCode() {
|
||||
return opCode;
|
||||
}
|
||||
|
||||
public void setOpCode(int opCode) {
|
||||
this.opCode = opCode;
|
||||
}
|
||||
|
||||
public int getqQNum() {
|
||||
return qQNum;
|
||||
}
|
||||
|
||||
public void setqQNum(int qQNum) {
|
||||
this.qQNum = qQNum;
|
||||
}
|
||||
|
||||
public int getVerifyFlag() {
|
||||
return verifyFlag;
|
||||
}
|
||||
|
||||
public void setVerifyFlag(int verifyFlag) {
|
||||
this.verifyFlag = verifyFlag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.xmzs.common.wechat.controller;
|
||||
|
||||
|
||||
import com.xmzs.common.wechat.utils.SleepUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.xmzs.common.wechat.api.WechatTools;
|
||||
import com.xmzs.common.wechat.core.Core;
|
||||
import com.xmzs.common.wechat.service.ILoginService;
|
||||
import com.xmzs.common.wechat.service.impl.LoginServiceImpl;
|
||||
import com.xmzs.common.wechat.thread.CheckLoginStatusThread;
|
||||
|
||||
import com.xmzs.common.wechat.utils.tools.CommonTools;
|
||||
|
||||
/**
|
||||
* 登陆控制器
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月13日 下午12:56:07
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class LoginController {
|
||||
private static Logger LOG = LoggerFactory.getLogger(LoginController.class);
|
||||
private ILoginService loginService = new LoginServiceImpl();
|
||||
private static Core core = Core.getInstance();
|
||||
|
||||
public void login(String qrPath) {
|
||||
if (core.isAlive()) { // 已登陆
|
||||
LOG.info("itchat4j已登陆");
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
for (int count = 0; count < 10; count++) {
|
||||
LOG.info("获取UUID");
|
||||
while (loginService.getUuid() == null) {
|
||||
LOG.info("1. 获取微信UUID");
|
||||
while (loginService.getUuid() == null) {
|
||||
LOG.warn("1.1. 获取微信UUID失败,两秒后重新获取");
|
||||
SleepUtils.sleep(2000);
|
||||
}
|
||||
}
|
||||
LOG.info("2. 获取登陆二维码图片");
|
||||
if (loginService.getQR(qrPath)) {
|
||||
break;
|
||||
} else if (count == 10) {
|
||||
LOG.error("2.2. 获取登陆二维码图片失败,系统退出");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
LOG.info("3. 请扫描二维码图片,并在手机上确认");
|
||||
if (!core.isAlive()) {
|
||||
loginService.login();
|
||||
core.setAlive(true);
|
||||
LOG.info(("登陆成功"));
|
||||
break;
|
||||
}
|
||||
LOG.info("4. 登陆超时,请重新扫描二维码图片");
|
||||
}
|
||||
|
||||
LOG.info("5. 登陆成功,微信初始化");
|
||||
if (!loginService.webWxInit()) {
|
||||
LOG.info("6. 微信初始化异常");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
LOG.info("6. 开启微信状态通知");
|
||||
loginService.wxStatusNotify();
|
||||
|
||||
LOG.info("7. 清除。。。。");
|
||||
CommonTools.clearScreen();
|
||||
LOG.info(String.format("欢迎回来, %s", core.getNickName()));
|
||||
|
||||
LOG.info("8. 开始接收消息");
|
||||
loginService.startReceiving();
|
||||
|
||||
LOG.info("9. 获取联系人信息");
|
||||
loginService.webWxGetContact();
|
||||
|
||||
LOG.info("10. 获取群好友及群好友列表");
|
||||
loginService.WebWxBatchGetContact();
|
||||
|
||||
LOG.info("11. 缓存本次登陆好友相关消息");
|
||||
WechatTools.setUserInfo(); // 登陆成功后缓存本次登陆好友相关消息(NickName, UserName)
|
||||
|
||||
LOG.info("12.开启微信状态检测线程");
|
||||
new Thread(new CheckLoginStatusThread()).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
package com.xmzs.common.wechat.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.xmzs.common.wechat.beans.BaseMsg;
|
||||
import com.xmzs.common.wechat.utils.MyHttpClient;
|
||||
import com.xmzs.common.wechat.utils.enums.parameters.BaseParaEnum;
|
||||
|
||||
/**
|
||||
* 核心存储类,全局只保存一份,单例模式
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月23日 下午2:33:56
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class Core {
|
||||
|
||||
private static Core instance;
|
||||
|
||||
private Core() {
|
||||
|
||||
}
|
||||
|
||||
public static Core getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (Core.class) {
|
||||
instance = new Core();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
boolean alive = false;
|
||||
private int memberCount = 0;
|
||||
|
||||
private String indexUrl;
|
||||
|
||||
private String userName;
|
||||
private String nickName;
|
||||
private List<BaseMsg> msgList = new ArrayList<BaseMsg>();
|
||||
|
||||
private JSONObject userSelf; // 登陆账号自身信息
|
||||
private List<JSONObject> memberList = new ArrayList<JSONObject>(); // 好友+群聊+公众号+特殊账号
|
||||
private List<JSONObject> contactList = new ArrayList<JSONObject>();// 好友
|
||||
private List<JSONObject> groupList = new ArrayList<JSONObject>();; // 群
|
||||
private Map<String, JSONArray> groupMemeberMap = new HashMap<String, JSONArray>(); // 群聊成员字典
|
||||
private List<JSONObject> publicUsersList = new ArrayList<JSONObject>();;// 公众号/服务号
|
||||
private List<JSONObject> specialUsersList = new ArrayList<JSONObject>();;// 特殊账号
|
||||
private List<String> groupIdList = new ArrayList<String>(); // 群ID列表
|
||||
private List<String> groupNickNameList = new ArrayList<String>(); // 群NickName列表
|
||||
|
||||
private Map<String, JSONObject> userInfoMap = new HashMap<String, JSONObject>();
|
||||
|
||||
Map<String, Object> loginInfo = new HashMap<String, Object>();
|
||||
// CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||
MyHttpClient myHttpClient = MyHttpClient.getInstance();
|
||||
String uuid = null;
|
||||
|
||||
boolean useHotReload = false;
|
||||
String hotReloadDir = "itchat.pkl";
|
||||
int receivingRetryCount = 5;
|
||||
|
||||
private long lastNormalRetcodeTime; // 最后一次收到正常retcode的时间,秒为单位
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
public Map<String, Object> getParamMap() {
|
||||
return new HashMap<String, Object>(1) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
{
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
for (BaseParaEnum baseRequest : BaseParaEnum.values()) {
|
||||
map.put(baseRequest.para(), getLoginInfo().get(baseRequest.value()).toString());
|
||||
}
|
||||
put("BaseRequest", map);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return alive;
|
||||
}
|
||||
|
||||
public void setAlive(boolean alive) {
|
||||
this.alive = alive;
|
||||
}
|
||||
|
||||
public List<JSONObject> getMemberList() {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
public void setMemberList(List<JSONObject> memberList) {
|
||||
this.memberList = memberList;
|
||||
}
|
||||
|
||||
public Map<String, Object> getLoginInfo() {
|
||||
return loginInfo;
|
||||
}
|
||||
|
||||
public void setLoginInfo(Map<String, Object> loginInfo) {
|
||||
this.loginInfo = loginInfo;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public int getMemberCount() {
|
||||
return memberCount;
|
||||
}
|
||||
|
||||
public void setMemberCount(int memberCount) {
|
||||
this.memberCount = memberCount;
|
||||
}
|
||||
|
||||
public boolean isUseHotReload() {
|
||||
return useHotReload;
|
||||
}
|
||||
|
||||
public void setUseHotReload(boolean useHotReload) {
|
||||
this.useHotReload = useHotReload;
|
||||
}
|
||||
|
||||
public String getHotReloadDir() {
|
||||
return hotReloadDir;
|
||||
}
|
||||
|
||||
public void setHotReloadDir(String hotReloadDir) {
|
||||
this.hotReloadDir = hotReloadDir;
|
||||
}
|
||||
|
||||
public int getReceivingRetryCount() {
|
||||
return receivingRetryCount;
|
||||
}
|
||||
|
||||
public void setReceivingRetryCount(int receivingRetryCount) {
|
||||
this.receivingRetryCount = receivingRetryCount;
|
||||
}
|
||||
|
||||
public MyHttpClient getMyHttpClient() {
|
||||
return myHttpClient;
|
||||
}
|
||||
|
||||
public List<BaseMsg> getMsgList() {
|
||||
return msgList;
|
||||
}
|
||||
|
||||
public void setMsgList(List<BaseMsg> msgList) {
|
||||
this.msgList = msgList;
|
||||
}
|
||||
|
||||
public void setMyHttpClient(MyHttpClient myHttpClient) {
|
||||
this.myHttpClient = myHttpClient;
|
||||
}
|
||||
|
||||
public List<String> getGroupIdList() {
|
||||
return groupIdList;
|
||||
}
|
||||
|
||||
public void setGroupIdList(List<String> groupIdList) {
|
||||
this.groupIdList = groupIdList;
|
||||
}
|
||||
|
||||
public List<JSONObject> getContactList() {
|
||||
return contactList;
|
||||
}
|
||||
|
||||
public void setContactList(List<JSONObject> contactList) {
|
||||
this.contactList = contactList;
|
||||
}
|
||||
|
||||
public List<JSONObject> getGroupList() {
|
||||
return groupList;
|
||||
}
|
||||
|
||||
public void setGroupList(List<JSONObject> groupList) {
|
||||
this.groupList = groupList;
|
||||
}
|
||||
|
||||
public List<JSONObject> getPublicUsersList() {
|
||||
return publicUsersList;
|
||||
}
|
||||
|
||||
public void setPublicUsersList(List<JSONObject> publicUsersList) {
|
||||
this.publicUsersList = publicUsersList;
|
||||
}
|
||||
|
||||
public List<JSONObject> getSpecialUsersList() {
|
||||
return specialUsersList;
|
||||
}
|
||||
|
||||
public void setSpecialUsersList(List<JSONObject> specialUsersList) {
|
||||
this.specialUsersList = specialUsersList;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public void setNickName(String nickName) {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public JSONObject getUserSelf() {
|
||||
return userSelf;
|
||||
}
|
||||
|
||||
public void setUserSelf(JSONObject userSelf) {
|
||||
this.userSelf = userSelf;
|
||||
}
|
||||
|
||||
public Map<String, JSONObject> getUserInfoMap() {
|
||||
return userInfoMap;
|
||||
}
|
||||
|
||||
public void setUserInfoMap(Map<String, JSONObject> userInfoMap) {
|
||||
this.userInfoMap = userInfoMap;
|
||||
}
|
||||
|
||||
public synchronized long getLastNormalRetcodeTime() {
|
||||
return lastNormalRetcodeTime;
|
||||
}
|
||||
|
||||
public synchronized void setLastNormalRetcodeTime(long lastNormalRetcodeTime) {
|
||||
this.lastNormalRetcodeTime = lastNormalRetcodeTime;
|
||||
}
|
||||
|
||||
public List<String> getGroupNickNameList() {
|
||||
return groupNickNameList;
|
||||
}
|
||||
|
||||
public void setGroupNickNameList(List<String> groupNickNameList) {
|
||||
this.groupNickNameList = groupNickNameList;
|
||||
}
|
||||
|
||||
public Map<String, JSONArray> getGroupMemeberMap() {
|
||||
return groupMemeberMap;
|
||||
}
|
||||
|
||||
public void setGroupMemeberMap(Map<String, JSONArray> groupMemeberMap) {
|
||||
this.groupMemeberMap = groupMemeberMap;
|
||||
}
|
||||
|
||||
public String getIndexUrl() {
|
||||
return indexUrl;
|
||||
}
|
||||
|
||||
public void setIndexUrl(String indexUrl) {
|
||||
this.indexUrl = indexUrl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.xmzs.common.wechat.core;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import com.xmzs.common.wechat.utils.enums.MsgCodeEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.xmzs.common.wechat.api.MessageTools;
|
||||
import com.xmzs.common.wechat.beans.BaseMsg;
|
||||
import com.xmzs.common.wechat.face.IMsgHandlerFace;
|
||||
|
||||
import com.xmzs.common.wechat.utils.enums.MsgTypeEnum;
|
||||
import com.xmzs.common.wechat.utils.tools.CommonTools;
|
||||
|
||||
/**
|
||||
* 消息处理中心
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月14日 下午12:47:50
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class MsgCenter {
|
||||
private static Logger LOG = LoggerFactory.getLogger(MsgCenter.class);
|
||||
|
||||
private static Core core = Core.getInstance();
|
||||
|
||||
/**
|
||||
* 接收消息,放入队列
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月23日 下午2:30:48
|
||||
* @param msgList
|
||||
* @return
|
||||
*/
|
||||
public static JSONArray produceMsg(JSONArray msgList) {
|
||||
JSONArray result = new JSONArray();
|
||||
for (int i = 0; i < msgList.size(); i++) {
|
||||
JSONObject msg = new JSONObject();
|
||||
JSONObject m = msgList.getJSONObject(i);
|
||||
m.put("groupMsg", false);// 是否是群消息
|
||||
if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) { // 群聊消息
|
||||
if (m.getString("FromUserName").contains("@@")
|
||||
&& !core.getGroupIdList().contains(m.getString("FromUserName"))) {
|
||||
core.getGroupIdList().add((m.getString("FromUserName")));
|
||||
} else if (m.getString("ToUserName").contains("@@")
|
||||
&& !core.getGroupIdList().contains(m.getString("ToUserName"))) {
|
||||
core.getGroupIdList().add((m.getString("ToUserName")));
|
||||
}
|
||||
// 群消息与普通消息不同的是在其消息体(Content)中会包含发送者id及":<br/>"消息,这里需要处理一下,去掉多余信息,只保留消息内容
|
||||
if (m.getString("Content").contains("<br/>")) {
|
||||
String content = m.getString("Content").substring(m.getString("Content").indexOf("<br/>") + 5);
|
||||
m.put("Content", content);
|
||||
m.put("groupMsg", true);
|
||||
}
|
||||
} else {
|
||||
CommonTools.msgFormatter(m, "Content");
|
||||
}
|
||||
if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_TEXT.getCode())) { // words
|
||||
// 文本消息
|
||||
if (m.getString("Url").length() != 0) {
|
||||
String regEx = "(.+?\\(.+?\\))";
|
||||
Matcher matcher = CommonTools.getMatcher(regEx, m.getString("Content"));
|
||||
String data = "Map";
|
||||
if (matcher.find()) {
|
||||
data = matcher.group(1);
|
||||
}
|
||||
msg.put("Type", "Map");
|
||||
msg.put("Text", data);
|
||||
} else {
|
||||
msg.put("Type", MsgTypeEnum.TEXT.getType());
|
||||
msg.put("Text", m.getString("Content"));
|
||||
}
|
||||
m.put("Type", msg.getString("Type"));
|
||||
m.put("Text", msg.getString("Text"));
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_IMAGE.getCode())
|
||||
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_EMOTICON.getCode())) { // 图片消息
|
||||
m.put("Type", MsgTypeEnum.PIC.getType());
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VOICE.getCode())) { // 语音消息
|
||||
m.put("Type", MsgTypeEnum.VOICE.getType());
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VERIFYMSG.getCode())) {// friends
|
||||
// 好友确认消息
|
||||
// MessageTools.addFriend(core, userName, 3, ticket); // 确认添加好友
|
||||
m.put("Type", MsgTypeEnum.VERIFYMSG.getType());
|
||||
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SHARECARD.getCode())) { // 共享名片
|
||||
m.put("Type", MsgTypeEnum.NAMECARD.getType());
|
||||
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VIDEO.getCode())
|
||||
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MICROVIDEO.getCode())) {// viedo
|
||||
m.put("Type", MsgTypeEnum.VIEDO.getType());
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MEDIA.getCode())) { // 多媒体消息
|
||||
m.put("Type", MsgTypeEnum.MEDIA.getType());
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_STATUSNOTIFY.getCode())) {// phone
|
||||
// init
|
||||
// 微信初始化消息
|
||||
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SYS.getCode())) {// 系统消息
|
||||
m.put("Type", MsgTypeEnum.SYS.getType());
|
||||
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_RECALLED.getCode())) { // 撤回消息
|
||||
|
||||
} else {
|
||||
LOG.info("Useless msg");
|
||||
}
|
||||
LOG.info("收到消息一条,来自: " + m.getString("FromUserName"));
|
||||
result.add(m);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息处理
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月14日 上午10:52:34
|
||||
* @param msgHandler
|
||||
*/
|
||||
public static void handleMsg(IMsgHandlerFace msgHandler) {
|
||||
while (true) {
|
||||
if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getContent() != null) {
|
||||
if (core.getMsgList().get(0).getContent().length() > 0) {
|
||||
BaseMsg msg = core.getMsgList().get(0);
|
||||
if (msg.getType() != null) {
|
||||
try {
|
||||
if (msg.getType().equals(MsgTypeEnum.TEXT.getType())) {
|
||||
String result = msgHandler.textMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.PIC.getType())) {
|
||||
|
||||
String result = msgHandler.picMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.VOICE.getType())) {
|
||||
String result = msgHandler.voiceMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.VIEDO.getType())) {
|
||||
String result = msgHandler.viedoMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.NAMECARD.getType())) {
|
||||
String result = msgHandler.nameCardMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.SYS.getType())) { // 系统消息
|
||||
msgHandler.sysMsgHandle(msg);
|
||||
} else if (msg.getType().equals(MsgTypeEnum.VERIFYMSG.getType())) { // 确认添加好友消息
|
||||
String result = msgHandler.verifyAddFriendMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result,
|
||||
core.getMsgList().get(0).getRecommendInfo().getUserName());
|
||||
} else if (msg.getType().equals(MsgTypeEnum.MEDIA.getType())) { // 多媒体消息
|
||||
String result = msgHandler.mediaMsgHandle(msg);
|
||||
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
core.getMsgList().remove(0);
|
||||
}
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.xmzs.common.wechat.face;
|
||||
|
||||
import com.xmzs.common.wechat.beans.BaseMsg;
|
||||
|
||||
/**
|
||||
* 消息处理接口
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月20日 上午12:13:49
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public interface IMsgHandlerFace {
|
||||
/**
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月20日 上午12:15:00
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String textMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理图片消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月21日 下午11:07:06
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String picMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理声音消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月22日 上午12:09:44
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String voiceMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理小视频消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月23日 下午12:19:50
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String viedoMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理名片消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月1日 上午12:50:50
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String nameCardMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理系统消息
|
||||
*
|
||||
* @author Relyn
|
||||
* @date 2017年6月21日17:43:51
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public void sysMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理确认添加好友消息
|
||||
*
|
||||
* @date 2017年6月28日 下午10:15:30
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String verifyAddFriendMsgHandle(BaseMsg msg);
|
||||
|
||||
/**
|
||||
* 处理收到的文件消息
|
||||
*
|
||||
* @date 2017年7月21日 下午11:59:14
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public String mediaMsgHandle(BaseMsg msg);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.xmzs.common.wechat.service;
|
||||
|
||||
/**
|
||||
* 登陆服务接口
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月13日 上午12:07:21
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public interface ILoginService {
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:14:07
|
||||
* @return
|
||||
*/
|
||||
boolean login();
|
||||
|
||||
/**
|
||||
* 获取UUID
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:21:40
|
||||
* @param qrPath
|
||||
* @return
|
||||
*/
|
||||
String getUuid();
|
||||
|
||||
/**
|
||||
* 获取二维码图片
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:13:51
|
||||
* @param qrPath
|
||||
* @return
|
||||
*/
|
||||
boolean getQR(String qrPath);
|
||||
|
||||
/**
|
||||
* web初始化
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:14:13
|
||||
* @return
|
||||
*/
|
||||
boolean webWxInit();
|
||||
|
||||
/**
|
||||
* 微信状态通知
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:14:24
|
||||
*/
|
||||
void wxStatusNotify();
|
||||
|
||||
/**
|
||||
* 接收消息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 上午12:14:37
|
||||
*/
|
||||
void startReceiving();
|
||||
|
||||
/**
|
||||
* 获取微信联系人
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月13日 下午2:26:18
|
||||
*/
|
||||
void webWxGetContact();
|
||||
|
||||
/**
|
||||
* 批量获取联系人信息
|
||||
*
|
||||
* @date 2017年6月22日 下午11:24:35
|
||||
*/
|
||||
void WebWxBatchGetContact();
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
package com.xmzs.common.wechat.thread;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.xmzs.common.wechat.core.Core;
|
||||
import com.xmzs.common.wechat.utils.SleepUtils;
|
||||
|
||||
/**
|
||||
* 检查微信在线状态
|
||||
* <p>
|
||||
* 如何来感知微信状态?
|
||||
* 微信会有心跳包,LoginServiceImpl.syncCheck()正常在线情况下返回的消息中retcode报文应该为"0",心跳间隔一般在25秒,
|
||||
* 那么可以通过最后收到正常报文的时间来作为判断是否在线的依据。若报文间隔大于60秒,则认为已掉线。
|
||||
* </p>
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月17日 下午10:53:15
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class CheckLoginStatusThread implements Runnable {
|
||||
private static Logger LOG = LoggerFactory.getLogger(CheckLoginStatusThread.class);
|
||||
private Core core = Core.getInstance();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (core.isAlive()) {
|
||||
long t1 = System.currentTimeMillis(); // 秒为单位
|
||||
if (t1 - core.getLastNormalRetcodeTime() > 60 * 1000) { // 超过60秒,判为离线
|
||||
core.setAlive(false);
|
||||
LOG.info("微信已离线");
|
||||
}
|
||||
SleepUtils.sleep(10 * 1000); // 休眠10秒
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.xmzs.common.wechat.utils;
|
||||
|
||||
import com.xmzs.common.wechat.utils.enums.OsNameEnum;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月23日 下午2:26:21
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
public static final String API_WXAPPID = "API_WXAPPID";
|
||||
|
||||
public static final String picDir = "D://itchat4j";
|
||||
public static final String VERSION = "1.4.1";
|
||||
public static final String BASE_URL = "https://login.weixin.qq.com";
|
||||
public static final String REFERER = "https://wx.qq.com/?&lang=zh_CN&target=t";
|
||||
public static final String OS = "";
|
||||
public static final String DIR = "";
|
||||
public static final String DEFAULT_QR = "QR.jpg";
|
||||
public static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36";
|
||||
public static final String UOS_PATCH_CLIENT_VERSION = "2.0.0";
|
||||
|
||||
public static final String UOS_PATCH_EXTSPAM =
|
||||
"Go8FCIkFEokFCggwMDAwMDAwMRAGGvAESySibk50w5Wb3uTl2c2h64jVVrV7gNs06GFlWplHQbY/5FfiO++1yH4ykCyNPWKXmco+wfQzK5R98D3so7rJ5LmGFvBLjGceleySrc3SOf2Pc1gVehzJgODeS0lDL3/I/0S2SSE98YgKleq6Uqx6ndTy9yaL9qFxJL7eiA/R3SEfTaW1SBoSITIu+EEkXff+Pv8NHOk7N57rcGk1w0ZzRrQDkXTOXFN2iHYIzAAZPIOY45Lsh+A4slpgnDiaOvRtlQYCt97nmPLuTipOJ8Qc5pM7ZsOsAPPrCQL7nK0I7aPrFDF0q4ziUUKettzW8MrAaiVfmbD1/VkmLNVqqZVvBCtRblXb5FHmtS8FxnqCzYP4WFvz3T0TcrOqwLX1M/DQvcHaGGw0B0y4bZMs7lVScGBFxMj3vbFi2SRKbKhaitxHfYHAOAa0X7/MSS0RNAjdwoyGHeOepXOKY+h3iHeqCvgOH6LOifdHf/1aaZNwSkGotYnYScW8Yx63LnSwba7+hESrtPa/huRmB9KWvMCKbDThL/nne14hnL277EDCSocPu3rOSYjuB9gKSOdVmWsj9Dxb/iZIe+S6AiG29Esm+/eUacSba0k8wn5HhHg9d4tIcixrxveflc8vi2/wNQGVFNsGO6tB5WF0xf/plngOvQ1/ivGV/C1Qpdhzznh0ExAVJ6dwzNg7qIEBaw+BzTJTUuRcPk92Sn6QDn2Pu3mpONaEumacjW4w6ipPnPw+g2TfywJjeEcpSZaP4Q3YV5HG8D6UjWA4GSkBKculWpdCMadx0usMomsSS/74QgpYqcPkmamB4nVv1JxczYITIqItIKjD35IGKAUwAA==";
|
||||
|
||||
|
||||
public static final ArrayList<String> API_SPECIAL_USER = new ArrayList<String>(Arrays.asList("filehelper", "weibo",
|
||||
"qqmail", "fmessage", "tmessage", "qmessage", "qqsync", "floatbottle", "lbsapp", "shakeapp", "medianote",
|
||||
"qqfriend", "readerapp", "blogapp", "facebookapp", "masssendapp", "meishiapp", "feedsapp", "voip",
|
||||
"blogappweixin", "brandsessionholder", "weixin", "weixinreminder", "officialaccounts", "wxitil",
|
||||
"notification_messages", "wxid_novlwrv3lqwv11", "gh_22b87fa7cb3c", "userexperience_alarm"));
|
||||
|
||||
/**
|
||||
* 获取文件目录
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月8日 下午10:27:42
|
||||
* @return
|
||||
*/
|
||||
public static String getLocalPath() {
|
||||
String localPath = null;
|
||||
try {
|
||||
localPath = new File("").getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return localPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统平台
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月8日 下午10:27:53
|
||||
*/
|
||||
public static OsNameEnum getOsNameEnum() {
|
||||
String os = System.getProperty("os.name").toUpperCase();
|
||||
if (os.indexOf(OsNameEnum.DARWIN.toString()) >= 0) {
|
||||
return OsNameEnum.DARWIN;
|
||||
} else if (os.indexOf(OsNameEnum.WINDOWS.toString()) >= 0) {
|
||||
return OsNameEnum.WINDOWS;
|
||||
} else if (os.indexOf(OsNameEnum.LINUX.toString()) >= 0) {
|
||||
return OsNameEnum.LINUX;
|
||||
} else if (os.indexOf(OsNameEnum.MAC.toString()) >= 0) {
|
||||
return OsNameEnum.MAC;
|
||||
}
|
||||
return OsNameEnum.OTHER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xmzs.common.wechat.utils;
|
||||
|
||||
/**
|
||||
* 常量
|
||||
*
|
||||
* @author https=//github.com/yaphone
|
||||
* @date 创建时间:2017年5月5日 下午11=29=04
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class ConstantConfigEnum {
|
||||
public static final int APPMSGTYPE_TEXT = 1;
|
||||
public static final int APPMSGTYPE_IMG = 2;
|
||||
public static final int APPMSGTYPE_AUDIO = 3;
|
||||
public static final int APPMSGTYPE_VIDEO = 4;
|
||||
public static final int APPMSGTYPE_URL = 5;
|
||||
public static final int APPMSGTYPE_ATTACH = 6;
|
||||
public static final int APPMSGTYPE_OPEN = 7;
|
||||
public static final int APPMSGTYPE_EMOJI = 8;
|
||||
public static final int APPMSGTYPE_VOICE_REMIND = 9;
|
||||
public static final int APPMSGTYPE_SCAN_GOOD = 10;
|
||||
public static final int APPMSGTYPE_GOOD = 13;
|
||||
public static final int APPMSGTYPE_EMOTION = 15;
|
||||
public static final int APPMSGTYPE_CARD_TICKET = 16;
|
||||
public static final int APPMSGTYPE_REALTIME_SHARE_LOCATION = 17;
|
||||
// public static final int APPMSGTYPE_TRANSFERS = 2e3;
|
||||
public static final int APPMSGTYPE_RED_ENVELOPES = 2001;
|
||||
public static final int APPMSGTYPE_READER_TYPE = 100001;
|
||||
public static final int UPLOAD_MEDIA_TYPE_IMAGE = 1;
|
||||
public static final int UPLOAD_MEDIA_TYPE_VIDEO = 2;
|
||||
public static final int UPLOAD_MEDIA_TYPE_AUDIO = 3;
|
||||
public static final int UPLOAD_MEDIA_TYPE_ATTACHMENT = 4;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.xmzs.common.wechat.utils;
|
||||
|
||||
public class MsgKeywords {
|
||||
public static String newFriendStr = "我通过了你的朋友验证请求";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.xmzs.common.wechat.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.CookieStore;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.cookie.Cookie;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.BasicCookieStore;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
/**
|
||||
* HTTP访问类,对Apache HttpClient进行简单封装,适配器模式
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月9日 下午7:05:04
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class MyHttpClient {
|
||||
private Logger logger = Logger.getLogger("MyHttpClient");
|
||||
|
||||
private static CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||
|
||||
private static MyHttpClient instance = null;
|
||||
|
||||
private static CookieStore cookieStore;
|
||||
|
||||
static {
|
||||
cookieStore = new BasicCookieStore();
|
||||
|
||||
// 将CookieStore设置到httpClient中
|
||||
httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
|
||||
}
|
||||
|
||||
public static String getCookie(String name) {
|
||||
List<Cookie> cookies = cookieStore.getCookies();
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equalsIgnoreCase(name)) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
private MyHttpClient() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cookies
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午8:37:17
|
||||
* @return
|
||||
*/
|
||||
public static MyHttpClient getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (MyHttpClient.class) {
|
||||
if (instance == null) {
|
||||
instance = new MyHttpClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理GET请求
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月9日 下午7:06:19
|
||||
* @param url
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public HttpEntity doGet(String url, List<BasicNameValuePair> params, boolean redirect,
|
||||
Map<String, String> headerMap) {
|
||||
HttpEntity entity = null;
|
||||
HttpGet httpGet = new HttpGet();
|
||||
|
||||
try {
|
||||
if (params != null) {
|
||||
String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
|
||||
httpGet = new HttpGet(url + "?" + paramStr);
|
||||
} else {
|
||||
httpGet = new HttpGet(url);
|
||||
}
|
||||
if (!redirect) {
|
||||
httpGet.setConfig(RequestConfig.custom().setRedirectsEnabled(false).build()); // 禁止重定向
|
||||
}
|
||||
httpGet.setHeader("User-Agent", Config.USER_AGENT);
|
||||
httpGet.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
|
||||
httpGet.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
|
||||
httpGet.setHeader("referer", Config.REFERER);
|
||||
if (headerMap != null) {
|
||||
Set<Entry<String, String>> entries = headerMap.entrySet();
|
||||
for (Entry<String, String> entry : entries) {
|
||||
httpGet.setHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
CloseableHttpResponse response = httpClient.execute(httpGet);
|
||||
entity = response.getEntity();
|
||||
} catch (ClientProtocolException e) {
|
||||
logger.info(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
logger.info(e.getMessage());
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理POST请求
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月9日 下午7:06:35
|
||||
* @param url
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public HttpEntity doPost(String url, String paramsStr) {
|
||||
HttpEntity entity = null;
|
||||
HttpPost httpPost = new HttpPost();
|
||||
try {
|
||||
StringEntity params = new StringEntity(paramsStr, Consts.UTF_8);
|
||||
httpPost = new HttpPost(url);
|
||||
httpPost.setEntity(params);
|
||||
httpPost.setHeader("Content-type", "application/json; charset=utf-8");
|
||||
httpPost.setHeader("User-Agent", Config.USER_AGENT);
|
||||
httpPost.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
|
||||
httpPost.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
|
||||
httpPost.setHeader("referer", Config.REFERER);
|
||||
|
||||
CloseableHttpResponse response = httpClient.execute(httpPost);
|
||||
entity = response.getEntity();
|
||||
} catch (ClientProtocolException e) {
|
||||
logger.info(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
logger.info(e.getMessage());
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到服务器
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年5月7日 下午9:19:23
|
||||
* @param url
|
||||
* @param reqEntity
|
||||
* @return
|
||||
*/
|
||||
public HttpEntity doPostFile(String url, HttpEntity reqEntity) {
|
||||
HttpEntity entity = null;
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.setHeader("User-Agent", Config.USER_AGENT);
|
||||
httpPost.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
|
||||
httpPost.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
|
||||
httpPost.setHeader("referer", Config.REFERER);
|
||||
|
||||
httpPost.setEntity(reqEntity);
|
||||
try {
|
||||
CloseableHttpResponse response = httpClient.execute(httpPost);
|
||||
entity = response.getEntity();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.info(e.getMessage());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static CloseableHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xmzs.common.wechat.utils;
|
||||
|
||||
/**
|
||||
* Created by xiaoxiaomo on 2017/5/6.
|
||||
*/
|
||||
public class SleepUtils {
|
||||
|
||||
/**
|
||||
* 毫秒为单位
|
||||
* @param time
|
||||
*/
|
||||
public static void sleep( long time ){
|
||||
try {
|
||||
Thread.sleep( time );
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月23日 下午12:15:00
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum MsgCodeEnum {
|
||||
|
||||
// public static final int MSGTYPE_TEXT = 1; // 文本消息类型
|
||||
// public static final int MSGTYPE_IMAGE = 3; // 图片消息
|
||||
// public static final int MSGTYPE_VOICE = 34; // 语音消息
|
||||
// public static final int MSGTYPE_VIDEO = 43; // 小视频消息
|
||||
// public static final int MSGTYPE_MICROVIDEO = 62; // 短视频消息
|
||||
// public static final int MSGTYPE_EMOTICON = 47; // 表情消息
|
||||
// public static final int MSGTYPE_APP = 49;
|
||||
// public static final int MSGTYPE_VOIPMSG = 50;
|
||||
// public static final int MSGTYPE_VOIPNOTIFY = 52;
|
||||
// public static final int MSGTYPE_VOIPINVITE = 53;
|
||||
// public static final int MSGTYPE_LOCATION = 48;
|
||||
// public static final int MSGTYPE_STATUSNOTIFY = 51;
|
||||
// public static final int MSGTYPE_SYSNOTICE = 9999;
|
||||
// public static final int MSGTYPE_POSSIBLEFRIEND_MSG = 40;
|
||||
// public static final int MSGTYPE_VERIFYMSG = 37;
|
||||
// public static final int MSGTYPE_SHARECARD = 42;
|
||||
// public static final int MSGTYPE_SYS = 10000;
|
||||
// public static final int MSGTYPE_RECALLED = 10002;
|
||||
MSGTYPE_TEXT(1, "文本消息类型"),
|
||||
MSGTYPE_IMAGE(3, "图片消息"),
|
||||
MSGTYPE_VOICE(34, "语音消息"),
|
||||
MSGTYPE_VIDEO(43, "小视频消息"),
|
||||
MSGTYPE_MICROVIDEO(62, "短视频消息"),
|
||||
MSGTYPE_EMOTICON(47, "表情消息"),
|
||||
MSGTYPE_MEDIA(49, "多媒体消息"),
|
||||
MSGTYPE_VOIPMSG(50, ""),
|
||||
MSGTYPE_VOIPNOTIFY(52, ""),
|
||||
MSGTYPE_VOIPINVITE(53, ""),
|
||||
MSGTYPE_LOCATION(48, ""),
|
||||
MSGTYPE_STATUSNOTIFY(51, ""),
|
||||
MSGTYPE_SYSNOTICE(9999, ""),
|
||||
MSGTYPE_POSSIBLEFRIEND_MSG(40, ""),
|
||||
MSGTYPE_VERIFYMSG(37, "好友请求"),
|
||||
MSGTYPE_SHARECARD(42, ""),
|
||||
MSGTYPE_SYS(10000, "系统消息"),
|
||||
MSGTYPE_RECALLED(10002, "")
|
||||
|
||||
;
|
||||
|
||||
private int code;
|
||||
private String type;
|
||||
|
||||
MsgCodeEnum(int code, String type) {
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 消息类型枚举类
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年5月13日 下午11:53:00
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum MsgTypeEnum {
|
||||
TEXT("Text", "文本消息"),
|
||||
PIC("Pic", "图片消息"),
|
||||
VOICE("Voice", "语音消息"),
|
||||
VIEDO("Viedo", "小视频消息"),
|
||||
NAMECARD("NameCard", "名片消息"),
|
||||
SYS("Sys", "系统消息"),
|
||||
VERIFYMSG("VerifyMsg", "添加好友"),
|
||||
MEDIA("app", "文件消息");
|
||||
|
||||
private String type;
|
||||
private String code;
|
||||
|
||||
MsgTypeEnum(String type, String code) {
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
/**
|
||||
* 系统平台
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月8日 下午10:36:28
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum OsNameEnum {
|
||||
WINDOWS, LINUX, DARWIN, MAC, OTHER
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
/**
|
||||
* 返回结构枚举类
|
||||
* <p>
|
||||
* Created by xiaoxiaomo on 2017/5/6.
|
||||
*/
|
||||
public enum ResultEnum {
|
||||
|
||||
SUCCESS("200", "成功"),
|
||||
WAIT_CONFIRM("201", "请在手机上点击确认"),
|
||||
WAIT_SCAN("400", "请扫描二维码");
|
||||
|
||||
private String code;
|
||||
private String msg;
|
||||
|
||||
ResultEnum(String code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
// public static MsgInfoEnum getCode(String code) {
|
||||
// switch (code) {
|
||||
// case "Text":
|
||||
// return MsgInfoEnum.TEXT;
|
||||
// default:
|
||||
// return MsgInfoEnum.VIDEO;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
public enum RetCodeEnum {
|
||||
|
||||
NORMAL("0", "普通"),
|
||||
LOGIN_OUT("1102", "退出"),
|
||||
LOGIN_OTHERWHERE("1101", "其它地方登陆"),
|
||||
MOBILE_LOGIN_OUT("1102", "移动端退出"),
|
||||
UNKOWN("9999", "未知")
|
||||
|
||||
;
|
||||
|
||||
|
||||
private String code;
|
||||
private String type;
|
||||
|
||||
RetCodeEnum(String code, String type) {
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by xiaoxiaomo on 2017/5/7.
|
||||
*/
|
||||
public enum StorageLoginInfoEnum {
|
||||
|
||||
//URL
|
||||
url("url",new String()),
|
||||
fileUrl("fileUrl",new String()),
|
||||
syncUrl("syncUrl",new String()),
|
||||
|
||||
deviceid("deviceid",new String()), //生成15位随机数
|
||||
|
||||
//baseRequest
|
||||
skey("skey",new String()),
|
||||
wxsid("wxsid",new String()),
|
||||
wxuin("wxuin",new String()),
|
||||
pass_ticket("pass_ticket",new String()),
|
||||
|
||||
|
||||
InviteStartCount("InviteStartCount",0),
|
||||
User("User",new JSONObject()),
|
||||
SyncKey("SyncKey",new JSONObject()),
|
||||
synckey("synckey",new String()),
|
||||
|
||||
|
||||
|
||||
MemberCount("MemberCount",new String()),
|
||||
MemberList("MemberList",new JSONArray()),
|
||||
|
||||
|
||||
|
||||
;
|
||||
|
||||
private String key;
|
||||
private Object type;
|
||||
|
||||
StorageLoginInfoEnum(String key, Object type) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
public Object getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
/**
|
||||
* URL
|
||||
* Created by xiaoxiaomo on 2017/5/6.
|
||||
*/
|
||||
public enum URLEnum {
|
||||
|
||||
|
||||
|
||||
BASE_URL("https://login.weixin.qq.com","基本的URL"),
|
||||
UUID_URL(BASE_URL.url+"/jslogin","UUIDLURL"),
|
||||
QRCODE_URL(BASE_URL.url+"/qrcode/","初始化URL"),
|
||||
STATUS_NOTIFY_URL(BASE_URL.url+"/webwxstatusnotify?lang=zh_CN&pass_ticket=%s","微信状态通知"),
|
||||
LOGIN_URL(BASE_URL.url+"/cgi-bin/mmwebwx-bin/login","登陆URL"),
|
||||
INIT_URL("%s/webwxinit?r=%s&pass_ticket=%s","初始化URL"),
|
||||
SYNC_CHECK_URL("/synccheck","检查心跳URL"),
|
||||
WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s","web微信消息同步URL"),
|
||||
WEB_WX_GET_CONTACT("%s/webwxgetcontact","web微信获取联系人信息URL"),
|
||||
WEB_WX_SEND_MSG("%s/webwxsendmsg","发送消息URL"),
|
||||
WEB_WX_UPLOAD_MEDIA("%s/webwxuploadmedia?f=json", "上传文件到服务器"),
|
||||
WEB_WX_GET_MSG_IMG("%s/webwxgetmsgimg", "下载图片消息"),
|
||||
WEB_WX_GET_VOICE("%s/webwxgetvoice", "下载语音消息"),
|
||||
WEB_WX_GET_VIEDO("%s/webwxgetvideo", "下载语音消息"),
|
||||
WEB_WX_PUSH_LOGIN("%s/webwxpushloginurl", "不扫码登陆"),
|
||||
WEB_WX_LOGOUT("%s/webwxlogout", "退出微信"),
|
||||
WEB_WX_BATCH_GET_CONTACT("%s/webwxbatchgetcontact?type=ex&r=%s&lang=zh_CN&pass_ticket=%s", "查询群信息"),
|
||||
WEB_WX_REMARKNAME("%s/webwxoplog?lang=zh_CN&pass_ticket=%s", "修改好友备注"),
|
||||
WEB_WX_VERIFYUSER("%s/webwxverifyuser?r=%s&lang=zh_CN&pass_ticket=%s", "被动添加好友"),
|
||||
WEB_WX_GET_MEDIA("%s/webwxgetmedia", "下载文件")
|
||||
|
||||
|
||||
|
||||
|
||||
;
|
||||
|
||||
private String url;
|
||||
private String msg;
|
||||
|
||||
URLEnum(String url, String msg) {
|
||||
this.url = url;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xmzs.common.wechat.utils.enums;
|
||||
|
||||
/**
|
||||
* 确认添加好友Enum
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年6月29日 下午9:47:14
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum VerifyFriendEnum {
|
||||
|
||||
ADD(2, "添加"),
|
||||
ACCEPT(3, "接受");
|
||||
|
||||
private int code;
|
||||
private String desc;
|
||||
|
||||
private VerifyFriendEnum(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.xmzs.common.wechat.utils.enums.parameters;
|
||||
|
||||
/**
|
||||
*
|
||||
* 基本请求参数
|
||||
* 1. webWxInit 初始化
|
||||
* 2. wxStatusNotify 微信状态通知
|
||||
*
|
||||
* <p>
|
||||
* Created by xiaoxiaomo on 2017/5/7.
|
||||
*/
|
||||
public enum BaseParaEnum {
|
||||
|
||||
Uin("Uin", "wxuin"),
|
||||
Sid("Sid", "wxsid"),
|
||||
Skey("Skey", "skey"),
|
||||
DeviceID("DeviceID", "pass_ticket");
|
||||
|
||||
private String para;
|
||||
private String value;
|
||||
|
||||
BaseParaEnum(String para, String value) {
|
||||
this.para = para;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String para() {
|
||||
return para;
|
||||
}
|
||||
|
||||
|
||||
public Object value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xmzs.common.wechat.utils.enums.parameters;
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
* <p>
|
||||
* Created by xiaoxiaomo on 2017/5/7.
|
||||
*/
|
||||
public enum LoginParaEnum {
|
||||
|
||||
LOGIN_ICON("loginicon", "true"),
|
||||
UUID("uuid", ""),
|
||||
TIP("tip", "0"),
|
||||
R("r", ""),
|
||||
_1("_", "");
|
||||
|
||||
private String para;
|
||||
private String value;
|
||||
|
||||
LoginParaEnum(String para, String value) {
|
||||
this.para = para;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String para() {
|
||||
return para;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xmzs.common.wechat.utils.enums.parameters;
|
||||
|
||||
/**
|
||||
* 状态通知
|
||||
* <p>
|
||||
* Created by xiaoxiaomo on 2017/5/7.
|
||||
*/
|
||||
public enum StatusNotifyParaEnum {
|
||||
|
||||
CODE("Code", "3"),
|
||||
FROM_USERNAME("FromUserName", ""),
|
||||
TO_USERNAME("ToUserName", ""),
|
||||
CLIENT_MSG_ID("ClientMsgId", ""); //时间戳
|
||||
|
||||
private String para;
|
||||
private String value;
|
||||
|
||||
StatusNotifyParaEnum(String para, String value) {
|
||||
this.para = para;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String para() {
|
||||
return para;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xmzs.common.wechat.utils.enums.parameters;
|
||||
|
||||
/**
|
||||
* UUID
|
||||
* <p>
|
||||
* Created by xiaoxiaomo on 2017/5/7.
|
||||
*/
|
||||
public enum UUIDParaEnum {
|
||||
|
||||
APP_ID("appid", "wx782c26e4c19acffb"),
|
||||
FUN("fun", "new"),
|
||||
LANG("lang", "zh_CN"),
|
||||
REDIRECT_URL("redirect_uri",
|
||||
"https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop"),
|
||||
_1("_", "时间戳");
|
||||
|
||||
|
||||
private String para;
|
||||
private String value;
|
||||
|
||||
UUIDParaEnum(String para, String value) {
|
||||
this.para = para;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String para() {
|
||||
return para;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package com.xmzs.common.wechat.utils.tools;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.vdurmont.emoji.EmojiParser;
|
||||
|
||||
import com.xmzs.common.wechat.utils.Config;
|
||||
import com.xmzs.common.wechat.utils.enums.OsNameEnum;
|
||||
|
||||
/**
|
||||
* 常用工具类
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 创建时间:2017年4月8日 下午10:59:55
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public class CommonTools {
|
||||
|
||||
public static boolean printQr(String qrPath) {
|
||||
|
||||
switch (Config.getOsNameEnum()) {
|
||||
case WINDOWS:
|
||||
if (Config.getOsNameEnum().equals(OsNameEnum.WINDOWS)) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
try {
|
||||
runtime.exec("cmd /c start " + qrPath);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MAC:
|
||||
if (Config.getOsNameEnum().equals(OsNameEnum.MAC)) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
try {
|
||||
runtime.exec("open " + qrPath);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean clearScreen() {
|
||||
switch (Config.getOsNameEnum()) {
|
||||
case WINDOWS:
|
||||
if (Config.getOsNameEnum().equals(OsNameEnum.WINDOWS)) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
try {
|
||||
runtime.exec("cmd /c " + "cls");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 正则表达式处理工具
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月9日 上午12:27:10
|
||||
* @return
|
||||
*/
|
||||
public static Matcher getMatcher(String regEx, String text) {
|
||||
Pattern pattern = Pattern.compile(regEx);
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
return matcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* xml解析器
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月9日 下午6:24:25
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public static Document xmlParser(String text) {
|
||||
Document doc = null;
|
||||
StringReader sr = new StringReader(text);
|
||||
InputSource is = new InputSource(sr);
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
doc = builder.parse(is);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static JSONObject structFriendInfo(JSONObject userObj) {
|
||||
Map<String, Object> friendInfoTemplate = new HashMap<String, Object>();
|
||||
friendInfoTemplate.put("UserName", "");
|
||||
friendInfoTemplate.put("City", "");
|
||||
friendInfoTemplate.put("DisplayName", "");
|
||||
friendInfoTemplate.put("PYQuanPin", "");
|
||||
friendInfoTemplate.put("RemarkPYInitial", "");
|
||||
friendInfoTemplate.put("Province", "");
|
||||
friendInfoTemplate.put("KeyWord", "");
|
||||
friendInfoTemplate.put("RemarkName", "");
|
||||
friendInfoTemplate.put("PYInitial", "");
|
||||
friendInfoTemplate.put("EncryChatRoomId", "");
|
||||
friendInfoTemplate.put("Alias", "");
|
||||
friendInfoTemplate.put("Signature", "");
|
||||
friendInfoTemplate.put("NickName", "");
|
||||
friendInfoTemplate.put("RemarkPYQuanPin", "");
|
||||
friendInfoTemplate.put("HeadImgUrl", "");
|
||||
|
||||
friendInfoTemplate.put("UniFriend", 0);
|
||||
friendInfoTemplate.put("Sex", 0);
|
||||
friendInfoTemplate.put("AppAccountFlag", 0);
|
||||
friendInfoTemplate.put("VerifyFlag", 0);
|
||||
friendInfoTemplate.put("ChatRoomId", 0);
|
||||
friendInfoTemplate.put("HideInputBarFlag", 0);
|
||||
friendInfoTemplate.put("AttrStatus", 0);
|
||||
friendInfoTemplate.put("SnsFlag", 0);
|
||||
friendInfoTemplate.put("MemberCount", 0);
|
||||
friendInfoTemplate.put("OwnerUin", 0);
|
||||
friendInfoTemplate.put("ContactFlag", 0);
|
||||
friendInfoTemplate.put("Uin", 0);
|
||||
friendInfoTemplate.put("StarFriend", 0);
|
||||
friendInfoTemplate.put("Statues", 0);
|
||||
|
||||
friendInfoTemplate.put("MemberList", new ArrayList<Object>());
|
||||
|
||||
JSONObject r = new JSONObject();
|
||||
Set<String> keySet = friendInfoTemplate.keySet();
|
||||
for (String key : keySet) {
|
||||
if (userObj.containsKey(key)) {
|
||||
r.put(key, userObj.get(key));
|
||||
} else {
|
||||
r.put(key, friendInfoTemplate.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public static String getSynckey(JSONObject obj) {
|
||||
JSONArray obj2 = obj.getJSONArray("List");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < obj2.size(); i++) {
|
||||
JSONObject obj3 = (JSONObject) JSON.toJSON(obj2.get(i));
|
||||
sb.append(obj3.get("Val") + "|");
|
||||
}
|
||||
return sb.substring(0, sb.length() - 1); // 656159784|656159911|656159873|1491905341
|
||||
|
||||
}
|
||||
|
||||
public static JSONObject searchDictList(List<JSONObject> list, String key, String value) {
|
||||
JSONObject r = null;
|
||||
for (JSONObject i : list) {
|
||||
if (i.getString(key).equals(value)) {
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理emoji表情
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月23日 下午2:39:04
|
||||
* @param d
|
||||
* @param k
|
||||
*/
|
||||
public static void emojiFormatter(JSONObject d, String k) {
|
||||
Matcher matcher = getMatcher("<span class=\"emoji emoji(.{1,10})\"></span>", d.getString(k));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String content = d.getString(k);
|
||||
int lastStart = 0;
|
||||
while (matcher.find()) {
|
||||
String str = matcher.group(1);
|
||||
if (str.length() == 6) {
|
||||
|
||||
} else if (str.length() == 10) {
|
||||
|
||||
} else {
|
||||
str = "&#x" + str + ";";
|
||||
String tmp = content.substring(lastStart, matcher.start());
|
||||
sb.append(tmp + str);
|
||||
lastStart = matcher.end();
|
||||
}
|
||||
}
|
||||
if (lastStart < content.length()) {
|
||||
sb.append(content.substring(lastStart));
|
||||
}
|
||||
if (sb.length() != 0) {
|
||||
d.put(k, EmojiParser.parseToUnicode(sb.toString()));
|
||||
} else {
|
||||
d.put(k, content);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息格式化
|
||||
*
|
||||
* @author https://github.com/yaphone
|
||||
* @date 2017年4月23日 下午4:19:08
|
||||
* @param d
|
||||
* @param k
|
||||
*/
|
||||
public static void msgFormatter(JSONObject d, String k) {
|
||||
d.put(k, d.getString(k).replace("<br/>", "\n"));
|
||||
emojiFormatter(d, k);
|
||||
// TODO 与emoji表情有部分兼容问题,目前暂未处理解码处理 d.put(k,
|
||||
// StringEscapeUtils.unescapeHtml4(d.getString(k)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user