diff --git a/.gitignore b/.gitignore index d954e3c..753bb80 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ hs_err_pid* # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* -deploy-demo.sh \ No newline at end of file +deploy-demo.sh +publish.sh \ No newline at end of file diff --git a/README.md b/README.md index b14504f..47699ad 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +

+升级到3.x 的版本,做了很多break change,但是改动不大,2.x版本在version_2.x分支 +

+ + # WxPusher 微信消息实时推送服务[WxPusher],可以通过API实时给个人微信推送消息.[http://wxpusher.zjiecode.com/admin](http://wxpusher.zjiecode.com/admin) @@ -6,7 +11,7 @@ 请直接访问官方说明文档[http://wxpusher.zjiecode.com/docs](http://wxpusher.zjiecode.com/docs) ## 目录说明 -- sdk 目录:JAVA SDK的源代码 +- client-sdk 目录:JAVA SDK的源代码 - demo 目录:[http://wxpusher.zjiecode.com/demo](http://wxpusher.zjiecode.com/demo)的源代码 # 其他语言SDK @@ -16,7 +21,7 @@ 如果不存在你需要语言的sdk,请你按照[参考文档](http://wxpusher.zjiecode.com/docs)直接使用http调用,另外,欢迎你贡献更多语言的SDK。 # Java版本SDK -[ ![version](https://img.shields.io/static/v1.svg?label=version&message=2.1.4&color=brightgreen) ](https://bintray.com/zjiecode/maven/wxpusher-java-sdk) +[ ![version](https://img.shields.io/static/v1.svg?label=version&message=3.0.2&color=brightgreen) ](https://bintray.com/zjiecode/maven/wxpusher-java-sdk) ## 目录模块说明 - demo @@ -31,7 +36,7 @@ ```groovy dependencies { ...... - compile 'com.zjiecode:wxpusher-java-sdk:2.1.4'//使用上面的版本号 + implementation 'com.smjcco.wxpusher:client-sdk:3.0.0'//使用上面的版本号 ...... } ``` @@ -40,52 +45,134 @@ dependencies { 在*pom.xml*文件中添加: ```xml - com.zjiecode - wxpusher-java-sdk - 2.1.4 - pom + com.smjcco.wxpusher + client-sdk + 3.0.2 ``` +## 系统回调 +WxPusher会提供一些用户事件,比如用户关注、用户上行消息等,我们会通过回调的方式把消息推送给你。 +具体方式请阅读接入文档:https://wxpusher.zjiecode.com/docs/#/?id=callback +相关的数据模型,已经定义在:com.smjcco.wxpusher.sdk.bean.callback 包下面,也可以可以参考demo模块的实现。 + ## 功能说明 +具体每个功能的说明,请参考API说明文档,这里不再赘述。 + +不想看文档,可以直接参考[单元测试的用法(client-sdk/src/test/java/com/smjcco/wxpusher/client/sdk/ClientTest.java)](https://github.com/wxpusher/wxpusher-sdk-java/blob/master/client-sdk/src/test/java/com/smjcco/wxpusher/client/sdk/ClientTest.java) + + + +### 初始化 +如果是你只需要一个实例(一个appToken),可以直接使用default,在使用之前进行初始化; +```java +WxPusher.initDefaultWxPusher("你自己的应用appToken"); +``` +在需要使用WxPusher的地方,世界访问default即可,比如下面这样: +```java +WxPusher.getDefaultWxPusher().send(xxx); +``` + +如果需要同时使用多个实例(appToken)可以直接实例化,自己进行保存: +```java +new WxPusher("你自己的应用appToken"); +``` + ### 发送消息 -最后可以在你需要的地方,直接调用方法,即可实时推送消息到微信上了,比如下面这样: +说明:调用此接口,即可把消息推送出去。 如果传递了多个uid或者topic,会返回多个结果。 ```java Message message = new Message(); -message.setAppToken("AT_xxxxx"); +message.setContent("扫描成功,你可以使用demo演示程序发送消息"); message.setContentType(Message.CONTENT_TYPE_TEXT); -message.setContent("不加限制的自由是很可怕的,因为很容易让任何人滑向深渊。"); -message.setUid("UID_xxxxxx"); -message.setUrl("http://wxpuser.zjiecode.com");//可选参数 -Result> result = WxPusher.send(message); +message.setUid("UID_XXXX"); + +Result> result = WxPusher.getDefaultWxPusher().send(message); +System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); +if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } +} +``` +### 删除消息 +说明:消息发送以后,可以调用次接口删除消息,但是请注意,只能删除用户点击详情查看的落地页面,已经推送到用户的消息记录不可以删除。 +```java +Result result = WxPusher.getDefaultWxPusher().deleteMessage(messageId); +System.out.println("删除结果:" + result.isSuccess() + ", 状态:" + result.getData()); ``` -### 创建带参数的二维码 -创建一个带参数的二维码,用户扫码的时候,回调里面会携带二维码的参数. + +### 创建带参数的app临时二维码 +说明:可以用于创建一个二维码,拿到扫码的用户,来和自己系统的用户做关联。 + +本接口和下面的queryScanUID配合使用,推荐更推荐回调:https://wxpusher.zjiecode.com/docs/#/?id=callback ```java -CreateQrcodeReq createQrcodeReq = new CreateQrcodeReq(); -createQrcodeReq.setAppToken("xxxx"); //必填,应用的appTOken -createQrcodeReq.setExtra("parameter");//必填,携带的参数 -createQrcodeReq.setValidTime(3600);//可选,二维码有效时间,默认1800 s,最大30天,单位是s -Result tempQrcode = WxPusher.createAppTempQrcode(createQrcodeReq); -if (tempQrcode.isSuccess()) { - //创建成功 +CreateQrcodeReq req = new CreateQrcodeReq(); +req.setExtra("test_extra_data"); +req.setValidTime(1800); // 设置有效期为30分钟 + +Result result = WxPusher.getDefaultWxPusher().createAppTempQrcode(req); +System.out.println("创建二维码结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); +if (result.isSuccess() && result.getData() != null) { + CreateQrcodeResp resp = result.getData(); + System.out.println("二维码Code: " + resp.getCode()); + System.out.println("二维码URL: " + resp.getUrl()); + System.out.println("二维码短链接: " + resp.getShortUrl()); + System.out.println("过期时间: " + resp.getExpires()); + System.out.println("附加数据: " + resp.getExtra()); } ``` +### 查询扫码用户UID +```java +String code = "上面 createAppTempQrcode 接口返回的code"; +// 注意:实际使用时,应该使用轮询方式,但是轮训时间不可以小于10秒,此处仅为示例 +// 更推荐使用回调的方式 https://wxpusher.zjiecode.com/docs/#/?id=callback +Result result = WxPusher.getDefaultWxPusher().queryScanUID(code); +``` +### 查询用户 +说明:同一个用户关注多个,可能返回多个数据 +```java +Result> result = WxPusher.getDefaultWxPusher().queryWxUserV2(1, 10, null, false, UserType.APP); +System.out.println("查询用户结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); +if (result.isSuccess() && result.getData() != null) { + Page page = result.getData(); + System.out.println("总用户数: " + page.getTotal()); + System.out.println("当前页: " + page.getPage()); + System.out.println("页大小: " + page.getPageSize()); -### 查询消息发送状态 -发送消息是异步的,你可以通过这个api查询消息发送状态,推送到微信,即标记发送成功。 + if (page.getRecords() != null) { + for (WxUser wxUser : page.getRecords()) { + System.out.println("用户UID: " + wxUser.getUid()); + System.out.println("用户ID: " + wxUser.getId()); + System.out.println("应用/主题ID: " + wxUser.getAppOrTopicId()); + System.out.println("关注类型: " + wxUser.getType()); + System.out.println("用户是否启用: " + wxUser.isEnable()); + System.out.println("用户是否拉黑: " + wxUser.isReject()); + System.out.println("创建时间: " + wxUser.getCreateTime()); + System.out.println("---------------------"); + } + } +} +``` +### 删除用户 +你可以通过本接口,删除用户对应用,主题的关注。 + +删除以后,用户可以重新关注,如不想让用户再次关注,可以调用拉黑接口,对用户拉黑。 ```java -Result result = WxPusher.queryMessageStatus(messageId); +Result result = wxPusher.deleteUser(userId); +System.out.println("删除用户结果:" + result.isSuccess() + ", 状态:" + result.getData()); ``` -### 查询关注APP的微信用户列表 +### 拉黑用户 +拉黑以后不能再发送消息,用户也不能再次关注,除非你取消对他的拉黑。调用拉黑接口,不用再调用删除接口。 ```java -//分页查询全部用户 -Result> wxUserList = WxPusher.queryWxUserV2("AT_xxx", 1, 50, null, false, 0); -wxUsers.getData().getRecords().forEach(d-> System.out.println(d.getUid())); -//根据查询指定UID用户 -Result> users = WxPusher.queryWxUserV2("AT_xxx", 1, 50, "UID_", false, 0); -System.out.println(JSONObject.toJSONString(users)); + // 拉黑用户 +Result result = WxPusher.getDefaultWxPusher().rejectUser(userId, true); +System.out.println("拉黑用户结果:" + result.isSuccess() + ", 状态:" + result.getData()); + +//取消拉黑用户 +Result result2 = WxPusher.getDefaultWxPusher().rejectUser(userId, false); +System.out.println("取消拉黑用户结果:" + result2.isSuccess() + ", 状态:" + result2.getData()); ``` 使用就是这么简单,有需要就来试试吧。 + diff --git a/build.gradle b/build.gradle index b3a6550..6345ca7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,21 @@ +group = 'com.smjcco.wxpusher' + buildscript { repositories { - jcenter() mavenCentral() } dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:2.1.4.RELEASE" - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' + classpath "org.springframework.boot:spring-boot-gradle-plugin:2.7.18" + } +} + +allprojects { + repositories { + mavenCentral() } } -task clean(type: Delete) { - delete project.buildDir +tasks.register('clean', Delete) { delete new File(getRootDir(), "out") + delete new File(getRootDir(), "build") } \ No newline at end of file diff --git a/client-sdk/build.gradle b/client-sdk/build.gradle new file mode 100644 index 0000000..d154e12 --- /dev/null +++ b/client-sdk/build.gradle @@ -0,0 +1,51 @@ +plugins { + id 'java-library' // Java 项目 + id 'maven-publish' // 应用发布插件 + id 'signing' // 用于生成 .asc 文件 + id("org.danilopianini.publish-on-central") version "8.0.6" +} + + +//还有很多开发者用1.8,编译成低版本的,方便兼容 +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +group = 'com.smjcco.wxpusher' + +publishOnCentral { + version = '3.0.2' + repoOwner.set("wxpusher") + projectDescription.set("WxPusher消息推送平台 是一个使用微信公众号作为通道的,实时信息推送平台,你可以通过调用API的方式,把信息推送到微信上,无需安装额外的软件,即可做到信息实时通知。 你可以使用WxPusher来做服务器报警通知、抢课通知、抢票通知,信息更新提示等。") + projectLongName.set("WxPusher消息推送平台 Java SDK") + licenseName.set("Apache License, Version 2.0") + licenseUrl.set("http://www.apache.org/licenses/LICENSE-2.0") + projectUrl.set("https://github.com/wxpusher/wxpusher-sdk-java") + scmConnection.set("git@github.com:wxpusher/wxpusher-sdk-java.git") +} + +publishing { + publications { + OSSRH(MavenPublication) { + pom { + developers { + developer { + id = 'zjiecode' + name = 'zjiecode' + email = 'zjiecode@gmail.com' + } + } + } + } + } +} + +signing { + useGpgCmd() + sign publishing.publications.OSSRH +} +dependencies { + implementation 'com.alibaba.fastjson2:fastjson2:2.0.56' + testImplementation 'junit:junit:4.13.1' +} diff --git a/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/HttpUtils.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/HttpUtils.java new file mode 100644 index 0000000..242f05f --- /dev/null +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/HttpUtils.java @@ -0,0 +1,179 @@ +package com.smjcco.wxpusher.client.sdk; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import com.smjcco.wxpusher.client.sdk.bean.Result; +import com.smjcco.wxpusher.client.sdk.bean.ResultCode; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Set; + +/** + * 说明:网络请求工具 + * 作者:zjiecode + * 时间:2019-09-05 + */ +public final class HttpUtils { + private static final String BASE_URL = "https://wxpusher.zjiecode.com"; + private static final String CHARSET_NAME = "UTF-8"; + + private HttpUtils() { + } + + public static Result request(Object body, Map queryMap, String path, String method, Type returnType) { + try { + String url = buildUrl(path); + if (queryMap != null) { + String query = parseMap2Query(queryMap); + if (!query.isEmpty()) { + url = url + "?" + query; + } + } + URL cUrl = new URL(url); + HttpURLConnection urlConnection = getHttpURLConnection(cUrl, method); + if (body != null) { + OutputStream outputStream = urlConnection.getOutputStream(); + String dataStr = JSON.toJSONString(body); + outputStream.write(dataStr.getBytes(Charset.forName(CHARSET_NAME))); + outputStream.flush(); + } + return dealConnect(urlConnection, returnType); + } catch (MalformedURLException e) { + return new Result<>(ResultCode.NETWORK_ERROR, e.getMessage()); + } catch (IOException e) { + return new Result<>(ResultCode.NETWORK_ERROR, e.toString()); + } catch (Throwable e) { + return new Result<>(ResultCode.UNKNOWN_ERROR, e.toString()); + } + } + + public static Result post(Object body, String path, Type returnType) { + return request(body, null, path, "POST", returnType); + } + + public static Result get(Map queryMap, String path, Type returnType) { + return request(null, queryMap, path, "GET", returnType); + } + + + public static Result delete(Map queryData, String path, Type returnType) { + return request(null, queryData, path, "DELETE", returnType); + } + + public static Result put(Map queryData, String path, Type returnType) { + return request(null, queryData, path, "PUT", returnType); + } + + private static HttpURLConnection getHttpURLConnection(URL cUrl, String method) throws IOException { + HttpURLConnection urlConnection = (HttpURLConnection) cUrl.openConnection(); + urlConnection.setConnectTimeout(60000); + urlConnection.setReadTimeout(60000); + urlConnection.setUseCaches(false); + urlConnection.setRequestMethod(method); + urlConnection.setRequestProperty("Content-Type", "application/json"); + urlConnection.setRequestProperty("Charset", CHARSET_NAME); + urlConnection.setDoOutput(true); + urlConnection.connect(); + return urlConnection; + } + + /** + * 把map转成query查询字符串 + */ + private static String parseMap2Query(Map data) { + if (data == null || data.size() <= 0) { + return ""; + } + Set> entries = data.entrySet(); + StringBuilder stringBuilder = new StringBuilder(); + for (Map.Entry entry : entries) { + if (stringBuilder.length() > 0) { + stringBuilder.append("&"); + } + stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()); + } + return stringBuilder.toString(); + } + + /** + * + */ + private static String buildUrl(String path) { + String url = BASE_URL; + if (path != null && !path.isEmpty()) { + if (path.startsWith("/")) { + url = BASE_URL + path; + } else { + url = BASE_URL + "/" + path; + } + } + return url; + } + + /** + * 处理连接以后的状态信息 + * + * @param urlConnection 打开的连接 + * @param type 返回的结果数据类型 + * @return 返回发送结果 + */ + private static Result dealConnect(HttpURLConnection urlConnection, Type type) throws IOException { + try { + int responseCode = urlConnection.getResponseCode(); + if (responseCode != 200) { + return new Result<>(urlConnection.getResponseCode(), "http请求错误:" + responseCode); + } + InputStream inputStream = urlConnection.getInputStream(); + String res = inputStream2String(inputStream); + if (res == null || res.isEmpty()) { + return new Result<>(ResultCode.INTERNAL_SERVER_ERROR, "服务器返回异常"); + } + // 构造 Result 的完整类型信息 + Type resultType = new TypeReference>(type) { + }.getType(); + // 反序列化 + Result result = JSONObject.parseObject(res, resultType); + if (result == null) { + return new Result<>(ResultCode.DATA_ERROR, "服务器返回数据解析异常"); + } + return result; + } catch (MalformedURLException e) { + return new Result<>(ResultCode.NETWORK_ERROR, e.getMessage()); + } catch (IOException e) { + return new Result<>(ResultCode.NETWORK_ERROR, e.getMessage()); + } catch (Throwable e) { + return new Result<>(ResultCode.UNKNOWN_ERROR, e.getMessage()); + } + } + + /** + * 从输入流中读取内容到字符串 + * + * @param inputStream 输入路 + * @return 返回字符串 + */ + private static String inputStream2String(InputStream inputStream) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + int len = 0; + byte[] bytes = new byte[4096]; + try { + while ((len = inputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, len); + } + return outputStream.toString(CHARSET_NAME); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/WxPusher.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/WxPusher.java new file mode 100644 index 0000000..24ea11d --- /dev/null +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/WxPusher.java @@ -0,0 +1,234 @@ +package com.smjcco.wxpusher.client.sdk; + +import com.alibaba.fastjson2.TypeReference; +import com.smjcco.wxpusher.client.sdk.bean.*; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 说明:WxPusher的客户端 + * 一般通过调用 initDefaultWxPusher(),初始化以后,然后就直接用getDefaultWxPusher()即可 + * 如果有多实例需求,可以用构造方法,多次实例化 + * 具体接口使用可以参考接口说明文档 + * 作者:zjiecode + * 时间:2019-05-03 + */ +public final class WxPusher { + + + /** + * 用来保存发送消息用的AppToken + */ + private String appToken; + + private static WxPusher defaultWxPusher; + + public WxPusher(String appToken) { + this.appToken = appToken; + } + + /** + * 初始化WxPusher的默认实力 + * + * @param appToken 获取到的AppToken,获取方式AppToken + */ + public static void initDefaultWxPusher(String appToken) { + defaultWxPusher = new WxPusher(appToken); + } + + public static WxPusher getDefaultWxPusher() { + if (defaultWxPusher == null) { + throw new RuntimeException("使用默认的实例前,请先调用initDefaultWxPusher进行初始化"); + } + return defaultWxPusher; + } + + /** + * 发送消息 + * + * @param message 发送消息的内容 + * @return 发送结果,如果传递了多个uid或者topic,会返回多个结果 + */ + public Result> send(Message message) { + message.setAppToken(appToken); + Result> result = verify(message); + if (result != null) { + return result; + } + Type resultType = new TypeReference>() { + }.getType(); + return HttpUtils.post(message, "/api/send/message", resultType); + } + + /** + * 查询消息发送状态 + * + * @param messageId 发送接口返回的的messageId + * @return 返回查询的状态 + * @deprecated 此接口返回数据可能不准确,只能确保wxpusher已经将消息推送到微信服务器了,用户可能拒绝接收 + */ + public Result queryMessageStatus(Long messageId) { + if (messageId == null || messageId <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "messageId为空"); + } + return HttpUtils.get(null, String.format("/api/send/query/%s", messageId), Integer.class); + } + + + /** + * 删除消息 + * 说明:消息发送以后,可以调用次接口删除消息,但是请注意,只能删除用户点击详情查看的落地页面,已经推送到用户的消息记录不可以删除。 + * + * @param messageId 发送接口返回的消息内容id,调用一次接口生成一个,如果是发送给多个用户,多个用户共享一个messageContentId,通过messageContentId可以删除内容,删除后本次发送的所有用户都无法再查看本条消息 + * @return 是否删除成功 + */ + public Result deleteMessage(Long messageId) { + if (messageId == null || messageId <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "messageId错误"); + } + Map params = new HashMap<>(); + params.put("messageContentId", messageId); + params.put("appToken", appToken); + return HttpUtils.delete(params, "/api/send/message", Boolean.class); + } + + /** + * 创建带参数的app临时二维码 + * + * @param createQrcodeReq 创建二维码参数 + * @return 返回创建的二维码 + */ + public Result createAppTempQrcode(CreateQrcodeReq createQrcodeReq) { + createQrcodeReq.setAppToken(appToken); + return HttpUtils.post(createQrcodeReq, "/api/fun/create/qrcode", CreateQrcodeResp.class); + } + + /** + * 查询用户,同一个用户关注多个,可能返回多个数据 + *

