Browse Source

重构代码,将用户管理、分组管理以及二维码相关的接口分别移到单独类中管理

master
BinaryWang 9 years ago
parent
commit
fcbdc8686e
21 changed files with 877 additions and 698 deletions
  1. +69
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java
  2. +12
    -9
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
  3. +30
    -17
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java
  4. +3
    -6
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java
  5. +77
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java
  6. +152
    -282
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  7. +46
    -253
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
  8. +72
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java
  9. +85
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java
  10. +23
    -20
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java
  11. +102
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java
  12. +83
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java
  13. +5
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java
  14. +5
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java
  15. +2
    -2
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java
  16. +1
    -39
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java
  17. +0
    -53
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java
  18. +8
    -6
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java
  19. +14
    -8
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java
  20. +85
    -0
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java
  21. +3
    -3
      weixin-java-mp/src/test/resources/testng.xml

+ 69
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java View File

@@ -0,0 +1,69 @@
package me.chanjar.weixin.mp.api;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.WxMpGroup;

import java.util.List;

/**
* 用户分组相关操作接口
* @author Binary Wang
*
*/
public interface WxMpGroupService {


/**
* <pre>
* 分组管理接口 - 创建分组
* 最多支持创建500个分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
*
* @param name 分组名字(30个字符以内)
*/
public WxMpGroup groupCreate(String name) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 查询所有分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
*/
public List<WxMpGroup> groupGet() throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 查询用户所在分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
*
* @param openid 微信用户的openid
*/
public long userGetGroup(String openid) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 修改分组名
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
*
* 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
* </pre>
*
* @param group 要更新的group,group的id,name必须设置
*/
public void groupUpdate(WxMpGroup group) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 移动用户分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
*
* 如果to_groupid为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
* </pre>
*
* @param openid 用户openid
* @param to_groupid 移动到的分组id
*/
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException;
}

+ 12
- 9
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java View File

@@ -1,23 +1,24 @@
package me.chanjar.weixin.mp.api;

import java.io.File;
import java.util.Date;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*;

import java.io.File;
import java.util.Date;

/**
* 客服接口 ,
* 命名采用kefu拼音的原因是:
* 其英文CustomerService如果再加上Service后缀显得有点啰嗦,
* 如果不加又显得表意不完整
* @author Binary Wang
*
* @author Binary Wang
*/
public interface WxMpKefuService {

//*******************客服管理接口***********************//

/**
* <pre>
* 获取客服基本信息
@@ -71,7 +72,7 @@ public interface WxMpKefuService {
* </pre>
*/
boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
throws WxErrorException;
throws WxErrorException;

/**
* <pre>
@@ -83,6 +84,7 @@ public interface WxMpKefuService {
boolean kfAccountDel(String kfAccount) throws WxErrorException;

//*******************客服会话控制接口***********************//

/**
* <pre>
* 创建会话
@@ -134,6 +136,7 @@ public interface WxMpKefuService {
WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException;

//*******************获取聊天记录的接口***********************//

/**
* <pre>
* 获取聊天记录(原始接口)
@@ -143,9 +146,9 @@ public interface WxMpKefuService {
* </pre>
*
* @param startTime 起始时间
* @param endTime 结束时间
* @param msgId 消息id顺序从小到大,从1开始
* @param number 每次获取条数,最多10000条
* @param endTime 结束时间
* @param msgId 消息id顺序从小到大,从1开始
* @param number 每次获取条数,最多10000条
* @return 聊天记录对象
* @throws WxErrorException
*/
@@ -160,7 +163,7 @@ public interface WxMpKefuService {
* </pre>
*
* @param startTime 起始时间
* @param endTime 结束时间
* @param endTime 结束时间
* @return 聊天记录对象
* @throws WxErrorException
*/


+ 30
- 17
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java View File

@@ -19,10 +19,11 @@ public interface WxMpMaterialService {

/**
* 新增临时素材
* @see #mediaUpload(String, String, InputStream)
*
* @param mediaType
* @param file
* @throws WxErrorException
* @see #mediaUpload(String, String, InputStream)
*/
public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException;

@@ -33,6 +34,7 @@ public interface WxMpMaterialService {
* 根据微信文档,视频文件下载不了,会返回null
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/9/677a85e3f3849af35de54bb5516c2521.html">获取临时素材</a>
* </pre>
*
* @param media_id
* @return 保存到本地的临时文件
* @throws WxErrorException
@@ -44,6 +46,7 @@ public interface WxMpMaterialService {
* 上传图文消息内的图片获取URL
* 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E5.86.85.E7.9A.84.E5.9B.BE.E7.89.87.E8.8E.B7.E5.8F.96URL.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
* </pre>
*
* @param file
* @return WxMediaImgUploadResult 返回图片url
* @throws WxErrorException
@@ -63,9 +66,10 @@ public interface WxMpMaterialService {
*
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/15/2d353966323806a202cd2deaafe8e557.html">新增临时素材</a>
* </pre>
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param inputStream 输入流
*
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param inputStream 输入流
* @throws WxErrorException
*/
public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException;
@@ -82,8 +86,9 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
* </pre>
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial}
*
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial}
*/
public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException;

@@ -93,7 +98,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
* </pre>
* @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews}
*
* @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews}
*/
public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException;

@@ -103,7 +109,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
* </pre>
* @param media_id 永久素材的id
*
* @param media_id 永久素材的id
*/
public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException;

@@ -113,7 +120,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
* </pre>
* @param media_id 永久素材的id
*
* @param media_id 永久素材的id
*/
public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException;

@@ -123,7 +131,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
* </pre>
* @param media_id 永久素材的id
*
* @param media_id 永久素材的id
*/
public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException;

@@ -133,7 +142,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html
* </pre>
* @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate}
*
* @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate}
*/
public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException;

@@ -143,7 +153,8 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html
* </pre>
* @param media_id 永久素材的id
*
* @param media_id 永久素材的id
*/
public boolean materialDelete(String media_id) throws WxErrorException;

@@ -162,8 +173,9 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
* </pre>
* @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
* @param count 返回素材的数量,取值在1到20之间
*
* @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
* @param count 返回素材的数量,取值在1到20之间
*/
public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException;

@@ -173,9 +185,10 @@ public interface WxMpMaterialService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
* </pre>
* @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
* @param count 返回素材的数量,取值在1到20之间
*
* @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
* @param count 返回素材的数量,取值在1到20之间
*/
public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException;



