【大的调整】重新定义(手贱)了「被动消息」「客服消息」「群发消息」的传输实体,另外新增了企业号「多媒体管理接口」「菜单管理接口」「发送消息接口」三个接口

This commit is contained in:
jy.hu
2014-11-23 16:35:59 +08:00
parent 5b213cd87f
commit 2ece136d46
126 changed files with 2419 additions and 1923 deletions
+20
View File
@@ -13,6 +13,18 @@ weixin4j-qy
+ UserApi `成员管理API`
+ TagApi `标签管理API`
+ MediaApi `多媒体管理API`
+ MenuApi `菜单管理API`
+ NotifyApi `消息发送API`
* **weixin4j-qy-server**
+ `netty服务器` & `消息分发`
+ 回调链接`AES`加密、解密
更新LOG
-------
@@ -25,3 +37,11 @@ weixin4j-qy
+ **weixin4j-qy-api**: 新增用户管理接口
+ **weixin4j-qy-api**: 新增标签管理接口
* 2014-11-23
+ **weixin4j-qy-api**: 新增`多媒体管理`接口
+ **weixin4j-qy-api**: 新增`发送消息`接口
+ **weixin4j-qy-api**: 新增`菜单管理`接口
+1 -1
View File
@@ -29,7 +29,7 @@ weixin.properties说明
> account={"id":"corpid","secret":"corpsecret",
> "token":"开放者的token 非必须",
> "encodingAesKey":"AES加密密钥"}
> token_path=/tmp/weixin/token <br/>
> token_path=/tmp/weixin/token </br>
2.实例化一个`WeixinProxy`对象,调用API
+3 -1
View File
@@ -13,11 +13,13 @@
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-qy/weixin4j-qy-api</url>
<description>微信企业号API</description>
<build>
<finalName>weixin4j-qy-api</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>${project.name}</finalName>
</configuration>
</plugin>
</plugins>
</build>
@@ -0,0 +1,156 @@
package com.foxinmy.weixin4j.qy.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.mime.content.ByteArrayBody;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.PartParameter;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.util.IOUtil;
/**
* 媒体相关API
*
* @className MediaApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">管理多媒体文件</a>
* @see com.foxinmy.weixin4j.type.MediaType
*/
public class MediaApi extends BaseApi {
private final TokenHolder tokenHolder;
public MediaApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 上传媒体文件
*
* @param file
* 媒体对象
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
public String uploadMedia(File file) throws WeixinException, IOException {
String mediaTypeKey = IOUtil.getExtension(file.getName());
if (StringUtils.isBlank(mediaTypeKey)) {
mediaTypeKey = FileUtil.getFileType(file);
}
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
return uploadMedia(file, mediaType);
}
/**
* 上传媒体文件
*
* @param file
* 文件对象
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#uploadMedia(File, byte[],String)}
*/
public String uploadMedia(File file, MediaType mediaType)
throws WeixinException, IOException {
byte[] datas = IOUtil.toByteArray(new FileInputStream(file));
return uploadMedia(file.getName(), datas, mediaType.name());
}
/**
* 上传媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传媒体文件说明</a>
* @throws WeixinException
*/
public String uploadMedia(String fileName, byte[] bytes, String mediaType)
throws WeixinException {
Token token = tokenHolder.getToken();
String file_upload_uri = getRequestUri("file_upload_uri");
Response response = request.post(String.format(file_upload_uri,
token.getAccessToken(), mediaType), new PartParameter("media",
new ByteArrayBody(bytes, fileName)));
return response.getAsJson().getString("media_id");
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param extension
* 媒体后缀名
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @throws IOException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, String extension)
throws WeixinException, IOException {
String media_path = ConfigUtil.getValue("media_path");
File file = new File(media_path + File.separator + mediaId + "."
+ extension);
if (file.exists()) {
return file;
}
byte[] datas = downloadMedia(mediaId);
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
out.write(datas);
out.close();
return file;
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
*
* @param mediaId
* 媒体ID
* @return 二进制数据包
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @throws WeixinException
*/
public byte[] downloadMedia(String mediaId) throws WeixinException {
Token token = tokenHolder.getToken();
String file_download_uri = getRequestUri("file_download_uri");
Response response = request.get(String.format(file_download_uri,
token.getAccessToken(), mediaId));
return response.getBody();
}
}
@@ -0,0 +1,89 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 菜单相关API
*
* @className MenuApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.model.Button
*/
public class MenuApi extends BaseApi {
private final TokenHolder tokenHolder;
public MenuApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param btnList
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95">创建自定义菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public JsonResult createMenu(List<Button> btnList, int agentid)
throws WeixinException {
String menu_create_uri = getRequestUri("menu_create_uri");
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.put("button", btnList);
Response response = request
.post(String.format(menu_create_uri, token.getAccessToken(),
agentid), obj.toJSONString());
return response.getAsJsonResult();
}
/**
* 查询菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式。)
*
* @return 菜单集合
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E8%8F%9C%E5%8D%95%E5%88%97%E8%A1%A8">查询菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public List<Button> getMenu(int agentid) throws WeixinException {
String menu_get_uri = getRequestUri("menu_get_uri");
Token token = tokenHolder.getToken();
Response response = request.get(String.format(menu_get_uri,
token.getAccessToken(), agentid));
String text = response.getAsJson().getJSONObject("menu")
.getString("button");
return JSON.parseArray(text, Button.class);
}
/**
* 删除菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%A0%E9%99%A4%E8%8F%9C%E5%8D%95">删除菜单</a>
* @return 处理结果
*/
public JsonResult deleteMenu(int agentid) throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.get(String.format(menu_delete_uri,
token.getAccessToken(), agentid));
return response.getAsJsonResult();
}
}
@@ -0,0 +1,69 @@
package com.foxinmy.weixin4j.qy.api;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 发送消息API
*
* @className NotifyApi
* @author jy.hu
* @date 2014年11月21日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">发送接口说明</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">发送格式说明</a>
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.File
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.msg.model.MpNews
*/
public class NotifyApi extends BaseApi {
private final TokenHolder tokenHolder;
public NotifyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 发送消息(需要管理员对应用有使用权限,对收件人touser、toparty、totag有查看权限,否则本次调用失败)
*
* @param notify
* 客服消息对象
* @return
* 如果对应用或收件人、部门、标签任何一个无权限,则本次发送失败;如果收件人、部门或标签不存在,发送仍然执行,但返回无效的部分</br>
* { "errcode": 0, "errmsg": "ok", "invaliduser": "UserID1",
* "invalidparty":"PartyID1", "invalidtag":"TagID1" }
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">发送接口说明</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">发送格式说明</a>
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.File
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see com.foxinmy.weixin4j.qy.message.NotifyMessage
*/
public JSONObject sendNotify(NotifyMessage notify) throws WeixinException {
String message_send_uri = getRequestUri("message_send_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(message_send_uri, token.getAccessToken()),
notify.toJson());
return response.getAsJson();
}
}
@@ -36,4 +36,16 @@ tag_get_user_uri={api_base_url}/tag/get?access_token=%s&tagid=%d
# \u6dfb\u52a0\u6807\u7b7e\u6210\u5458
tag_add_user_uri={api_base_url}/tag/addtagusers?access_token=%s
# \u5220\u9664\u6807\u7b7e\u6210\u5458
tag_delete_user_uri={api_base_url}/tag/deltagusers?access_token=%s
tag_delete_user_uri={api_base_url}/tag/deltagusers?access_token=%s
# \u4e0a\u4f20\u5a92\u4f53\u6587\u4ef6
file_upload_uri={api_base_url}/media/upload?access_token=%s&type=%s
# \u4e0b\u8f7d\u5a92\u4f53\u6587\u4ef6
file_download_uri={api_base_url}/media/get?access_token=%s&media_id=%s
# \u81ea\u5b9a\u4e49\u83dc\u5355
menu_create_uri={api_base_url}/menu/create?access_token=%s&agentid=%d
# \u5220\u9664\u83dc\u5355
menu_delete_uri={api_base_url}/menu/delete?access_token=%s&agentid=%d
# \u67e5\u8be2\u83dc\u5355
menu_get_uri={api_base_url}/menu/get?access_token=%s&agentid=%d
# \u53d1\u9001\u6d88\u606f
message_send_uri={api_base_url}/message/send?access_token=%s
@@ -0,0 +1,154 @@
package com.foxinmy.weixin4j.qy.message;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.msg.model.Base;
/**
* 发送消息对象
*
* @className NotifyMessage
* @author jy
* @date 2014年11月22日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.File
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">消息说明</a>
*/
public class NotifyMessage implements Serializable {
private static final long serialVersionUID = 1219589414293000383L;
private static final String SEPARATOR = "|";
private String touser;// UserID列表(消息接收者,多个接收者用‘|’分隔)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
private String toparty;// PartyID列表,多个接受者用‘|’分隔。当touser为@all时忽略本参数
private String totag;// TagID列表,多个接受者用‘|’分隔。当touser为@all时忽略本参数
private int agentid;// 企业应用的id,整型。可在应用的设置页面查看
private int safe;// 表示是否是保密消息,0表示否,1表示是,默认0
@JSONField(name = "%s")
private Base box;// 消息项
public NotifyMessage(Base box, int agentid) {
this(null, null, null, box, agentid, false);
this.touser = "@all";
}
public NotifyMessage(List<String> tousers, List<String> topartys,
List<String> totags, Base box, int agentid, boolean isSafe) {
if (tousers != null && !tousers.isEmpty()) {
this.touser = StringUtils.join(tousers, SEPARATOR);
}
if (topartys != null && !topartys.isEmpty()) {
this.toparty = StringUtils.join(topartys, SEPARATOR);
}
if (totags != null && !totags.isEmpty()) {
this.totag = StringUtils.join(totags, SEPARATOR);
}
this.agentid = agentid;
this.safe = isSafe ? 1 : 0;
this.box = box;
}
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public void setTouser(List<String> tousers) {
if (tousers != null && !tousers.isEmpty()) {
this.touser = StringUtils.join(tousers, SEPARATOR);
}
}
public String getToparty() {
return toparty;
}
public void setToparty(String toparty) {
this.toparty = toparty;
}
public void setToparty(List<String> topartys) {
if (topartys != null && !topartys.isEmpty()) {
this.toparty = StringUtils.join(topartys, SEPARATOR);
}
}
public String getTotag() {
return totag;
}
public void setTotag(String totag) {
this.totag = totag;
}
public void setTotag(List<String> totags) {
if (totags != null && !totags.isEmpty()) {
this.totag = StringUtils.join(totags, SEPARATOR);
}
}
public int getAgentid() {
return agentid;
}
public void setAgentid(int agentid) {
this.agentid = agentid;
}
public int getSafe() {
return safe;
}
public void setSafe(int safe) {
this.safe = safe;
}
public void setSafe(boolean isSafe) {
this.safe = isSafe ? 1 : 0;
}
public Base getBox() {
return box;
}
public void setBox(Base box) {
this.box = box;
}
/**
* 消息json化
*
* @return
* {"image":{"media_id":"123"},"agentid":0,"msgtype":"image","safe":0
* ,"touser":"@all"}
*/
public String toJson() {
String msgtype = box.getMediaType().name();
JSONObject obj = (JSONObject) JSON.toJSON(this);
obj.put("msgtype", msgtype);
return String.format(obj.toJSONString(), msgtype);
}
@Override
public String toString() {
return "NotifyMessage [touser=" + touser + ", toparty=" + toparty
+ ", totag=" + totag + ", agentid=" + agentid + ", safe="
+ safe + ", box=" + box + "]";
}
}
@@ -7,7 +7,5 @@ account={"id":"wxd9d9fa581a07cefd","secret":"7tr6FXh2NORvqq1la9CVwxV0xZWGsRSgI6t
# \u4f7f\u7528FileTokenHolder\u65f6token\u7684\u5b58\u653e\u8def\u5f84
token_path=/tmp/weixin/token
# \u4e8c\u7ef4\u7801\u4fdd\u5b58\u8def\u5f84
qr_path=/tmp/weixin/qr
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
media_path=/tmp/weixin/media
@@ -0,0 +1,64 @@
package com.foxinmy.weixin4j.qy.test;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
public class AesMsgTest extends MessagePush {
StringBuilder xmlSb = new StringBuilder();
@Test
public void testValidate() throws WeixinException, IOException {
String para = "?msg_signature=33f680b72cfd87a6f8f4d751575bcc31266853a9&timestamp=1416488666&nonce=1358224345&echostr=WZu9tT6KDuyhgOZ1aT%2FIoPNaUkA%2FsfVR%2F%2BDua5q84Kvhs6Fc1%2F6f2510%2BUuMByessdQWsoeak0lSIpaYOIlHrw%3D%3D";
xmlSb.delete(0, xmlSb.length());
String response = get(para);
Assert.assertEquals("2143641595566077626", response);
}
@Test
public void testType1() throws WeixinException, IOException {
String para = "?signature=6dd806a20a314723e78bc58742a1b98a7adfd151&timestamp=1415979366&nonce=1865915590";
xmlSb.delete(0, xmlSb.length());
xmlSb.append("<xml>");
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
xmlSb.append("<CreateTime>1415979365</CreateTime>");
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
xmlSb.append("</xml>");
String response = push(para, xmlSb.toString());
Assert.assertNotNull(response);
}
@Test
public void testType2() throws WeixinException, IOException {
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5&timestamp=1415980001&nonce=1803216865&encrypt_type=raw&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
xmlSb.delete(0, xmlSb.length());
xmlSb.append("<xml>");
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
xmlSb.append("<CreateTime>1415980001</CreateTime>");
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
xmlSb.append("</xml>");
String response = push(para, xmlSb.toString());
Assert.assertNotNull(response);
}
@Test
public void testType3() throws WeixinException, IOException {
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5&timestamp=1415980001&nonce=1803216865&encrypt_type=aes&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
xmlSb.delete(0, xmlSb.length());
xmlSb.append("<xml>");
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
xmlSb.append("<Encrypt><![CDATA[R6VQIWDR14XgSRLm25zc7V/WJYqK15gsUiMh0u/5GTMZME6jGtHkyfVN079ZPL065b+ZDq3TnoFKKtjtZlzcodY6Fm8+EujvtbTdVMMFSwdo8AwqVViAn09+DDfqPaNvbHUSiYsL3qlxArs1MH6APRUHFo7MU/piY1x2stJc8+kv28xtF+K8Aou0RuPO7PeQ18Zu/GkLnYNiI1E7UG31UYfOgVKcRjeE0PXa18iF5LBS8G/ce/l+/pH/DJWUBw5uXaqSOlo21tctlgLXu3bYUUkIu8tT49QwhHvRZILtO9icoyCNuTA7iTcHIdlAe1bD1S0ncmopIQCGmoU2/AXC2CCi6trONf3EPNKKKfDeQYHadnVZOg6kTX2cnYmHZLviYeLzjCKFSqSNkimoSKQ/Dcutpsq1D82NCwiExUZW4oo=]]></Encrypt>");
xmlSb.append("</xml>");
String response = push(para, xmlSb.toString());
Assert.assertNotNull(response);
}
}
@@ -0,0 +1,50 @@
package com.foxinmy.weixin4j.qy.test;
import java.io.File;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.qy.api.MediaApi;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 媒体上传下载测试
*
* @className MediaTest
* @author jy.hu
* @date 2014年4月10日
* @since JDK 1.7
* @see
*/
public class MediaTest extends TokenTest {
private MediaApi mediaApi;
@Before
public void init() {
mediaApi = new MediaApi(tokenHolder);
}
@Test
public void upload() throws IOException, WeixinException {
File file = new File("/tmp/test.docx");
String mediaId = mediaApi.uploadMedia(file, MediaType.file);
// 1-1gpykXsR8bhNvO13-ZvskptCBxQF1UE535jFdCF63N2inGRAqEb-psF6eppjIIl
// 1CF6sBgWWFGY9s4JCEet5ASszsTuyHpeN1f2LWXADveqBlKoxSgb3cO401NEM7dNY
Assert.assertNotNull(mediaId);
System.out.println(mediaId);
}
@Test
public void download() throws WeixinException, IOException {
File file = mediaApi
.downloadMedia(
"1CF6sBgWWFGY9s4JCEet5ASszsTuyHpeN1f2LWXADveqBlKoxSgb3cO401NEM7dNY",
"docx");
Assert.assertTrue(file.exists());
}
}
@@ -0,0 +1,62 @@
package com.foxinmy.weixin4j.qy.test;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.qy.api.MenuApi;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 自定义菜单测试
*
* @className MenuTest
* @author jy.hu
* @date 2014年4月10日
* @since JDK 1.7
*/
public class MenuTest extends TokenTest {
private MenuApi menuApi;
private List<Button> btnList;
@Before
public void init() {
menuApi = new MenuApi(tokenHolder);
}
@Test
public void create() throws WeixinException {
btnList = new ArrayList<Button>();
Button b = new Button("click", "name", ButtonType.click);
btnList.add(b);
b = new Button("qq", "http://www.qq.com", ButtonType.view);
btnList.add(b);
JsonResult result = menuApi.createMenu(btnList, 1);
Assert.assertEquals(0, result.getCode());
}
@Test
public void get() throws WeixinException {
btnList = menuApi.getMenu(1);
for (Button btn : btnList) {
System.out.println(btn);
}
Assert.assertEquals(2, btnList.size());
}
@Test
public void delete() throws WeixinException {
JsonResult result = menuApi.deleteMenu(1);
Assert.assertEquals(0, result.getCode());
}
}
@@ -0,0 +1,68 @@
package com.foxinmy.weixin4j.qy.test;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import com.foxinmy.weixin4j.exception.WeixinException;
public class MessagePush {
private final String server = "http://localhost:8090";
private final HttpClient httpClient;
private final HttpPost httpPost;
private final HttpGet httpGet;
public MessagePush() {
httpClient = new DefaultHttpClient();
httpPost = new HttpPost();
httpPost.setURI(URI.create(server));
httpGet = new HttpGet();
httpGet.setURI(URI.create(server));
}
public String get(String para) throws WeixinException, IOException {
httpGet.setURI(URI.create(server + para));
HttpResponse httpResponse = httpClient.execute(httpGet);
return entity(httpResponse);
}
public String push(String xml) throws WeixinException, IOException {
return push("", xml);
}
public String push(String para, String xml) throws WeixinException,
IOException {
httpPost.setURI(URI.create(server + para));
httpPost.setEntity(new StringEntity(xml, StandardCharsets.UTF_8));
HttpResponse httpResponse = httpClient.execute(httpPost);
return entity(httpResponse);
}
private String entity(HttpResponse httpResponse) throws WeixinException,
IOException {
StatusLine statusLine = httpResponse.getStatusLine();
int status = statusLine.getStatusCode();
if (status != HttpStatus.SC_OK) {
throw new WeixinException(Integer.toString(status), "request fail");
}
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
throw new WeixinException(Integer.toString(status), "uri moved");
}
return EntityUtils.toString(httpResponse.getEntity(),
StandardCharsets.UTF_8);
}
}
@@ -0,0 +1,93 @@
package com.foxinmy.weixin4j.qy.test;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.msg.model.File;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.msg.model.MpNews;
import com.foxinmy.weixin4j.msg.model.News;
import com.foxinmy.weixin4j.msg.model.Text;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.msg.model.Voice;
import com.foxinmy.weixin4j.qy.api.NotifyApi;
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
/**
* 客服消息测试
*
* @className MessageNotifyTest
* @author jy.hu
* @date 2014年4月10日
* @since JDK 1.7
* @see
*/
public class NotifyMsgTest extends TokenTest {
private NotifyApi notifyApi;
@Before
public void init() {
notifyApi = new NotifyApi(tokenHolder);
}
@Test
public void text() {
NotifyMessage notify = new NotifyMessage(new Text("content"), 0);
System.out.println(notify.toJson());
}
@Test
public void image() {
NotifyMessage notify = new NotifyMessage(new Image("123"), 0);
System.out.println(notify.toJson());
}
@Test
public void voice() {
NotifyMessage notify = new NotifyMessage(new Voice("123"), 0);
System.out.println(notify.toJson());
}
@Test
public void video() {
NotifyMessage notify = new NotifyMessage(new Video("123"), 0);
System.out.println(notify.toJson());
}
@Test
public void file() {
File file = new File("file");
NotifyMessage notify = new NotifyMessage(file, 0);
System.out.println(notify.toJson());
}
@Test
public void news() {
News news = new News();
NotifyMessage notify = new NotifyMessage(news, 0);
news.pushArticle("title1", "desc1", "picUrl1", "url1");
news.pushArticle("title2", "desc2", "picUrl2", "url2");
System.out.println(notify.toJson());
}
@Test
public void mpnews() {
MpNews news = new MpNews();
NotifyMessage notify = new NotifyMessage(news, 0);
news.pushArticle("thumbMediaId1", "title1", "content1");
news.pushArticle("thumbMediaId2", "title1", "content2");
System.out.println(notify.toJson());
}
@Test
public void send1() throws WeixinException {
Text text = new Text("this is a text");
JSONObject result = notifyApi.sendNotify(new NotifyMessage(text, 0));
Assert.assertEquals(0, result.getIntValue("errcode"));
}
}
+16 -2
View File
@@ -11,14 +11,28 @@
<artifactId>weixin4j-qy-server</artifactId>
<name>weixin4j-qy-server</name>
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-qy/weixin4j-qy-server</url>
<description>微信企业号工具包</description>
<description>微信企业号netty服务</description>
<build>
<finalName>weixin-qy-server</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>weixin-qy-server</finalName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>com.foxinmy.weixin4j</groupId>
<artifactId>weixin4j-qy-api</artifactId>
<version>${weixin4j.qy.version}</version>
</dependency>
</dependencies>
</project>
@@ -6,10 +6,10 @@ JAVA_HOME="/usr/local/java/"
RUNNING_USER=root
#Run home
APP_HOME="/usr/local/weixin/weixin-mp-server"
APP_HOME="/usr/local/weixin/weixin-qy-server"
#main class
APP_MAINCLASS=com.foxinmy.weixin4j.mp.startup.WeixinServerBootstrap
APP_MAINCLASS=com.foxinmy.weixin4j.qy.startup.WeixinServerBootstrap
#classpath
CLASSPATH=$APP_HOME/classes