+ * 查询用户信息 + *

+ * + * @param page 请求数据的页码 + * @param pageSize 分页大小,不能超过100 + * @param uid 用户的uid,可选,如果不传就是查询所有用户,传uid就是查某个用户的信息。 + * @param isBlock 查询拉黑用户,可选,不传查询所有用户,true查询拉黑用户,false查询没有拉黑的用户 + * @param type 关注的类型,可选,不传查询所有用户,0是应用,1是主题 + * @return 返回查询到的用户分页数据 + */ + public Result> queryWxUserV2(Integer page, Integer pageSize, + String uid, boolean isBlock, UserType type) { + if (appToken == null || appToken.isEmpty()) { + return new Result<>(ResultCode.BIZ_FAIL, "appToken不能为空"); + } + if (page == null || page <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "page不合法"); + } + if (pageSize == null || pageSize <= 0 || pageSize > 100) { + return new Result<>(ResultCode.BIZ_FAIL, "pageSize不合法"); + } + Map params = new HashMap<>(); + params.put("appToken", appToken); + params.put("page", page); + params.put("pageSize", pageSize); + params.put("isBlock", isBlock); + params.put("type", type.getType()); + if (uid != null && !uid.isEmpty()) { + params.put("uid", uid); + } + + Type resultType = new TypeReference>() { + }.getType(); + return HttpUtils.get(params, "/api/fun/wxuser/v2", resultType); + } + + /** + * 查询扫码用户UID + * 用户扫描参数二维码后,设置了回调地址,我们会通过回调地址把用户的UID推送给你的服务,具体见回调说明,推荐使用这种回调的方式。 + * 但是部分用户场景简单,或者没有后端服务,比如客户端软件,使用很不方便,因此我们增加了这个查询接口,通过上面的创建参数二维码接口创建一个二维码,你会拿到一个二维码的code,用此code配合这个接口,可以查询到最后一次扫描参数二维码用户的UID。 + * 【轮训时间间隔不能小于10秒!!禁止死循环轮训,用户退出后,必须关闭轮训,否则封号。】 + * + * @param code 创建参数二维码接口返回的code参数。 + * @return 扫码用户的UID + */ + public Result queryScanUID(String code) { + if (appToken == null || appToken.isEmpty()) { + return new Result<>(ResultCode.BIZ_FAIL, "appToken不能为空"); + } + if (code == null || code.isEmpty()) { + return new Result<>(ResultCode.BIZ_FAIL, "code不能为空"); + } + Map params = new HashMap<>(); + params.put("appToken", appToken); + params.put("code", code); + return HttpUtils.get(params, "/api/fun/scan-qrcode-uid", String.class); + } + + /** + * 删除用户 + * 你可以通过本接口,删除用户对应用,主题的关注。 + * 说明:你可以删除用户对应用、主题的关注,删除以后,用户可以重新关注,如不想让用户再次关注,可以调用拉黑接口,对用户拉黑。 + * + * @param id 用户id,通过用户查询接口可以获取 + * @return 操作是否成功 + */ + public Result deleteUser(Long id) { + if (id == null || id <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "id错误"); + } + Map params = new HashMap<>(); + params.put("id", id); + params.put("appToken", appToken); + Result respResult = HttpUtils.delete(params, "/api/fun/remove", String.class); + //兼容一下返回数据 + Result result = new Result<>(respResult.getCode(), respResult.getMsg()); + result.setData(respResult.isSuccess()); + return result; + } + + /** + * 你可以通过本接口,可以拉黑用户 + * 说明:拉黑以后不能再发送消息,用户也不能再次关注,除非你取消对他的拉黑。调用拉黑接口,不用再调用删除接口。 + * + * @param id 通过用户查询接口可以获取 + * @param reject 是否拉黑,true表示拉黑,false表示取消拉黑 + * @return 操作结果 + */ + public Result rejectUser(Long id, Boolean reject) { + if (id == null || id <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "id错误"); + } + if (reject == null) { + return new Result<>(ResultCode.BIZ_FAIL, "reject错误"); + } + Map params = new HashMap<>(); + params.put("id", id); + params.put("appToken", appToken); + params.put("reject", reject); + Result respResult = HttpUtils.put(params, "/api/fun/reject", String.class); + //兼容一下返回数据 + Result result = new Result<>(respResult.getCode(), respResult.getMsg()); + result.setData(respResult.isSuccess()); + return result; + } + + /** + * 验证消息合法性,客户端验证比较宽松,主要在服务端进行校验 + */ + private static Result verify(Message message) { + if (message == null) { + return new Result<>(ResultCode.BIZ_FAIL, "消息不能为空"); + } + if (message.getAppToken() == null || message.getAppToken().length() <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "appToken不能为空"); + } + if (message.getContent() == null || message.getContent().length() <= 0) { + return new Result<>(ResultCode.BIZ_FAIL, "content内容不能为空"); + } + return null; + } + +} diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeReq.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeReq.java similarity index 94% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeReq.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeReq.java index a5c8d52..18c20fa 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeReq.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeReq.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; /** * 说明:创建带参数的app临时二维码 diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeResp.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeResp.java similarity index 95% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeResp.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeResp.java index 24e2c5a..cdfd41b 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/CreateQrcodeResp.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/CreateQrcodeResp.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; /** * 说明:创建带参数的app临时二维码 diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Message.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Message.java similarity index 88% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Message.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Message.java index f410f7f..e07b6a8 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Message.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Message.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; import java.util.HashSet; import java.util.Set; @@ -39,23 +39,19 @@ public class Message { private String summary; - /** - * 是否验证付费 - * @deprecated 请使用verifyPayType - */ - private Boolean verifyPay; - private Integer verifyPayType; - /** - * 仅针对text消息类型有效 - */ private String url; public String getAppToken() { return appToken; } + /** + * 不需要外部设置,后面会删除这个字段 + * @param appToken 应用token + * @deprecated 不要使用,内部接口依赖,后面会删除。 + */ public void setAppToken(String appToken) { this.appToken = appToken; } @@ -108,6 +104,7 @@ public void setSummary(String summary) { /** * 只需要 body 标签内部的内容。 + * @param content 内容 */ public void setContent(String content) { this.content = content; @@ -121,14 +118,6 @@ public void setUrl(String url) { this.url = url; } - public void setVerifyPay(Boolean verifyPay) { - this.verifyPay = verifyPay; - } - - public Boolean isVerifyPay() { - return verifyPay; - } - public void setVerifyPayType(Integer verifyPayType) { this.verifyPayType = verifyPayType; } diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/MessageResult.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/MessageResult.java similarity index 84% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/MessageResult.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/MessageResult.java index b20f9c6..969645b 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/MessageResult.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/MessageResult.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; /** * 说明: @@ -12,8 +12,8 @@ public class MessageResult { private Long messageId; /** - * 消息是否发送成功 - * @return + * 请求服务端是否成功,这个判断成功 以后,再判断业务状态 + * @return 结果 */ public boolean isSuccess() { return code == ResultCode.SUCCESS.getCode(); diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Page.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Page.java similarity index 94% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Page.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Page.java index bf5e8c4..35db8e8 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Page.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Page.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; import java.util.List; diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Result.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Result.java similarity index 94% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Result.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Result.java index 520003a..e1beec3 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/Result.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/Result.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; public class Result { private Integer code; diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/ResultCode.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/ResultCode.java similarity index 93% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/ResultCode.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/ResultCode.java index 2e51cf8..84f6d7a 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/ResultCode.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/ResultCode.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; /** * 返回编码,参考http语义 diff --git a/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/UserType.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/UserType.java new file mode 100644 index 0000000..0525593 --- /dev/null +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/UserType.java @@ -0,0 +1,16 @@ +package com.smjcco.wxpusher.client.sdk.bean; + +public enum UserType { + APP(0), + TOPIC(1), + ; + private final Integer type; + + UserType(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } +} \ No newline at end of file diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/WxUser.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/WxUser.java similarity index 85% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/WxUser.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/WxUser.java index 431dd8e..b3cbf21 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/WxUser.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/WxUser.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean; +package com.smjcco.wxpusher.client.sdk.bean; /** * 说明:微信用户数据 @@ -22,21 +22,18 @@ public class WxUser { /** * 昵称 * - * @deprecated 微信已经不再返回这个字段 + * @deprecated 微信已经不再返回这个字段,如果后台后备注,会返回备注 */ private String nickName; - /** - * 微信头像 - * - * @deprecated 微信已经不再返回这个字段 - */ - private String headImg; /** * 是否拉黑用户 */ private boolean reject; - //关注类型,0:关注应用,1:关注topic + /** + * 关注类型,0:关注应用,1:关注topic + * @see UserType + */ private int type; //关注的应用或者主题名字 private String name; @@ -96,14 +93,6 @@ public void setNickName(String nickName) { this.nickName = nickName; } - public String getHeadImg() { - return headImg; - } - - public void setHeadImg(String headImg) { - this.headImg = headImg; - } - public boolean isReject() { return reject; } diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/AppSubscribeBean.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/AppSubscribeBean.java similarity index 84% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/AppSubscribeBean.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/AppSubscribeBean.java index 8fb7ee4..1a61959 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/AppSubscribeBean.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/AppSubscribeBean.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean.callback; +package com.smjcco.wxpusher.client.sdk.bean.callback; /** * 说明:二维码被扫描的时候的回调数据结构 @@ -8,12 +8,11 @@ public class AppSubscribeBean { public static final String SOURCE_SCAN = "scan"; public static final String SOURCE_LINK = "link"; + public static final String SOURCE_COMMAND = "command"; + public static final String SOURCE_ORDER = "order"; + private String uid; private Long appId; - /** - * @deprecated 请使用appId,appKey将在后续版本删除 - */ - private String appKey; private String appName; private String userName; private String userHeadImg; @@ -31,14 +30,6 @@ public void setUid(String uid) { this.uid = uid; } - public String getAppKey() { - return appKey; - } - - public void setAppKey(String appKey) { - this.appKey = appKey; - } - public String getAppName() { return appName; } diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/BaseCallBackReq.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/BaseCallBackReq.java similarity index 93% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/BaseCallBackReq.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/BaseCallBackReq.java index c57ad52..b4134bd 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/BaseCallBackReq.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/BaseCallBackReq.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean.callback; +package com.smjcco.wxpusher.client.sdk.bean.callback; /** * 说明:wxpusher回调的数据结构 diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/OrderPayBean.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/OrderPayBean.java similarity index 96% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/OrderPayBean.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/OrderPayBean.java index e929893..4bfd54c 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/OrderPayBean.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/OrderPayBean.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean.callback; +package com.smjcco.wxpusher.client.sdk.bean.callback; public class OrderPayBean { //付费增加的时间,毫秒。退款是负数,表示减少的订阅时间。 diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/UpCommandBean.java b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/UpCommandBean.java similarity index 83% rename from sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/UpCommandBean.java rename to client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/UpCommandBean.java index fd9f3fc..d88728e 100644 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/bean/callback/UpCommandBean.java +++ b/client-sdk/src/main/java/com/smjcco/wxpusher/client/sdk/bean/callback/UpCommandBean.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.client.bean.callback; +package com.smjcco.wxpusher.client.sdk.bean.callback; /** * 说明:上行消息内容 @@ -11,7 +11,6 @@ public class UpCommandBean { private String appKey; private String appName; private String userName; - private String userHeadImg; private Long time; //消息内容 private String content; @@ -56,14 +55,6 @@ public void setUserName(String userName) { this.userName = userName; } - public String getUserHeadImg() { - return userHeadImg; - } - - public void setUserHeadImg(String userHeadImg) { - this.userHeadImg = userHeadImg; - } - public Long getTime() { return time; } diff --git a/client-sdk/src/test/java/com/smjcco/wxpusher/client/sdk/ClientTest.java b/client-sdk/src/test/java/com/smjcco/wxpusher/client/sdk/ClientTest.java new file mode 100644 index 0000000..c6def30 --- /dev/null +++ b/client-sdk/src/test/java/com/smjcco/wxpusher/client/sdk/ClientTest.java @@ -0,0 +1,486 @@ +package com.smjcco.wxpusher.client.sdk; + +import com.smjcco.wxpusher.client.sdk.bean.*; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 说明:接口测试 + * 作者:zjiecode + * 时间:2019-05-03 + */ +public class ClientTest { + + private static final String TEST_APP_TOKEN = "AT_xxx"; // 测试用的APP_TOKEN,请替换为自己的 + private static final String TEST_UID = "UID_xx"; // 测试用的UID,请替换为自己的 + private static final Long TEST_TOPIC_ID = 6950L; // 测试用的主题ID,请替换为自己的 + + + @Before + public void setup() { + // 也可以使用静态方法初始化默认实例 + WxPusher.initDefaultWxPusher(TEST_APP_TOKEN); + } + + /** + * 测试发送文本消息到单个用户 + */ + @Test + public void testSendTextToUser() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条测试文本消息"); + message.setUid(TEST_UID); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送消息应该成功", result.isSuccess()); + Assert.assertEquals("处理成功", result.getMsg()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + + MessageResult messageResult = result.getData().get(0); + Assert.assertEquals("UID应匹配", TEST_UID, messageResult.getUid()); + Assert.assertTrue("消息发送状态应包含'创建发送任务成功'", messageResult.getStatus().contains("创建发送任务成功")); + Assert.assertTrue("消息发送码应为成功", messageResult.isSuccess()); + } + + /** + * 测试发送HTML消息到单个用户 + */ + @Test + public void testSendHtmlToUser() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_HTML); + message.setContent("