+ 3
- 6
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java View File

@@ -2,16 +2,11 @@ package me.chanjar.weixin.mp.api;

import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*;

import java.io.File;
import java.util.Date;

/**
* 菜单相关操作接口
* @author Binary Wang
*
* @author Binary Wang
*/
public interface WxMpMenuService {

@@ -38,6 +33,7 @@ public interface WxMpMenuService {
* 删除个性化菜单接口
* 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
* </pre>
*
* @param menuid
*/
public void menuDelete(String menuid) throws WxErrorException;
@@ -55,6 +51,7 @@ public interface WxMpMenuService {
* 测试个性化菜单匹配结果
* 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
* </pre>
*
* @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。
*/
public WxMenu menuTryMatch(String userid) throws WxErrorException;


+ 77
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java View File

@@ -0,0 +1,77 @@
package me.chanjar.weixin.mp.api;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;

import java.io.File;

/**
* 二维码相关操作接口
*
* @author Binary Wang
*/
public interface WxMpQrcodeService {

/**
* <pre>
* 换取临时二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param scene_id 参数。
* @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒
*/
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException;

/**
* <pre>
* 换取永久二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000)
*/
public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException;

/**
* <pre>
* 换取永久字符串二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param scene_str 参数。字符串类型长度现在为1到64
*/
public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException;

/**
* <pre>
* 换取二维码图片文件,jpg格式
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param ticket 二维码ticket
*/
public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException;

/**
* <pre>
* 换取二维码图片url地址(可以选择是否生成压缩的网址)
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param ticket 二维码ticket
* @param needShortUrl 是否需要压缩的二维码地址
*/
public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException;

/**
* <pre>
* 换取二维码图片url地址
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param ticket 二维码ticket
*/
public String qrCodePictureUrl(String ticket) throws WxErrorException;

}

+ 152
- 282
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java View File

@@ -1,40 +1,14 @@
package me.chanjar.weixin.mp.api;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import me.chanjar.weixin.common.bean.WxCardApiSignature;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
import me.chanjar.weixin.mp.bean.WxMpGroup;
import me.chanjar.weixin.mp.bean.WxMpIndustry;
import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage;
import me.chanjar.weixin.mp.bean.WxMpMassNews;
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage;
import me.chanjar.weixin.mp.bean.WxMpMassVideo;
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.result.*;

import java.text.SimpleDateFormat;
import java.util.Map;

/**
* 微信API的Service
@@ -42,6 +16,7 @@ import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
public interface WxMpService {

public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

/**
* <pre>
* 验证推送过来的消息的正确性
@@ -52,6 +27,7 @@ public interface WxMpService {

/**
* 获取access_token, 不强制刷新access_token
*
* @see #getAccessToken(boolean)
*/
public String getAccessToken() throws WxErrorException;
@@ -64,15 +40,17 @@ public interface WxMpService {
* 另:本service的所有方法都会在access_token过期是调用此方法
*
* 程序员在非必要情况下尽量不要主动调用此方法
*
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
* </pre>
*
* @param forceRefresh 强制刷新
*/
public String getAccessToken(boolean forceRefresh) throws WxErrorException;

/**
* 获得jsapi_ticket,不强制刷新jsapi_ticket
*
* @see #getJsapiTicket(boolean)
*/
public String getJsapiTicket() throws WxErrorException;
@@ -84,6 +62,7 @@ public interface WxMpService {
*
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
* </pre>
*
* @param forceRefresh 强制刷新
*/
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException;
@@ -111,6 +90,7 @@ public interface WxMpService {
*
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* </pre>
*
* @param news
* @throws WxErrorException
* @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassGroupMessage)
@@ -123,6 +103,7 @@ public interface WxMpService {
* 上传群发用的视频,上传后才能群发视频消息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* </pre>
*
* @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassGroupMessage)
* @see #massOpenIdsMessageSend(me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage)
*/
@@ -148,146 +129,12 @@ public interface WxMpService {
*/
public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 创建分组
* 最多支持创建500个分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
* @param name 分组名字(30个字符以内)
*/
public WxMpGroup groupCreate(String name) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 查询所有分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
*/
public List<WxMpGroup> groupGet() throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 查询用户所在分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
* </pre>
* @param openid 微信用户的openid
*/
public long userGetGroup(String openid) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 修改分组名
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
*
* 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
* </pre>
* @param group 要更新的group,group的id,name必须设置
*/
public void groupUpdate(WxMpGroup group) throws WxErrorException;

/**
* <pre>
* 分组管理接口 - 移动用户分组
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
*
* 如果to_groupid为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
* </pre>
* @param openid 用户openid
* @param to_groupid 移动到的分组id
*/
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException;

/**
* <pre>
* 设置用户备注名接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=设置用户备注名接口
* </pre>
* @param openid 用户openid
* @param remark 备注名
*/
public void userUpdateRemark(String openid, String remark) throws WxErrorException;

/**
* <pre>
* 获取用户基本信息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取用户基本信息
* </pre>
* @param openid 用户openid
* @param lang 语言,zh_CN 简体(默认),zh_TW 繁体,en 英语
*/
public WxMpUser userInfo(String openid, String lang) throws WxErrorException;

/**
* <pre>
* 获取关注者列表
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表
* </pre>
* @param next_openid 可选,第一个拉取的OPENID,null为从头开始拉取
*/
public WxMpUserList userList(String next_openid) throws WxErrorException;

/**
* <pre>
* 换取临时二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
* @param scene_id 参数。
* @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒
*/
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException;

/**
* <pre>
* 换取永久二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
* @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000)
*/
public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException;

/**
* <pre>
* 换取永久字符串二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
*
* @param scene_str 参数。字符串类型长度现在为1到64
*/
public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException;

/**
* <pre>
* 换取二维码图片文件,jpg格式
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
* @param ticket 二维码ticket
*/
public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException;

/**
* <pre>
* 换取二维码图片url地址(可以选择是否生成压缩的网址)
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
* @param ticket 二维码ticket
* @param needShortUrl 是否需要压缩的二维码地址
*/
public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException;
/**
* <pre>
* 换取二维码图片url地址
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* </pre>
* @param ticket 二维码ticket
*/
public String qrCodePictureUrl(String ticket) throws WxErrorException;

/**
* <pre>
* 长链接转短链接接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
* </pre>
*
* @param long_url
*/
public String shortUrl(String long_url) throws WxErrorException;
@@ -297,9 +144,10 @@ public interface WxMpService {
* 发送模板消息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=模板消息接口
* </pre>
*
* @param templateMessage
* @throws WxErrorException
* @return msgid
* @throws WxErrorException
*/
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException;

@@ -316,6 +164,7 @@ public interface WxMpService {
* 构造oauth2授权的url连接
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
* </pre>
*
* @param scope
* @param state
* @return url
@@ -327,8 +176,8 @@ public interface WxMpService {
* 构造oauth2授权的url连接
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
* </pre>
* @param redirectURI
* 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode
*
* @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode
* @param scope
* @param state
* @return url
@@ -354,8 +203,9 @@ public interface WxMpService {
* <pre>
* 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以
* </pre>
*
* @param oAuth2AccessToken
* @param lang zh_CN, zh_TW, en
* @param lang zh_CN, zh_TW, en
*/
public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException;

@@ -363,6 +213,7 @@ public interface WxMpService {
* <pre>
* 验证oauth2的access token是否有效
* </pre>
*
* @param oAuth2AccessToken
*/
public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken);
@@ -375,26 +226,6 @@ public interface WxMpService {
*/
String[] getCallbackIP() throws WxErrorException;

/**
* <pre>
* 获取用户增减数据
* http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
* </pre>
* @param beginDate 最大时间跨度7天
* @param endDate endDate不能早于begingDate
*/
List<WxMpUserSummary> getUserSummary(Date beginDate, Date endDate) throws WxErrorException;

/**
* <pre>
* 获取累计用户数据
* http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
* </pre>
* @param beginDate 最大时间跨度7天
* @param endDate endDate不能早于begingDate
*/
List<WxMpUserCumulate> getUserCumulate(Date beginDate, Date endDate) throws WxErrorException;

/**
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
*/
@@ -438,13 +269,14 @@ public interface WxMpService {
/**
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
* @param openId 支付人openId
*
* @param openId 支付人openId
* @param outTradeNo 商户端对应订单号
* @param amt 金额(单位元)
* @param body 商品描述
* @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @param amt 金额(单位元)
* @param body 商品描述
* @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map<String, String>) instead
*/
@Deprecated
@@ -454,8 +286,7 @@ public interface WxMpService {
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
*
* @param parameters
* All required/optional parameters for weixin payment
* @param parameters All required/optional parameters for weixin payment
* @throws IllegalArgumentException
*/
WxMpPrepayIdResult getPrepayId(Map<String, String> parameters);
@@ -463,21 +294,22 @@ public interface WxMpService {
/**
* 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
* @param parameters
* the required or optional parameters
*
* @param parameters the required or optional parameters
*/
Map<String, String> getPayInfo(Map<String, String> parameters) throws WxErrorException;
Map<String, String> getPayInfo(Map<String, String> parameters) throws WxErrorException;
/**
* 该接口调用“统一下单”接口,并拼装NATIVE发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
* tradeType 交易类型 NATIVE (其他交易类型JSAPI,APP,WAP)
* @param productId 商户商品ID
* tradeType 交易类型 NATIVE (其他交易类型JSAPI,APP,WAP)
*
* @param productId 商户商品ID
* @param outTradeNo 商户端对应订单号
* @param amt 金额(单位元)
* @param body 商品描述
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @param amt 金额(单位元)
* @param body 商品描述
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead
*/
@Deprecated
@@ -487,12 +319,13 @@ public interface WxMpService {
* 该接口调用“统一下单”接口,并拼装JSAPI发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
* tradeType 交易类型 JSAPI(其他交易类型NATIVE,APP,WAP)
* @param openId 支付人openId
*
* @param openId 支付人openId
* @param outTradeNo 商户端对应订单号
* @param amt 金额(单位元)
* @param body 商品描述
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @param amt 金额(单位元)
* @param body 商品描述
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead
*/
@Deprecated
@@ -501,6 +334,7 @@ public interface WxMpService {
/**
* 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
*
* @param transactionId
* @param outTradeNo
*/
@@ -509,6 +343,7 @@ public interface WxMpService {
/**
* 读取支付结果通知
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*
* @param xmlData
*/
WxMpPayCallback getJSSDKCallbackData(String xmlData);
@@ -516,12 +351,13 @@ public interface WxMpService {
/**
* 微信支付-申请退款
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
*
* @param parameters 需要传入的退款参数的Map。以下几项为参数的必须项:<br/>
* <li/> transaction_id
* <li/> out_trade_no (仅在上述transaction_id为空时是必须项)
* <li/> out_refund_no
* <li/> total_fee
* <li/> refund_fee
* <li/> transaction_id
* <li/> out_trade_no (仅在上述transaction_id为空时是必须项)
* <li/> out_refund_no
* <li/> total_fee
* <li/> refund_fee
* @return 退款操作结果
* @throws WxErrorException
*/
@@ -532,39 +368,41 @@ public interface WxMpService {
* 计算Map键值对是否和签名相符,
* 按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的 格式(即 key1=value1&key2=value2...)拼接成字符串
* </pre>
*
* @param kvm
* @param signature
*/
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);

/**
* 发送微信红包给个人用户
*
* 需要传入的必填参数如下:
* mch_billno//商户订单号
* send_name//商户名称
* re_openid//用户openid
* total_amount//红包总额
* total_num//红包发放总人数
* wishing//红包祝福语
* client_ip//服务器Ip地址
* act_name//活动名称
* remark //备注
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5
*
* 使用现金红包功能需要在xml配置文件中额外设置:
* <partnerId></partnerId>微信商户平台ID
* <partnerKey></partnerKey>商户平台设置的API密钥
*
* @param parameters
*/
* 发送微信红包给个人用户
* <p>
* 需要传入的必填参数如下:
* mch_billno//商户订单号
* send_name//商户名称
* re_openid//用户openid
* total_amount//红包总额
* total_num//红包发放总人数
* wishing//红包祝福语
* client_ip//服务器Ip地址
* act_name//活动名称
* remark //备注
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5
* <p>
* 使用现金红包功能需要在xml配置文件中额外设置:
* <partnerId></partnerId>微信商户平台ID
* <partnerKey></partnerKey>商户平台设置的API密钥
*
* @param parameters
*/
public WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException;

/**
* 获得卡券api_ticket,不强制刷新卡券api_ticket
* @see #getCardApiTicket(boolean)
*
* @return 卡券api_ticket
* @throws WxErrorException
* @see #getCardApiTicket(boolean)
*/
public String getCardApiTicket() throws WxErrorException;

@@ -575,6 +413,7 @@ public interface WxMpService {
*
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94.9F.E6.88.90.E7.AE.97.E6.B3.95
* </pre>
*
* @param forceRefresh 强制刷新
* @return 卡券api_ticket
* @throws WxErrorException
@@ -591,15 +430,16 @@ public interface WxMpService {
* </pre>
*
* @param optionalSignParam 参与签名的参数数组。
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
* @return 卡券Api签名对象
*/
public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws
WxErrorException;
WxErrorException;

/**
* 卡券Code解码
*
* @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得
* @return 解密后的Code
* @throws WxErrorException
@@ -608,14 +448,15 @@ public interface WxMpService {

/**
* 卡券Code查询
* @param cardId 卡券ID代表一类卡券
* @param code 单张卡券的唯一标准
*
* @param cardId 卡券ID代表一类卡券
* @param code 单张卡券的唯一标准
* @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同
* @return WxMpCardResult对象
* @throws WxErrorException
*/
public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume)
throws WxErrorException;
throws WxErrorException;

/**
* 卡券Code核销。核销失败会抛出异常
@@ -638,51 +479,55 @@ public interface WxMpService {
*/
public String consumeCardCode(String code, String cardId) throws WxErrorException;

/**
* 卡券Mark接口。
* 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住),
* 才能进一步调用核销接口,否则报错。
* @param code 卡券的code码
* @param cardId 卡券的ID
* @param openId 用券用户的openid
* @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用
* @throws WxErrorException
*/
/**
* 卡券Mark接口。
* 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住),
* 才能进一步调用核销接口,否则报错。
*
* @param code 卡券的code码
* @param cardId 卡券的ID
* @param openId 用券用户的openid
* @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用
* @throws WxErrorException
*/
public void markCardCode(String code, String cardId, String openId, boolean isMark) throws
WxErrorException;
WxErrorException;

/**
* 查看卡券详情接口
* 详见 https://mp.weixin.qq.com/wiki/14/8dd77aeaee85f922db5f8aa6386d385e.html#.E6.9F.A5.E7.9C.8B.E5.8D.A1.E5.88.B8.E8.AF.A6.E6.83.85
*
* @param cardId 卡券的ID
* @return 返回的卡券详情JSON字符串
* <br> [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。
* <br> 可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。
* <br> [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。
* <br> 可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。
* @throws WxErrorException
*/
public String getCardDetail(String cardId) throws WxErrorException;

/**
* <pre>
* 预览接口
* 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E9.A2.84.E8.A7.88.E6.8E.A5.E5.8F.A3.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
* </pre>
* @param wxMpMassPreviewMessage
* @return wxMpMassSendResult
* @throws WxErrorException
*/
* <pre>
* 预览接口
* 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E9.A2.84.E8.A7.88.E6.8E.A5.E5.8F.A3.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
* </pre>
*
* @param wxMpMassPreviewMessage
* @return wxMpMassSendResult
* @throws WxErrorException
*/
public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception;

/**
* <pre>
* 设置所属行业
* 官方文档中暂未告知响应内容
* 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A
* </pre>
* @param wxMpIndustry
* @return JsonObject
* @throws WxErrorException
*/
* <pre>
* 设置所属行业
* 官方文档中暂未告知响应内容
* 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A
* </pre>
*
* @param wxMpIndustry
* @return JsonObject
* @throws WxErrorException
*/
String setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException;

/***
@@ -695,28 +540,53 @@ public interface WxMpService {
* @throws WxErrorException
*/
WxMpIndustry getIndustry() throws WxErrorException;

/**
* 获取WxMpConfigStorage 对象
*
* @return WxMpConfigStorage
*/
WxMpConfigStorage getWxMpConfigStorage();

/**
* 返回客服接口方法实现类,以方便调用个其各种接口
*
* @return WxMpKefuService
*/
*/
WxMpKefuService getKefuService();

/**
* 返回素材相关接口的方法实现类,以方便调用个其各种接口
*
* @return WxMpMaterialService
*/
WxMpMaterialService getMaterialService();

/**
* 返回素材相关接口的方法实现类,以方便调用个其各种接口
* 返回菜单相关接口的方法实现类,以方便调用个其各种接口
*
* @return WxMpMenuService
*/
WxMpMenuService getMenuService();

/**
* 获取WxMpConfigStorage 对象
* @return WxMpConfigStorage
* 返回用户相关接口的方法实现类,以方便调用个其各种接口
*
* @return WxMpUserService
*/
WxMpConfigStorage getWxMpConfigStorage();
WxMpUserService getUserService();

/**
* 返回用户分组相关接口的方法实现类,以方便调用个其各种接口
*
* @return WxMpGroupService
*/
WxMpGroupService getGroupService();

/**
* 返回二维码相关接口的方法实现类,以方便调用个其各种接口
*
* @return WxMpQrcodeService
*/
WxMpQrcodeService getQrcodeService();
}

+ 46
- 253
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java View File

@@ -1,46 +1,10 @@
package me.chanjar.weixin.mp.api;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.http.Consts;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.*;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.thoughtworks.xstream.XStream;

import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.WxCardApiSignature;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
@@ -51,45 +15,32 @@ import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.RandomUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.http.DefaultApacheHttpHttpClientBuilder;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.http.*;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpMenuServiceImpl;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
import me.chanjar.weixin.mp.bean.WxMpGroup;
import me.chanjar.weixin.mp.bean.WxMpIndustry;
import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage;
import me.chanjar.weixin.mp.bean.WxMpMassNews;
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage;
import me.chanjar.weixin.mp.bean.WxMpMassVideo;
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor;
import me.chanjar.weixin.mp.api.impl.*;
import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import org.apache.http.Consts;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;

import java.io.IOException;
import java.io.StringReader;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.Map.Entry;

public class WxMpServiceImpl implements WxMpService {

@@ -118,6 +69,12 @@ public class WxMpServiceImpl implements WxMpService {

protected WxMpMenuService menuService = new WxMpMenuServiceImpl(this);

protected WxMpUserService userService = new WxMpUserServiceImpl(this);

protected WxMpGroupService groupService = new WxMpGroupServiceImpl(this);

protected WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this);

protected CloseableHttpClient httpClient;

protected HttpHost httpProxy;
@@ -266,158 +223,6 @@ public class WxMpServiceImpl implements WxMpService {
return WxMpMassSendResult.fromJson(responseContent);
}

@Override
public WxMpGroup groupCreate(String name) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/create";
JsonObject json = new JsonObject();
JsonObject groupJson = new JsonObject();
json.add("group", groupJson);
groupJson.addProperty("name", name);

String responseContent = execute(
new SimplePostRequestExecutor(),
url,
json.toString());
return WxMpGroup.fromJson(responseContent);
}

@Override
public List<WxMpGroup> groupGet() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/get";
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
/*
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} }
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] }
*/
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("groups"),
new TypeToken<List<WxMpGroup>>() {
}.getType());
}

@Override
public long userGetGroup(String openid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/getid";
JsonObject o = new JsonObject();
o.addProperty("openid", openid);
String responseContent = execute(new SimplePostRequestExecutor(), url, o.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid"));
}

@Override
public void groupUpdate(WxMpGroup group) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/update";
execute(new SimplePostRequestExecutor(), url, group.toJson());
}

@Override
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/members/update";
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("to_groupid", to_groupid);
execute(new SimplePostRequestExecutor(), url, json.toString());
}

@Override
public void userUpdateRemark(String openid, String remark) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark";
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("remark", remark);
execute(new SimplePostRequestExecutor(), url, json.toString());
}

@Override
public WxMpUser userInfo(String openid, String lang) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/user/info";
lang = lang == null ? "zh_CN" : lang;
String responseContent = execute(new SimpleGetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang);
return WxMpUser.fromJson(responseContent);
}

@Override
public WxMpUserList userList(String next_openid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/user/get";
String responseContent = execute(new SimpleGetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid);
return WxMpUserList.fromJson(responseContent);
}

@Override
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_SCENE");
if (expire_seconds != null) {
json.addProperty("expire_seconds", expire_seconds);
}
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_SCENE");
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_STR_SCENE");
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_str", scene_str);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException {
String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode";
return execute(new QrCodeRequestExecutor(), url, ticket);
}

@Override
public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException {
String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
try {
String resultUrl = String.format(url,
URLEncoder.encode(ticket, StandardCharsets.UTF_8.name()));
if(needShortUrl){
return this.shortUrl(resultUrl);
}
return resultUrl;
} catch (UnsupportedEncodingException e) {
WxError error = WxError.newBuilder().setErrorCode(-1)
.setErrorMsg(e.getMessage()).build();
throw new WxErrorException(error);
}
}
@Override
public String qrCodePictureUrl(String ticket) throws WxErrorException {
return qrCodePictureUrl(ticket, false);
}

@Override
public String shortUrl(String long_url) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/shorturl";
@@ -562,33 +367,6 @@ public class WxMpServiceImpl implements WxMpService {
return ipArray;
}


@Override
public List<WxMpUserSummary> getUserSummary(Date beginDate, Date endDate) throws WxErrorException {
String url = "https://api.weixin.qq.com/datacube/getusersummary";
JsonObject param = new JsonObject();
param.addProperty("begin_date", SIMPLE_DATE_FORMAT.format(beginDate));
param.addProperty("end_date", SIMPLE_DATE_FORMAT.format(endDate));
String responseContent = post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"),
new TypeToken<List<WxMpUserSummary>>() {
}.getType());
}

@Override
public List<WxMpUserCumulate> getUserCumulate(Date beginDate, Date endDate) throws WxErrorException {
String url = "https://api.weixin.qq.com/datacube/getusercumulate";
JsonObject param = new JsonObject();
param.addProperty("begin_date", SIMPLE_DATE_FORMAT.format(beginDate));
param.addProperty("end_date", SIMPLE_DATE_FORMAT.format(endDate));
String responseContent = post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"),
new TypeToken<List<WxMpUserCumulate>>() {
}.getType());
}

@Override
public String get(String url, String queryParam) throws WxErrorException {
return execute(new SimpleGetRequestExecutor(), url, queryParam);
@@ -1255,4 +1033,19 @@ public class WxMpServiceImpl implements WxMpService {
return this.menuService;
}

@Override
public WxMpUserService getUserService() {
return this.userService;
}

@Override
public WxMpGroupService getGroupService() {
return this.groupService;
}

@Override
public WxMpQrcodeService getQrcodeService() {
return this.qrCodeService;
}

}

+ 72
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java View File

@@ -0,0 +1,72 @@
package me.chanjar.weixin.mp.api;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;

import java.util.Date;
import java.util.List;

/**
* 用户管理和统计相关操作接口
*
* @author Binary Wang
*/
public interface WxMpUserService {

/**
* <pre>
* 设置用户备注名接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=设置用户备注名接口
* </pre>
*
* @param openid 用户openid
* @param remark 备注名
*/
public void userUpdateRemark(String openid, String remark) throws WxErrorException;

/**
* <pre>
* 获取用户基本信息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取用户基本信息
* </pre>
*
* @param openid 用户openid
* @param lang 语言,zh_CN 简体(默认),zh_TW 繁体,en 英语
*/
public WxMpUser userInfo(String openid, String lang) throws WxErrorException;

/**
* <pre>
* 获取关注者列表
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表
* </pre>
*
* @param next_openid 可选,第一个拉取的OPENID,null为从头开始拉取
*/
public WxMpUserList userList(String next_openid) throws WxErrorException;

/**
* <pre>
* 获取用户增减数据
* http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
* </pre>
*
* @param beginDate 最大时间跨度7天
* @param endDate endDate不能早于begingDate
*/
List<WxMpUserSummary> dataCubeUserSummary(Date beginDate, Date endDate) throws WxErrorException;

/**
* <pre>
* 获取累计用户数据
* http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
* </pre>
*
* @param beginDate 最大时间跨度7天
* @param endDate endDate不能早于begingDate
*/
List<WxMpUserCumulate> dataCubeUserCumulate(Date beginDate, Date endDate) throws WxErrorException;
}

+ 85
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java View File

@@ -0,0 +1,85 @@
package me.chanjar.weixin.mp.api.impl;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.mp.api.WxMpGroupService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpGroup;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;

import java.io.StringReader;
import java.util.List;

/**
* Created by Binary Wang on 2016/7/21.
*/
public class WxMpGroupServiceImpl implements WxMpGroupService {
private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/groups";
private WxMpService wxMpService;

public WxMpGroupServiceImpl(WxMpService wxMpService) {
this.wxMpService = wxMpService;
}

@Override
public WxMpGroup groupCreate(String name) throws WxErrorException {
String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject();
JsonObject groupJson = new JsonObject();
json.add("group", groupJson);
groupJson.addProperty("name", name);

String responseContent = this.wxMpService.execute(
new SimplePostRequestExecutor(),
url,
json.toString());
return WxMpGroup.fromJson(responseContent);
}

@Override
public List<WxMpGroup> groupGet() throws WxErrorException {
String url = API_URL_PREFIX + "/get";
String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null);
/*
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} }
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] }
*/
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("groups"),
new TypeToken<List<WxMpGroup>>() {
}.getType());
}

@Override
public long userGetGroup(String openid) throws WxErrorException {
String url = API_URL_PREFIX + "/getid";
JsonObject o = new JsonObject();
o.addProperty("openid", openid);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, o.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid"));
}

@Override
public void groupUpdate(WxMpGroup group) throws WxErrorException {
String url = API_URL_PREFIX + "/update";
this.wxMpService.execute(new SimplePostRequestExecutor(), url, group.toJson());
}

@Override
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException {
String url = API_URL_PREFIX + "/members/update";
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("to_groupid", to_groupid);
this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
}

}

+ 23
- 20
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java View File

@@ -7,11 +7,12 @@ import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.mp.api.WxMpMaterialService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.WxMpMaterial;
import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate;
import me.chanjar.weixin.mp.bean.WxMpMaterialNews;
import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.mp.util.http.*;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
@@ -27,6 +28,8 @@ import java.util.UUID;
* Created by Binary Wang on 2016/7/21.
*/
public class WxMpMaterialServiceImpl implements WxMpMaterialService {
private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode";
private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode";
private WxMpService wxMpService;

public WxMpMaterialServiceImpl(WxMpService wxMpService) {
@@ -40,19 +43,25 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {

@Override
public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
String url = MEDIA_API_URL_PREFIX + "/upload?type=" + mediaType;
return this.wxMpService.execute(new MediaUploadRequestExecutor(), url, file);
}

@Override
public File mediaDownload(String media_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/media/get";
String url = MEDIA_API_URL_PREFIX + "/get";
return this.wxMpService.execute(new MediaDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, "media_id=" + media_id);
}

@Override
public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException {
String url = MEDIA_API_URL_PREFIX + "/uploadimg";
return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file);
}

@Override
public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=" + mediaType;
String url = MATERIAL_API_URL_PREFIX + "/add_material?type=" + mediaType;
return this.wxMpService.execute(new MaterialUploadRequestExecutor(), url, material);
}

@@ -61,32 +70,32 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {
if (news == null || news.isEmpty()) {
throw new IllegalArgumentException("news is empty!");
}
String url = "https://api.weixin.qq.com/cgi-bin/material/add_news";
String url = MATERIAL_API_URL_PREFIX + "/add_news";
String responseContent = this.wxMpService.post(url, news.toJson());
return WxMpMaterialUploadResult.fromJson(responseContent);
}

@Override
public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
String url = MATERIAL_API_URL_PREFIX + "/get_material";
return this.wxMpService.execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, media_id);
}

@Override
public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
String url = MATERIAL_API_URL_PREFIX + "/get_material";
return this.wxMpService.execute(new MaterialVideoInfoRequestExecutor(), url, media_id);
}

@Override
public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
String url = MATERIAL_API_URL_PREFIX + "/get_material";
return this.wxMpService.execute(new MaterialNewsInfoRequestExecutor(), url, media_id);
}

@Override
public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/update_news";
String url = MATERIAL_API_URL_PREFIX + "/update_news";
String responseText = this.wxMpService.post(url, wxMpMaterialArticleUpdate.toJson());
WxError wxError = WxError.fromJson(responseText);
if (wxError.getErrorCode() == 0) {
@@ -98,13 +107,13 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {

@Override
public boolean materialDelete(String media_id) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/del_material";
String url = MATERIAL_API_URL_PREFIX + "/del_material";
return this.wxMpService.execute(new MaterialDeleteRequestExecutor(), url, media_id);
}

@Override
public WxMpMaterialCountResult materialCount() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount";
String url = MATERIAL_API_URL_PREFIX + "/get_materialcount";
String responseText = this.wxMpService.get(url, null);
WxError wxError = WxError.fromJson(responseText);
if (wxError.getErrorCode() == 0) {
@@ -116,7 +125,7 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {

@Override
public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
String url = MATERIAL_API_URL_PREFIX + "/batchget_material";
Map<String, Object> params = new HashMap<>();
params.put("type", WxConsts.MATERIAL_NEWS);
params.put("offset", offset);
@@ -132,7 +141,7 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {

@Override
public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
String url = MATERIAL_API_URL_PREFIX + "/batchget_material";
Map<String, Object> params = new HashMap<>();
params.put("type", type);
params.put("offset", offset);
@@ -146,10 +155,4 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService {
}
}

@Override
public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg";
return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file);
}

}

+ 102
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java View File

@@ -0,0 +1,102 @@
package me.chanjar.weixin.mp.api.impl;

import com.google.gson.JsonObject;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
* Created by Binary Wang on 2016/7/21.
*/
public class WxMpQrcodeServiceImpl implements WxMpQrcodeService {
private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode";
private WxMpService wxMpService;

public WxMpQrcodeServiceImpl(WxMpService wxMpService) {
this.wxMpService = wxMpService;
}

@Override
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException {
String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_SCENE");
if (expire_seconds != null) {
json.addProperty("expire_seconds", expire_seconds);
}
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException {
String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_SCENE");
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException {
String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_STR_SCENE");
JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject();
scene.addProperty("scene_str", scene_str);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
}

@Override
public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException {
String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode";
return this.wxMpService.execute(new QrCodeRequestExecutor(), url, ticket);
}

@Override
public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException {
String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
try {
String resultUrl = String.format(url,
URLEncoder.encode(ticket, StandardCharsets.UTF_8.name()));
if (needShortUrl) {
return this.wxMpService.shortUrl(resultUrl);
}

return resultUrl;
} catch (UnsupportedEncodingException e) {
WxError error = WxError.newBuilder().setErrorCode(-1)
.setErrorMsg(e.getMessage()).build();
throw new WxErrorException(error);
}
}

@Override
public String qrCodePictureUrl(String ticket) throws WxErrorException {
return qrCodePictureUrl(ticket, false);
}

}

+ 83
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java View File

@@ -0,0 +1,83 @@
package me.chanjar.weixin.mp.api.impl;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;

import java.io.StringReader;
import java.util.Date;
import java.util.List;

/**
* Created by Binary Wang on 2016/7/21.
*/
public class WxMpUserServiceImpl implements WxMpUserService {
private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/user";
private WxMpService wxMpService;

public WxMpUserServiceImpl(WxMpService wxMpService) {
this.wxMpService = wxMpService;
}

@Override
public void userUpdateRemark(String openid, String remark) throws WxErrorException {
String url = API_URL_PREFIX + "/info/updateremark";
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("remark", remark);
this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
}

@Override
public WxMpUser userInfo(String openid, String lang) throws WxErrorException {
String url = API_URL_PREFIX + "/info";
lang = lang == null ? "zh_CN" : lang;
String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang);
return WxMpUser.fromJson(responseContent);
}

@Override
public WxMpUserList userList(String next_openid) throws WxErrorException {
String url = API_URL_PREFIX + "/get";
String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid);
return WxMpUserList.fromJson(responseContent);
}

@Override
public List<WxMpUserSummary> dataCubeUserSummary(Date beginDate, Date endDate) throws WxErrorException {
String url = "https://api.weixin.qq.com/datacube/getusersummary";
JsonObject param = new JsonObject();
param.addProperty("begin_date", WxMpService.SIMPLE_DATE_FORMAT.format(beginDate));
param.addProperty("end_date", WxMpService.SIMPLE_DATE_FORMAT.format(endDate));
String responseContent = this.wxMpService.post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"),
new TypeToken<List<WxMpUserSummary>>() {
}.getType());
}

@Override
public List<WxMpUserCumulate> dataCubeUserCumulate(Date beginDate, Date endDate) throws WxErrorException {
String url = "https://api.weixin.qq.com/datacube/getusercumulate";
JsonObject param = new JsonObject();
param.addProperty("begin_date", WxMpService.SIMPLE_DATE_FORMAT.format(beginDate));
param.addProperty("end_date", WxMpService.SIMPLE_DATE_FORMAT.format(endDate));
String responseContent = this.wxMpService.post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"),
new TypeToken<List<WxMpUserCumulate>>() {
}.getType());
}
}

+ 5
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java View File

@@ -45,4 +45,9 @@ public class WxMpQrCodeTicket implements Serializable {
public static WxMpQrCodeTicket fromJson(String json) {
return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpQrCodeTicket.class);
}

@Override
public String toString() {
return WxMpGsonBuilder.INSTANCE.create().toJson(this);
}
}

+ 5
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java View File

@@ -44,4 +44,9 @@ public class WxMpUserList {
public static WxMpUserList fromJson(String json) {
return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpUserList.class);
}

@Override
public String toString() {
return WxMpGsonBuilder.INSTANCE.create().toJson(this);
}
}

