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

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
+7 -1
View File
@@ -82,4 +82,10 @@ weixin4j-mp
* 2014-11-17
+ **weixin4j-mp-api**: 新增`冲正``被扫支付`接口
+ **weixin4j-mp-api**: 新增`冲正``被扫支付`接口
* 2014-11-23
+ **weixin4j-mp-api**: 重新定义(手贱)了「被动消息」「客服消息」「群发消息」的传输实体
+ **weixin4j-mp-server**: `WeixinServerBootstrap`重命名为`WeixinMpServerBootstrap`
-3
View File
@@ -17,9 +17,6 @@
<module>weixin4j-mp-api</module>
<module>weixin4j-mp-server</module>
</modules>
<build>
<finalName>weixin4j-mp</finalName>
</build>
<dependencies>
<dependency>
<groupId>com.foxinmy.weixin4j</groupId>
+7 -7
View File
@@ -47,17 +47,17 @@ weixin.properties说明
示例(properties中换行用右斜杆\\)
> account={"id":"appId","secret":"appSecret",
> "token":"开放者的token 必须","openId":"公众号的openid 非必须",
> "token":"开放者的token 必须","openId":"公众号的openid 非必须",
> "encodingAesKey":"公众号设置了加密方式且为「安全模式」需要填入",
> "mchId":"V3.x版本下的微信商户号",
> "partnerId":"财付通的商户号","partnerKey":"财付通商户权限密钥Key",
> "version":"针对微信支付的版本号(2,3),如果不填则按照mchId非空与否来判断",
> "paySignKey":"微信支付中调用API的密钥"} <br/>
> token_path=/tmp/weixin/token <br/>
> qr_path=/tmp/weixin/qr <br/>
> media_path=/tmp/weixin/media <br/>
> bill_path=/tmp/weixin/bill <br/>
> ca_file=/tmp/weixin/xxxxx.p12 | xxxx.pfx <br/>
> "paySignKey":"微信支付中调用API的密钥"} </br>
> token_path=/tmp/weixin/token </br>
> qr_path=/tmp/weixin/qr </br>
> media_path=/tmp/weixin/media </br>
> bill_path=/tmp/weixin/bill </br>
> ca_file=/tmp/weixin/xxxxx.p12 | xxxx.pfx </br>
2.实例化一个`WeixinProxy`对象,调用API,需要强调的是如果只传入appid,appsecret两个参数将无法调用支付相关接口
+3 -1
View File
@@ -13,11 +13,13 @@
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-mp-api</url>
<description>微信公众号API</description>
<build>
<finalName>weixin4j-mp-api</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>${project.name}</finalName>
</configuration>
</plugin>
</plugins>
</build>
@@ -6,10 +6,10 @@ import java.io.InputStream;
import java.util.Date;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.XmlResult;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.api.CustomApi;
import com.foxinmy.weixin4j.mp.api.GroupApi;
@@ -22,27 +22,26 @@ import com.foxinmy.weixin4j.mp.api.PayApi;
import com.foxinmy.weixin4j.mp.api.QrApi;
import com.foxinmy.weixin4j.mp.api.TmplApi;
import com.foxinmy.weixin4j.mp.api.UserApi;
import com.foxinmy.weixin4j.mp.model.Button;
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.mp.model.CustomRecord;
import com.foxinmy.weixin4j.mp.model.Following;
import com.foxinmy.weixin4j.mp.model.Group;
import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.MpArticle;
import com.foxinmy.weixin4j.mp.model.OauthToken;
import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.model.SemQuery;
import com.foxinmy.weixin4j.mp.model.SemResult;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.mp.msg.model.Article;
import com.foxinmy.weixin4j.mp.msg.model.BaseMsg;
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.mp.payment.ApiResult;
import com.foxinmy.weixin4j.mp.payment.Refund;
import com.foxinmy.weixin4j.mp.payment.RefundResult;
import com.foxinmy.weixin4j.mp.payment.v2.Order;
import com.foxinmy.weixin4j.mp.response.TemplateMessage;
import com.foxinmy.weixin4j.mp.type.BillType;
import com.foxinmy.weixin4j.mp.type.IdQuery;
import com.foxinmy.weixin4j.msg.model.Base;
import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.AccountType;
@@ -119,10 +118,20 @@ public class WeixinProxy {
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param file
* 媒体对象
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
public String uploadMedia(File file) throws WeixinException, IOException {
return mediaApi.uploadMedia(file);
}
/**
* 上传媒体文件
*
* @param file
* 文件对象
@@ -131,10 +140,8 @@ public class WeixinProxy {
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(String, byte[],String)}
*/
public String uploadMedia(File file, MediaType mediaType)
throws WeixinException, IOException {
@@ -143,17 +150,24 @@ public class WeixinProxy {
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param fileName
* 文件名
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(File, MediaType)}
* @throws WeixinException
*/
public String uploadMedia(String fileName, byte[] data, MediaType mediaType)
public String uploadMedia(String fileName, byte[] data, String mediaType)
throws WeixinException {
return mediaApi.uploadMedia(fileName, data, mediaType);
}
@@ -175,6 +189,7 @@ public class WeixinProxy {
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, MediaType mediaType)
throws WeixinException, IOException {
@@ -185,15 +200,13 @@ public class WeixinProxy {
* 下载媒体文件
*
* @param mediaId
* @param mediaType
* 媒体ID
* @return 二进制数据包
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String, MediaType)}
*/
public byte[] downloadMediaData(String mediaId, MediaType mediaType)
throws WeixinException {
return mediaApi.downloadMediaData(mediaId, mediaType);
public byte[] downloadMedia(String mediaId) throws WeixinException {
return mediaApi.downloadMedia(mediaId);
}
/**
@@ -204,57 +217,18 @@ public class WeixinProxy {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
* @see com.foxinmy.weixin4j.mp.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify
* @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.Music
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.mp.api.NotifyApi
*/
public JsonResult sendNotify(BaseNotify notify) throws WeixinException {
public JsonResult sendNotify(NotifyMessage notify) throws WeixinException {
return notifyApi.sendNotify(notify);
}
/**
* 发送图文消息
*
* @param touser
* 目标ID
* @param articles
* 图文列表
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.msg.model.Article
* @see com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify
* @see com.foxinmy.weixin4j.mp.api.NotifyApi
*/
public JsonResult sendNotify(String touser, List<Article> articles)
throws WeixinException {
return notifyApi.sendNotify(touser, articles);
}
/**
* 发送客服消息(不包含图文消息)
*
* @param touser
* 目标用户
* @param baseMsg
* 消息类型
* @return 发送结果
* @see com.foxinmy.weixin4j.mp.msg.model.Text
* @see com.foxinmy.weixin4j.mp.msg.model.Image
* @see com.foxinmy.weixin4j.mp.msg.model.Music
* @see com.foxinmy.weixin4j.mp.msg.model.Video
* @see com.foxinmy.weixin4j.mp.msg.model.Voice
* @see com.foxinmy.weixin4j.mp.api.NotifyApi
* @throws WeixinException
*/
public JsonResult sendNotify(String touser, BaseMsg baseMsg)
throws WeixinException {
return notifyApi.sendNotify(touser, baseMsg);
}
/**
* 客服聊天记录
*
@@ -310,7 +284,7 @@ public class WeixinProxy {
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">高级群发</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E7.B4.A0.E6.9D.90">上传图文消息</a>
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @see com.foxinmy.weixin4j.mp.api.MassApi
*/
public String uploadArticle(List<MpArticle> articles)
@@ -321,106 +295,96 @@ public class WeixinProxy {
/**
* 上传分组群发的视频素材
*
* @param mediaId
* 媒体文件中上传得到的Id
* @param title
* 标题 可为空
* @param desc
* 描述 可为空
* @param video
* 视频对象 其中mediaId媒体文件中上传得到的Id 不能为空
* @return 上传后的ID
* @throws WeixinException
*
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">高级群发</a>
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.MpVideo
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
*/
public String uploadVideo(String mediaId, String title, String desc)
throws WeixinException {
return massApi.uploadVideo(mediaId, title, desc);
public String uploadVideo(Video video) throws WeixinException {
return massApi.uploadVideo(video);
}
/**
* 分组群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param box
* 消息项
* @param groupId
* 分组ID
* @return
* @return 群发后的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @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.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroupByOpenId(String)}
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
*/
public String massByGroup(String mediaId, MediaType mediaType,
String groupId) throws WeixinException {
return massApi.massByGroup(mediaId, mediaType, groupId);
public String massByGroupId(Base box, int groupId) throws WeixinException {
return massApi.massByGroupId(box, groupId);
}
/**
* 分组群发图文消息
* 分组ID群发图文消息
*
* @param articles
* 图文消息列表
* @param groupId
* 分组ID
* @return 发送出去的消息ID
* 图文列表
* @param openIds
* openId列表
* @return 群发后的消息ID
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Base,int)}
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroup(String,MediaType,String)}
*/
public String massArticleByGroup(List<MpArticle> articles, String groupId)
public String massArticleByGroupId(List<MpArticle> articles, int groupId)
throws WeixinException {
return massApi.massArticleByGroup(articles, groupId);
return massApi.massArticleByGroupId(articles, groupId);
}
/**
* openId群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param box
* 消息项
* @param openIds
* openId列表
* @return
* @return 群发后的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.User
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(JSONObject,String...)}
* @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.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
* @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String)}
*/
public String massByOpenIds(String mediaId, MediaType mediaType,
String... openIds) throws WeixinException {
return massApi.massByOpenIds(mediaId, mediaType, openIds);
public String massByOpenIds(Base box, String... openIds)
throws WeixinException {
return massApi.massByOpenIds(box, openIds);
}
/**
* openId图文群发
* 根据openid群发图文消息
*
* @param articles
* 图文消息列表
* 图文列表
* @param openIds
* 目标ID列表
* @return 发送出去的消息ID
* openId列表
* @return 群发后的消息ID
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Base,String...)}
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.mp.model.User
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(String,MediaType,String...)}
*/
public String massArticleByOpenIds(List<MpArticle> articles,
String... openIds) throws WeixinException {
@@ -439,8 +403,8 @@ public class WeixinProxy {
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E5.88.A0.E9.99.A4.E7.BE.A4.E5.8F.91">删除群发</a>
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroup(JSONObject, String)}
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(JSONObject, String...)
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Base, int)}
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Base, String...)
*/
public JsonResult deleteMassNews(String msgid) throws WeixinException {
@@ -643,7 +607,7 @@ public class WeixinProxy {
* @param btnList
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3">创建自定义菜单</a>
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3">创建自定义菜单</a>
* @see com.foxinmy.weixin4j.model.Button
* @see com.foxinmy.weixin4j.type.ButtonType
* @see com.foxinmy.weixin4j.mp.api.MenuApi
@@ -658,7 +622,7 @@ public class WeixinProxy {
* @return 菜单集合
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3">查询菜单</a>
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3">查询菜单</a>
* @see com.foxinmy.weixin4j.model.Button
* @see com.foxinmy.weixin4j.mp.api.MenuApi
*/
@@ -671,7 +635,7 @@ public class WeixinProxy {
*
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%A0%E9%99%A4%E6%8E%A5%E5%8F%A3">删除菜单</a>
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%A0%E9%99%A4%E6%8E%A5%E5%8F%A3">删除菜单</a>
* @see com.foxinmy.weixin4j.model.Button
* @see com.foxinmy.weixin4j.mp.api.MenuApi
*/
@@ -737,7 +701,7 @@ public class WeixinProxy {
* @return 发送结果
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息</a>
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息</a>
* @see com.foxinmy.weixin4j.mp.message.TemplateMessage
* @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
* @see com.foxinmy.weixin4j.mp.api.TmplApi
@@ -854,11 +818,10 @@ public class WeixinProxy {
return payApi.downloadbill(billDate, billType);
}
/**
/**
* 申请退款(V3请求需要双向证书)</br>
* <p style="color:red">
* 交易时间超过 1 年的订单无法提交退款; <br/>
* 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 败后重新提交,要采用原来的
* <p style="color:red">
* 交易时间超过 1 年的订单无法提交退款; </br> 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失
* 败后重新提交,要采用原来的 out_refund_no。总退款金额不能超过用户实际支付金额。</br>
* </p>
*
@@ -893,9 +856,8 @@ public class WeixinProxy {
opUserId, opUserPasswd);
}
/**
* 不同的退款接口选择<br/>
* V3支付则采用properties中配置的ca文件<br/>
/**
* 不同的退款接口选择</br> V3支付则采用properties中配置的ca文件</br>
* V2支付则需要传入opUserPasswd参数</br>
*
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#refund(InputStream, IdQuery, String, double, double, String,String)}
@@ -907,8 +869,7 @@ public class WeixinProxy {
opUserId, opUserPasswd);
}
/**
* 退款查询<br/>
/**
* 退款查询</br> 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
*
* @param idQuery
@@ -925,8 +886,7 @@ public class WeixinProxy {
return payApi.refundQuery(idQuery);
}
/**
* 关闭订单<br/>
/**
* 关闭订单</br> 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
*
@@ -3,14 +3,20 @@ package com.foxinmy.weixin4j.mp.api;
import java.io.File;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
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.Token;
import com.foxinmy.weixin4j.mp.model.MpArticle;
import com.foxinmy.weixin4j.msg.model.Base;
import com.foxinmy.weixin4j.msg.model.Massable;
import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.msg.model.MpNews;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 群发相关API
@@ -21,7 +27,7 @@ import com.foxinmy.weixin4j.type.MediaType;
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">群发接口</a>
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.msg.model.MpArticle
*/
public class MassApi extends BaseApi {
@@ -32,8 +38,7 @@ public class MassApi extends BaseApi {
}
/**
* 上传图文消息,一个图文消息支持1到10条图文<br/>
* <font
* 上传图文消息,一个图文消息支持1到10条图文</br> <font
* color="red">具备微信支付权限的公众号,在使用高级群发接口上传、群发图文消息类型时,可使用&lta&gt标签加入外链</font>
*
* @param articles
@@ -44,7 +49,7 @@ public class MassApi extends BaseApi {
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">高级群发</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E7.B4.A0.E6.9D.90">上传图文消息</a>
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.msg.model.MpArticle
*/
public String uploadArticle(List<MpArticle> articles)
throws WeixinException {
@@ -62,29 +67,22 @@ public class MassApi extends BaseApi {
/**
* 上传分组群发的视频素材
*
* @param mediaId
* 媒体文件中上传得到的Id
* @param title
* 标题 可为空
* @param desc
* 描述 可为空
* @return 上传后的ID
* @param video
* 视频对象 其中mediaId媒体文件中上传得到的Id 不能为空
* @return 上传后的ID 可用于群发视频消息
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">高级群发</a>
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.MpVideo
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
*/
public String uploadVideo(String mediaId, String title, String desc)
throws WeixinException {
public String uploadVideo(Video video) throws WeixinException {
String video_upload_uri = getRequestUri("video_upload_uri");
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.put("media_id", mediaId);
obj.put("title", title);
obj.put("description", desc);
Response response = request.post(
String.format(video_upload_uri, token.getAccessToken()),
obj.toJSONString());
JSON.toJSONString(video));
return response.getAsJson().getString("media_id");
}
@@ -96,151 +94,128 @@ public class MassApi extends BaseApi {
* 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
* </p>
*
* @param jsonPara
* json格式的参数
* @param box
* 消息项
* @param groupId
* 分组ID
* @return 发送出去的消息ID
* @return 群发后的消息ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91">分组群发</a>
* @see com.foxinmy.weixin4j.mp.model.Group
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroupByOpenId(String)}
* @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.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
*/
private String massByGroup(JSONObject jsonPara, String groupId)
throws WeixinException {
public String massByGroupId(Base box, int groupId) throws WeixinException {
if (box instanceof MpNews) {
MpNews _news = (MpNews) box;
List<MpArticle> _articles = _news.getArticles();
if (StringUtils.isBlank(_news.getMediaId()) && _articles != null
&& !_articles.isEmpty()) {
return massArticleByGroupId(_articles, groupId);
}
}
if (!(box instanceof Massable)) {
throw new WeixinException("-1", String.format(
"%s not implement Massable", box.getClass()));
}
String msgtype = box.getMediaType().name();
JSONObject obj = new JSONObject();
JSONObject item = new JSONObject();
item.put("group_id", groupId);
obj.put("filter", item);
obj.put(msgtype, JSON.toJSON(box));
obj.put("msgtype", msgtype);
String mass_group_uri = getRequestUri("mass_group_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(mass_group_uri, token.getAccessToken()),
jsonPara.toJSONString());
obj.toJSONString());
return response.getAsJson().getString("msg_id");
}
/**
* 分组ID群发图文消息
*
* @param articles
* 图文列表
* @param openIds
* openId列表
* @return 群发后的消息ID
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroupId(Base,int)}
* @throws WeixinException
*/
public String massArticleByGroupId(List<MpArticle> articles, int groupId)
throws WeixinException {
String mediaId = uploadArticle(articles);
return massByGroupId(new MpNews(mediaId), groupId);
}
/**
* openId群发
*
* @param jsonPara
* json格式的参数
* @param box
* 消息项
* @param openIds
* 目标ID列表
* @return 发送出去的消息ID
* openId列表
* @return 群发后的消息ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91">openId群发</a>
* @see com.foxinmy.weixin4j.mp.model.User
* @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.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
* @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String)}
*/
private String massByOpenIds(JSONObject jsonPara, String... openIds)
public String massByOpenIds(Base box, String... openIds)
throws WeixinException {
if (box instanceof MpNews) {
MpNews _news = (MpNews) box;
List<MpArticle> _articles = _news.getArticles();
if (StringUtils.isBlank(_news.getMediaId()) && _articles != null
&& !_articles.isEmpty()) {
return massArticleByOpenIds(_articles, openIds);
}
}
if (!(box instanceof Massable)) {
throw new WeixinException("-1", String.format(
"%s not implement Massable", box.getClass()));
}
String msgtype = box.getMediaType().name();
JSONObject obj = new JSONObject();
obj.put("touser", openIds);
obj.put(msgtype, JSON.toJSON(box));
obj.put("msgtype", msgtype);
String mass_openid_uri = getRequestUri("mass_openid_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(mass_openid_uri, token.getAccessToken()),
jsonPara.toJSONString());
obj.toJSONString());
return response.getAsJson().getString("msg_id");
}
/**
* 分组群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param groupId
* 分组ID
* @return
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroupByOpenId(String)}
* @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroup(JSONObject,String)}
*/
public String massByGroup(String mediaId, MediaType mediaType,
String groupId) throws WeixinException {
JSONObject jsonPara = new JSONObject();
jsonPara.put("filter", new JSONObject().put("group_id", groupId));
jsonPara.put(mediaType.name(), new JSONObject().put(
mediaType == MediaType.text ? "content" : "media_id", mediaId));
jsonPara.put("msgtype", mediaType.name());
return massByGroup(jsonPara, groupId);
}
/**
* 分组群发图文消息
* 根据openid群发图文消息
*
* @param articles
* 图文消息列表
* @param groupId
* 分组ID
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.mp.model.Group
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroup(String,MediaType,String)}
*/
public String massArticleByGroup(List<MpArticle> articles, String groupId)
throws WeixinException {
String mediaId = uploadArticle(articles);
return massByGroup(mediaId, MediaType.mpnews, groupId);
}
/**
* openId群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* 图文列表
* @param openIds
* openId列表
* @return
* @return 群发后的消息ID
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Base,String...)}
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.User
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(JSONObject,String...)}
*/
public String massByOpenIds(String mediaId, MediaType mediaType,
String... openIds) throws WeixinException {
JSONObject jsonPara = new JSONObject();
jsonPara.put("touser", openIds);
jsonPara.put(mediaType.name(), new JSONObject().put(
mediaType == MediaType.text ? "content" : "media_id", mediaId));
jsonPara.put("msgtype", mediaType.name());
return massByOpenIds(jsonPara, openIds);
}
/**
* openId图文群发
*
* @param articles
* 图文消息列表
* @param openIds
* 目标ID列表
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MpArticle
* @see com.foxinmy.weixin4j.mp.model.User
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(String,MediaType,String...)}
*/
public String massArticleByOpenIds(List<MpArticle> articles,
String... openIds) throws WeixinException {
String mediaId = uploadArticle(articles);
return massByOpenIds(mediaId, MediaType.mpnews, openIds);
return massByOpenIds(new MpNews(mediaId), openIds);
}
/**
@@ -254,8 +229,8 @@ public class MassApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E5.88.A0.E9.99.A4.E7.BE.A4.E5.8F.91">删除群发</a>
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroup(JSONObject, String)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(JSONObject, String...)
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroup(Base, int)}
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Base, String...)
*/
public JsonResult deleteMassNews(String msgid) throws WeixinException {
@@ -5,6 +5,7 @@ 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;
@@ -13,6 +14,8 @@ 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;
/**
@@ -36,10 +39,25 @@ public class MediaApi extends BaseApi {
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param file
* 媒体对象
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.mp.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
* 文件对象
@@ -48,35 +66,40 @@ public class MediaApi extends BaseApi {
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @throws
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(String, 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);
return uploadMedia(file.getName(), datas, mediaType.name());
}
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param fileName
* 文件名
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
*/
public String uploadMedia(String fileName, byte[] bytes, MediaType mediaType)
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.name()), new PartParameter(
"media", new ByteArrayBody(bytes, fileName)));
token.getAccessToken(), mediaType), new PartParameter("media",
new ByteArrayBody(bytes, fileName)));
return response.getAsJson().getString("media_id");
}
@@ -97,16 +120,17 @@ public class MediaApi extends BaseApi {
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, MediaType mediaType)
throws WeixinException, IOException {
String media_path = getRequestUri("media_path");
byte[] datas = downloadMediaData(mediaId, mediaType);
String filename = mediaId + "." + mediaType.getFormatType();
File file = new File(media_path + File.separator + filename);
String media_path = ConfigUtil.getValue("media_path");
File file = new File(media_path + File.separator + mediaId + "."
+ mediaType.getFormatName());
if (file.exists()) {
return file;
}
byte[] datas = downloadMedia(mediaId);
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
out.write(datas);
@@ -118,13 +142,13 @@ public class MediaApi extends BaseApi {
* 下载媒体文件
*
* @param mediaId
* @param mediaType
* 媒体ID
* @return 二进制数据包
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String, MediaType)}
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
*/
public byte[] downloadMediaData(String mediaId, MediaType mediaType)
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,
@@ -7,8 +7,8 @@ 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.mp.model.Button;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
@@ -18,7 +18,7 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.mp.model.Button
* @see com.foxinmy.weixin4j.model.Button
*/
public class MenuApi extends BaseApi {
@@ -35,7 +35,7 @@ public class MenuApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3">创建自定义菜单</a>
* @see com.foxinmy.weixin4j.mp.model.Button
* @see com.foxinmy.weixin4j.model.Button
*/
public JsonResult createMenu(List<Button> btnList) throws WeixinException {
String menu_create_uri = getRequestUri("menu_create_uri");
@@ -56,7 +56,7 @@ public class MenuApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3">查询菜单</a>
* @see com.foxinmy.weixin4j.mp.model.Button
* @see com.foxinmy.weixin4j.model.Button
*/
public List<Button> getMenu() throws WeixinException {
String menu_get_uri = getRequestUri("menu_get_uri");
@@ -75,7 +75,7 @@ public class MenuApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%A0%E9%99%A4%E6%8E%A5%E5%8F%A3">删除菜单</a>
* @see com.foxinmy.weixin4j.mp.model.Button
* @return 处理结果
*/
public JsonResult deleteMenu() throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_uri");
@@ -1,15 +1,11 @@
package com.foxinmy.weixin4j.mp.api;
import java.util.List;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.msg.model.Article;
import com.foxinmy.weixin4j.mp.msg.model.BaseMsg;
import com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify;
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
import com.foxinmy.weixin4j.msg.model.Notifyable;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
@@ -21,12 +17,7 @@ import com.foxinmy.weixin4j.token.TokenHolder;
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">客服消息</a>
* @see com.foxinmy.weixin4j.mp.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify
* @see com.foxinmy.weixin4j.mp.message.NotifyMessage
*/
public class NotifyApi extends BaseApi {
@@ -36,25 +27,6 @@ public class NotifyApi extends BaseApi {
this.tokenHolder = tokenHolder;
}
/**
* 发送客服消息
*
* @param jsonPara
* @return
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">发送客服消息</a>
*/
private JsonResult sendNotify(String jsonPara) throws WeixinException {
String custom_notify_uri = getRequestUri("custom_notify_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(custom_notify_uri, token.getAccessToken()),
jsonPara);
return response.getAsJsonResult();
}
/**
* 发送客服消息(在48小时内不限制发送次数)
*
@@ -63,64 +35,25 @@ public class NotifyApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
* @see com.foxinmy.weixin4j.mp.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify
* @see {@link com.foxinmy.weixin4j.mp.api.NotifyApi#sendNotify(String)}
* @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.Music
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.mp.message.NotifyMessage
*/
public JsonResult sendNotify(BaseNotify notify) throws WeixinException {
return sendNotify(notify.toJson());
}
public JsonResult sendNotify(NotifyMessage notify) throws WeixinException {
if (!(notify.getBox() instanceof Notifyable)) {
throw new WeixinException("-1", String.format(
"%s not implement Notifyable", notify.getBox().getClass()));
}
String custom_notify_uri = getRequestUri("custom_notify_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(custom_notify_uri, token.getAccessToken()),
notify.toJson());
/**
* 发送图文消息
*
* @param touser
* 目标ID
* @param articles
* 图文列表
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.msg.model.Article
* @see com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify
*/
public JsonResult sendNotify(String touser, List<Article> articles)
throws WeixinException {
ArticleNotify notify = new ArticleNotify(touser);
notify.pushAll(articles);
return sendNotify(notify);
}
/**
* 发送客服消息(不包含图文消息)
*
* @param touser
* 目标用户
* @param baseMsg
* 消息类型
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.msg.model.Text
* @see com.foxinmy.weixin4j.mp.msg.model.Image
* @see com.foxinmy.weixin4j.mp.msg.model.Music
* @see com.foxinmy.weixin4j.mp.msg.model.Video
* @see com.foxinmy.weixin4j.mp.msg.model.Voice
* @see {@link com.foxinmy.weixin4j.mp.msg.model.BaseMsg#toNotifyJson()}
* @see {@link com.foxinmy.weixin4j.mp.api.NotifyApi#sendNotify(String)}
*/
public JsonResult sendNotify(String touser, BaseMsg baseMsg)
throws WeixinException {
StringBuilder jsonPara = new StringBuilder();
String mediaType = baseMsg.getMediaType().name();
jsonPara.append("{");
jsonPara.append("\"touser\":\"").append(touser).append("\",");
jsonPara.append("\"msgtype\":\"").append(mediaType).append("\",");
jsonPara.append("\"").append(mediaType).append("\":");
jsonPara.append(baseMsg.toNotifyJson()).append("}");
return sendNotify(jsonPara.toString());
return response.getAsJsonResult();
}
}
@@ -42,10 +42,10 @@ import com.foxinmy.weixin4j.http.SSLHttpRequest;
import com.foxinmy.weixin4j.http.XmlResult;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.converter.RefundConverter;
import com.foxinmy.weixin4j.mp.payment.ApiResult;
import com.foxinmy.weixin4j.mp.payment.PayUtil;
import com.foxinmy.weixin4j.mp.payment.Refund;
import com.foxinmy.weixin4j.mp.payment.RefundConverter;
import com.foxinmy.weixin4j.mp.payment.RefundResult;
import com.foxinmy.weixin4j.mp.payment.v2.Order;
import com.foxinmy.weixin4j.mp.type.BillType;
@@ -1,7 +1,6 @@
package com.foxinmy.weixin4j.mp.api;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -11,6 +10,7 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.type.QRType;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 二维码相关API
@@ -34,9 +34,9 @@ public class QrApi extends BaseApi {
* 生成带参数的二维码
*
* @param parameter
* 二维码参数
* @return byte数据包
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.mp.api.QrApi#getQR(QRParameter)}
*/
public byte[] getQRData(QRParameter parameter) throws WeixinException {
Token token = tokenHolder.getToken();
@@ -78,14 +78,14 @@ public class QrApi extends BaseApi {
* 二维码参数
* @return 硬盘存储的文件对象
* @throws WeixinException
* @throws FileNotFoundException
* @throws IOException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%94%9F%E6%88%90%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E4%BA%8C%E7%BB%B4%E7%A0%81">二维码</a>
* @see com.foxinmy.weixin4j.mp.model.QRParameter
*/
public File getQR(QRParameter parameter) throws WeixinException,
IOException {
String qr_path = getRequestUri("qr_path");
String qr_path = ConfigUtil.getValue("qr_path");
String filename = String.format("%s_%d_%d.jpg", parameter.getQrType()
.name(), parameter.getSceneId(), parameter.getExpireSeconds());
File file = new File(qr_path + File.separator + filename);
@@ -5,7 +5,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.response.TemplateMessage;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
@@ -33,7 +33,7 @@ public class TmplApi extends BaseApi {
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息</a>
* @see com.foxinmy.weixin4j.mp.response.TemplateMessage
* @see com.foxinmy.weixin4j.mp.message.TemplateMessage
* @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
*/
public JsonResult sendTmplMessage(TemplateMessage tplMessage)
@@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment;
package com.foxinmy.weixin4j.mp.converter;
import java.lang.reflect.Field;
import java.util.HashMap;
@@ -9,6 +9,8 @@ import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.foxinmy.weixin4j.mp.payment.Refund;
import com.foxinmy.weixin4j.mp.payment.RefundDetail;
import com.foxinmy.weixin4j.xml.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
@@ -0,0 +1,30 @@
package com.foxinmy.weixin4j.mp.converter;
import com.foxinmy.weixin4j.msg.model.Text;
import com.thoughtworks.xstream.converters.SingleValueConverter;
/**
* Text回复消息转换
*
* @className TextConverter
* @author jy
* @date 2014年11月22日
* @since JDK 1.7
*/
public class TextConverter implements SingleValueConverter {
@Override
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
return clazz.equals(Text.class);
}
@Override
public String toString(Object obj) {
return ((Text) obj).getContent();
}
@Override
public Object fromString(String text) {
return new Text(text);
}
}
@@ -0,0 +1,74 @@
package com.foxinmy.weixin4j.mp.message;
import java.io.Serializable;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.msg.model.Base;
/**
* 客服消息(48小时内不限制发送次数)
*
* @author jy.hu
* @date 2014年4月4日
* @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.Music
* @see com.foxinmy.weixin4j.msg.model.News
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
*/
public class NotifyMessage implements Serializable {
private static final long serialVersionUID = 7190233634431087729L;
private String touser;
@JSONField(name = "%s")
private Base box;// 消息项
public NotifyMessage(Base box) {
this(null, box);
}
public NotifyMessage(String touser, Base box) {
this.touser = touser;
this.box = box;
}
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public Base getBox() {
return box;
}
public void setBox(Base box) {
this.box = box;
}
/**
* 客服消息json化
*
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
*/
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 + ", box=" + box + "]";
}
}
@@ -0,0 +1,5 @@
NotifyMessage: 客服消息
ResponseMessage: 被动消息
TemplateMessage: 模板消息
@@ -0,0 +1,113 @@
package com.foxinmy.weixin4j.mp.message;
import org.apache.commons.lang3.StringUtils;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.converter.TextConverter;
import com.foxinmy.weixin4j.msg.model.Article;
import com.foxinmy.weixin4j.msg.model.Base;
import com.foxinmy.weixin4j.msg.model.News;
import com.foxinmy.weixin4j.msg.model.Responseable;
import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.xml.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 被动消息
* <p>
* <font color="red">回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器,
* 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试</font>
* </p>
*
* @className ResponseMessage
* @author jy.hu
* @date 2014年4月6日
* @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.Music
* @see com.foxinmy.weixin4j.msg.model.News
* @see com.foxinmy.weixin4j.msg.model.Trans
* @see <a href=
* "http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF"
* >回复被动消息</a>
*/
@XStreamAlias("xml")
public class ResponseMessage extends BaseMsg {
private static final long serialVersionUID = 7761192742840031607L;
protected final static XStream xmlStream = XStream.get();
static {
Class<?>[] classes = ClassUtil.getClasses(Base.class.getPackage())
.toArray(new Class[0]);
xmlStream.autodetectAnnotations(true);
xmlStream.processAnnotations(classes);
xmlStream.processAnnotations(ResponseMessage.class);
xmlStream.registerConverter(new TextConverter());
xmlStream.omitField(BaseMsg.class, "msgId");
xmlStream.alias("item", Article.class);
xmlStream.addImplicitCollection(News.class, "articles");
xmlStream.aliasSystemAttribute(null, "class");
}
private String attach; // 附加数据
private final Base box;
public ResponseMessage(Base box) {
this(box, null);
}
public ResponseMessage(Base box, BaseMsg inMessage) {
this(box, inMessage.getFromUserName(), inMessage.getToUserName());
}
public ResponseMessage(Base box, String toUserName, String fromUserName) {
super(box.getMediaType().name(), toUserName, fromUserName);
this.box = box;
}
public String getAttach() {
return attach;
}
public Base getBox() {
return box;
}
/**
* 消息对象转换为微信服务器接受的xml格式消息 </br> <font
* color="color">需Responseable标识,否则返回空</font>
*
* @see com.foxinmy.weixin4j.msg.model.Responseable
* @return xml字符串
*/
public String toXml() {
// check responseable
if (!(box instanceof Responseable)) {
return "";
}
String boxAlias = StringUtils.capitalize(getMsgType());
XStreamAlias alias = box.getClass().getAnnotation(XStreamAlias.class);
if (alias != null) {
boxAlias = alias.value();
}
xmlStream.aliasField(boxAlias, ResponseMessage.class, "box");
if (box instanceof News) {
attach = Integer.toString(((News) box).getArticles().size());
xmlStream.aliasField("ArticleCount", ResponseMessage.class,
"attach");
}
return xmlStream.toXML(this);
}
@Override
public String toString() {
return "ResponseMessage [box=" + box + ", getToUserName()="
+ getToUserName() + ", getFromUserName()=" + getFromUserName()
+ ", getCreateTime()=" + getCreateTime() + ", getMsgType()="
+ getMsgType() + "]";
}
}
@@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.response;
package com.foxinmy.weixin4j.mp.message;
import java.io.Serializable;
import java.util.HashMap;
@@ -1,113 +0,0 @@
package com.foxinmy.weixin4j.mp.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 菜单按钮
* <p>
* 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替
* 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果
* </p>
*
* @className Button
* @author jy.hu
* @date 2014年4月5日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.type.ButtonType
*/
public class Button implements Serializable {
private static final long serialVersionUID = -6422234732203854866L;
private String name;
private ButtonType type; // 菜单的响应动作类型
private String key; // click等点击类型必须
private String url; // view类型必须
@JSONField(name = "sub_button")
private List<Button> subs;
public Button() {
}
public Button(String name, String value, ButtonType buttonType) {
this.name = name;
this.type = buttonType;
if (buttonType == ButtonType.view) {
this.url = value;
} else {
this.key = value;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ButtonType getType() {
return type;
}
public void setType(ButtonType type) {
this.type = type;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<Button> getSubs() {
return subs;
}
public void setSubs(List<Button> subs) {
this.subs = subs;
}
public Button pushSub(Button btn) {
if (this.subs == null) {
this.subs = new ArrayList<Button>();
}
this.subs.add(btn);
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[Button name=").append(name);
sb.append(" ,type=").append(type);
sb.append(" ,key=").append(key);
sb.append(" ,url=").append(url);
if (subs != null && !subs.isEmpty()) {
sb.append("{");
for (Button sub : subs) {
sb.append(sub.toString());
}
sb.append("}");
}
sb.append("]");
return sb.toString();
}
}
@@ -4,7 +4,6 @@ import java.io.Serializable;
import java.util.Date;
import com.foxinmy.weixin4j.mp.type.CustomRecordOperCode;
import com.foxinmy.weixin4j.mp.util.EntityUtil;
/**
* 客服聊天记录
@@ -46,7 +45,7 @@ public class CustomRecord implements Serializable {
}
public void setOpercode(int opercode) {
this.opercode = EntityUtil.getCustomRecordOperCode(opercode);
this.opercode = CustomRecordOperCode.getOper(opercode);
}
public Date getTime() {
@@ -1,109 +0,0 @@
package com.foxinmy.weixin4j.mp.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 群发图文消息
*
* @author jy.hu
* @date 2014年4月26日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E7.B4.A0.E6.9D.90">群发消息描述</a>
*/
public class MpArticle implements Serializable {
private static final long serialVersionUID = 5583479943661639234L;
@JSONField(name = "thumb_media_id")
private String thumbMediaId; // 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得 非空
private String author;// 图文消息的作者 可为空
private String title;// 图文消息的标题 非空
@JSONField(name = "content_source_url")
private String url;// 在图文消息页面点击“阅读原文”后的页面 可为空
private String content;// 图文消息页面的内容,支持HTML标签 非空
private String digest;// 图文消息的描述 可为空
@JSONField(name = "show_cover_pic")
private String showCoverPic; // 是否显示封面,1为显示,0为不显示 可为空
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public String getShowCoverPic() {
return showCoverPic;
}
public void setShowCoverPic(boolean showCoverPic) {
this.showCoverPic = showCoverPic ? "1" : "0";
}
public MpArticle(String thumbMediaId, String title, String content) {
this.thumbMediaId = thumbMediaId;
this.title = title;
this.content = content;
}
public MpArticle() {
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[MpArticle thumbMediaId=").append(thumbMediaId);
sb.append(", author=").append(author);
sb.append(", title=").append(title);
sb.append(", url=").append(url);
sb.append(", content=").append(content);
sb.append(", digest=").append(digest);
sb.append(", showCoverPic=").append(showCoverPic).append("]");
return sb.toString();
}
}
@@ -1,75 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 图文对象
*
* @className Article
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Article extends BaseMsg {
private static final long serialVersionUID = 1L;
private String title; // 图文消息标题
@XStreamAlias("description")
private String desc; // 图文消息描述
@XStreamAlias("picurl")
private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
private String url; // 点击图文消息跳转链接
public Article(String title, String desc, String picUrl, String url) {
this.title = title;
this.desc = desc;
this.picUrl = picUrl;
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Article [title=" + title + ", desc=" + desc + ", picUrl="
+ picUrl + ", url=" + url + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.mpnews;
}
}
@@ -1,39 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import java.io.Serializable;
import java.io.Writer;
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.xml.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;
public abstract class BaseMsg implements Serializable {
private static final long serialVersionUID = 1L;
private final static XStream xstream = new XStream(
new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
static {
xstream.setMode(XStream.NO_REFERENCES);
xstream.autodetectAnnotations(true);
xstream.processAnnotations(ClassUtil.getClasses(
BaseNotify.class.getPackage()).toArray(new Class[0]));
}
public abstract MediaType getMediaType();
/**
* 客服消息json化,适用于客服消息接口
*
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
*/
public String toNotifyJson() {
return xstream.toXML(this);
}
}
@@ -1,38 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 图片对象
*
* @className Image
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Image extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
public Image(String mediaId) {
this.mediaId = mediaId;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
@Override
public MediaType getMediaType() {
return MediaType.image;
}
}
@@ -1,93 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 音乐对象
*
* @className Music
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Music extends BaseMsg {
private static final long serialVersionUID = 1L;
private String title;
@XStreamAlias("description")
private String desc;
@XStreamAlias("musicurl")
private String musicUrl;
@XStreamAlias("hqmusicurl")
private String hqMusicUrl;
@XStreamAlias("thumb_media_id")
private String thumbMediaId;
public Music(String thumbMediaId) {
this(null, null, null, null, thumbMediaId);
}
public Music(String title, String desc, String musicUrl, String hqMusicUrl,
String thumbMediaId) {
this.title = title;
this.desc = desc;
this.musicUrl = musicUrl;
this.hqMusicUrl = hqMusicUrl;
this.thumbMediaId = thumbMediaId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getMusicUrl() {
return musicUrl;
}
public void setMusicUrl(String musicUrl) {
this.musicUrl = musicUrl;
}
public String getHqMusicUrl() {
return hqMusicUrl;
}
public void setHqMusicUrl(String hqMusicUrl) {
this.hqMusicUrl = hqMusicUrl;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
@Override
public String toString() {
return "Music [title=" + title + ", desc=" + desc + ", musicUrl="
+ musicUrl + ", hqMusicUrl=" + hqMusicUrl + ", thumbMediaId="
+ thumbMediaId + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.music;
}
}
@@ -1 +0,0 @@
不同的消息类型中的模型
@@ -1,40 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 文本对象
* @className Text
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Text extends BaseMsg {
private static final long serialVersionUID = 1L;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Text(String content) {
this.content = content;
}
@Override
public String toString() {
return "Text [content=" + content + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.text;
}
}
@@ -1,88 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 视频对象
*
* @className Video
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Video extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
@XStreamAlias("thumb_media_id")
private String thumbMediaId;
private String title;
@XStreamAlias("description")
private String desc;
public Video(String mediaId) {
this(mediaId, null, null, null);
}
public Video(String mediaId, String thumbMediaId) {
this(mediaId, thumbMediaId, null, null);
}
public Video(String mediaId, String title, String desc) {
this(mediaId, null, title, desc);
}
public Video(String mediaId, String thumbMediaId, String title, String desc) {
this.mediaId = mediaId;
this.thumbMediaId = thumbMediaId;
this.title = title;
this.desc = desc;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Video [mediaId=" + mediaId + ", thumbMediaId=" + thumbMediaId
+ ", title=" + title + ", desc=" + desc + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.vedio;
}
}
@@ -1,38 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 语音对象
*
* @className Image
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Voice extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
public Voice(String mediaId) {
this.mediaId = mediaId;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
@Override
public MediaType getMediaType() {
return MediaType.voice;
}
}
@@ -1,102 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import java.util.LinkedList;
import java.util.List;
import com.foxinmy.weixin4j.mp.msg.model.Article;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
/**
* 客服图文消息
*
* @className ArticleNotify
* @author jy.hu
* @date 2014年4月6日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF">客服图文消息</a>
* @see com.foxinmy.weixin.msg.model.Article
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class ArticleNotify extends BaseNotify {
private static final int MAX_ARTICLE_COUNT = 10;
private static final long serialVersionUID = 1740696901128709998L;
public ArticleNotify() {
this(null);
}
public ArticleNotify(String touser) {
super(touser, ResponseType.news);
}
@XStreamAlias("news")
private News news;
@XStreamOmitField
private int count; // 图文消息个数,限制为10条以内
public void pushArticle(String title, String desc, String picUrl, String url) {
if ((count + 1) > MAX_ARTICLE_COUNT) {
return;
}
if (this.news == null) {
this.news = new News();
}
this.news.pushArticle(title, desc, picUrl, url);
count++;
}
public void pushAll(List<Article> articles) {
count = articles.size();
if (articles.size() > MAX_ARTICLE_COUNT) {
count = MAX_ARTICLE_COUNT;
articles = articles.subList(0, count);
}
if (this.news == null) {
this.news = new News();
}
this.news.setArticles(articles);
}
private static class News {
@XStreamAlias("articles")
private List<Article> articles;
public News() {
this.articles = new LinkedList<Article>();
}
public void pushArticle(String title, String desc, String picUrl,
String url) {
this.articles.add(new Article(title, desc, picUrl, url));
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Article article : articles) {
sb.append("{title=").append(article.getTitle());
sb.append(" ,description=").append(article.getDesc());
sb.append(" ,picUrl=").append(article.getPicUrl());
sb.append(" ,url=").append(article.getUrl()).append("}");
}
return sb.toString();
}
}
@Override
public String toString() {
return String.format(
"[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]",
super.getTouser(), super.getMsgtype().name(),
this.news.toString());
}
}
@@ -1,83 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import java.io.Serializable;
import java.io.Writer;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.xml.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;
/**
* 客服消息基类(48小时内不限制发送次数)
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
*/
public class BaseNotify implements Serializable {
private static final long serialVersionUID = 7190233634431087729L;
private final static XStream jsonStream = new XStream(
new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
static {
Class<?>[] classes = ClassUtil
.getClasses(BaseNotify.class.getPackage())
.toArray(new Class[0]);
jsonStream.setMode(XStream.NO_REFERENCES);
jsonStream.autodetectAnnotations(true);
jsonStream.processAnnotations(classes);
}
private String touser;
private ResponseType msgtype;
public BaseNotify(ResponseType msgtype) {
this.msgtype = msgtype;
}
public BaseNotify(String touser, ResponseType msgtype) {
this.touser = touser;
this.msgtype = msgtype;
}
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public ResponseType getMsgtype() {
return msgtype;
}
public void setMsgtype(ResponseType msgtype) {
this.msgtype = msgtype;
}
/**
* 客服消息json化
*
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
*/
public String toJson() {
return jsonStream.toXML(this);
}
@Override
public String toString() {
return String.format("[BaseNotify touser=%s ,msgtype=%s]", touser,
msgtype.name());
}
}
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import com.foxinmy.weixin4j.mp.msg.model.Image;
import com.foxinmy.weixin4j.mp.type.ResponseType;
/**
* 客服图片消息
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">客服图片消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Image
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class ImageNotify extends BaseNotify {
private static final long serialVersionUID = -7698823863398518425L;
public ImageNotify() {
this(null, null);
}
public ImageNotify(String touser) {
this(null, touser);
}
public ImageNotify(String mediaId, String touser) {
super(touser, ResponseType.image);
this.pushMediaId(mediaId);
}
public void pushMediaId(String mediaId) {
this.image = new Image(mediaId);
}
private Image image;
@Override
public String toString() {
return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]",
super.getTouser(), super.getMsgtype().name(),
this.image.getMediaId());
}
}
@@ -1,46 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import com.foxinmy.weixin4j.mp.msg.model.Music;
import com.foxinmy.weixin4j.mp.type.ResponseType;
/**
* 客服音乐消息
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">客服音乐消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Music
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class MusicNotify extends BaseNotify {
private static final long serialVersionUID = -7698823863398518425L;
public MusicNotify() {
this(null);
}
public MusicNotify(String touser) {
super(touser, ResponseType.music);
}
public void pushMusic(String musicurl, String hqUrl, String mediaId) {
this.music = new Music(null, null, musicurl, hqUrl, mediaId);
}
private Music music;
public void setMusic(Music music) {
this.music = music;
}
@Override
public String toString() {
return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]",
super.getTouser(), super.getMsgtype().name(),
this.music.toString());
}
}
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import com.foxinmy.weixin4j.mp.msg.model.Text;
import com.foxinmy.weixin4j.mp.type.ResponseType;
/**
* 客服文本消息
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">客服文本消息</a>
* @see com.foxinmy.weixin.msg.model.Text
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class TextNotify extends BaseNotify {
private static final long serialVersionUID = -7698823863398518425L;
public TextNotify() {
this(null, null);
}
public TextNotify(String content) {
this(content,null);
}
public TextNotify(String content, String touser) {
super(touser, ResponseType.text);
this.text = new Text(content);
}
public void setContent(String content) {
this.text = new Text(content);
}
private Text text;
@Override
public String toString() {
return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]",
super.getTouser(), super.getMsgtype().name(),
this.text.getContent());
}
}
@@ -1,46 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import com.foxinmy.weixin4j.mp.msg.model.Video;
import com.foxinmy.weixin4j.mp.type.ResponseType;
/**
* 客服视频消息
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">客服视频消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Video
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class VideoNotify extends BaseNotify {
private static final long serialVersionUID = -7698823863398518425L;
public VideoNotify() {
this(null);
}
public VideoNotify(String touser) {
super(touser, ResponseType.video);
}
public void pushVideo(String mediaId, String thumbMediaId) {
this.video = new Video(mediaId, thumbMediaId);
}
private Video video;
public void setVideo(Video video) {
this.video = video;
}
@Override
public String toString() {
return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]",
super.getTouser(), super.getMsgtype().name(),
this.video.toString());
}
}
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.mp.msg.notify;
import com.foxinmy.weixin4j.mp.msg.model.Voice;
import com.foxinmy.weixin4j.mp.type.ResponseType;
/**
* 客服语音消息
*
* @author jy.hu
* @date 2014年4月4日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">客服语音消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Voice
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify
* @see com.foxinmy.weixin4j.mp.msg.notify.BaseNotify#toJson()
*/
public class VoiceNotify extends BaseNotify {
private static final long serialVersionUID = -7698823863398518425L;
public VoiceNotify() {
this(null, null);
}
public VoiceNotify(String touser) {
this(null, touser);
}
public VoiceNotify(String mediaId, String touser) {
super(touser, ResponseType.voice);
this.pushMediaId(mediaId);
}
public void pushMediaId(String mediaId) {
this.voice = new Voice(mediaId);
}
private Voice voice;
@Override
public String toString() {
return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]",
super.getTouser(), super.getMsgtype().name(),
this.voice.getMediaId());
}
}
@@ -79,16 +79,16 @@ public class PayAction {
/**
* JSAPI(V2)支付成功(前端)时的回调通知<br>
* &ltxml&gt<br/>
* &ltOpenId&gt&lt![CDATA[111222]]&gt&lt/OpenId&gt<br/>
* &ltAppId&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/AppId&gt<br/>
* &ltIsSubscribe&gt1&lt/IsSubscribe&gt<br/>
* &ltTimeStamp&gt1369743511&lt/TimeStamp&gt<br/>
* &ltNonceStr&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/NonceStr&gt<br/>
* &ltxml&gt</br>
* &ltOpenId&gt&lt![CDATA[111222]]&gt&lt/OpenId&gt</br>
* &ltAppId&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/AppId&gt</br>
* &ltIsSubscribe&gt1&lt/IsSubscribe&gt</br>
* &ltTimeStamp&gt1369743511&lt/TimeStamp&gt</br>
* &ltNonceStr&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/NonceStr&gt</br>
* &ltAppSignature>&lt![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]&gt
* &lt/AppSignature&gt<br/>
* &ltSignMethod>&lt![CDATA[sha1]]&gt&lt/SignMethod&gt<br/>
* &lt/xml&gt<br/>
* &lt/AppSignature&gt</br>
* &ltSignMethod>&lt![CDATA[sha1]]&gt&lt/SignMethod&gt</br>
* &lt/xml&gt</br>
* 参与签名的字段为: appid、appkey、timestamp、noncestr、openid、issubscribe
*
* @param 订单信息
@@ -165,17 +165,17 @@ public class PayAction {
/**
* V2.x版本Native支付时POST数据<br>
* &ltxml&gt<br/>
* &ltOpenId&gt&lt![CDATA[111222]]&gt&lt/OpenId&gt<br/>
* &ltAppId&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/AppId&gt<br/>
* &ltIsSubscribe&gt1&lt/IsSubscribe&gt<br/>
* &ltProductId&gt[CDATA[000000]]&lt/ProductId&gt<br/>
* &ltTimeStamp&gt1369743511&lt/TimeStamp&gt<br/>
* &ltNonceStr&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/NonceStr&gt<br/>
* &ltxml&gt</br>
* &ltOpenId&gt&lt![CDATA[111222]]&gt&lt/OpenId&gt</br>
* &ltAppId&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/AppId&gt</br>
* &ltIsSubscribe&gt1&lt/IsSubscribe&gt</br>
* &ltProductId&gt[CDATA[000000]]&lt/ProductId&gt</br>
* &ltTimeStamp&gt1369743511&lt/TimeStamp&gt</br>
* &ltNonceStr&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/NonceStr&gt</br>
* &ltAppSignature>&lt![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]&gt
* &lt/AppSignature&gt<br/>
* &ltSignMethod>&lt![CDATA[sha1]]&gt&lt/SignMethod&gt<br/>
* &lt/xml&gt<br/>
* &lt/AppSignature&gt</br>
* &ltSignMethod>&lt![CDATA[sha1]]&gt&lt/SignMethod&gt</br>
* &lt/xml&gt</br>
* 参与签名的字段为: appid、appkey、timestamp、noncestr、openid、issubscribe、productId
*
* @param inputStream
@@ -208,16 +208,16 @@ public class PayAction {
/**
* V3.x版本native回调<br>
* &ltxml&gt<br/>
* &ltopenid&gt&lt![CDATA[111222]]&gt&lt/openid&gt<br/>
* &ltappid&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/appid&gt<br/>
* &ltmch_id&gt&lt![CDATA[1100022]]&gt&lt/mch_id&gt<br/>
* &ltis_subscribe&gt1&lt/is_subscribe&gt<br/>
* &ltproduct_id&gt[CDATA[000000]]&lt/product_id&gt<br/>
* &ltnonce_str&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/nonce_str&gt<br/>
* &ltxml&gt</br>
* &ltopenid&gt&lt![CDATA[111222]]&gt&lt/openid&gt</br>
* &ltappid&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/appid&gt</br>
* &ltmch_id&gt&lt![CDATA[1100022]]&gt&lt/mch_id&gt</br>
* &ltis_subscribe&gt1&lt/is_subscribe&gt</br>
* &ltproduct_id&gt[CDATA[000000]]&lt/product_id&gt</br>
* &ltnonce_str&gt&lt![CDATA[jALldRTHAFd5Tgs5]]&gt&lt/nonce_str&gt</br>
* &ltsign>&lt![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]&gt&lt/sign&
* gt<br/>
* &lt/xml&gt<br/>
* gt</br>
* &lt/xml&gt</br>
*
* @return
* @throws PayException
@@ -251,17 +251,17 @@ public class PayAction {
}
/**
* 告警通知 需要成功返回 success <br/>
* &ltxml&gt<br/>
* &ltAppId&gt&lt![CDATA[wxf8b4f85f3a794e77]]&gt&lt/AppId&gt<br/>
* &ltErrorType&gt1001&lt/ErrorType&gt<br/>
* &ltDescription&gt&lt![CDATA[错误描述]]>&lt/Description&gt<br/>
* &ltAlarmContent&gt&lt![CDATA[错误详情]]>&lt/AlarmContent&gt<br/>
* &ltTimeStamp&gt1393860740&lt/TimeStamp&gt<br/>
* 告警通知 需要成功返回 success </br>
* &ltxml&gt</br>
* &ltAppId&gt&lt![CDATA[wxf8b4f85f3a794e77]]&gt&lt/AppId&gt</br>
* &ltErrorType&gt1001&lt/ErrorType&gt</br>
* &ltDescription&gt&lt![CDATA[错误描述]]>&lt/Description&gt</br>
* &ltAlarmContent&gt&lt![CDATA[错误详情]]>&lt/AlarmContent&gt</br>
* &ltTimeStamp&gt1393860740&lt/TimeStamp&gt</br>
* &ltAppSignature&gt&lt![CDATA[签名方式跟JsPayRequest中的paySign一样]]&gt&lt/
* AppSignature&gt<br/>
* &ltSignMethod&gt&lt![CDATA[sha1]]&gt&lt/SignMethod&gt<br/>
* &lt/xml&gt<br/>
* AppSignature&gt</br>
* &ltSignMethod&gt&lt![CDATA[sha1]]&gt&lt/SignMethod&gt</br>
* &lt/xml&gt</br>
* 参与签名字段:alarmcontent、appid、appkey、description、errortype、timestamp
*
* @param inputStream
@@ -211,16 +211,16 @@ public class PayUtil {
* 生成编辑地址请求
* </p>
*
* err_msg edit_address:ok获取编辑收货地址成功<br/>
* edit_address:fail获取编辑收货地址失败<br/>
* userName 收货人姓名<br/>
* telNumber 收货人电话<br/>
* addressPostalCode 邮编<br/>
* proviceFirstStageName 国标收货地址第一级地址<br/>
* addressCitySecondStageName 国标收货地址第二级地址<br/>
* addressCountiesThirdStageName 国标收货地址第三级地址<br/>
* addressDetailInfo 详细收货地址信息<br/>
* nationalCode 收货地址国家码<br/>
* err_msg edit_address:ok获取编辑收货地址成功</br>
* edit_address:fail获取编辑收货地址失败</br>
* userName 收货人姓名</br>
* telNumber 收货人电话</br>
* addressPostalCode 邮编</br>
* proviceFirstStageName 国标收货地址第一级地址</br>
* addressCitySecondStageName 国标收货地址第二级地址</br>
* addressCountiesThirdStageName 国标收货地址第三级地址</br>
* addressDetailInfo 详细收货地址信息</br>
* nationalCode 收货地址国家码</br>
*
* @param appId
* 公众号的ID
@@ -10,7 +10,7 @@ import com.foxinmy.weixin4j.mp.payment.PayRequest;
import com.foxinmy.weixin4j.util.MapUtil;
/**
* 微信JS支付:get_brand_wcpay_request<br/>
* 微信JS支付:get_brand_wcpay_request</br>
* <font color="red">所列参数均为非空字符串</font>
* <p>
* get_brand_wcpay_request:ok 支付成功<br>
@@ -11,7 +11,7 @@ import com.foxinmy.weixin4j.util.RandomUtil;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* V3支付的订单详情<br/>
* V3支付的订单详情</br>
* 注意: <font color="red">total_fee字段传入时单位为元,创建支付时会转换为分</font>
*
* @className PayPackageV3
@@ -7,7 +7,7 @@ import com.foxinmy.weixin4j.mp.payment.PayRequest;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
/**
* JS支付:get_brand_wcpay_request<br/>
* JS支付:get_brand_wcpay_request</br>
* <p>
* get_brand_wcpay_request:ok 支付成功<br>
* get_brand_wcpay_request:cancel 支付过程中用户取消<br>
@@ -1,103 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import java.util.LinkedList;
import com.foxinmy.weixin4j.mp.msg.model.Article;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复图文消息
*
* @className ArticleResponse
* @author jy.hu
* @date 2014年3月23日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF">回复图文消息</a>
* @see com.foxinmy.weixin.msg.model.Article
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class ArticleResponse extends BaseResponse {
private static final int MAX_ARTICLE_COUNT = 10;
private static final long serialVersionUID = -7331603018352309317L;
public ArticleResponse(BaseMessage inMessage) {
super(ResponseType.news, inMessage);
}
@XStreamAlias("ArticleCount")
private int count; // 图文消息个数,限制为10条以内
@XStreamAlias("Articles")
private LinkedList<Article> articles;
public void pushArticle(String title, String desc, String picUrl, String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
if ((articles.size() + 1) > MAX_ARTICLE_COUNT) {
return;
}
this.articles.add(new Article(title, desc, picUrl, url));
}
public void pushFirstArticle(String title, String desc, String picUrl,
String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
this.articles.addFirst(new Article(title, desc, picUrl, url));
}
public void pushLastArticle(String title, String desc, String picUrl,
String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
this.articles.addLast(new Article(title, desc, picUrl, url));
}
public Article removeLastArticle() {
Article article = null;
if (this.articles != null) {
article = this.articles.removeLast();
}
return article;
}
public Article removeFirstArticle() {
if (this.articles != null) {
return this.articles.removeFirst();
}
return null;
}
public boolean isMaxCount() {
return this.articles.size() == MAX_ARTICLE_COUNT;
}
@Override
public String toXml() {
this.count = articles.size();
xmlStream.alias("item", Article.class);
xmlStream.aliasField("Title", Article.class, "title");
xmlStream.aliasField("Description", Article.class, "desc");
xmlStream.aliasField("PicUrl", Article.class, "picUrl");
xmlStream.aliasField("Url", Article.class, "url");
return xmlStream.toXML(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[BaseResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,articles=").append(this.articles.toString());
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1,67 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.xml.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 响应消息基类
* <p>
* <font color="red">回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器,
* 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试</font>
* </p>
*
* @className BaseResponse
* @author jy.hu
* @date 2014年4月6日
* @since JDK 1.7
*/
public class BaseResponse extends BaseMsg {
private static final long serialVersionUID = 7761192742840031607L;
protected final static XStream xmlStream = XStream.get();
static {
Class<?>[] classes = ClassUtil.getClasses(
BaseResponse.class.getPackage()).toArray(new Class[0]);
xmlStream.autodetectAnnotations(true);
xmlStream.processAnnotations(classes);
}
@XStreamAlias("MsgType")
private ResponseType msgType; // 消息类型
public BaseResponse(ResponseType msgType) {
this.msgType = msgType;
}
public BaseResponse(ResponseType msgType, BaseMessage inMessage) {
this(msgType, inMessage.getFromUserName(), inMessage.getToUserName());
}
public BaseResponse(ResponseType msgType, String toUserName,
String fromUserName) {
super(toUserName, fromUserName);
this.msgType = msgType;
}
public ResponseType getMsgType() {
return msgType;
}
public void setMsgType(ResponseType msgType) {
this.msgType = msgType;
}
/**
* 消息对象转换为微信服务器接受的xml格式消息
*
* @return xml字符串
*/
public String toXml() {
return xmlStream.toXML(this);
}
}
@@ -1,59 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.msg.model.Image;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复图片消息
*
* @className ImageResponse
* @author jy.hu
* @date 2014年3月23日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">回复图片消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Image
* @see com.foxinmy.weixin4j.msg.BaseMessage
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class ImageResponse extends BaseResponse {
private static final long serialVersionUID = 6998255203997554731L;
public ImageResponse(BaseMessage inMessage) {
this(null, inMessage);
}
public ImageResponse(String mediaId, BaseMessage inMessage) {
super(ResponseType.image, inMessage);
super.getMsgType().setMessageClass(ImageResponse.class);
this.pushMediaId(mediaId);
}
@XStreamAlias("Image")
private Image image;
public void pushMediaId(String mediaId) {
this.image = new Image(mediaId);
}
@Override
public String toXml() {
xmlStream.aliasField("MediaId", Image.class, "mediaId");
return xmlStream.toXML(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ImageResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,mediaId=").append(this.image.getMediaId());
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1,61 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.msg.model.Music;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复音乐消息
*
* @className MusicResponse
* @author jy.hu
* @date 2014年3月23日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">回复音乐消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Music
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class MusicResponse extends BaseResponse {
private static final long serialVersionUID = 4384403772658796395L;
public MusicResponse(BaseMessage inMessage) {
super(ResponseType.music, inMessage);
}
@XStreamAlias("Music")
private Music music;
public void pushMusic(String mediaId) {
this.music = new Music(mediaId);
}
public void setMusic(Music music) {
this.music = music;
}
@Override
public String toXml() {
xmlStream.aliasField("MediaId", Music.class, "musicUrl");
xmlStream.aliasField("Title", Music.class, "title");
xmlStream.aliasField("Description", Music.class, "desc");
xmlStream.aliasField("HQMusicUrl", Music.class, "hqMusicUrl");
xmlStream.aliasField("ThumbMediaId", Music.class, "thumbMediaId");
return xmlStream.toXML(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[MusicResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,music=").append(music.toString());
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1 +0,0 @@
被动响应消息
@@ -1,57 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复文本消息
*
* @className TextResponse
* @author jy.hu
* @date 2014年4月6日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">接收文本消息</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">回复文本消息</a>
* @see com.foxinmy.weixin4j.msg.BaseMessage
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class TextResponse extends BaseResponse {
private static final long serialVersionUID = -7018053906644190260L;
public TextResponse() {
super(ResponseType.text);
}
public TextResponse(String content, BaseMessage inMessage) {
super(ResponseType.text, inMessage);
this.content = content;
}
@XStreamAlias("Content")
private String content; // 消息内容
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[TextResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,content=").append(content);
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1,73 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 转移消息到多客服端消息
*
* @className TransferResponse
* @author jy.hu
* @date 2014年6月28日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%B0%86%E6%B6%88%E6%81%AF%E8%BD%AC%E5%8F%91%E5%88%B0%E5%A4%9A%E5%AE%A2%E6%9C%8D">多客服转移消息</a>
* @see <a href="http://dkf.qq.com/document-4_1.html">将消息转发到多客服</a>
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class TransferResponse extends BaseResponse {
private static final long serialVersionUID = -5479496746108594940L;
public TransferResponse(BaseMessage inMessage) {
super(ResponseType.transfer_customer_service, inMessage);
}
/**
* 需如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满) 该用户会一直等待指定客服有接入能力后才会被接入 而不会被其他客服接待
*
* @param inMessage
* @param kfAccount
* 转移客服的账号
*/
public TransferResponse(BaseMessage inMessage, String kfAccount) {
super(ResponseType.transfer_customer_service, inMessage);
this.transInfo = new TransInfo(kfAccount);
}
@XStreamAlias("TransInfo")
private TransInfo transInfo;
public String getTransAccount() {
if (transInfo != null) {
return transInfo.getKfAccount();
}
return null;
}
public void setTransAccount(String kfAccount) {
this.transInfo = new TransInfo(kfAccount);
}
private static class TransInfo {
// 指定会话接入的客服账号
@XStreamAlias("KfAccount")
private String kfAccount;
public TransInfo(String kfAccount) {
this.kfAccount = kfAccount;
}
public String getKfAccount() {
return kfAccount;
}
@Override
public String toString() {
return "TransInfo [kfAccount=" + kfAccount + "]";
}
}
}
@@ -1,61 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.msg.model.Video;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复视频消息
*
* @className VideoResponse
* @author jy.hu
* @date 2014年4月6日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">回复视频消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Video
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class VideoResponse extends BaseResponse {
private static final long serialVersionUID = -1013075358679078381L;
public VideoResponse(BaseMessage inMessage) {
super(ResponseType.video, inMessage);
super.getMsgType().setMessageClass(VideoResponse.class);
}
@XStreamAlias("Video")
private Video video;
public void pushVideo(String mediaId) {
this.video = new Video(mediaId);
}
public void setVideo(Video video) {
this.video = video;
}
@Override
public String toXml() {
xmlStream.aliasField("MediaId", Video.class, "mediaId");
xmlStream.aliasField("Title", Video.class, "title");
xmlStream.aliasField("Description", Video.class, "desc");
xmlStream.omitField(Video.class, "thumbMediaId");
return xmlStream.toXML(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[VideoResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,video=").append(video.toString());
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1,59 +0,0 @@
package com.foxinmy.weixin4j.mp.response;
import com.foxinmy.weixin4j.mp.msg.model.Voice;
import com.foxinmy.weixin4j.mp.type.ResponseType;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 回复语音消息
*
* @className VoiceResponse
* @author jy.hu
* @date 2014年3月23日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">回复语音消息</a>
* @see com.foxinmy.weixin4j.mp.msg.model.Voice
* @see com.foxinmy.weixin4j.mp.response.BaseResponse
* @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml()
*/
@XStreamAlias("xml")
public class VoiceResponse extends BaseResponse {
private static final long serialVersionUID = -7944926238652243793L;
public VoiceResponse(BaseMessage inMessage) {
this(null, inMessage);
}
public VoiceResponse(String mediaId, BaseMessage inMessage) {
super(ResponseType.voice, inMessage);
super.getMsgType().setMessageClass(VoiceResponse.class);
this.pushMediaId(mediaId);
}
@XStreamAlias("Voice")
private Voice voice;
public void pushMediaId(String mediaId) {
this.voice = new Voice(mediaId);
}
@Override
public String toXml() {
xmlStream.aliasField("MediaId", Voice.class, "mediaId");
return xmlStream.toXML(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[VoiceResponse ,toUserName=").append(super.getToUserName());
sb.append(" ,fromUserName=").append(super.getFromUserName());
sb.append(" ,msgType=").append(super.getMsgType().name());
sb.append(" ,mediaId=").append(voice.getMediaId());
sb.append(" ,createTime=").append(super.getCreateTime()).append("]");
return sb.toString();
}
}
@@ -1,7 +1,11 @@
package com.foxinmy.weixin4j.mp.type;
import java.util.HashMap;
import java.util.Map;
/**
* 客服消息记录中的回话状态
*
* @className CustomRecordOperCode
* @author jy
* @date 2014年11月16日
@@ -14,6 +18,17 @@ public enum CustomRecordOperCode {
2002, "客服发送消息"), RECEIVE2(2003, "客服收到消息");
private int code;
private String desc;
private static Map<Integer, CustomRecordOperCode> customRecordOperCodeMap;
static {
customRecordOperCodeMap = new HashMap<Integer, CustomRecordOperCode>();
for (CustomRecordOperCode operCode : CustomRecordOperCode.values()) {
customRecordOperCodeMap.put(operCode.getCode(), operCode);
}
}
public static CustomRecordOperCode getOper(int code) {
return customRecordOperCodeMap.get(code);
}
CustomRecordOperCode(int code, String desc) {
this.code = code;
@@ -1,38 +0,0 @@
package com.foxinmy.weixin4j.mp.type;
import com.foxinmy.weixin4j.mp.response.ArticleResponse;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.mp.response.ImageResponse;
import com.foxinmy.weixin4j.mp.response.MusicResponse;
import com.foxinmy.weixin4j.mp.response.TextResponse;
import com.foxinmy.weixin4j.mp.response.TransferResponse;
import com.foxinmy.weixin4j.mp.response.VideoResponse;
import com.foxinmy.weixin4j.mp.response.VoiceResponse;
/**
* 被动响应类型
* @className ResponseType
* @author jy
* @date 2014年11月5日
* @since JDK 1.7
* @see
*/
public enum ResponseType {
text(TextResponse.class), image(ImageResponse.class), voice(
VoiceResponse.class), video(VideoResponse.class), music(
MusicResponse.class), news(ArticleResponse.class), transfer_customer_service(
TransferResponse.class);
private Class<? extends BaseResponse> messageClass;
ResponseType(Class<? extends BaseResponse> messageClass) {
this.messageClass = messageClass;
}
public void setMessageClass(Class<? extends BaseResponse> messageClass) {
this.messageClass = messageClass;
}
public Class<? extends BaseResponse> getMessageClass() {
return messageClass;
}
}
@@ -1,29 +0,0 @@
package com.foxinmy.weixin4j.mp.util;
import java.util.HashMap;
import java.util.Map;
import com.foxinmy.weixin4j.mp.type.CustomRecordOperCode;
/**
* 实体帮助类
*
* @className EntityUtil
* @author jy
* @date 2014年11月16日
* @since JDK 1.7
* @see
*/
public class EntityUtil {
private static Map<Integer, CustomRecordOperCode> customRecordOperCodeMap;
static {
customRecordOperCodeMap = new HashMap<Integer, CustomRecordOperCode>();
for (CustomRecordOperCode operCode : CustomRecordOperCode.values()) {
customRecordOperCodeMap.put(operCode.getCode(), operCode);
}
}
public static CustomRecordOperCode getCustomRecordOperCode(int code) {
return customRecordOperCodeMap.get(code);
}
}
@@ -1,12 +1,12 @@
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
# \u516c\u4f17\u53f7\u4fe1\u606f
account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
"token":"\u5f00\u653e\u8005\u7684token \u975e\u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
"token":"\u5f00\u653e\u8005\u7684token \u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u65f6\u9700\u8981\u586b\u5165",\
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7",\
"version":3,\
"partnerId":"\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7","partnerKey":"\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5"}
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"version":2,\
"partnerId":"\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165","partnerKey":"\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
# \u4f7f\u7528FileTokenHolder\u65f6token\u7684\u5b58\u653e\u8def\u5f84
token_path=/tmp/weixin/token
@@ -17,4 +17,4 @@ media_path=/tmp/weixin/media
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
bill_path=/tmp/weixin/bill
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
ca_file=/tmp/weixin/xxxxxx.p12
ca_file=/tmp/weixin/xxxxx.p12 | xxxxx.pfx
@@ -9,8 +9,8 @@ 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.mp.api.MenuApi;
import com.foxinmy.weixin4j.mp.model.Button;
import com.foxinmy.weixin4j.type.ButtonType;
/**
@@ -13,8 +13,10 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.mp.api.MassApi;
import com.foxinmy.weixin4j.mp.api.MediaApi;
import com.foxinmy.weixin4j.mp.model.MpArticle;
import com.foxinmy.weixin4j.mp.test.TokenTest;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.type.MediaType;
/**
@@ -47,20 +49,20 @@ public class MassMsgTest extends TokenTest {
@Test
public void uploadVideo() throws WeixinException {
String massId = massApi.uploadVideo("mediaId", "title", "desc");
Video video = new Video("mediaId", "title", "desc");
String massId = massApi.uploadVideo(video);
Assert.assertTrue(massId != null);
}
@Test
public void massByGroup() throws WeixinException {
String massId = massApi.massByGroup("123", MediaType.image, "groupId");
String massId = massApi.massByGroupId(new Image("mediaId"), 0);
Assert.assertTrue(massId != null);
}
@Test
public void massByOpenIds() throws WeixinException {
String massId = massApi
.massByOpenIds("123", MediaType.image, "openIds");
String massId = massApi.massByOpenIds(new Image("mediaId"), "openIds");
Assert.assertTrue(massId != null);
}
@@ -70,7 +72,7 @@ public class MassMsgTest extends TokenTest {
String thumbMediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
MediaType.image);
articles.add(new MpArticle(thumbMediaId, "title", "content"));
String massId = massApi.massArticleByGroup(articles, "0");
String massId = massApi.massArticleByGroupId(articles, 0);
Assert.assertTrue(massId != null);
}
@@ -11,14 +11,14 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.mp.api.MediaApi;
import com.foxinmy.weixin4j.mp.api.NotifyApi;
import com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify;
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.mp.msg.notify.ImageNotify;
import com.foxinmy.weixin4j.mp.msg.notify.MusicNotify;
import com.foxinmy.weixin4j.mp.msg.notify.TextNotify;
import com.foxinmy.weixin4j.mp.msg.notify.VideoNotify;
import com.foxinmy.weixin4j.mp.msg.notify.VoiceNotify;
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
import com.foxinmy.weixin4j.mp.test.TokenTest;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.msg.model.Music;
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.type.MediaType;
/**
@@ -43,50 +43,48 @@ public class NotifyMsgTest extends TokenTest {
@Test
public void text() {
TextNotify notify = new TextNotify("123", "to");
NotifyMessage notify = new NotifyMessage("to", new Text("ttt"));
System.out.println(notify.toJson());
}
@Test
public void image() {
ImageNotify notify = new ImageNotify("to");
notify.pushMediaId("123");
NotifyMessage notify = new NotifyMessage("to", new Image("image"));
System.out.println(notify.toJson());
}
@Test
public void voice() {
VoiceNotify notify = new VoiceNotify("to");
notify.pushMediaId("123");
NotifyMessage notify = new NotifyMessage("to", new Voice("voice"));
System.out.println(notify.toJson());
}
@Test
public void video() {
VideoNotify notify = new VideoNotify("to");
notify.pushVideo("123", "m123");
NotifyMessage notify = new NotifyMessage("to", new Video("video"));
System.out.println(notify.toJson());
}
@Test
public void music() {
MusicNotify notify = new MusicNotify("to");
notify.pushMusic("url", "hqUrl", "mediaId");
NotifyMessage notify = new NotifyMessage("to", new Music("music"));
System.out.println(notify.toJson());
}
@Test
public void article() {
ArticleNotify notify = new ArticleNotify("to");
notify.pushArticle("title1", "desc1", "picUrl1", "url1");
notify.pushArticle("title2", "desc2", "picUrl2", "url2");
public void news() {
News news = new News();
NotifyMessage notify = new NotifyMessage("to", news);
news.pushArticle("title1", "desc1", "picUrl1", "url1");
news.pushArticle("title2", "desc2", "picUrl2", "url2");
System.out.println(notify.toJson());
}
@Test
public void send1() throws IOException, WeixinException {
BaseNotify notify = new TextNotify("this is a notify message!",
"owGBft_vbBbOaQOmpEUE4xDLeRSU");
NotifyMessage notify = new NotifyMessage(
"owGBft_vbBbOaQOmpEUE4xDLeRSU", new Text(
"this is a notify message!"));
JsonResult result = notifyApi.sendNotify(notify);
Assert.assertEquals(0, result.getCode());
}
@@ -95,9 +93,8 @@ public class NotifyMsgTest extends TokenTest {
public void send2() throws WeixinException, IOException {
String mediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
MediaType.image);
ImageNotify imageNotify = new ImageNotify(
"owGBft_vbBbOaQOmpEUE4xDLeRSU");
imageNotify.pushMediaId(mediaId);
NotifyMessage imageNotify = new NotifyMessage(
"owGBft_vbBbOaQOmpEUE4xDLeRSU", new Image(mediaId));
JsonResult result = notifyApi.sendNotify(imageNotify);
Assert.assertEquals(0, result.getCode());
}
@@ -4,14 +4,16 @@ import org.dom4j.DocumentException;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.mp.response.ArticleResponse;
import com.foxinmy.weixin4j.mp.response.ImageResponse;
import com.foxinmy.weixin4j.mp.response.MusicResponse;
import com.foxinmy.weixin4j.mp.response.TextResponse;
import com.foxinmy.weixin4j.mp.response.VideoResponse;
import com.foxinmy.weixin4j.mp.response.VoiceResponse;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.msg.TextMessage;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.msg.model.Music;
import com.foxinmy.weixin4j.msg.model.News;
import com.foxinmy.weixin4j.msg.model.Text;
import com.foxinmy.weixin4j.msg.model.Trans;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.msg.model.Voice;
/**
* 发送消息格式测试
@@ -21,7 +23,7 @@ import com.foxinmy.weixin4j.msg.TextMessage;
* @since JDK 1.7
*/
public class OutMsgTest {
private BaseMessage inMessage;
private BaseMsg inMessage;
@Before
public void init() {
@@ -32,43 +34,51 @@ public class OutMsgTest {
@Test
public void text() throws DocumentException {
TextResponse message = new TextResponse("text", inMessage);
ResponseMessage message = new ResponseMessage(new Text("text"), inMessage);
System.out.println(message.toXml());
}
@Test
public void image() {
ImageResponse message = new ImageResponse(inMessage);
message.pushMediaId("mediaId");
ResponseMessage message = new ResponseMessage(new Image("image"), inMessage);
System.out.println(message.toXml());
}
@Test
public void voice() {
VoiceResponse message = new VoiceResponse(inMessage);
message.pushMediaId("mediaId");
ResponseMessage message = new ResponseMessage(new Voice("voice"), inMessage);
System.out.println(message.toXml());
}
@Test
public void video() {
VideoResponse message = new VideoResponse(inMessage);
message.pushVideo("mediaId");
Video video = new Video("video");
video.setDesc("desc");
ResponseMessage message = new ResponseMessage(video, inMessage);
System.out.println(message.toXml());
}
@Test
public void music() {
MusicResponse message = new MusicResponse(inMessage);
message.pushMusic("mediaId");
Music music = new Music("title", "desc", "musicUrl", "hqMusicUrl",
"thumbMediaId");
ResponseMessage message = new ResponseMessage(music, inMessage);
System.out.println(message.toXml());
}
@Test
public void article() {
ArticleResponse message = new ArticleResponse(inMessage);
message.pushArticle("title1", "desc1", "picUrl1", "url1");
message.pushArticle("title2", "desc2", "picUrl2", "url2");
News news = new News();
ResponseMessage message = new ResponseMessage(news, inMessage);
news.pushArticle("title1", "desc1", "picUrl1", "url1");
news.pushArticle("title2", "desc2", "picUrl2", "url2");
System.out.println(message.toXml());
}
@Test
public void trans(){
ResponseMessage message = new ResponseMessage(new Trans(),inMessage);
System.out.println(message.toXml());
message = new ResponseMessage(new Trans("accountid"),inMessage);
System.out.println(message.toXml());
}
}
@@ -7,7 +7,7 @@ import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.mp.api.TmplApi;
import com.foxinmy.weixin4j.mp.response.TemplateMessage;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.mp.test.TokenTest;
public class TemplateMsgTest extends TokenTest {
+13 -9
View File
@@ -27,21 +27,21 @@ weixin4j-mp-server
示例(properties中换行用右斜杆\\)
> account={"id":"appId","secret":"appSecret",
> "token":"开放者的token 必须","openId":"公众号的openid 非必须",
> "token":"开放者的token 必须","openId":"公众号的openid 非必须",
> "encodingAesKey":"公众号设置了加密方式且为「安全模式」时需要填入",
> "mchId":"V3.x版本下的微信商户号",
> "partnerId":"财付通的商户号","partnerKey":"财付通商户权限密钥Key",
> "version":"针对微信支付的版本号(目前可能为2,3),如果不填则按照mchId非空与否来做判断",
> "paySignKey":"微信支付中调用API的密钥"} <br/>
> token_path=/tmp/weixin/token <br/>
> qr_path=/tmp/weixin/qr <br/>
> media_path=/tmp/weixin/media <br/>
> bill_path=/tmp/weixin/bill <br/>
> ca_file=/tmp/weixin/xxxxx.p12 | xxxxx.pfx <br/>
> "paySignKey":"微信支付中调用API的密钥"} </br>
> token_path=/tmp/weixin/token </br>
> qr_path=/tmp/weixin/qr </br>
> media_path=/tmp/weixin/media </br>
> bill_path=/tmp/weixin/bill </br>
> ca_file=/tmp/weixin/xxxxx.p12 | xxxxx.pfx </br>
2.mvn package,得到一个zip的压缩包,解压到启动目录(见`src/main/startup.sh/APP_HOME`)
3.启动netty服务(`com.foxinmy.weixin4j.mp.startup.WeixinServerBootstrap`)
3.启动netty服务(`com.foxinmy.weixin4j.mp.startup.WeixinMpServerBootstrap`)
sh startup.sh start
@@ -55,4 +55,8 @@ weixin4j-mp-server
+ 解决`server工程`打包后不能运行问题(`ClassUtil`无法获取jar包里面的类)
+ 新增被动消息的`加密`以及回复消息的`解密`
+ 新增被动消息的`加密`以及回复消息的`解密`
* 2014-11-23
+ `WeixinServerBootstrap`重命名为`WeixinMpServerBootstrap`
+4 -2
View File
@@ -11,13 +11,15 @@
<artifactId>weixin4j-mp-server</artifactId>
<name>weixin4j-mp-server</name>
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-mp-server</url>
<description>微信公众服务</description>
<description>微信公众平台netty服务</description>
<build>
<finalName>weixin-mp-server</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>weixin-mp-server</finalName>
</configuration>
</plugin>
</plugins>
</build>
@@ -5,8 +5,8 @@ import java.lang.reflect.Type;
import org.dom4j.DocumentException;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.xml.XStream;
@@ -20,14 +20,14 @@ import com.foxinmy.weixin4j.xml.XStream;
* @see com.foxinmy.weixin4j.mp.action.WeixinAction
*/
@SuppressWarnings("unchecked")
public abstract class AbstractAction<M extends BaseMessage> implements
public abstract class AbstractAction<M extends BaseMsg> implements
WeixinAction {
public abstract BaseResponse execute(M inMessage);
public abstract ResponseMessage execute(M inMessage);
@Override
public BaseResponse execute(String msg) throws DocumentException {
BaseMessage message = MessageUtil.xml2msg(msg);
public ResponseMessage execute(String msg) throws DocumentException {
BaseMsg message = MessageUtil.xml2msg(msg);
if (message == null) {
Class<M> messageClass = getGenericType();
XStream xstream = XStream.get();
@@ -1,7 +1,7 @@
package com.foxinmy.weixin4j.mp.action;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
/**
* 回复一个空字符串 而不是一个XML结构体中content字段的内容为空
@@ -12,10 +12,10 @@ import com.foxinmy.weixin4j.msg.BaseMessage;
* @since JDK 1.7
* @see com.foxinmy.weixin4j.mp.action.AbstractAction
*/
public class BlankAction<M extends BaseMessage> extends AbstractAction<M> {
public class BlankAction<M extends BaseMsg> extends AbstractAction<M> {
@Override
public BaseResponse execute(M inMessage) {
public ResponseMessage execute(M inMessage) {
return null;
}
}
@@ -1,7 +1,8 @@
package com.foxinmy.weixin4j.mp.action;
import com.foxinmy.weixin4j.mp.response.TextResponse;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.model.BaseMsg;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.msg.model.Text;
/**
* 调试输出用户消息
@@ -12,11 +13,10 @@ import com.foxinmy.weixin4j.msg.BaseMessage;
* @since JDK 1.7
* @see
*/
public abstract class DebugAction<M extends BaseMessage> extends
AbstractAction<M> {
public abstract class DebugAction<M extends BaseMsg> extends AbstractAction<M> {
@Override
public TextResponse execute(M message) {
return new TextResponse(message.toString(), message);
public ResponseMessage execute(M message) {
return new ResponseMessage(new Text(message.toString()), message);
}
}
@@ -1,8 +1,9 @@
package com.foxinmy.weixin4j.mp.action;
import com.foxinmy.weixin4j.mp.mapping.Action;
import com.foxinmy.weixin4j.mp.response.TextResponse;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.msg.TextMessage;
import com.foxinmy.weixin4j.msg.model.Text;
import com.foxinmy.weixin4j.type.MessageType;
/**
@@ -18,7 +19,7 @@ import com.foxinmy.weixin4j.type.MessageType;
public class TextAction extends AbstractAction<TextMessage> {
@Override
public TextResponse execute(TextMessage inMessage) {
return new TextResponse("Hello World!", inMessage);
public ResponseMessage execute(TextMessage inMessage) {
return new ResponseMessage(new Text("Hello World!"), inMessage);
}
}
@@ -2,7 +2,7 @@ package com.foxinmy.weixin4j.mp.action;
import org.dom4j.DocumentException;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
/**
* 消息处理接口
@@ -16,5 +16,5 @@ import com.foxinmy.weixin4j.mp.response.BaseResponse;
* @see com.foxinmy.weixin4j.mp.action.DebugAction
*/
public interface WeixinAction {
public BaseResponse execute(String msg) throws DocumentException;
public ResponseMessage execute(String inMsg) throws DocumentException;
}
@@ -12,7 +12,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.foxinmy.weixin4j.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.mp.util.HttpUtil;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.DateUtil;
@@ -33,7 +33,7 @@ import com.thoughtworks.xstream.mapper.DefaultMapper;
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%85%A5%E6%8C%87%E5%BC%95">加密接入指引</a>
*/
public class WeixinMessageEncoder extends MessageToMessageEncoder<BaseResponse> {
public class WeixinMessageEncoder extends MessageToMessageEncoder<ResponseMessage> {
private final Logger log = LoggerFactory.getLogger(getClass());
protected final static XStream mapXstream = XStream.get();
static {
@@ -43,7 +43,7 @@ public class WeixinMessageEncoder extends MessageToMessageEncoder<BaseResponse>
}
@Override
protected void encode(ChannelHandlerContext ctx, BaseResponse response,
protected void encode(ChannelHandlerContext ctx, ResponseMessage response,
List<Object> out) throws Exception {
WeixinMpAccount mpAccount = ConfigUtil.getWeixinMpAccount();
String xmlContent = response.toXml();
@@ -13,8 +13,8 @@ import org.slf4j.LoggerFactory;
import com.foxinmy.weixin4j.mp.action.WeixinAction;
import com.foxinmy.weixin4j.mp.mapping.ActionMapping;
import com.foxinmy.weixin4j.mp.message.ResponseMessage;
import com.foxinmy.weixin4j.mp.model.HttpWeixinMessage;
import com.foxinmy.weixin4j.mp.response.BaseResponse;
import com.foxinmy.weixin4j.mp.type.EncryptType;
import com.foxinmy.weixin4j.mp.util.HttpUtil;
import com.foxinmy.weixin4j.util.MessageUtil;
@@ -84,7 +84,7 @@ public class WeixinServerHandler extends
HttpResponseStatus.NOT_FOUND));
return;
}
BaseResponse response = action.execute(xmlContent);
ResponseMessage response = action.execute(xmlContent);
log.info("\n=================message out=================\n{}",
response);
if (response == null) {
@@ -13,15 +13,15 @@ import java.util.ResourceBundle;
import com.foxinmy.weixin4j.mp.server.WeixinServerInitializer;
/**
* 微信服务netty启动程序
* 微信公众平台服务netty启动程序
*
* @className WeixinServerBootstrap
* @className WeixinMpServerBootstrap
* @author jy
* @date 2014年10月12日
* @since JDK 1.7
* @see
*/
public final class WeixinServerBootstrap {
public final class WeixinMpServerBootstrap {
private final static int port;
private final static int workerThreads;
@@ -25,7 +25,7 @@
<!--for further documentation -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/tmp/weixin/log/weixin.%d{yyyy-MM-dd}.log
<fileNamePattern>/tmp/weixin/log/weixin.mp.%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
@@ -1,11 +1,11 @@
# \u516c\u4f17\u53f7\u4fe1\u606f
account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
"token":"\u5f00\u653e\u8005\u7684token \u975e\u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u9700\u8981\u586b\u5165",\
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7",\
"version":3,\
"partnerId":"\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7","partnerKey":"\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5"}
account={"id":"appid","secret":"appsecret",\
"token":"\u5f00\u653e\u8005\u7684token \u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u65f6\u9700\u8981\u586b\u5165",\
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"version":\u6570\u5b57\u7c7b\u578b(2\u6216\u80053):\u5fae\u4fe1\u652f\u4ed8\u7684\u7248\u672c,\u5927\u6982\u57282014-09-14\u4e4b\u524d\u7533\u8bf7\u5e76\u4e14\u901a\u8fc7\u7684\u516c\u4f17\u53f7\u4e3aV2,\u5728\u8fd9\u4e4b\u540e\u5219\u4e3aV3 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165,\
"partnerId":"\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165","partnerKey":"\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
# \u4f7f\u7528FileTokenHolder\u65f6token\u7684\u5b58\u653e\u8def\u5f84
token_path=/tmp/weixin/token
@@ -16,4 +16,4 @@ media_path=/tmp/weixin/media
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
bill_path=/tmp/weixin/bill
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
ca_file=/tmp/weixin/xxxxxx.p12
ca_file=/tmp/weixin/xxxxx.p12 | xxxxx.pfx
@@ -9,7 +9,7 @@ RUNNING_USER=root
APP_HOME="/usr/local/weixin/weixin-mp-server"
#main class
APP_MAINCLASS=com.foxinmy.weixin4j.mp.startup.WeixinServerBootstrap
APP_MAINCLASS=com.foxinmy.weixin4j.mp.startup.WeixinMpServerBootstrap
#classpath
CLASSPATH=$APP_HOME/classes