HTML消息测试

这是一条红色的测试消息

"); + message.setUid(TEST_UID); + message.setSummary("HTML消息测试"); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送HTML消息应该成功", result.isSuccess()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + + MessageResult messageResult = result.getData().get(0); + Assert.assertEquals("UID应匹配", TEST_UID, messageResult.getUid()); + } + + /** + * 测试发送Markdown消息到单个用户 + */ + @Test + public void testSendMarkdownToUser() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_MD); + message.setContent("# Markdown消息测试\n\n**这是加粗文本**\n\n*这是斜体文本*"); + message.setUid(TEST_UID); + message.setSummary("Markdown消息测试"); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送Markdown消息应该成功", result.isSuccess()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + } + + /** + * 测试发送消息到主题 + */ + @Test + public void testSendToTopic() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条发送到主题的测试消息"); + message.setTopicId(TEST_TOPIC_ID); + message.setSummary("主题消息测试"); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送主题消息应该成功", result.isSuccess()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + } + + /** + * 测试发送消息到多个用户 + */ + @Test + public void testSendToMultiUsers() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条发送到多个用户的测试消息"); + + // 添加多个UID + Set uids = new HashSet<>(); + uids.add(TEST_UID); + // 添加更多用户... + // uids.add("UID_xxx2"); + message.setUids(uids); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送多用户消息应该成功", result.isSuccess()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + + MessageResult messageResult = result.getData().get(0); + Assert.assertEquals("UID应匹配", TEST_UID, messageResult.getUid()); + Assert.assertTrue("消息发送状态应包含'创建发送任务成功'", messageResult.getStatus().contains("创建发送任务成功")); + } + + /** + * 测试发送带URL的消息 + */ + @Test + public void testSendWithUrl() { + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条带链接的测试消息"); + message.setUid(TEST_UID); + message.setUrl("https://wxpusher.zjiecode.com"); + + Result> result = WxPusher.getDefaultWxPusher().send(message); + System.out.println("发送结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + for (MessageResult messageResult : result.getData()) { + System.out.println("发送到UID: " + messageResult.getUid() + ", 结果:" + messageResult.getStatus()); + } + } + + // 添加断言 + Assert.assertTrue("发送带URL消息应该成功", result.isSuccess()); + Assert.assertEquals("处理成功", result.getMsg()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + Assert.assertFalse("返回结果列表不应为空", result.getData().isEmpty()); + + MessageResult messageResult = result.getData().get(0); + Assert.assertEquals("UID应匹配", TEST_UID, messageResult.getUid()); + Assert.assertTrue("消息发送状态应包含'创建发送任务成功'", messageResult.getStatus().contains("创建发送任务成功")); + } + + /** + * 测试查询消息状态 + */ + @Test + public void testQueryMessageStatus() { + // 先发送一条消息获取消息ID + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条用于测试查询状态的消息"); + message.setUid(TEST_UID); + + Result> sendResult = WxPusher.getDefaultWxPusher().send(message); + if (sendResult.isSuccess() && sendResult.getData() != null && !sendResult.getData().isEmpty()) { + Long messageId = sendResult.getData().get(0).getMessageId(); + if (messageId != null) { + Result result = WxPusher.getDefaultWxPusher().queryMessageStatus(messageId); + System.out.println("查询结果:" + result.isSuccess() + ", 消息状态:" + result.getData()); + + // 添加断言 + Assert.assertTrue("查询消息状态应该成功", result.isSuccess()); + Assert.assertNotNull("状态码不应为空", result.getData()); + Assert.assertEquals("消息状态应为1", 1, result.getData().intValue()); + } else { + System.out.println("消息ID为空,无法查询状态"); + Assert.fail("消息ID不应为空"); + } + } else { + System.out.println("发送消息失败,无法测试查询状态"); + Assert.fail("发送消息应该成功"); + } + } + + /** + * 测试删除消息 + */ + @Test + public void testDeleteMessage() { + // 先发送一条消息获取消息ID + Message message = new Message(); + message.setContentType(Message.CONTENT_TYPE_TEXT); + message.setContent("这是一条用于测试删除的消息"); + message.setUid(TEST_UID); + + Result> sendResult = WxPusher.getDefaultWxPusher().send(message); + if (sendResult.isSuccess() && sendResult.getData() != null && !sendResult.getData().isEmpty()) { + Long messageId = sendResult.getData().get(0).getMessageId(); + if (messageId != null) { + Result result = WxPusher.getDefaultWxPusher().deleteMessage(messageId); + System.out.println("删除结果:" + result.isSuccess() + ", 状态:" + result.getData()); + + // 根据实际情况,可能删除失败是正常的,因为消息已经推送给用户 + // 这里我们只检查API调用是否返回了结果,而不检查删除是否成功 + Assert.assertNotNull("应该返回结果", result); + } else { + System.out.println("消息ID为空,无法删除消息"); + Assert.fail("消息ID不应为空"); + } + } else { + System.out.println("发送消息失败,无法测试删除消息"); + Assert.fail("发送消息应该成功"); + } + } + + /** + * 测试创建带参数的临时二维码 + */ + @Test + public void testCreateTempQrcode() { + CreateQrcodeReq req = new CreateQrcodeReq(); + req.setExtra("test_extra_data"); + req.setValidTime(1800); // 设置有效期为30分钟 + + Result result = WxPusher.getDefaultWxPusher().createAppTempQrcode(req); + System.out.println("创建二维码结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + CreateQrcodeResp resp = result.getData(); + System.out.println("二维码Code: " + resp.getCode()); + System.out.println("二维码URL: " + resp.getUrl()); + System.out.println("二维码短链接: " + resp.getShortUrl()); + System.out.println("过期时间: " + resp.getExpires()); + System.out.println("附加数据: " + resp.getExtra()); + } + + // 添加断言 + Assert.assertTrue("创建二维码应该成功", result.isSuccess()); + Assert.assertEquals("处理成功", result.getMsg()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + + CreateQrcodeResp resp = result.getData(); + Assert.assertNotNull("二维码Code不应为空", resp.getCode()); + Assert.assertNotNull("二维码URL不应为空", resp.getUrl()); + Assert.assertTrue("二维码URL应包含正确格式", resp.getUrl().contains(".jpg")); + Assert.assertEquals("附加数据应匹配", "test_extra_data", resp.getExtra()); + Assert.assertTrue("过期时间应大于当前时间", resp.getExpires() > System.currentTimeMillis()); + } + + /** + * 测试查询用户列表 + */ + @Test + public void testQueryWxUser() { + Result> result = WxPusher.getDefaultWxPusher().queryWxUserV2(1, 10, null, false, UserType.APP); + System.out.println("查询用户结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + Page page = result.getData(); + System.out.println("总用户数: " + page.getTotal()); + System.out.println("当前页: " + page.getPage()); + System.out.println("页大小: " + page.getPageSize()); + + if (page.getRecords() != null) { + for (WxUser wxUser : page.getRecords()) { + System.out.println("用户UID: " + wxUser.getUid()); + System.out.println("用户ID: " + wxUser.getId()); + System.out.println("应用/主题ID: " + wxUser.getAppOrTopicId()); + System.out.println("关注类型: " + wxUser.getType()); + System.out.println("用户是否启用: " + wxUser.isEnable()); + System.out.println("用户是否拉黑: " + wxUser.isReject()); + System.out.println("创建时间: " + wxUser.getCreateTime()); + System.out.println("---------------------"); + } + } + } + + // 添加断言 + Assert.assertTrue("查询用户应该成功", result.isSuccess()); + Assert.assertEquals("处理成功", result.getMsg()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + + Page page = result.getData(); + Assert.assertNotNull("用户列表不应为空", page.getRecords()); + Assert.assertFalse("用户列表不应为空", page.getRecords().isEmpty()); + Assert.assertEquals("当前页应为1", Integer.valueOf(1), page.getPage()); + Assert.assertEquals("页大小应为10", Integer.valueOf(10), page.getPageSize()); + Assert.assertTrue("总用户数应大于0", page.getTotal() > 0); + + // 检查是否包含测试用户 + boolean containsTestUser = false; + for (WxUser user : page.getRecords()) { + if (TEST_UID.equals(user.getUid())) { + containsTestUser = true; + Assert.assertEquals("应用ID应匹配", Long.valueOf(141), user.getAppOrTopicId()); + Assert.assertEquals("关注类型应为APP", 0, user.getType()); + break; + } + } + Assert.assertTrue("用户列表应包含测试用户", containsTestUser); + } + + /** + * 测试查询指定UID用户信息 + */ + @Test + public void testQuerySpecificUser() { + Result> result = WxPusher.getDefaultWxPusher().queryWxUserV2(1, 10, TEST_UID, false, UserType.APP); + System.out.println("查询指定用户结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + Page page = result.getData(); + if (page.getRecords() != null && !page.getRecords().isEmpty()) { + WxUser wxUser = page.getRecords().get(0); + System.out.println("用户UID: " + wxUser.getUid()); + System.out.println("用户ID: " + wxUser.getId()); + System.out.println("应用/主题ID: " + wxUser.getAppOrTopicId()); + System.out.println("关注类型: " + wxUser.getType()); + System.out.println("用户是否启用: " + wxUser.isEnable()); + System.out.println("用户是否拉黑: " + wxUser.isReject()); + System.out.println("创建时间: " + wxUser.getCreateTime()); + } else { + System.out.println("未找到指定UID的用户"); + } + } + + // 添加断言 + Assert.assertTrue("查询指定用户应该成功", result.isSuccess()); + Assert.assertEquals("处理成功", result.getMsg()); + Assert.assertNotNull("返回数据不应为空", result.getData()); + + Page page = result.getData(); + Assert.assertNotNull("用户记录不应为空", page.getRecords()); + Assert.assertFalse("用户记录不应为空", page.getRecords().isEmpty()); + + WxUser wxUser = page.getRecords().get(0); + Assert.assertEquals("用户UID应匹配", TEST_UID, wxUser.getUid()); + Assert.assertEquals("应用ID应匹配", Long.valueOf(141), wxUser.getAppOrTopicId()); + Assert.assertEquals("关注类型应为APP", 0, wxUser.getType()); + } + + /** + * 测试查询扫码用户UID + * 注意:此方法需要用户扫描二维码才能查询到结果 + */ + @Test + public void testQueryScanUID() { + // 先创建一个带参数的临时二维码 + CreateQrcodeReq req = new CreateQrcodeReq(); + req.setExtra("test_scan_uid"); + req.setValidTime(300); // 设置有效期为5分钟 + + Result createResult = WxPusher.getDefaultWxPusher().createAppTempQrcode(req); + if (createResult.isSuccess() && createResult.getData() != null) { + String code = createResult.getData().getCode(); + System.out.println("请扫描这个二维码URL: " + createResult.getData().getUrl()); + System.out.println("等待用户扫描..."); + + // 注意:实际使用时,应该使用轮询方式,此处仅为示例 + Result result = WxPusher.getDefaultWxPusher().queryScanUID(code); + System.out.println("查询扫码用户结果:" + result.isSuccess() + ", 消息:" + result.getMsg()); + if (result.isSuccess() && result.getData() != null) { + System.out.println("扫码用户UID: " + result.getData()); + } + + // 添加断言 - 注意这里可能失败是正常的,因为没有用户扫码 + Assert.assertNotNull("查询结果不应为空", result); + } else { + System.out.println("创建二维码失败,无法测试查询扫码用户"); + Assert.fail("创建二维码应该成功"); + } + } + + /** + * 测试删除用户 + * 注意:此方法会真实删除用户,谨慎使用 + */ + @Test + public void testDeleteUser() { + // 先查询出用户ID + Result> queryResult = WxPusher.getDefaultWxPusher().queryWxUserV2(1, 10, TEST_UID, false, UserType.APP); + if (queryResult.isSuccess() && queryResult.getData() != null + && queryResult.getData().getRecords() != null + && !queryResult.getData().getRecords().isEmpty()) { + + Long userId = queryResult.getData().getRecords().get(0).getId(); + System.out.println("找到用户ID: " + userId); + + // 谨慎执行以下代码,会真实删除用户关注 + // Result result = wxPusher.deleteUser(userId); + // System.out.println("删除用户结果:" + result.isSuccess() + ", 状态:" + result.getData()); + + // 添加断言 + Assert.assertTrue("查询用户应该成功", queryResult.isSuccess()); + Assert.assertNotNull("用户ID不应为空", userId); + Assert.assertEquals("用户ID应匹配预期", Long.valueOf(28134), userId); + + System.out.println("为避免真实删除用户,该测试方法已被注释"); + } else { + System.out.println("未找到指定UID的用户,无法测试删除"); + Assert.fail("应该能找到测试用户"); + } + } + + /** + * 测试拉黑用户 + * 注意:此方法会真实拉黑用户,谨慎使用 + */ + @Test + public void testRejectUser() { + // 先查询出用户ID + Result> queryResult = WxPusher.getDefaultWxPusher().queryWxUserV2(1, 10, TEST_UID, false, UserType.APP); + if (queryResult.isSuccess() && queryResult.getData() != null + && queryResult.getData().getRecords() != null + && !queryResult.getData().getRecords().isEmpty()) { + + Long userId = queryResult.getData().getRecords().get(0).getId(); + System.out.println("找到用户ID: " + userId); + + // 拉黑和取消拉黑用户的完整测试 + Result result = WxPusher.getDefaultWxPusher().rejectUser(userId, true); + System.out.println("拉黑用户结果:" + result.isSuccess() + ", 状态:" + result.getData()); + + // 添加断言 + Assert.assertTrue("拉黑用户应该成功", result.isSuccess()); + Assert.assertTrue("操作状态应为true", result.getData()); + + Result result2 = WxPusher.getDefaultWxPusher().rejectUser(userId, false); + System.out.println("取消拉黑用户结果:" + result2.isSuccess() + ", 状态:" + result2.getData()); + + // 添加断言 + Assert.assertTrue("取消拉黑用户应该成功", result2.isSuccess()); + Assert.assertTrue("操作状态应为true", result2.getData()); + } else { + System.out.println("未找到指定UID的用户,无法测试拉黑"); + Assert.fail("应该能找到测试用户"); + } + } + +} diff --git a/demo/build.gradle b/demo/build.gradle index 320542d..2c3eb34 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,27 +1,14 @@ apply plugin: 'java' -apply plugin: 'idea' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' -//Java 8 -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -buildscript { - repositories { - jcenter() - mavenCentral() - } - dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:2.1.4.RELEASE" - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' - } +//还有很多开发者用1.8,编译成低版本的,方便兼容 +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } repositories { - group 'com.zjiecode.wxpusher' - version '0.0.1' - jcenter() mavenCentral() } @@ -30,19 +17,14 @@ dependencies { compileOnly 'org.projectlombok:lombok:1.18.8' annotationProcessor 'org.projectlombok:lombok:1.18.8' //spring boot - compile 'org.springframework.boot:spring-boot-starter-web:2.1.4.RELEASE' + implementation 'org.springframework.boot:spring-boot-starter-web:2.1.4.RELEASE' //freemarker html模版渲染引擎 - compile 'org.springframework.boot:spring-boot-starter-freemarker:2.1.4.RELEASE' + implementation 'org.springframework.boot:spring-boot-starter-freemarker:2.1.4.RELEASE' - //test - testCompile 'org.springframework.boot:spring-boot-starter-test:2.1.4.RELEASE' - testCompile 'org.springframework.boot:spring-boot-test:2.1.4.RELEASE' - testCompile 'org.springframework:spring-test:5.1.6.RELEASE' - testCompile 'junit:junit:4.12' + implementation 'com.alibaba.fastjson2:fastjson2:2.0.56' //实际开发中,请直接通过jar包依赖,在本demo中,直接工程依赖的sdk源码 - compile project(":sdk") -// compile 'com.zjiecode:wxpusher-sdk-java:{version}' + implementation project(":client-sdk") } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/AppWebMvcConfigurer.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/AppWebMvcConfigurer.java similarity index 91% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/AppWebMvcConfigurer.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/AppWebMvcConfigurer.java index 9c16aa8..b4f2ebd 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/AppWebMvcConfigurer.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/AppWebMvcConfigurer.java @@ -1,9 +1,9 @@ -package com.zjiecode.wxpusher.demo; +package com.smjcco.wxpusher.client.sdk.demo; import com.fasterxml.jackson.databind.ObjectMapper; -import com.zjiecode.wxpusher.demo.result.*; +import com.smjcco.wxpusher.client.sdk.demo.result.*; -import com.zjiecode.wxpusher.demo.utils.ThrowableUtils; +import com.smjcco.wxpusher.client.sdk.demo.utils.ThrowableUtils; import org.springframework.context.annotation.Configuration; import org.springframework.validation.BindException; import org.springframework.validation.ObjectError; @@ -78,11 +78,11 @@ public void configureHandlerExceptionResolvers(List re result = new Result(ResultCode.INTERNAL_SERVER_ERROR, "服务器错误:" + throwable.getMessage()); responseResult(response, result); log.error(result.toString(), throwable); - }else if (throwable instanceof HttpException){ + } else if (throwable instanceof HttpException) { //返回原始的http status code result = new Result(ResultCode.INTERNAL_SERVER_ERROR, "服务器错误:" + throwable.getMessage()); - responseResult(response, result,((HttpException) throwable).getHttpStatus()); - } else { + responseResult(response, result, ((HttpException) throwable).getHttpStatus()); + } else { //其他错误 String message = String.format("接口 [%s] 出现异常", request.getRequestURI()); result = new Result(ResultCode.INTERNAL_SERVER_ERROR, message); @@ -97,19 +97,21 @@ public void configureHandlerExceptionResolvers(List re public void addCorsMappings(CorsRegistry registry) { //配置跨域请求 registry.addMapping("/**") + .allowedOrigins("https://wxpusher.zjiecode.com") .allowedOrigins("*") .allowedHeaders("*") - .allowCredentials(true) + .allowCredentials(false) .allowedMethods("*"); } private void responseResult(HttpServletResponse response, Result result) { - responseResult(response, result,200); + responseResult(response, result, 200); } - /** - * 遇到错误,拦截以后输出响应到客户端 - */ - private void responseResult(HttpServletResponse response, Result result,int httpCode) { + + /** + * 遇到错误,拦截以后输出响应到客户端 + */ + private void responseResult(HttpServletResponse response, Result result, int httpCode) { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-type", "application/json;charset=UTF-8"); response.setHeader("Access-Control-Allow-Credentials", "true"); diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/CommonService.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/CommonService.java similarity index 61% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/CommonService.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/CommonService.java index b3369a9..d874557 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/CommonService.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/CommonService.java @@ -1,5 +1,6 @@ -package com.zjiecode.wxpusher.demo; +package com.smjcco.wxpusher.client.sdk.demo; +import com.smjcco.wxpusher.client.sdk.WxPusher; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -7,19 +8,19 @@ import lombok.extern.slf4j.Slf4j; -/** - * 说明: - * 作者:zjiecode - * 时间:2019-10-07 - */ @Component @Slf4j public class CommonService { @Value("${spring.profiles.active}") String activeEnv; + @Value("${wxpusher.biz.apptoken}") + private String appToken; @PostConstruct private void init() { log.info("运行环境:" + activeEnv); + //初始化默认的WxPusher + WxPusher.initDefaultWxPusher(appToken); + } } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/JavaWebApplication.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/JavaWebApplication.java similarity index 75% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/JavaWebApplication.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/JavaWebApplication.java index c651af4..b12cae8 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/JavaWebApplication.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/JavaWebApplication.java @@ -1,9 +1,8 @@ -package com.zjiecode.wxpusher.demo; +package com.smjcco.wxpusher.client.sdk.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; @SpringBootApplication public class JavaWebApplication { diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CallBackController.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CallBackController.java similarity index 64% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CallBackController.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CallBackController.java index 4c256b8..8c7b6e0 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CallBackController.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CallBackController.java @@ -1,14 +1,14 @@ -package com.zjiecode.wxpusher.demo.controller; +package com.smjcco.wxpusher.client.sdk.demo.controller; -import com.alibaba.fastjson.JSONObject; -import com.zjiecode.wxpusher.client.WxPusher; -import com.zjiecode.wxpusher.client.bean.Message; -import com.zjiecode.wxpusher.client.bean.callback.AppSubscribeBean; -import com.zjiecode.wxpusher.client.bean.callback.BaseCallBackReq; -import com.zjiecode.wxpusher.client.bean.callback.UpCommandBean; -import com.zjiecode.wxpusher.demo.data.ScanQrocodeDataRepo; - -import com.zjiecode.wxpusher.demo.data.UpCommandDataRepo; +import com.alibaba.fastjson2.JSON; +import com.smjcco.wxpusher.client.sdk.demo.data.ScanQrocodeDataRepo; +import com.smjcco.wxpusher.client.sdk.demo.data.UpCommandDataRepo; +import com.smjcco.wxpusher.client.sdk.WxPusher; +import com.smjcco.wxpusher.client.sdk.bean.Message; +import com.smjcco.wxpusher.client.sdk.bean.callback.AppSubscribeBean; +import com.smjcco.wxpusher.client.sdk.bean.callback.BaseCallBackReq; +import com.smjcco.wxpusher.client.sdk.bean.callback.UpCommandBean; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; @@ -16,8 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import lombok.extern.slf4j.Slf4j; - /** * 说明:接收来自WxPusher服务的回调 * 当用户扫码关注的时候会触发 @@ -33,28 +31,27 @@ public class CallBackController { @PostMapping("/callback") public String callback(@RequestBody BaseCallBackReq callBackReq) { - log.info("收到wxpusher回调:{}", JSONObject.toJSONString(callBackReq)); + log.info("收到wxpusher回调:{}", JSON.toJSONString(callBackReq)); if (BaseCallBackReq.ACTION_APP_SUBSCRIBE.equalsIgnoreCase(callBackReq.getAction())) { - AppSubscribeBean appSubscribeBean = JSONObject.parseObject(JSONObject.toJSONString(callBackReq.getData()), AppSubscribeBean.class); + AppSubscribeBean appSubscribeBean = JSON.parseObject(JSON.toJSONString(callBackReq.getData()), AppSubscribeBean.class); if (!StringUtils.isEmpty(appSubscribeBean.getExtra())) { //这里的extra 就是创建二维码的时候,携带的数据,也就是qrcodeId, ScanQrocodeDataRepo.put(appSubscribeBean.getExtra(), appSubscribeBean); - log.info("存储回调数据:{}", JSONObject.toJSONString(appSubscribeBean)); + log.info("存储回调数据:{}", JSON.toJSONString(appSubscribeBean)); //扫码以后,发送一条消息给用户 Message message = new Message(); message.setContent("扫描成功,你可以使用demo演示程序发送消息"); message.setContentType(Message.CONTENT_TYPE_TEXT); message.setUid(appSubscribeBean.getUid()); - message.setAppToken(appToken); - WxPusher.send(message); + WxPusher.getDefaultWxPusher().send(message); } else { - //无参数二维码(默认二维码) + //无参数二维码(默认二维码),不需要发送提醒,会自动发送后台设置的 } return ""; } //上行命令消息 if (BaseCallBackReq.ACTION_SEND_UP_CMD.equalsIgnoreCase(callBackReq.getAction())) { - UpCommandBean upCommandBean = JSONObject.parseObject(JSONObject.toJSONString(callBackReq.getData()), UpCommandBean.class); + UpCommandBean upCommandBean = JSON.parseObject(JSON.toJSONString(callBackReq.getData()), UpCommandBean.class); UpCommandDataRepo.add(upCommandBean); //收到上行消息后,发送一条消息给用户 Message message = new Message(); @@ -62,7 +59,7 @@ public String callback(@RequestBody BaseCallBackReq callBackReq) { message.setContentType(Message.CONTENT_TYPE_TEXT); message.setUid(upCommandBean.getUid()); message.setAppToken(appToken); - WxPusher.send(message); + WxPusher.getDefaultWxPusher().send(message); return ""; } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CommonController.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CommonController.java similarity index 89% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CommonController.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CommonController.java index 6a1c94c..70c6098 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/CommonController.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/CommonController.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.controller; +package com.smjcco.wxpusher.client.sdk.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/DisplayController.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/DisplayController.java similarity index 70% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/controller/DisplayController.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/DisplayController.java index 2e7e3d8..ee8b6b4 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/DisplayController.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/DisplayController.java @@ -1,18 +1,17 @@ -package com.zjiecode.wxpusher.demo.controller; +package com.smjcco.wxpusher.client.sdk.demo.controller; -import com.zjiecode.wxpusher.client.WxPusher; -import com.zjiecode.wxpusher.client.bean.CreateQrcodeReq; -import com.zjiecode.wxpusher.client.bean.CreateQrcodeResp; -import com.zjiecode.wxpusher.client.bean.Result; -import com.zjiecode.wxpusher.client.bean.ResultCode; -import com.zjiecode.wxpusher.client.bean.callback.AppSubscribeBean; -import com.zjiecode.wxpusher.client.bean.callback.UpCommandBean; -import com.zjiecode.wxpusher.demo.data.ScanQrocodeDataRepo; -import com.zjiecode.wxpusher.demo.data.UpCommandDataRepo; -import com.zjiecode.wxpusher.demo.result.BizException; -import com.zjiecode.wxpusher.demo.utils.RandomUtil; - -import org.springframework.beans.factory.annotation.Value; +import com.smjcco.wxpusher.client.sdk.demo.data.ScanQrocodeDataRepo; +import com.smjcco.wxpusher.client.sdk.demo.data.UpCommandDataRepo; +import com.smjcco.wxpusher.client.sdk.demo.result.BizException; +import com.smjcco.wxpusher.client.sdk.demo.utils.RandomUtil; +import com.smjcco.wxpusher.client.sdk.WxPusher; +import com.smjcco.wxpusher.client.sdk.bean.CreateQrcodeReq; +import com.smjcco.wxpusher.client.sdk.bean.CreateQrcodeResp; +import com.smjcco.wxpusher.client.sdk.bean.Result; +import com.smjcco.wxpusher.client.sdk.bean.ResultCode; +import com.smjcco.wxpusher.client.sdk.bean.callback.AppSubscribeBean; +import com.smjcco.wxpusher.client.sdk.bean.callback.UpCommandBean; +import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -24,8 +23,6 @@ import java.util.List; import java.util.Map; -import lombok.extern.slf4j.Slf4j; - /** * 说明:演示发送消息 * 作者:zjiecode @@ -35,8 +32,6 @@ @RequestMapping("/demo") @Slf4j public class DisplayController { - @Value("${wxpusher.biz.apptoken}") - private String appToken; /** * 发送普通文本 @@ -47,10 +42,9 @@ public ModelAndView display() { String qrcodeId = RandomUtil.getRandomStr(32); //创建一个参数二维码 CreateQrcodeReq createQrcodeReq = new CreateQrcodeReq(); - createQrcodeReq.setAppToken(appToken); createQrcodeReq.setValidTime(3600);//二维码有效时间 createQrcodeReq.setExtra(qrcodeId); - Result tempQrcode = WxPusher.createAppTempQrcode(createQrcodeReq); + Result tempQrcode = WxPusher.getDefaultWxPusher().createAppTempQrcode(createQrcodeReq); if (!tempQrcode.isSuccess()) { throw new BizException(tempQrcode.getMsg()); } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/HealthCheckController.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/HealthCheckController.java similarity index 66% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/controller/HealthCheckController.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/HealthCheckController.java index b4f037d..8f9a94c 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/HealthCheckController.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/HealthCheckController.java @@ -1,11 +1,11 @@ -package com.zjiecode.wxpusher.demo.controller; +package com.smjcco.wxpusher.client.sdk.demo.controller; -import com.alibaba.fastjson.JSONObject; -import com.zjiecode.wxpusher.client.WxPusher; -import com.zjiecode.wxpusher.demo.result.HttpException; -import com.zjiecode.wxpusher.demo.result.Result; -import com.zjiecode.wxpusher.demo.result.ResultCode; -import com.zjiecode.wxpusher.demo.utils.DateUtil; +import com.alibaba.fastjson2.JSON; +import com.smjcco.wxpusher.client.sdk.demo.result.HttpException; +import com.smjcco.wxpusher.client.sdk.demo.result.Result; +import com.smjcco.wxpusher.client.sdk.demo.result.ResultCode; +import com.smjcco.wxpusher.client.sdk.demo.utils.DateUtil; +import com.smjcco.wxpusher.client.sdk.WxPusher; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -28,7 +28,7 @@ public Result alive() { long now = System.currentTimeMillis(); Map data = new HashMap<>(); data.put("系统启动时间", DateUtil.formatTimeLong(now - startTime)); - com.zjiecode.wxpusher.client.bean.Result result = WxPusher.queryMessageStatus(1L); + com.smjcco.wxpusher.client.sdk.bean.Result result = WxPusher.getDefaultWxPusher().queryMessageStatus(1L); boolean connectWxPusher = (result.getCode() == ResultCode.SUCCESS.getCode()) || (result.getCode() == ResultCode.BIZ_FAIL.getCode()); data.put("到WxPuhser的链接状态", connectWxPusher); @@ -36,6 +36,6 @@ public Result alive() { if (connectWxPusher) { return Result.getSuccess(data); } - throw new HttpException(JSONObject.toJSONString(data), 500); + throw new HttpException(JSON.toJSONString(data), 500); } } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/SendController.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/SendController.java similarity index 81% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/controller/SendController.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/SendController.java index 376965a..6aebd56 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/controller/SendController.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/controller/SendController.java @@ -1,11 +1,10 @@ -package com.zjiecode.wxpusher.demo.controller; +package com.smjcco.wxpusher.client.sdk.demo.controller; -import com.zjiecode.wxpusher.client.WxPusher; -import com.zjiecode.wxpusher.client.bean.Message; -import com.zjiecode.wxpusher.client.bean.Result; +import com.smjcco.wxpusher.client.sdk.WxPusher; +import com.smjcco.wxpusher.client.sdk.bean.Message; +import com.smjcco.wxpusher.client.sdk.bean.Result; import org.springframework.beans.factory.annotation.Value; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -34,8 +33,8 @@ public Result sendText(@PathVariable("uid") String uid) { message.setContentType(Message.CONTENT_TYPE_TEXT); message.setUid(uid); message.setAppToken(appToken); - message.setContent("WxPusher演示消息,这里是一天普通的演示消息\n\n\n" + sign); - return WxPusher.send(message); + message.setContent("WxPusher演示消息,这里是一条普通的演示消息\n\n\n" + sign); + return WxPusher.getDefaultWxPusher().send(message); } /** @@ -49,7 +48,7 @@ public Result sendHtml(@PathVariable("uid") String uid) { message.setAppToken(appToken); message.setContent("WxPusher演示消息,这是一个html消息
标题:这是标题
状态:成功" + "