+ 2
- 2
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java View File

@@ -63,7 +63,7 @@ public class WxMpMassMessageAPITest {
WxMpMassGroupMessage massMessage = new WxMpMassGroupMessage();
massMessage.setMsgtype(WxConsts.MASS_MSG_TEXT);
massMessage.setContent("测试群发消息\n欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");
massMessage.setGroupId(wxService.groupGet().get(0).getId());
massMessage.setGroupId(wxService.getGroupService().groupGet().get(0).getId());
WxMpMassSendResult massResult = wxService.massGroupMessageSend(massMessage);
Assert.assertNotNull(massResult);
@@ -75,7 +75,7 @@ public class WxMpMassMessageAPITest {
WxMpMassGroupMessage massMessage = new WxMpMassGroupMessage();
massMessage.setMsgtype(massMsgType);
massMessage.setMediaId(mediaId);
massMessage.setGroupId(wxService.groupGet().get(0).getId());
massMessage.setGroupId(wxService.getGroupService().groupGet().get(0).getId());

WxMpMassSendResult massResult = wxService.massGroupMessageSend(massMessage);
Assert.assertNotNull(massResult);


+ 1
- 39
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java View File

@@ -1,37 +1,19 @@
package me.chanjar.weixin.mp.api;

import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage;
import me.chanjar.weixin.mp.bean.WxMpMassNews;
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
import me.chanjar.weixin.mp.bean.WxMpMassVideo;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
*
* @author chanjarster
*
*/
@Test(groups = "miscAPI", dependsOnGroups = { "baseAPI"})
@Test(groups = "miscAPI")
@Guice(modules = ApiTestModule.class)
public class WxMpMiscAPITest {

@@ -46,24 +28,4 @@ public class WxMpMiscAPITest {
Assert.assertNotEquals(ipArray.length, 0);
}

@Test
public void testGetUserSummary() throws WxErrorException, ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = simpleDateFormat.parse("2015-01-01");
Date endDate = simpleDateFormat.parse("2015-01-02");
List<WxMpUserSummary> summaries = wxService.getUserSummary(beginDate, endDate);
System.out.println(summaries);
Assert.assertNotNull(summaries);
}

@Test
public void testGetUserCumulate() throws WxErrorException, ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = simpleDateFormat.parse("2015-01-01");
Date endDate = simpleDateFormat.parse("2015-01-02");
List<WxMpUserCumulate> cumulates = wxService.getUserCumulate(beginDate, endDate);
System.out.println(cumulates);
Assert.assertNotNull(cumulates);
}

}

+ 0
- 53
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java View File

@@ -1,53 +0,0 @@
package me.chanjar.weixin.mp.api;

import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

/**
* 测试用户相关的接口
* @author chanjarster
*
*/
@Test(groups = "userAPI", dependsOnGroups = { "baseAPI", "groupAPI" })
@Guice(modules = ApiTestModule.class)
public class WxMpUserAPITest {

@Inject
protected WxMpServiceImpl wxService;

public void testUserUpdateRemark() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage;
wxService.userUpdateRemark(configProvider.getOpenId(), "测试备注名");
}

public void testUserInfo() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage;
WxMpUser user = wxService.userInfo(configProvider.getOpenId(), null);
Assert.assertNotNull(user);
}
public void testUserList() throws WxErrorException {
WxMpUserList wxMpUserList = wxService.userList(null);
Assert.assertNotNull(wxMpUserList);
Assert.assertFalse(wxMpUserList.getCount() == -1);
Assert.assertFalse(wxMpUserList.getTotal() == -1);
Assert.assertFalse(wxMpUserList.getOpenIds().size() == -1);
}
public void testGroupQueryUserGroup() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage;
long groupid = wxService.userGetGroup(configStorage.getOpenId());
Assert.assertTrue(groupid != -1l);
}
public void getGroupMoveUser() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage;
wxService.userUpdateGroup(configStorage.getOpenId(), wxService.groupGet().get(3).getId());
}
}

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpGroupAPITest.java → weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java View File