" + sign); - return WxPusher.send(message); + return WxPusher.getDefaultWxPusher().send(message); } @@ -64,7 +63,7 @@ public Result sendMarkdown(@PathVariable("uid") String uid) { message.setAppToken(appToken); message.setContent("WxPusher演示消息,这是一个Markdown消息\n# 目录\n- 什么是Wxpusher\n- Wxpusher可好用了\n## 发送状态:_成功_" + "\n\n


" + sign); - return WxPusher.send(message); + return WxPusher.getDefaultWxPusher().send(message); } /** @@ -77,7 +76,7 @@ public Result sendCustom(@PathVariable("uid") String uid, String content) { message.setUid(uid); message.setAppToken(appToken); message.setContent(content + "\n\n\n" + sign); - return WxPusher.send(message); + return WxPusher.getDefaultWxPusher().send(message); } } diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/cron/ClearTimeoutDataScheduleTask.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/cron/ClearTimeoutDataScheduleTask.java similarity index 78% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/cron/ClearTimeoutDataScheduleTask.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/cron/ClearTimeoutDataScheduleTask.java index e721d22..73fa84e 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/cron/ClearTimeoutDataScheduleTask.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/cron/ClearTimeoutDataScheduleTask.java @@ -1,7 +1,7 @@ -package com.zjiecode.wxpusher.demo.cron; +package com.smjcco.wxpusher.client.sdk.demo.cron; -import com.zjiecode.wxpusher.demo.data.ScanQrocodeDataRepo; -import com.zjiecode.wxpusher.demo.data.UpCommandDataRepo; +import com.smjcco.wxpusher.client.sdk.demo.data.ScanQrocodeDataRepo; +import com.smjcco.wxpusher.client.sdk.demo.data.UpCommandDataRepo; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/data/ScanQrocodeDataRepo.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/ScanQrocodeDataRepo.java similarity index 91% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/data/ScanQrocodeDataRepo.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/ScanQrocodeDataRepo.java index e13aaa1..7d75f75 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/data/ScanQrocodeDataRepo.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/ScanQrocodeDataRepo.java @@ -1,8 +1,8 @@ -package com.zjiecode.wxpusher.demo.data; +package com.smjcco.wxpusher.client.sdk.demo.data; import java.util.*; -import com.zjiecode.wxpusher.client.bean.callback.AppSubscribeBean; +import com.smjcco.wxpusher.client.sdk.bean.callback.AppSubscribeBean; import lombok.extern.slf4j.Slf4j; /** diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/data/UpCommandDataRepo.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/UpCommandDataRepo.java similarity index 86% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/data/UpCommandDataRepo.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/UpCommandDataRepo.java index f91f27a..f082da2 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/data/UpCommandDataRepo.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/data/UpCommandDataRepo.java @@ -1,6 +1,6 @@ -package com.zjiecode.wxpusher.demo.data; +package com.smjcco.wxpusher.client.sdk.demo.data; -import com.zjiecode.wxpusher.client.bean.callback.UpCommandBean; +import com.smjcco.wxpusher.client.sdk.bean.callback.UpCommandBean; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/AppException.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/AppException.java similarity index 90% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/result/AppException.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/AppException.java index 0e48257..3a51039 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/AppException.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/AppException.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.result; +package com.smjcco.wxpusher.client.sdk.demo.result; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/BizException.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/BizException.java similarity index 92% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/result/BizException.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/BizException.java index 0deb56e..788945d 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/BizException.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/BizException.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.result; +package com.smjcco.wxpusher.client.sdk.demo.result; /** * 业务异常,一般不是应用的错误,比如:用户登陆没有输入账号 diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/HttpException.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/HttpException.java similarity index 87% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/result/HttpException.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/HttpException.java index d33c1b3..691a0a6 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/HttpException.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/HttpException.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.result; +package com.smjcco.wxpusher.client.sdk.demo.result; import lombok.Getter; diff --git a/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/Result.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/Result.java new file mode 100644 index 0000000..51b3f15 --- /dev/null +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/Result.java @@ -0,0 +1,46 @@ +package com.smjcco.wxpusher.client.sdk.demo.result; + +import lombok.Getter; +import lombok.Setter; + +/** + * 返回结果数据结构 + */ +@Setter +@Getter +public class Result { + private Integer code; + private String msg; + private T data; + + public Result(ResultCode code, String msg, T data) { + this.code = code.getCode(); + this.msg = msg; + this.data = data; + } + + public Result(ResultCode code, String msg) { + this.code = code.getCode(); + this.msg = msg; + } + public static Result getSuccess(T data) { + return new Result<>(ResultCode.SUCCESS, "处理成功", data); + } + + public static Result getSuccess() { + return new Result<>(ResultCode.SUCCESS, "处理成功"); + } + + public static Result getBizFail(String msg) { + return new Result<>(ResultCode.BIZ_FAIL, msg); + } + + public boolean isSuccess() { + return code == ResultCode.SUCCESS.getCode(); + } + + @Override + public String toString() { + return "[" + getCode() + "]" + getMsg(); + } +} diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/ResultCode.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/ResultCode.java similarity index 91% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/result/ResultCode.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/ResultCode.java index 9cde427..4ec6b8b 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/ResultCode.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/result/ResultCode.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.result; +package com.smjcco.wxpusher.client.sdk.demo.result; /** * 返回编码,参考http语义 diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/DateUtil.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/DateUtil.java similarity index 97% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/utils/DateUtil.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/DateUtil.java index c4f050d..8a4ae6d 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/DateUtil.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/DateUtil.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.utils; +package com.smjcco.wxpusher.client.sdk.demo.utils; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/RandomUtil.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/RandomUtil.java similarity index 95% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/utils/RandomUtil.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/RandomUtil.java index 0218bbc..c33000b 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/RandomUtil.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/RandomUtil.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.utils; +package com.smjcco.wxpusher.client.sdk.demo.utils; import java.util.concurrent.ThreadLocalRandom; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/ThrowableUtils.java b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/ThrowableUtils.java similarity index 88% rename from demo/src/main/java/com/zjiecode/wxpusher/demo/utils/ThrowableUtils.java rename to demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/ThrowableUtils.java index d384ae5..bc7ec90 100644 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/utils/ThrowableUtils.java +++ b/demo/src/main/java/com/smjcco/wxpusher/client/sdk/demo/utils/ThrowableUtils.java @@ -1,4 +1,4 @@ -package com.zjiecode.wxpusher.demo.utils; +package com.smjcco.wxpusher.client.sdk.demo.utils; import org.springframework.lang.Nullable; diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/bean/CreateQrcodeRes.java b/demo/src/main/java/com/zjiecode/wxpusher/demo/bean/CreateQrcodeRes.java deleted file mode 100644 index c545d42..0000000 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/bean/CreateQrcodeRes.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.zjiecode.wxpusher.demo.bean; - -/** - * 说明: - * 作者:zjiecode - * 时间:2019-10-05 - */ -public class CreateQrcodeRes { - -} diff --git a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/Result.java b/demo/src/main/java/com/zjiecode/wxpusher/demo/result/Result.java deleted file mode 100644 index 8eb5425..0000000 --- a/demo/src/main/java/com/zjiecode/wxpusher/demo/result/Result.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.zjiecode.wxpusher.demo.result; - -/** - * 返回结果数据结构 - */ -public class Result { - private Integer code; - private String msg; - private T data; - - public Result(ResultCode code, String msg, T data) { - this.code = code.getCode(); - this.msg = msg; - this.data = data; - } - - public Result(ResultCode code, String msg) { - this.code = code.getCode(); - this.msg = msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public void setData(T data) { - this.data = data; - } - - public static Result getSuccess(T data) { - return new Result(ResultCode.SUCCESS, "处理成功", data); - } - - public static Result getSuccess() { - return new Result(ResultCode.SUCCESS, "处理成功"); - } - - public static Result getBizFail(String msg) { - return new Result(ResultCode.BIZ_FAIL, msg); - } - - public Integer getCode() { - return code; - } - - - public String getMsg() { - return msg; - } - - public T getData() { - return data; - } - - public boolean isSuccess() { - return code == ResultCode.SUCCESS.getCode(); - } - - @Override - public String toString() { - return "[" + getCode() + "]" + getMsg(); - } -} diff --git a/demo/src/main/resources/templates/display.ftl b/demo/src/main/resources/templates/display.ftl index 587f4ba..2a98044 100644 --- a/demo/src/main/resources/templates/display.ftl +++ b/demo/src/main/resources/templates/display.ftl @@ -89,7 +89,7 @@
-