@@ -1,7 +1,9 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.mp.api.impl;

import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.WxMpGroup;
import org.testng.Assert;
import org.testng.annotations.Guice;
@@ -14,9 +16,9 @@ import java.util.List;
*
* @author chanjarster
*/
@Test(groups = "groupAPI", dependsOnGroups = "baseAPI")
@Test(groups = "groupAPI")
@Guice(modules = ApiTestModule.class)
public class WxMpGroupAPITest {
public class WxMpGroupServiceImplTest {

@Inject
protected WxMpServiceImpl wxService;
@@ -24,13 +26,13 @@ public class WxMpGroupAPITest {
protected WxMpGroup group;
public void testGroupCreate() throws WxErrorException {
WxMpGroup res = wxService.groupCreate("测试分组1");
WxMpGroup res = this.wxService.getGroupService().groupCreate("测试分组1");
Assert.assertEquals(res.getName(), "测试分组1");
}

@Test(dependsOnMethods="testGroupCreate")
public void testGroupGet() throws WxErrorException {
List<WxMpGroup> groupList = wxService.groupGet();
List<WxMpGroup> groupList = this.wxService.getGroupService().groupGet();
Assert.assertNotNull(groupList);
Assert.assertTrue(groupList.size() > 0);
for (WxMpGroup g : groupList) {
@@ -42,7 +44,7 @@ public class WxMpGroupAPITest {
@Test(dependsOnMethods={"testGroupGet", "testGroupCreate"})
public void getGroupUpdate() throws WxErrorException {
group.setName("分组改名");
wxService.groupUpdate(group);
this.wxService.getGroupService().groupUpdate(group);
}

}

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java → weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java View File

@@ -1,7 +1,9 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.mp.api.impl;

import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.testng.Assert;
import org.testng.annotations.Guice;
@@ -16,35 +18,39 @@ import java.io.File;
*/
@Test(groups = "qrCodeAPI")
@Guice(modules = ApiTestModule.class)
public class WxMpQrCodeAPITest {
public class WxMpQrCodeServiceImplTest {

@Inject
protected WxMpServiceImpl wxService;

public void testQrCodeCreateTmpTicket() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateTmpTicket(1, null);
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateTmpTicket(1, null);
Assert.assertNotNull(ticket.getUrl());
Assert.assertNotNull(ticket.getTicket());
Assert.assertTrue(ticket.getExpire_seconds() != -1);
System.out.println(ticket);
}

public void testQrCodeCreateLastTicket() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1);
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1);
Assert.assertNotNull(ticket.getUrl());
Assert.assertNotNull(ticket.getTicket());
Assert.assertTrue(ticket.getExpire_seconds() == -1);
System.out.println(ticket);
}

public void testQrCodePicture() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1);
File file = this.wxService.qrCodePicture(ticket);
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1);
File file = this.wxService.getQrcodeService().qrCodePicture(ticket);
Assert.assertNotNull(file);
System.out.println(file.getAbsolutePath());
}
public void testQrCodePictureUrl() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1);
String url = this.wxService.qrCodePictureUrl(ticket.getTicket());
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1);
String url = this.wxService.getQrcodeService().qrCodePictureUrl(ticket.getTicket());
Assert.assertNotNull(url);
System.out.println(url);
}

}

+ 85
- 0
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java View File

@@ -0,0 +1,85 @@
package me.chanjar.weixin.mp.api.impl;

import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
* 测试用户相关的接口
*
* @author chanjarster
* @author Binary Wang
*/
@Test(groups = "userAPI")
@Guice(modules = ApiTestModule.class)
public class WxMpUserServiceImplTest {

@Inject
protected WxMpServiceImpl wxService;

public void testUserUpdateRemark() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage();
this.wxService.getUserService().userUpdateRemark(configProvider.getOpenId(), "测试备注名");
}

public void testUserInfo() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage();
WxMpUser user = this.wxService.getUserService().userInfo(configProvider.getOpenId(), null);
Assert.assertNotNull(user);
System.out.println(user);
}

public void testUserList() throws WxErrorException {
WxMpUserList wxMpUserList = this.wxService.getUserService().userList(null);
Assert.assertNotNull(wxMpUserList);
Assert.assertFalse(wxMpUserList.getCount() == -1);
Assert.assertFalse(wxMpUserList.getTotal() == -1);
Assert.assertFalse(wxMpUserList.getOpenIds().size() == -1);
System.out.println(wxMpUserList);
}

public void testGroupQueryUserGroup() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage();
long groupid = this.wxService.getGroupService().userGetGroup(configStorage.getOpenId());
Assert.assertTrue(groupid != -1l);
}