WxPusher 演示程序

+

WxPusher消息推送平台 - 演示程序

使用WxPusher免费推送消息到个人微信上,更快更便捷。
本程序已经开源,你可以点击这里参考源码。
@@ -159,6 +159,7 @@ var user = response.data.data.scan; if (!hasUser && user) { hasUser = true; + clearInterval(interval); var tips = document.getElementById("step-1"); tips.innerText = "1、已经成功获取到扫码用户,信息如下:" tips.setAttribute("style", "color:#42b983"); diff --git a/demo/src/test/java/com/zjiecode/wxpusher/demo/DemoTest.java b/demo/src/test/java/com/zjiecode/wxpusher/demo/DemoTest.java deleted file mode 100644 index 164e06f..0000000 --- a/demo/src/test/java/com/zjiecode/wxpusher/demo/DemoTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zjiecode.wxpusher.demo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * 说明:测试代码 - * 作者:zjiecode - * 时间:2019-10-05 - */ - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = JavaWebApplication.class) -public class DemoTest { - @Test - public void test() { - System.out.println("test"); - } - -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5d383c7..5b5aed8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip diff --git a/publish.sh b/publish.sh deleted file mode 100644 index 7d948a6..0000000 --- a/publish.sh +++ /dev/null @@ -1,2 +0,0 @@ - -./gradlew sdk:clean sdk:build sdk:bintrayUpload -PbintrayApiKey=$BINTRAY_API_KEY \ No newline at end of file diff --git a/sdk/build.gradle b/sdk/build.gradle deleted file mode 100644 index 0fe4de9..0000000 --- a/sdk/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -apply plugin: 'java' -apply plugin: 'maven-publish' -apply plugin: 'com.jfrog.bintray' - - -//包配置信息 -ext { - version = "2.1.8-local" - artifactId = "wxpusher-java-sdk" - projectUrl = "https://github.com/wxpusher/wxpusher-java-sdk.git" - description = "微信消息实时推送服务[WxPusher],可以通过API实时给个人微信推送消息,详情请看:http://wxpusher.zjiecode.com/docs" - user = 'zjiecode' -} - -repositories { - jcenter() - mavenCentral() -} -dependencies { - compile 'com.alibaba:fastjson:1.2.70' - testCompile 'junit:junit:4.12' -} - -publishing { - publications { - Production(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - groupId 'com.zjiecode' - artifactId this.ext.artifactId - version this.ext.version - pom.withXml { - //添加pom中缺失的信息,以发布到mavencenter - def projectNode = asNode() - projectNode.appendNode('name', this.ext.artifactId) - projectNode.appendNode('description', this.ext.description) - projectNode.appendNode('url', this.ext.projectUrl) - projectNode.appendNode('scm').appendNode("url", this.ext.projectUrl) - def license = projectNode.appendNode('licenses').appendNode("license") - license.appendNode('name', "MIT") - license.appendNode('url', "https://mit-license.org/") - def developer = projectNode.appendNode("developers").appendNode("developer") - developer.appendNode("id", "zjiecode") - developer.appendNode("email", "zjiecode@qq.com") - } - } - } -} - - -bintray { - user = this.ext.user - key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') - publications = ['Production'] - pkg { - repo = 'maven' - name = this.ext.artifactId - userOrg = this.ext.user - licenses = ['MIT'] - vcsUrl = this.ext.projectUrl - labels = ['wechat', 'push', 'notification', 'pushsdk'] - publicDownloadNumbers = true - version { - desc = this.ext.description - vcsTag = this.ext.version - released = new Date() - name = this.ext.version - } - } -} - -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/HttpUtils.java b/sdk/src/main/java/com/zjiecode/wxpusher/client/HttpUtils.java deleted file mode 100644 index 170c697..0000000 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/HttpUtils.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.zjiecode.wxpusher.client; - -import com.alibaba.fastjson.JSONObject; -import com.zjiecode.wxpusher.client.bean.Result; -import com.zjiecode.wxpusher.client.bean.ResultCode; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import java.util.Set; - -/** - * 说明:网络请求工具 - * 作者:zjiecode - * 时间:2019-09-05 - */ -public final class HttpUtils { - private static final String BASE_URL = "https://wxpusher.zjiecode.com"; - private static final String CHARSET_NAME ="UTF-8"; - - private HttpUtils() { - } - - /** - * 发送post请求 - * - * @param data 发送的数据 - * @param path 请求后台的path - * @return 发送的result结果 - */ - public static Result post(Object data, String path) { - try { - if (data == null) { - return new Result(ResultCode.UNKNOWN_ERROR, "数据为空"); - } - String dataStr = JSONObject.toJSONString(data); - - URL cUrl = new URL(buildUrl(path)); - HttpURLConnection urlConnection = (HttpURLConnection) cUrl.openConnection(); - urlConnection.setConnectTimeout(60000); - urlConnection.setReadTimeout(60000); - urlConnection.setUseCaches(false); - urlConnection.setRequestMethod("POST"); - //设置请求属性 - urlConnection.setRequestProperty("Content-Type", "application/json"); - urlConnection.setRequestProperty("Charset", CHARSET_NAME); - urlConnection.setDoOutput(true); - urlConnection.connect(); - OutputStream outputStream = urlConnection.getOutputStream(); - outputStream.write(dataStr.getBytes(Charset.forName(CHARSET_NAME))); - outputStream.flush(); - return dealConnect(urlConnection); - } catch (MalformedURLException e) { - return new Result(ResultCode.NETWORK_ERROR, e.getMessage()); - } catch (IOException e) { - return new Result(ResultCode.NETWORK_ERROR, e.toString()); - } catch (Throwable e) { - return new Result(ResultCode.UNKNOWN_ERROR, e.toString()); - } - } - - public static Result get(String path) { - return get(null, path); - } - - /** - * 发送get请求 - */ - public static Result get(Map data, String path) { - try { - String url = buildUrl(path); - String query = parseMap2Query(data); - if (!query.isEmpty()) { - url = url + "?" + query; - } - URL cUrl = new URL(url); - HttpURLConnection urlConnection = (HttpURLConnection) cUrl.openConnection(); - urlConnection.setConnectTimeout(60000); - urlConnection.setReadTimeout(60000); - urlConnection.setUseCaches(false); - urlConnection.setRequestMethod("GET"); - //设置请求属性 - urlConnection.setRequestProperty("Charset", CHARSET_NAME); - urlConnection.setDoOutput(true); - urlConnection.connect(); - return dealConnect(urlConnection); - } catch (MalformedURLException e) { - return new Result(ResultCode.NETWORK_ERROR, e.getMessage()); - } catch (IOException e) { - return new Result(ResultCode.NETWORK_ERROR, e.toString()); - } catch (Throwable e) { - return new Result(ResultCode.UNKNOWN_ERROR, e.toString()); - } - } - - /** - * 把map转成query查询字符串 - */ - private static String parseMap2Query(Map data) { - if (data == null || data.size() <= 0) { - return ""; - } - Set> entries = data.entrySet(); - StringBuilder stringBuilder = new StringBuilder(); - for (Map.Entry entry : entries) { - if (stringBuilder.length() > 0) { - stringBuilder.append("&"); - } - stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()); - } - return stringBuilder.toString(); - } - - /** - * - */ - private static String buildUrl(String path) { - String url = BASE_URL; - if (path != null && path.length() > 0) { - if (path.startsWith("/")) { - url = BASE_URL + path; - } else { - url = BASE_URL + "/" + path; - } - } - return url; - } - - /** - * 处理连接以后的状态信息 - * - * @param urlConnection 打开的连接 - * @return 返回发送结果 - */ - private static Result dealConnect(HttpURLConnection urlConnection) { - try { - int responseCode = urlConnection.getResponseCode(); - if (responseCode != 200) { - return new Result(urlConnection.getResponseCode(), "http请求错误:" + responseCode); - } - InputStream inputStream = urlConnection.getInputStream(); - String res = inputStream2String(inputStream); - if (res == null || res.isEmpty()) { - return new Result(ResultCode.INTERNAL_SERVER_ERROR, "服务器返回异常"); - } - Result result = JSONObject.parseObject(res, Result.class); - if (result == null) { - return new Result(ResultCode.DATA_ERROR, "服务器返回数据解析异常"); - } - return result; - } catch (MalformedURLException e) { - return new Result(ResultCode.NETWORK_ERROR, e.getMessage()); - } catch (IOException e) { - return new Result(ResultCode.NETWORK_ERROR, e.getMessage()); - } catch (Throwable e) { - return new Result(ResultCode.UNKNOWN_ERROR, e.getMessage()); - } - } - - /** - * 从输入流中读取内容到字符串 - * - * @param inputStream 输入路 - * @return 返回字符串 - */ - private static String inputStream2String(InputStream inputStream) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - int len = 0; - byte[] bytes = new byte[4096]; - try { - while ((len = inputStream.read(bytes)) != -1) { - outputStream.write(bytes, 0, len); - } - return new String(outputStream.toByteArray(),CHARSET_NAME); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/sdk/src/main/java/com/zjiecode/wxpusher/client/WxPusher.java b/sdk/src/main/java/com/zjiecode/wxpusher/client/WxPusher.java deleted file mode 100644 index 2d4cc6a..0000000 --- a/sdk/src/main/java/com/zjiecode/wxpusher/client/WxPusher.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.zjiecode.wxpusher.client; - -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.TypeReference; -import com.zjiecode.wxpusher.client.bean.*; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 说明:WxPusher的客户端 - * 作者:zjiecode - * 时间:2019-05-03 - */ -public final class WxPusher { - private WxPusher() { - } - - /** - * 发送消息 - */ - public static Result> send(Message message) { - Result result = verify(message); - if (result != null) { - return result; - } - Result sendResult = HttpUtils.post(message, "/api/send/message"); - if (sendResult.isSuccess()) { - //转换,方便调用 - Object data = sendResult.getData(); - String s = JSONObject.toJSONString(data); - List messageResults = JSONObject.parseObject(s, new TypeReference>() { - }); - sendResult.setData(messageResults); - } - return sendResult; - } - - /** - * 查询消息发送状态 - */ - public static Result queryMessageStatus(Long messageId) { - if (messageId == null || messageId <= 0) { - return new Result(ResultCode.BIZ_FAIL, "messageId为空"); - } - return HttpUtils.get(String.format("/api/send/query/%s", messageId)); - } - - /** - * 创建带参数的app临时二维码 - */ - public static Result createAppTempQrcode(CreateQrcodeReq createQrcodeReq) { - Result result = HttpUtils.post(createQrcodeReq, "/api/fun/create/qrcode"); - if (result.getData() != null) { - String jsonString = JSONObject.toJSONString(result.getData()); - CreateQrcodeResp createQrcodeResp = JSONObject.parseObject(jsonString, CreateQrcodeResp.class); - result.setData(createQrcodeResp); - } - return result; - } - - /** - * 查询关注你App的微信用户 - * - * @param appToken 应用token - * @param page 页码 - * @param pageSize 分页大小 - * @return 查询的数据 - * @deprecated 请使用 {@link #queryWxUserV2(String, Integer, Integer, String, boolean, int)} 代替 - */ - public static Result> queryWxUser(String appToken, Integer page, Integer pageSize) { - return queryWxUser(appToken, page, pageSize, null); - } - - /** - * 查询关注你App的微信用户 - * - * @param appToken 应用token - * @param uid 根据UID过滤用户 - * @return 查询的数据 - * @deprecated 请使用 {@link #queryWxUserV2(String, Integer, Integer, String, boolean, int)} 代替 - */ - public static Result> queryWxUser(String appToken, String uid) { - return queryWxUser(appToken, 1, 1, uid); - } - - /** - * 查询关注你App的微信用户 - * - * @param appToken 应用token - * @param page 页码 - * @param pageSize 分页大小 - * @param uid 根据UID过滤用户 - * @return 查询的数据 - * @deprecated 请使用 {@link #queryWxUserV2(String, Integer, Integer, String, boolean, int)} 代替 - */ - public static Result> queryWxUser(String appToken, Integer page, Integer pageSize, String uid) { - if (appToken == null || appToken.isEmpty()) { - return new Result(ResultCode.BIZ_FAIL, "appToken不能为空"); - } - if (page == null || page <= 0) { - return new Result(ResultCode.BIZ_FAIL, "page不合法"); - } - if (pageSize == null || pageSize <= 0 || pageSize > 100) { - return new Result(ResultCode.BIZ_FAIL, "pageSize不合法"); - } - Map params = new HashMap<>(); - params.put("appToken", appToken); - params.put("page", page); - params.put("pageSize", pageSize); - if (uid != null && !uid.isEmpty()) { - params.put("uid", uid); - } - Result result = HttpUtils.get(params, "/api/fun/wxuser"); - if (result.getData() != null) { - String jsonString = JSONObject.toJSONString(result.getData()); - Page pageData = JSONObject.parseObject(jsonString, new TypeReference>() { - }); - result.setData(pageData); - } - return result; - } - - /** - * 查询用户 - * - * @param appToken 应用密钥标志 - * @param page 请求数据的页码 - * @param pageSize 分页大小,不能超过100 - * @param uid 用户的uid,可选,如果不传就是查询所有用户,传uid就是查某个用户的信息。 - * @param isBlock 查询拉黑用户,可选,不传查询所有用户,true查询拉黑用户,false查询没有拉黑的用户 - * @param type 关注的类型,可选,不传查询所有用户,0是应用,1是主题 - */ - public static Result> queryWxUserV2(String appToken, Integer page, Integer pageSize, - String uid, boolean isBlock, int type) { - if (appToken == null || appToken.isEmpty()) { - return new Result(ResultCode.BIZ_FAIL, "appToken不能为空"); - } - if (page == null || page <= 0) { - return new Result(ResultCode.BIZ_FAIL, "page不合法"); - } - if (pageSize == null || pageSize <= 0 || pageSize > 100) { - return new Result(ResultCode.BIZ_FAIL, "pageSize不合法"); - } - Map params = new HashMap<>(); - params.put("appToken", appToken); - params.put("page", page); - params.put("pageSize", pageSize); - params.put("isBlock", isBlock); - params.put("type", type); - if (uid != null && !uid.isEmpty()) { - params.put("uid", uid); - } - Result result = HttpUtils.get(params, "/api/fun/wxuser/v2"); - if (result.getData() != null) { - String jsonString = JSONObject.toJSONString(result.getData()); - Page pageData = JSONObject.parseObject(jsonString, new TypeReference>() { - }); - result.setData(pageData); - } - return result; - } - - /** - * 验证消息合法性,客户端验证比较宽松,主要在服务端进行校验 - */ - private static Result verify(Message message) { - if (message == null) { - return new Result(ResultCode.BIZ_FAIL, "消息不能为空"); - } - if (message.getAppToken() == null || message.getAppToken().length() <= 0) { - return new Result(ResultCode.BIZ_FAIL, "appToken不能为空"); - } - if (message.getContent() == null || message.getContent().length() <= 0) { - return new Result(ResultCode.BIZ_FAIL, "content内容不能为空"); - } - return null; - } - -} diff --git a/sdk/src/test/java/com/zjiecode/wxpusher/client/ClientTest.java b/sdk/src/test/java/com/zjiecode/wxpusher/client/ClientTest.java deleted file mode 100644 index e2aee58..0000000 --- a/sdk/src/test/java/com/zjiecode/wxpusher/client/ClientTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.zjiecode.wxpusher.client; - -import com.alibaba.fastjson.JSONObject; -import com.zjiecode.wxpusher.client.bean.*; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 说明:接口测试 - * 作者:zjiecode - * 时间:2019-05-03 - */ -public class ClientTest { - - - public static void main(String[] args) { - AtomicInteger count = new AtomicInteger(); - AtomicLong time = new AtomicLong(System.currentTimeMillis()); - for (int i = 0; i < 200; i++) { - new Thread(() -> { - while (true) { - Message message = new Message(); - message.setContentType(Message.CONTENT_TYPE_HTML); - message.setContent("接口测试接口测试接口测试"); - message.setSummary(Thread.currentThread() + "-测试消息摘要:" + System.currentTimeMillis() + "
"); - message.setAppToken("AT_a2zb61nhS33h54NOLvSYxgrMO4KcJ2vG"); - message.setUid("UID_LffjrW6nh4vpNWGC85QMzX82OURf"); - Result> result = WxPusher.send(message); - count.incrementAndGet(); - if (!result.isSuccess()) { - System.out.println(JSONObject.toJSONString(result)); - } - if (count.get() % 100 == 0) { - long during = System.currentTimeMillis() - time.get(); - time.set(System.currentTimeMillis()); - System.out.println(count.get() + "-" + (100F / during * 1000F)); - } - } - }).start(); - } - - } - - @Test - public void testQuery() { - Result> users = WxPusher.queryWxUser("AT_xxxxx", "UID_xxxxx"); - System.out.println(JSONObject.toJSONString(users)); - } -} diff --git a/settings.gradle b/settings.gradle index 001c67e..718ef65 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'wxpusher-sdk-java' include ":demo" -include ":sdk" +include ":client-sdk"