public void testGroupMoveUser() throws WxErrorException {
ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage();
this.wxService.getGroupService().userUpdateGroup(configStorage.getOpenId(), this.wxService.getGroupService().groupGet().get(3).getId());
}

@Test
public void testGetUserSummary() throws WxErrorException, ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = simpleDateFormat.parse("2015-01-01");
Date endDate = simpleDateFormat.parse("2015-01-02");
List<WxMpUserSummary> summaries = this.wxService.getUserService().dataCubeUserSummary(beginDate, endDate);
Assert.assertNotNull(summaries);
System.out.println(summaries);
}

@Test
public void testGetUserCumulate() throws WxErrorException, ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = simpleDateFormat.parse("2015-01-01");
Date endDate = simpleDateFormat.parse("2015-01-02");
List<WxMpUserCumulate> cumulates = this.wxService.getUserService().dataCubeUserCumulate(beginDate, endDate);
Assert.assertNotNull(cumulates);
System.out.println(cumulates);
}

}

+ 3
- 3
weixin-java-mp/src/test/resources/testng.xml View File

@@ -7,10 +7,10 @@
<class name="me.chanjar.weixin.mp.api.WxMpBaseAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpCustomMessageAPITest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpMenuAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpGroupAPITest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpGroupServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.WxMpMassMessageAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpUserAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpQrCodeAPITest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpUserServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpQrCodeServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.WxMpShortUrlAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpMessageRouterTest" />
<class name="me.chanjar.weixin.mp.api.WxMpJsAPITest" />


Loading…
Cancel
Save