Merge pull request #1730 from Wechat-Group/develop

合并develop分支,发布最新正式版
This commit is contained in:
Binary Wang 2020-08-24 00:20:47 +08:00 committed by GitHub
commit 0fcd371f71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
467 changed files with 12371 additions and 3987 deletions

16
pom.xml
View File

@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.8.0</version>
<version>3.9.0</version>
<packaging>pom</packaging>
<name>WxJava - Weixin/Wechat Java SDK</name>
<description>微信开发Java SDK</description>
@ -90,6 +90,11 @@
<email>liuxinghao1988@gmail.com</email>
<url>https://github.com/howardliu-cn</url>
</developer>
<developer>
<name>huangxiaoming</name>
<email>huangxm129@163.com</email>
<url>https://github.com/huangxm129</url>
</developer>
</developers>
<scm>
@ -111,8 +116,8 @@
</modules>
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<httpclient.version>4.5</httpclient.version>
@ -126,11 +131,10 @@
<artifactId>qrcode-utils</artifactId>
<version>1.1</version>
</dependency>
<!-- 由于jodd-http较新的3.8版本需要jdk8故而此处采用较低版本 -->
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<version>5.1.4</version>
<version>5.1.6</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -239,7 +243,7 @@
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<version>3.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<packaging>pom</packaging>
<artifactId>wx-java-spring-boot-starters</artifactId>

View File

@ -18,12 +18,12 @@
wx.miniapp.msgDataFormat = @msgDataFormat # 消息格式XML或者JSON.
# 存储配置redis(可选)
# 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)
wx.miniapp.config-storage.type = jedis # 配置类型: memory(默认), jedis, redistemplate
wx.miniapp.config-storage.type = Jedis # 配置类型: Memory(默认), Jedis, RedisTemplate
wx.miniapp.config-storage.key-prefix = wa # 相关redis前缀配置: wa(默认)
wx.miniapp.config-storage.redis.host = 127.0.0.1
wx.miniapp.config-storage.redis.port = 6379
# http客户端配置
wx.miniapp.config-storage.http-client-type=httpclient # http客户端类型: httpclient(默认)
wx.miniapp.config-storage.http-client-type=HttpClient # http客户端类型: HttpClient(默认), OkHttp, JoddHttp
wx.miniapp.config-storage.http-proxy-host=
wx.miniapp.config-storage.http-proxy-port=
wx.miniapp.config-storage.http-proxy-username=

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -22,13 +22,11 @@
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring.boot.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -1,10 +1,14 @@
package com.binarywang.spring.starter.wxjava.miniapp.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpClientImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceJoddHttpImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaRedisBetterConfigImpl;
import com.binarywang.spring.starter.wxjava.miniapp.enums.HttpClientType;
import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.redis.JedisWxRedisOps;
@ -46,22 +50,35 @@ public class WxMaAutoConfiguration {
@Bean
@ConditionalOnMissingBean(WxMaService.class)
public WxMaService service(WxMaConfig wxMaConfig) {
final WxMaServiceImpl service = new WxMaServiceImpl();
service.setWxMaConfig(wxMaConfig);
return service;
HttpClientType httpClientType = wxMaProperties.getConfigStorage().getHttpClientType();
WxMaService wxMaService;
if (httpClientType == HttpClientType.OkHttp) {
wxMaService = new WxMaServiceOkHttpImpl();
} else if (httpClientType == HttpClientType.JoddHttp) {
wxMaService = new WxMaServiceJoddHttpImpl();
} else if (httpClientType == HttpClientType.HttpClient) {
wxMaService = new WxMaServiceHttpClientImpl();
} else {
wxMaService = new WxMaServiceImpl();
}
wxMaService.setWxMaConfig(wxMaConfig);
return wxMaService;
}
@Bean
@ConditionalOnMissingBean(WxMaConfig.class)
public WxMaConfig wxMaConfig() {
WxMaProperties.StorageType type = wxMaProperties.getConfigStorage().getType();
WxMaDefaultConfigImpl config;
if (type == WxMaProperties.StorageType.jedis) {
config = wxMaInJedisConfigStorage();
} else if (type == WxMaProperties.StorageType.redistemplate) {
config = wxMaInRedisTemplateConfigStorage();
} else {
config = wxMaInMemoryConfigStorage();
switch (wxMaProperties.getConfigStorage().getType()) {
case Jedis:
config = wxMaJedisConfigStorage();
break;
case RedisTemplate:
config = wxMaRedisTemplateConfigStorage();
break;
default:
config = wxMaDefaultConfigStorage();
break;
}
config.setAppid(StringUtils.trimToNull(this.wxMaProperties.getAppid()));
@ -80,52 +97,42 @@ public class WxMaAutoConfiguration {
return config;
}
private WxMaDefaultConfigImpl wxMaInMemoryConfigStorage() {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
return config;
private WxMaDefaultConfigImpl wxMaDefaultConfigStorage() {
return new WxMaDefaultConfigImpl();
}
private WxMaDefaultConfigImpl wxMaInJedisConfigStorage() {
private WxMaDefaultConfigImpl wxMaJedisConfigStorage() {
WxMaProperties.RedisProperties redisProperties = wxMaProperties.getConfigStorage().getRedis();
JedisPool jedisPool;
if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
jedisPool = getJedisPool();
if (StringUtils.isNotEmpty(redisProperties.getHost())) {
JedisPoolConfig config = new JedisPoolConfig();
if (redisProperties.getMaxActive() != null) {
config.setMaxTotal(redisProperties.getMaxActive());
}
if (redisProperties.getMaxIdle() != null) {
config.setMaxIdle(redisProperties.getMaxIdle());
}
if (redisProperties.getMaxWaitMillis() != null) {
config.setMaxWaitMillis(redisProperties.getMaxWaitMillis());
}
if (redisProperties.getMinIdle() != null) {
config.setMinIdle(redisProperties.getMinIdle());
}
config.setTestOnBorrow(true);
config.setTestWhileIdle(true);
jedisPool = new JedisPool(config, redisProperties.getHost(), redisProperties.getPort(),
redisProperties.getTimeout(), redisProperties.getPassword(), redisProperties.getDatabase());
} else {
jedisPool = applicationContext.getBean(JedisPool.class);
}
WxRedisOps redisOps = new JedisWxRedisOps(jedisPool);
WxMaRedisBetterConfigImpl wxMaRedisConfig = new WxMaRedisBetterConfigImpl(redisOps, wxMaProperties.getConfigStorage().getKeyPrefix());
return wxMaRedisConfig;
return new WxMaRedisBetterConfigImpl(redisOps, wxMaProperties.getConfigStorage().getKeyPrefix());
}
private WxMaDefaultConfigImpl wxMaInRedisTemplateConfigStorage() {
private WxMaDefaultConfigImpl wxMaRedisTemplateConfigStorage() {
StringRedisTemplate redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
WxRedisOps redisOps = new RedisTemplateWxRedisOps(redisTemplate);
WxMaRedisBetterConfigImpl wxMaRedisConfig = new WxMaRedisBetterConfigImpl(redisOps, wxMaProperties.getConfigStorage().getKeyPrefix());
return wxMaRedisConfig;
}
private JedisPool getJedisPool() {
WxMaProperties.ConfigStorage storage = wxMaProperties.getConfigStorage();
WxMaProperties.RedisProperties redis = storage.getRedis();
JedisPoolConfig config = new JedisPoolConfig();
if (redis.getMaxActive() != null) {
config.setMaxTotal(redis.getMaxActive());
}
if (redis.getMaxIdle() != null) {
config.setMaxIdle(redis.getMaxIdle());
}
if (redis.getMaxWaitMillis() != null) {
config.setMaxWaitMillis(redis.getMaxWaitMillis());
}
if (redis.getMinIdle() != null) {
config.setMinIdle(redis.getMinIdle());
}
config.setTestOnBorrow(true);
config.setTestWhileIdle(true);
return new JedisPool(config, redis.getHost(), redis.getPort(), redis.getTimeout(), redis.getPassword(),
redis.getDatabase());
return new WxMaRedisBetterConfigImpl(redisOps, wxMaProperties.getConfigStorage().getKeyPrefix());
}
}

View File

@ -0,0 +1,22 @@
package com.binarywang.spring.starter.wxjava.miniapp.enums;
/**
* httpclient类型.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* @date 2020-05-25
*/
public enum HttpClientType {
/**
* HttpClient.
*/
HttpClient,
/**
* OkHttp.
*/
OkHttp,
/**
* JoddHttp.
*/
JoddHttp,
}

View File

@ -0,0 +1,22 @@
package com.binarywang.spring.starter.wxjava.miniapp.enums;
/**
* storage类型.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* @date 2020-05-25
*/
public enum StorageType {
/**
* 内存.
*/
Memory,
/**
* redis(JedisClient).
*/
Jedis,
/**
* redis(RedisTemplate).
*/
RedisTemplate
}

View File

@ -1,10 +1,10 @@
package com.binarywang.spring.starter.wxjava.miniapp.properties;
import com.binarywang.spring.starter.wxjava.miniapp.enums.HttpClientType;
import com.binarywang.spring.starter.wxjava.miniapp.enums.StorageType;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.Serializable;
/**
* 属性配置类.
*
@ -42,16 +42,15 @@ public class WxMaProperties {
/**
* 存储策略
*/
private ConfigStorage configStorage = new ConfigStorage();
private final ConfigStorage configStorage = new ConfigStorage();
@Data
public static class ConfigStorage implements Serializable {
private static final long serialVersionUID = 4815731027000065434L;
public static class ConfigStorage {
/**
* 存储类型.
*/
private StorageType type = StorageType.memory;
private StorageType type = StorageType.Memory;
/**
* 指定key前缀.
@ -61,12 +60,12 @@ public class WxMaProperties {
/**
* redis连接配置.
*/
private RedisProperties redis;
private final RedisProperties redis = new RedisProperties();
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.httpclient;
private HttpClientType httpClientType = HttpClientType.HttpClient;
/**
* http代理主机.
@ -87,37 +86,13 @@ public class WxMaProperties {
* http代理密码.
*/
private String httpProxyPassword;
}
public enum StorageType {
/**
* 内存.
*/
memory,
/**
* redis(JedisClient).
*/
jedis,
/**
* redis(RedisTemplate).
*/
redistemplate
}
public enum HttpClientType {
/**
* HttpClient.
*/
httpclient
}
@Data
public static class RedisProperties implements Serializable {
private static final long serialVersionUID = -5924815351660074401L;
public static class RedisProperties {
/**
* 主机地址.
* 主机地址.不填则从spring容器内获取JedisPool
*/
private String host;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,6 +1,7 @@
package com.binarywang.spring.starter.wxjava.mp.config;
import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
import me.chanjar.weixin.common.api.WxOcrService;
import me.chanjar.weixin.mp.api.*;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
@ -25,9 +26,9 @@ public class WxMpServiceAutoConfiguration {
WxMpProperties.HttpClientType httpClientType = wxMpProperties.getConfigStorage().getHttpClientType();
WxMpService wxMpService;
if (httpClientType == WxMpProperties.HttpClientType.okhttp) {
wxMpService = newWxMpServiceJoddHttpImpl();
} else if (httpClientType == WxMpProperties.HttpClientType.joddhttp) {
wxMpService = newWxMpServiceOkHttpImpl();
} else if (httpClientType == WxMpProperties.HttpClientType.joddhttp) {
wxMpService = newWxMpServiceJoddHttpImpl();
} else if (httpClientType == WxMpProperties.HttpClientType.httpclient) {
wxMpService = newWxMpServiceHttpClientImpl();
} else {
@ -54,130 +55,4 @@ public class WxMpServiceAutoConfiguration {
return new WxMpServiceJoddHttpImpl();
}
@Bean
@Deprecated
public WxMpKefuService wxMpKefuService(WxMpService wxMpService) {
return wxMpService.getKefuService();
}
@Bean
@Deprecated
public WxMpMaterialService wxMpMaterialService(WxMpService wxMpService) {
return wxMpService.getMaterialService();
}
@Bean
@Deprecated
public WxMpMenuService wxMpMenuService(WxMpService wxMpService) {
return wxMpService.getMenuService();
}
@Bean
@Deprecated
public WxMpUserService wxMpUserService(WxMpService wxMpService) {
return wxMpService.getUserService();
}
@Bean
@Deprecated
public WxMpUserTagService wxMpUserTagService(WxMpService wxMpService) {
return wxMpService.getUserTagService();
}
@Bean
@Deprecated
public WxMpQrcodeService wxMpQrcodeService(WxMpService wxMpService) {
return wxMpService.getQrcodeService();
}
@Bean
@Deprecated
public WxMpCardService wxMpCardService(WxMpService wxMpService) {
return wxMpService.getCardService();
}
@Bean
@Deprecated
public WxMpDataCubeService wxMpDataCubeService(WxMpService wxMpService) {
return wxMpService.getDataCubeService();
}
@Bean
@Deprecated
public WxMpUserBlacklistService wxMpUserBlacklistService(WxMpService wxMpService) {
return wxMpService.getBlackListService();
}
@Bean
@Deprecated
public WxMpStoreService wxMpStoreService(WxMpService wxMpService) {
return wxMpService.getStoreService();
}
@Bean
@Deprecated
public WxMpTemplateMsgService wxMpTemplateMsgService(WxMpService wxMpService) {
return wxMpService.getTemplateMsgService();
}
@Bean
@Deprecated
public WxMpSubscribeMsgService wxMpSubscribeMsgService(WxMpService wxMpService) {
return wxMpService.getSubscribeMsgService();
}
@Bean
@Deprecated
public WxMpDeviceService wxMpDeviceService(WxMpService wxMpService) {
return wxMpService.getDeviceService();
}
@Bean
@Deprecated
public WxMpShakeService wxMpShakeService(WxMpService wxMpService) {
return wxMpService.getShakeService();
}
@Bean
@Deprecated
public WxMpMemberCardService wxMpMemberCardService(WxMpService wxMpService) {
return wxMpService.getMemberCardService();
}
@Bean
@Deprecated
public WxMpMassMessageService wxMpMassMessageService(WxMpService wxMpService) {
return wxMpService.getMassMessageService();
}
@Bean
@Deprecated
public WxMpAiOpenService wxMpAiOpenService(WxMpService wxMpService) {
return wxMpService.getAiOpenService();
}
@Bean
@Deprecated
public WxMpWifiService wxMpWifiService(WxMpService wxMpService) {
return wxMpService.getWifiService();
}
@Bean
@Deprecated
public WxMpMarketingService wxMpMarketingService(WxMpService wxMpService) {
return wxMpService.getMarketingService();
}
@Bean
@Deprecated
public WxMpCommentService wxMpCommentService(WxMpService wxMpService) {
return wxMpService.getCommentService();
}
@Bean
@Deprecated
public WxMpOcrService wxMpOcrService(WxMpService wxMpService) {
return wxMpService.getOcrService();
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<artifactId>weixin-graal</artifactId>

View File

@ -1,7 +1,6 @@
package cn.binarywang.wx.graal;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<artifactId>weixin-java-common</artifactId>

View File

@ -1,14 +1,30 @@
package me.chanjar.weixin.common.api;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static me.chanjar.weixin.common.error.WxMpErrorMsgEnum.*;
/**
* 微信开发所使用到的常量类.
*
* @author Daniel Qian & binarywang
*/
public class WxConsts {
/**
* access_token 相关错误代码
* <pre>
* 发生以下情况时尝试刷新access_token
* 40001 获取access_token时AppSecret错误或者access_token无效
* 42001 access_token超时
* 40014 不合法的access_token请开发者认真比对access_token的有效性如是否过期或查看是否正在为恰当的公众号调用接口
* </pre>
*/
public static final List<Integer> ACCESS_TOKEN_ERROR_CODES = Arrays.asList(CODE_40001.getCode(),
CODE_40014.getCode(), CODE_42001.getCode());
/**
* 微信推送过来的消息的类型和发送给微信xml格式消息的消息类型.
*/
@ -105,6 +121,31 @@ public class WxConsts {
public static final String MINIPROGRAM_NOTICE = "miniprogram_notice";
}
/**
* 群机器人的消息类型.
*/
public static class GroupRobotMsgType {
/**
* 文本消息.
*/
public static final String TEXT = "text";
/**
* 图片消息.
*/
public static final String IMAGE = "image";
/**
* markdown消息.
*/
public static final String MARKDOWN = "markdown";
/**
* 图文消息点击跳转到外链.
*/
public static final String NEWS = "news";
}
/**
* 表示是否是保密消息0表示否1表示是默认0.
*/
@ -394,5 +435,17 @@ public class WxConsts {
public static final String OPERATORDEFAULT = "DEFAULT";
}
/**
* appId 类型
*/
public static class AppIdType {
/**
* 公众号appId类型
*/
public static final String MP_TYPE = "mp";
/**
* 小程序appId类型
*/
public static final String MINI_TYPE = "mini";
}
}

View File

@ -1,9 +1,9 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.common.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.imgproc.WxMpImgProcAiCropResult;
import me.chanjar.weixin.mp.bean.imgproc.WxMpImgProcQrCodeResult;
import me.chanjar.weixin.mp.bean.imgproc.WxMpImgProcSuperResolutionResult;
import me.chanjar.weixin.common.bean.imgproc.WxImgProcAiCropResult;
import me.chanjar.weixin.common.bean.imgproc.WxImgProcQrCodeResult;
import me.chanjar.weixin.common.bean.imgproc.WxImgProcSuperResolutionResult;
import java.io.File;
@ -13,7 +13,7 @@ import java.io.File;
*
* @author Theo Nie
*/
public interface WxMpImgProcService {
public interface WxImgProcService {
/**
* 二维码/条码识别接口
@ -27,7 +27,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcQrCodeResult
* @throws WxErrorException .
*/
WxMpImgProcQrCodeResult qrCode(String imgUrl) throws WxErrorException;
WxImgProcQrCodeResult qrCode(String imgUrl) throws WxErrorException;
/**
* 二维码/条码识别接口
@ -41,7 +41,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcQrCodeResult
* @throws WxErrorException .
*/
WxMpImgProcQrCodeResult qrCode(File imgFile) throws WxErrorException;
WxImgProcQrCodeResult qrCode(File imgFile) throws WxErrorException;
/**
* 图片高清化接口
@ -55,7 +55,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcSuperResolutionResult
* @throws WxErrorException .
*/
WxMpImgProcSuperResolutionResult superResolution(String imgUrl) throws WxErrorException;
WxImgProcSuperResolutionResult superResolution(String imgUrl) throws WxErrorException;
/**
* 图片高清化接口
@ -69,7 +69,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcSuperResolutionResult
* @throws WxErrorException .
*/
WxMpImgProcSuperResolutionResult superResolution(File imgFile) throws WxErrorException;
WxImgProcSuperResolutionResult superResolution(File imgFile) throws WxErrorException;
/**
* 图片智能裁剪接口
@ -81,7 +81,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxMpImgProcAiCropResult aiCrop(String imgUrl) throws WxErrorException;
WxImgProcAiCropResult aiCrop(String imgUrl) throws WxErrorException;
/**
* 图片智能裁剪接口
@ -93,7 +93,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxMpImgProcAiCropResult aiCrop(String imgUrl, String ratios) throws WxErrorException;
WxImgProcAiCropResult aiCrop(String imgUrl, String ratios) throws WxErrorException;
/**
* 图片智能裁剪接口
@ -105,7 +105,7 @@ public interface WxMpImgProcService {
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxMpImgProcAiCropResult aiCrop(File imgFile) throws WxErrorException;
WxImgProcAiCropResult aiCrop(File imgFile) throws WxErrorException;
/**
* 图片智能裁剪接口
@ -117,5 +117,5 @@ public interface WxMpImgProcService {
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxMpImgProcAiCropResult aiCrop(File imgFile, String ratios) throws WxErrorException;
WxImgProcAiCropResult aiCrop(File imgFile, String ratios) throws WxErrorException;
}

View File

@ -1,12 +1,12 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.common.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBankCardResult;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBizLicenseResult;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrCommResult;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingLicenseResult;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingResult;
import me.chanjar.weixin.mp.bean.ocr.WxMpOcrIdCardResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrBankCardResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrBizLicenseResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrCommResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrDrivingLicenseResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrDrivingResult;
import me.chanjar.weixin.common.bean.ocr.WxOcrIdCardResult;
import java.io.File;
@ -17,7 +17,7 @@ import java.io.File;
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* @date 2019-06-22
*/
public interface WxMpOcrService {
public interface WxOcrService {
/**
* 身份证OCR识别接口.
@ -26,7 +26,7 @@ public interface WxMpOcrService {
* @return WxMpOcrIdCardResult
* @throws WxErrorException .
*/
WxMpOcrIdCardResult idCard(String imgUrl) throws WxErrorException;
WxOcrIdCardResult idCard(String imgUrl) throws WxErrorException;
/**
* 身份证OCR识别接口.
@ -35,7 +35,7 @@ public interface WxMpOcrService {
* @return WxMpOcrIdCardResult
* @throws WxErrorException .
*/
WxMpOcrIdCardResult idCard(File imgFile) throws WxErrorException;
WxOcrIdCardResult idCard(File imgFile) throws WxErrorException;
/**
* 银行卡OCR识别接口
@ -44,7 +44,7 @@ public interface WxMpOcrService {
* @return WxMpOcrBankCardResult
* @throws WxErrorException .
*/
WxMpOcrBankCardResult bankCard(String imgUrl) throws WxErrorException;
WxOcrBankCardResult bankCard(String imgUrl) throws WxErrorException;
/**
* 银行卡OCR识别接口
@ -53,7 +53,7 @@ public interface WxMpOcrService {
* @return WxMpOcrBankCardResult
* @throws WxErrorException .
*/
WxMpOcrBankCardResult bankCard(File imgFile) throws WxErrorException;
WxOcrBankCardResult bankCard(File imgFile) throws WxErrorException;
/**
* 行驶证OCR识别接口
@ -62,7 +62,7 @@ public interface WxMpOcrService {
* @return WxMpOcrDrivingResult
* @throws WxErrorException .
*/
WxMpOcrDrivingResult driving(String imgUrl) throws WxErrorException;
WxOcrDrivingResult driving(String imgUrl) throws WxErrorException;
/**
* 行驶证OCR识别接口
@ -71,7 +71,7 @@ public interface WxMpOcrService {
* @return WxMpOcrDrivingResult
* @throws WxErrorException .
*/
WxMpOcrDrivingResult driving(File imgFile) throws WxErrorException;
WxOcrDrivingResult driving(File imgFile) throws WxErrorException;
/**
* 驾驶证OCR识别接口
@ -80,7 +80,7 @@ public interface WxMpOcrService {
* @return WxMpOcrDrivingLicenseResult
* @throws WxErrorException .
*/
WxMpOcrDrivingLicenseResult drivingLicense(String imgUrl) throws WxErrorException;
WxOcrDrivingLicenseResult drivingLicense(String imgUrl) throws WxErrorException;
/**
* 驾驶证OCR识别接口
@ -89,7 +89,7 @@ public interface WxMpOcrService {
* @return WxMpOcrDrivingLicenseResult
* @throws WxErrorException .
*/
WxMpOcrDrivingLicenseResult drivingLicense(File imgFile) throws WxErrorException;
WxOcrDrivingLicenseResult drivingLicense(File imgFile) throws WxErrorException;
/**
* 营业执照OCR识别接口
@ -98,7 +98,7 @@ public interface WxMpOcrService {
* @return WxMpOcrBizLicenseResult
* @throws WxErrorException .
*/
WxMpOcrBizLicenseResult bizLicense(String imgUrl) throws WxErrorException;
WxOcrBizLicenseResult bizLicense(String imgUrl) throws WxErrorException;
/**
* 营业执照OCR识别接口
@ -107,7 +107,7 @@ public interface WxMpOcrService {
* @return WxMpOcrBizLicenseResult
* @throws WxErrorException .
*/
WxMpOcrBizLicenseResult bizLicense(File imgFile) throws WxErrorException;
WxOcrBizLicenseResult bizLicense(File imgFile) throws WxErrorException;
/**
* 通用印刷体OCR识别接口
@ -117,7 +117,7 @@ public interface WxMpOcrService {
* @return WxMpOcrCommResult
* @throws WxErrorException .
*/
WxMpOcrCommResult comm(String imgUrl) throws WxErrorException;
WxOcrCommResult comm(String imgUrl) throws WxErrorException;
/**
* 通用印刷体OCR识别接口
@ -127,5 +127,5 @@ public interface WxMpOcrService {
* @return WxMpOcrCommResult
* @throws WxErrorException .
*/
WxMpOcrCommResult comm(File imgFile) throws WxErrorException;
WxOcrCommResult comm(File imgFile) throws WxErrorException;
}

View File

@ -13,7 +13,6 @@ import java.util.List;
*/
@Data
public class WxNetCheckResult implements Serializable {
private static final long serialVersionUID = 6918924418847404172L;
private List<WxNetCheckDnsInfo> dnsInfos = new ArrayList<>();

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.imgproc;
package me.chanjar.weixin.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
@ -11,50 +11,59 @@ import java.util.List;
* @author Theo Nie
*/
@Data
public class WxMpImgProcAiCropResult implements Serializable {
public class WxImgProcAiCropResult implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("img_size")
private ImgSize imgSize;
@SerializedName("results")
private List<Results> results;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
public static WxMpImgProcAiCropResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpImgProcAiCropResult.class);
public static WxImgProcAiCropResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcAiCropResult.class);
}
@Data
public static class ImgSize {
public static class ImgSize implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("w")
private int w;
@SerializedName("h")
private int h;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
@Data
public static class Results {
public static class Results implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("crop_left")
private int cropLeft;
@SerializedName("crop_top")
private int cropTop;
@SerializedName("crop_right")
private int cropRight;
@SerializedName("crop_bottom")
private int cropBottom;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,28 +1,31 @@
package me.chanjar.weixin.mp.bean.imgproc;
package me.chanjar.weixin.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 二维码/条码识别返回结果
*
* @author Theo Nie
*/
@Data
public class WxMpImgProcQrCodeResult implements Serializable {
public class WxImgProcQrCodeResult implements Serializable {
private static final long serialVersionUID = -1194154790100866123L;
@SerializedName("img_size")
private ImgSize imgSize;
@SerializedName("code_results")
private List<CodeResults> codeResults;
@Data
public static class ImgSize implements Serializable{
public static class ImgSize implements Serializable {
private static final long serialVersionUID = -8847603245514017839L;
@SerializedName("w")
private int w;
@SerializedName("h")
@ -30,64 +33,71 @@ public class WxMpImgProcQrCodeResult implements Serializable {
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
@Data
public static class CodeResults implements Serializable{
public static class CodeResults implements Serializable {
private static final long serialVersionUID = -6138135951229076759L;
@SerializedName("type_name")
private String typeName;
@SerializedName("data")
private String data;
@SerializedName("pos")
private Pos pos;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Pos implements Serializable{
public static class Pos implements Serializable {
private static final long serialVersionUID = 7754894061212819602L;
@SerializedName("left_top")
private Coordinate leftTop;
@SerializedName("right_top")
private Coordinate rightTop;
@SerializedName("right_bottom")
private Coordinate rightBottom;
@SerializedName("left_bottom")
private Coordinate leftBottom;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Coordinate implements Serializable{
public static class Coordinate implements Serializable {
private static final long serialVersionUID = 8930443668927359677L;
@SerializedName("x")
private int x;
@SerializedName("y")
private int y;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
}
}
public static WxMpImgProcQrCodeResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpImgProcQrCodeResult.class);
public static WxImgProcQrCodeResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcQrCodeResult.class);
}
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,28 @@
package me.chanjar.weixin.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 图片高清化返回结果
* @author Theo Nie
*/
@Data
public class WxImgProcSuperResolutionResult implements Serializable {
private static final long serialVersionUID = 8007440280170407021L;
@SerializedName("media_id")
private String mediaId;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxImgProcSuperResolutionResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcSuperResolutionResult.class);
}
}

View File

@ -0,0 +1,29 @@
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 银行卡OCR识别结果
*
* @author Theo Nie
*/
@Data
public class WxOcrBankCardResult implements Serializable {
private static final long serialVersionUID = 554136620394204143L;
@SerializedName("number")
private String number;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxOcrBankCardResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrBankCardResult.class);
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author Theo Nie
*/
@Data
public class WxMpOcrBizLicenseResult implements Serializable {
public class WxOcrBizLicenseResult implements Serializable {
private static final long serialVersionUID = -5007671093920178291L;
/**
@ -82,26 +82,27 @@ public class WxMpOcrBizLicenseResult implements Serializable {
* 图片大小
*/
@SerializedName("img_size")
private WxMpOcrImgSize imgSize;
private WxOcrImgSize imgSize;
public static WxMpOcrBizLicenseResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpOcrBizLicenseResult.class);
public static WxOcrBizLicenseResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrBizLicenseResult.class);
}
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class CertPosition implements Serializable {
private static final long serialVersionUID = 290286813344131863L;
@SerializedName("pos")
private WxMpOcrPos pos;
private WxOcrPos pos;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
@ -11,35 +11,35 @@ import java.util.List;
* @author Theo Nie
*/
@Data
public class WxMpOcrCommResult implements Serializable {
public class WxOcrCommResult implements Serializable {
private static final long serialVersionUID = 455833771627756440L;
@SerializedName("img_size")
private WxMpOcrImgSize imgSize;
private WxOcrImgSize imgSize;
@SerializedName("items")
private List<Items> items;
public static WxMpOcrCommResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpOcrCommResult.class);
public static WxOcrCommResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrCommResult.class);
}
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Items implements Serializable {
private static final long serialVersionUID = 3066181677009102791L;
@SerializedName("text")
private String text;
@SerializedName("pos")
private WxMpOcrPos pos;
private WxOcrPos pos;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author Theo Nie
*/
@Data
public class WxMpOcrDrivingLicenseResult implements Serializable {
public class WxOcrDrivingLicenseResult implements Serializable {
private static final long serialVersionUID = -6984670645802585738L;
/**
@ -71,10 +71,10 @@ public class WxMpOcrDrivingLicenseResult implements Serializable {
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
public static WxMpOcrDrivingLicenseResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpOcrDrivingLicenseResult.class);
public static WxOcrDrivingLicenseResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrDrivingLicenseResult.class);
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -10,9 +10,9 @@ import java.io.Serializable;
* @author Theo Nie
*/
@Data
public class WxMpOcrDrivingResult implements Serializable {
public class WxOcrDrivingResult implements Serializable {
private static final long serialVersionUID = -7477484374200211303L;
/**
* 车牌号码
*/
@ -107,26 +107,27 @@ public class WxMpOcrDrivingResult implements Serializable {
* 图片大小
*/
@SerializedName("img_size")
private WxMpOcrImgSize imgSize;
private WxOcrImgSize imgSize;
@Data
public static class CardPosition implements Serializable {
private static final long serialVersionUID = 2884515165228160517L;
@SerializedName("pos")
private WxMpOcrPos pos;
private WxOcrPos pos;
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
public static WxMpOcrDrivingResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpOcrDrivingResult.class);
public static WxOcrDrivingResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrDrivingResult.class);
}
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,9 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -14,7 +13,7 @@ import java.io.Serializable;
* @date 2019-06-23
*/
@Data
public class WxMpOcrIdCardResult implements Serializable {
public class WxOcrIdCardResult implements Serializable {
private static final long serialVersionUID = 8184352486986729980L;
@SerializedName("type")
@ -26,8 +25,8 @@ public class WxMpOcrIdCardResult implements Serializable {
@SerializedName("valid_date")
private String validDate;
public static WxMpOcrIdCardResult fromJson(String json) {
return WxMpGsonBuilder.create().fromJson(json, WxMpOcrIdCardResult.class);
public static WxOcrIdCardResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrIdCardResult.class);
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author Theo Nie
*/
@Data
public class WxMpOcrImgSize implements Serializable {
public class WxOcrImgSize implements Serializable {
private static final long serialVersionUID = 5234409123551074168L;
@SerializedName("w")
@ -20,6 +20,6 @@ public class WxMpOcrImgSize implements Serializable {
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.ocr;
package me.chanjar.weixin.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author Theo Nie
*/
@Data
public class WxMpOcrPos implements Serializable {
public class WxOcrPos implements Serializable {
private static final long serialVersionUID = 4204160206873907920L;
@SerializedName("left_top")
@ -24,11 +24,11 @@ public class WxMpOcrPos implements Serializable {
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Coordinate implements Serializable{
public static class Coordinate implements Serializable {
private static final long serialVersionUID = 8675059935386304399L;
@SerializedName("x")
private int x;
@ -37,7 +37,7 @@ public class WxMpOcrPos implements Serializable {
@Override
public String toString() {
return WxMpGsonBuilder.create().toJson(this);
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -21,7 +21,7 @@ public enum TicketType {
/**
* sdk
*/
SDK("sdk"),
SDK("2"),
/**
* 微信卡券
*/

View File

@ -1,4 +1,4 @@
package me.chanjar.weixin.common;
package me.chanjar.weixin.common.enums;
/**
* <pre>

View File

@ -1069,10 +1069,26 @@ public enum WxCpErrorMsgEnum {
* 获取打卡记录时间间隔超限保证开始时间大于0 且结束时间大于 0 且结束时间大于开始时间且间隔少于93天.
*/
CODE_301024(301024, "获取打卡记录时间间隔超限保证开始时间大于0 且结束时间大于 0 且结束时间大于开始时间且间隔少于93天"),
/**
* 提交审批单请求参数错误
*/
CODE_301025(301025,"提交审批单请求参数错误"),
/**
* 不允许更新该用户的userid.
*/
CODE_301036(301036, "不允许更新该用户的userid"),
/**
* 无审批应用权限,或者提单者不在审批应用/自建应用的可见范围
*/
CODE_301055(301055,"无审批应用权限,或者提单者不在审批应用/自建应用的可见范围"),
/**
* 审批应用已停用
*/
CODE_301056(301056,"审批应用已停用"),
/**
* 通用错误码提交审批单内部接口失败
*/
CODE_301057(301057,"通用错误码,提交审批单内部接口失败"),
/**
* 批量导入任务的文件中userid有重复.
*/

View File

@ -2,7 +2,7 @@ package me.chanjar.weixin.common.error;
import lombok.Builder;
import lombok.Data;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import org.apache.commons.lang3.StringUtils;

View File

@ -3,14 +3,13 @@ package me.chanjar.weixin.common.redis;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.util.locks.JedisDistributedLock;
import redis.clients.jedis.Jedis;
import redis.clients.util.Pool;
import redis.clients.jedis.util.Pool;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@RequiredArgsConstructor
public class JedisWxRedisOps implements WxRedisOps {
private final Pool<Jedis> jedisPool;
@Override

View File

@ -1,11 +1,12 @@
package me.chanjar.weixin.common.redis;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.util.locks.RedisTemplateSimpleDistributedLock;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@RequiredArgsConstructor
public class RedisTemplateWxRedisOps implements WxRedisOps {
@ -37,7 +38,7 @@ public class RedisTemplateWxRedisOps implements WxRedisOps {
}
@Override
public Lock getLock(String key) {
return new ReentrantLock();
public Lock getLock(@NonNull String key) {
return new RedisTemplateSimpleDistributedLock(redisTemplate, key, 60 * 1000);
}
}

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.mp.util.requestexecuter.ocr;
package me.chanjar.weixin.common.requestexecuter.ocr;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.mp.util.requestexecuter.ocr;
package me.chanjar.weixin.common.requestexecuter.ocr;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
@ -12,8 +12,8 @@ import java.io.IOException;
/**
* .
*
* @author zhayueran
* @date 2019/6/27 15:06
* @author zhayueran
* @date 2019/6/27 15:06
*/
public abstract class OcrDiscernRequestExecutor<H, P> implements RequestExecutor<String, File> {
protected RequestHttp<H, P> requestHttp;

View File

@ -12,6 +12,8 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;
import org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -64,7 +66,7 @@ public class WxCryptUtil {
public WxCryptUtil(String token, String encodingAesKey, String appidOrCorpid) {
this.token = token;
this.appidOrCorpid = appidOrCorpid;
this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey));
}
private static String extractEncryptPart(String xml) {

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Base64;
public class FileUtils {
@ -34,4 +35,32 @@ public class FileUtils {
return createTmpFile(inputStream, name, ext, Files.createTempDirectory("weixin-java-tools-temp").toFile());
}
/**
* 文件流生成base64
*
* @param in 文件流
* @return base64编码
*/
public static String imageToBase64ByStream(InputStream in) {
byte[] data = null;
// 读取图片字节数组
try {
data = new byte[in.available()];
in.read(data);
// 返回Base64编码过的字节数组字符串
return Base64.getEncoder().encodeToString(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}

View File

@ -3,7 +3,7 @@ package me.chanjar.weixin.common.util.http;
import java.io.File;
import java.io.IOException;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.apache.ApacheMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.jodd.JoddHttpMediaDownloadRequestExecutor;

View File

@ -3,7 +3,7 @@ package me.chanjar.weixin.common.util.http;
import java.io.File;
import java.io.IOException;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.apache.ApacheMediaUploadRequestExecutor;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.util.http;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import java.io.IOException;

View File

@ -2,7 +2,7 @@ package me.chanjar.weixin.common.util.http;
import java.io.IOException;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.apache.ApacheSimpleGetRequestExecutor;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.util.http;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.apache.ApacheSimplePostRequestExecutor;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.util.http.apache;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.util.http.apache;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -1,7 +1,6 @@
package me.chanjar.weixin.common.util.http.apache;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;

View File

@ -1,7 +1,6 @@
package me.chanjar.weixin.common.util.http.apache;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
@ -12,7 +11,6 @@ import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;

View File

@ -5,7 +5,7 @@ import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;

View File

@ -5,7 +5,7 @@ import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -5,8 +5,7 @@ import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;

View File

@ -5,7 +5,7 @@ import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;

View File

@ -1,7 +1,7 @@
package me.chanjar.weixin.common.util.http.okhttp;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.util.http.okhttp;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -1,7 +1,6 @@
package me.chanjar.weixin.common.util.http.okhttp;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;

View File

@ -1,7 +1,7 @@
package me.chanjar.weixin.common.util.http.okhttp;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;

View File

@ -0,0 +1,27 @@
package me.chanjar.weixin.common.util.json;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import lombok.NoArgsConstructor;
import java.io.Reader;
/**
* @author niefy
*/
public class GsonParser {
private static final JsonParser JSON_PARSER = new JsonParser();
public static JsonObject parse(String json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}
public static JsonObject parse(Reader json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}
public static JsonObject parse(JsonReader json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}
}

View File

@ -13,7 +13,6 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
* @author chanjarster
*/
public class WxGsonBuilder {
private static final GsonBuilder INSTANCE = new GsonBuilder();
static {

View File

@ -6,7 +6,7 @@ import java.util.concurrent.locks.Lock;
import com.github.jedis.lock.JedisLock;
import redis.clients.jedis.Jedis;
import redis.clients.util.Pool;
import redis.clients.jedis.util.Pool;
/**
* JedisPool 分布式锁

View File

@ -0,0 +1,126 @@
package me.chanjar.weixin.common.util.locks;
import lombok.Getter;
import lombok.NonNull;
import org.jetbrains.annotations.NotNull;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.types.Expiration;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* 实现简单的redis分布式锁, 支持重入, 不是红锁
*
* @see <a href="https://redis.io/topics/distlock">reids distlock</a>
*/
public class RedisTemplateSimpleDistributedLock implements Lock {
@Getter
private final StringRedisTemplate redisTemplate;
@Getter
private final String key;
@Getter
private final int leaseMilliseconds;
private final ThreadLocal<String> valueThreadLocal = new ThreadLocal<>();
public RedisTemplateSimpleDistributedLock(@NonNull StringRedisTemplate redisTemplate, int leaseMilliseconds) {
this(redisTemplate, "lock:" + UUID.randomUUID().toString(), leaseMilliseconds);
}
public RedisTemplateSimpleDistributedLock(@NonNull StringRedisTemplate redisTemplate, @NonNull String key, int leaseMilliseconds) {
if (leaseMilliseconds <= 0) {
throw new IllegalArgumentException("Parameter 'leaseMilliseconds' must grate then 0: " + leaseMilliseconds);
}
this.redisTemplate = redisTemplate;
this.key = key;
this.leaseMilliseconds = leaseMilliseconds;
}
@Override
public void lock() {
while (!tryLock()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
while (!tryLock()) {
Thread.sleep(1000);
}
}
@Override
public boolean tryLock() {
String value = valueThreadLocal.get();
if (value == null || value.length() == 0) {
value = UUID.randomUUID().toString();
valueThreadLocal.set(value);
}
final byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
final byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8);
List<Object> redisResults = redisTemplate.executePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
connection.set(keyBytes, valueBytes, Expiration.milliseconds(leaseMilliseconds), RedisStringCommands.SetOption.SET_IF_ABSENT);
connection.get(keyBytes);
return null;
}
});
Object currentLockSecret = redisResults.size() > 1 ? redisResults.get(1) : redisResults.get(0);
return currentLockSecret != null && currentLockSecret.toString().equals(value);
}
@Override
public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException {
long waitMs = unit.toMillis(time);
boolean locked = tryLock();
while (!locked && waitMs > 0) {
long sleep = waitMs < 1000 ? waitMs : 1000;
Thread.sleep(sleep);
waitMs -= sleep;
locked = tryLock();
}
return locked;
}
@Override
public void unlock() {
if (valueThreadLocal.get() != null) {
// 提示: 必须指定returnType, 类型: 此处必须为Long, 不能是Integer
RedisScript<Long> script = new DefaultRedisScript("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", Long.class);
redisTemplate.execute(script, Arrays.asList(key), valueThreadLocal.get());
valueThreadLocal.remove();
}
}
@Override
public Condition newCondition() {
throw new UnsupportedOperationException();
}
/**
* 获取当前锁的值
* return 返回null意味着没有加锁, 但是返回非null值并不以为着当前加锁成功(redis中key可能自动过期)
*/
public String getLockSecretValue() {
return valueThreadLocal.get();
}
}

View File

@ -1,6 +1,5 @@
package me.chanjar.weixin.common.api;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;

View File

@ -0,0 +1,58 @@
package me.chanjar.weixin.common.bean;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* @date 2020-06-06
*/
public class WxNetCheckResultTest {
@Test
public void testFromJson() {
String json = "{\n" +
" \"dns\": [\n" +
" {\n" +
" \"ip\": \"111.161.64.40\", \n" +
" \"real_operator\": \"UNICOM\"\n" +
" }, \n" +
" {\n" +
" \"ip\": \"111.161.64.48\", \n" +
" \"real_operator\": \"UNICOM\"\n" +
" }\n" +
" ], \n" +
" \"ping\": [\n" +
" {\n" +
" \"ip\": \"111.161.64.40\", \n" +
" \"from_operator\": \"UNICOM\"," +
" \"package_loss\": \"0%\", \n" +
" \"time\": \"23.079ms\"\n" +
" }, \n" +
" {\n" +
" \"ip\": \"111.161.64.48\", \n" +
" \"from_operator\": \"UNICOM\", \n" +
" \"package_loss\": \"0%\", \n" +
" \"time\": \"21.434ms\"\n" +
" }\n" +
" ]\n" +
"}";
WxNetCheckResult result = WxNetCheckResult.fromJson(json);
Assert.assertNotNull(result);
Assert.assertNotNull(result.getDnsInfos());
WxNetCheckResult.WxNetCheckDnsInfo dnsInfo = new WxNetCheckResult.WxNetCheckDnsInfo();
dnsInfo.setIp("111.161.64.40");
dnsInfo.setRealOperator("UNICOM");
Assert.assertEquals(result.getDnsInfos().get(0), dnsInfo);
WxNetCheckResult.WxNetCheckPingInfo pingInfo = new WxNetCheckResult.WxNetCheckPingInfo();
pingInfo.setTime("21.434ms");
pingInfo.setFromOperator("UNICOM");
pingInfo.setIp("111.161.64.48");
pingInfo.setPackageLoss("0%");
Assert.assertEquals(result.getPingInfos().get(1), pingInfo);
}
}

View File

@ -1,6 +1,6 @@
package me.chanjar.weixin.common.error;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;

View File

@ -0,0 +1,79 @@
package me.chanjar.weixin.common.util.locks;
import lombok.SneakyThrows;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.testng.Assert.*;
@Test(enabled = false)
public class RedisTemplateSimpleDistributedLockTest {
RedisTemplateSimpleDistributedLock redisLock;
StringRedisTemplate redisTemplate;
AtomicInteger lockCurrentExecuteCounter;
@BeforeTest
public void init() {
JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
connectionFactory.setHostName("127.0.0.1");
connectionFactory.setPort(6379);
connectionFactory.afterPropertiesSet();
StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
this.redisTemplate = redisTemplate;
this.redisLock = new RedisTemplateSimpleDistributedLock(redisTemplate, 60000);
this.lockCurrentExecuteCounter = new AtomicInteger(0);
}
@Test(description = "多线程测试锁排他性")
public void testLockExclusive() throws InterruptedException {
int threadSize = 100;
final CountDownLatch startLatch = new CountDownLatch(threadSize);
final CountDownLatch endLatch = new CountDownLatch(threadSize);
for (int i = 0; i < threadSize; i++) {
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
startLatch.await();
redisLock.lock();
assertEquals(lockCurrentExecuteCounter.incrementAndGet(), 1, "临界区同时只能有一个线程执行");
lockCurrentExecuteCounter.decrementAndGet();
redisLock.unlock();
endLatch.countDown();
}
}).start();
startLatch.countDown();
}
endLatch.await();
}
@Test
public void testTryLock() throws InterruptedException {
assertTrue(redisLock.tryLock(3, TimeUnit.SECONDS), "第一次加锁应该成功");
assertNotNull(redisLock.getLockSecretValue());
String redisValue = this.redisTemplate.opsForValue().get(redisLock.getKey());
assertEquals(redisValue, redisLock.getLockSecretValue());
redisLock.unlock();
assertNull(redisLock.getLockSecretValue());
redisValue = this.redisTemplate.opsForValue().get(redisLock.getKey());
assertNull(redisValue, "释放锁后key会被删除");
redisLock.unlock();
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.8.0</version>
<version>3.9.0</version>
</parent>
<artifactId>weixin-java-cp</artifactId>

View File

@ -12,10 +12,6 @@ import java.util.List;
* @author gaigeshen
*/
public interface WxCpChatService {
@Deprecated
String chatCreate(String name, String owner, List<String> users, String chatId) throws WxErrorException;
/**
* 创建群聊会话注意刚创建的群如果没有下发消息在企业微信不会出现该群.
*
@ -28,9 +24,6 @@ public interface WxCpChatService {
*/
String create(String name, String owner, List<String> users, String chatId) throws WxErrorException;
@Deprecated
void chatUpdate(String chatId, String name, String owner, List<String> usersToAdd, List<String> usersToDelete) throws WxErrorException;
/**
* 修改群聊会话.
*
@ -43,9 +36,6 @@ public interface WxCpChatService {
*/
void update(String chatId, String name, String owner, List<String> usersToAdd, List<String> usersToDelete) throws WxErrorException;
@Deprecated
WxCpChat chatGet(String chatId) throws WxErrorException;
/**
* 获取群聊会话.
*

View File

@ -1,9 +1,10 @@
package me.chanjar.weixin.cp.api;
import lombok.NonNull;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.*;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@ -16,6 +17,83 @@ import java.util.List;
* @author <a href="https://github.com/JoeCao">JoeCao</a>
*/
public interface WxCpExternalContactService {
/**
* 配置客户联系联系我方式
* <pre>
* 企业可以在管理后台-客户联系中配置成员的联系我的二维码或者小程序按钮客户通过扫描二维码或点击小程序上的按钮即可获取成员联系方式主动联系到成员
* 企业可通过此接口为具有客户联系功能的成员生成专属的联系我二维码或者联系我按钮
* 如果配置的是联系我按钮需要开发者的小程序接入小程序插件
*
* 注意:
* 通过API添加的联系我不会在管理端进行展示每个企业可通过API最多配置50万个联系我
* 用户需要妥善存储返回的config_idconfig_id丢失可能导致用户无法编辑或删除联系我
* 临时会话模式不占用联系我数量但每日最多添加10万个并且仅支持单人
* 临时会话模式的二维码添加好友完成后该二维码即刻失效
* </pre>
*
* @param info 客户联系联系我方式
* @return wx cp contact way result
* @throws WxErrorException the wx error exception
*/
WxCpContactWayResult addContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException;
/**
* 获取企业已配置的联系我方式
*
* <pre>
* <b>批量</b>获取企业配置的联系我二维码和联系我小程序按钮
* </pre>
*
* @param configId 联系方式的配置id,必填
* @return contact way
* @throws WxErrorException the wx error exception
*/
WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException;
/**
* 更新企业已配置的联系我方式
*
* <pre>
* 更新企业配置的联系我二维码和联系我小程序按钮中的信息如使用人员和备注等
* </pre>
*
* @param info 客户联系联系我方式
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp updateContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException;
/**
* 删除企业已配置的联系我方式
*
* <pre>
* 删除一个已配置的联系我二维码或者联系我小程序按钮
* </pre>
*
* @param configId 企业联系方式的配置id,必填
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp deleteContactWay(@NonNull String configId) throws WxErrorException;
/**
* 结束临时会话
*
* <pre>
* 将指定的企业成员和客户之前的临时会话断开断开前会自动下发已配置的结束语
*
* 注意请保证传入的企业成员和客户之间有仍然有效的临时会话, 通过<b>其他方式的添加外部联系人无法通过此接口关闭会话</b>
* </pre>
*
* @param userId the user id
* @param externalUserId the external user id
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp closeTempChat(@NonNull String userId, @NonNull String externalUserId) throws WxErrorException;
/**
* 获取外部联系人详情.
* <pre>
@ -26,7 +104,8 @@ public interface WxCpExternalContactService {
* </pre>
*
* @param userId 外部联系人的userid
* @return .
* @return . external contact
* @throws WxErrorException the wx error exception
* @deprecated 建议使用 {@link #getContactDetail(String)}
*/
@Deprecated
@ -48,7 +127,7 @@ public interface WxCpExternalContactService {
* </pre>
*
* @param userId 外部联系人的userid注意不是企业成员的帐号
* @return .
* @return . contact detail
* @throws WxErrorException .
*/
WxCpUserExternalContactInfo getContactDetail(String userId) throws WxErrorException;
@ -89,31 +168,42 @@ public interface WxCpExternalContactService {
/**
* 企业和第三方可通过此接口获取所有离职成员的客户列表并可进一步调用离职成员的外部联系人再分配接口将这些客户重新分配给其他企业成员
* @param page
* @param pageSize
* @return
* @throws WxErrorException
*
* @param page the page
* @param pageSize the page size
* @return wx cp user external unassign list
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalUnassignList listUnassignedList(Integer page, Integer pageSize) throws WxErrorException;
/**
* 企业可通过此接口将已离职成员的外部联系人分配给另一个成员接替联系
* @param externalUserid
* @param handOverUserid
* @param takeOverUserid
* @return
* @throws WxErrorException
*
* @param externalUserid the external userid
* @param handOverUserid the hand over userid
* @param takeOverUserid the take over userid
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp transferExternalContact(String externalUserid,String handOverUserid,String takeOverUserid)throws WxErrorException;
WxCpBaseResp transferExternalContact(String externalUserid, String handOverUserid, String takeOverUserid) throws WxErrorException;
/** <pre>
* 该接口用于获取配置过客户群管理的客户群列表
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 暂不支持第三方调用
* 微信文档https://work.weixin.qq.com/api/doc/90000/90135/92119
* </pre>
*/
WxCpUserExternalGroupChatList listGroupChat(Integer pageIndex,Integer pageSize,int status,String[] userIds,String[] partyIds) throws WxErrorException;
/**
* <pre>
* 该接口用于获取配置过客户群管理的客户群列表
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 暂不支持第三方调用
* 微信文档https://work.weixin.qq.com/api/doc/90000/90135/92119
* </pre>
*
* @param pageIndex the page index
* @param pageSize the page size
* @param status the status
* @param userIds the user ids
* @param partyIds the party ids
* @return the wx cp user external group chat list
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalGroupChatList listGroupChat(Integer pageIndex, Integer pageSize, int status, String[] userIds, String[] partyIds) throws WxErrorException;
/**
* <pre>
@ -123,9 +213,9 @@ public interface WxCpExternalContactService {
* 微信文档https://work.weixin.qq.com/api/doc/90000/90135/92122
* </pre>
*
* @param chatId
* @return
* @throws WxErrorException
* @param chatId the chat id
* @return group chat
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalGroupChatInfo getGroupChat(String chatId) throws WxErrorException;
@ -136,12 +226,13 @@ public interface WxCpExternalContactService {
* 第三方应用需拥有企业客户权限
* 第三方/自建应用调用时传入的userid和partyid要在应用的可见范围内;
* </pre>
* @param startTime
* @param endTime
* @param userIds
* @param partyIds
* @return
* @throws WxErrorException
*
* @param startTime the start time
* @param endTime the end time
* @param userIds the user ids
* @param partyIds the party ids
* @return user behavior statistic
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalUserBehaviorStatistic getUserBehaviorStatistic(Date startTime, Date endTime, String[] userIds, String[] partyIds) throws WxErrorException;
@ -151,15 +242,118 @@ public interface WxCpExternalContactService {
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 暂不支持第三方调用
* </pre>
* @param startTime
* @param orderBy
* @param orderAsc
* @param pageIndex
* @param pageSize
* @param userIds
* @param partyIds
* @return
* @throws WxErrorException
*
* @param startTime the start time
* @param orderBy the order by
* @param orderAsc the order asc
* @param pageIndex the page index
* @param pageSize the page size
* @param userIds the user ids
* @param partyIds the party ids
* @return group chat statistic
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime,Integer orderBy,Integer orderAsc,Integer pageIndex,Integer pageSize, String[] userIds, String[] partyIds) throws WxErrorException;
WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime, Integer orderBy, Integer orderAsc, Integer pageIndex, Integer pageSize, String[] userIds, String[] partyIds) throws WxErrorException;
/**
* 添加企业群发消息任务
* 企业可通过此接口添加企业群发消息的任务并通知客服人员发送给相关客户或客户群企业微信终端需升级到2.7.5版本及以上
* 注意调用该接口并不会直接发送消息给客户/客户群需要相关的客服人员操作以后才会实际发送客服人员的企业微信需要升级到2.7.5及以上版本
* 同一个企业每个自然月内仅可针对一个客户/客户群发送4条消息超过限制的用户将会被忽略
* <p>
* 请求方式: POST(HTTP)
* <p>
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=ACCESS_TOKEN
* <p>
* 文档地址https://work.weixin.qq.com/api/doc/90000/90135/92135
*
* @param wxCpMsgTemplate the wx cp msg template
* @return the wx cp msg template add result
* @throws WxErrorException the wx error exception
*/
WxCpMsgTemplateAddResult addMsgTemplate(WxCpMsgTemplate wxCpMsgTemplate) throws WxErrorException;
/**
* 发送新客户欢迎语
* <pre>
* 企业微信在向企业推送添加外部联系人事件时会额外返回一个welcome_code企业以此为凭据调用接口即可通过成员向新添加的客户发送个性化的欢迎语
* 为了保证用户体验以及避免滥用企业仅可在收到相关事件后20秒内调用且只可调用一次
* 如果企业已经在管理端为相关成员配置了可用的欢迎语则推送添加外部联系人事件时不会返回welcome_code
* 每次添加新客户时可能有多个企业自建应用/第三方应用收到带有welcome_code的回调事件但仅有最先调用的可以发送成功后续调用将返回41051externaluser has started chatting错误请用户根据实际使用需求合理设置应用可见范围避免冲突
* 请求方式: POST(HTTP)
*
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=ACCESS_TOKEN
*
* 文档地址https://work.weixin.qq.com/api/doc/90000/90135/92137
* </pre>
*
* @param msg .
* @throws WxErrorException .
*/
void sendWelcomeMsg(WxCpWelcomeMsg msg) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口获取企业客户标签详情
* </pre>
*
* @param tagId the tag id
* @return corp tag list
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalTagGroupList getCorpTagList(String[] tagId) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口向客户标签库中添加新的标签组和标签每个企业最多可配置3000个企业标签
* 暂不支持第三方调用
* </pre>
*
* @param tagGroup the tag group
* @return wx cp user external tag group info
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalTagGroupInfo addCorpTag(WxCpUserExternalTagGroupInfo tagGroup) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口编辑客户标签/标签组的名称或次序值
* 暂不支持第三方调用
* </pre>
*
* @param id the id
* @param name the name
* @param order the order
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp editCorpTag(String id, String name, Integer order) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口删除客户标签库中的标签或删除整个标签组
* 暂不支持第三方调用
* </pre>
*
* @param tagId the tag id
* @param groupId the group id
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp delCorpTag(String[] tagId, String[] groupId) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口为指定成员的客户添加上由企业统一配置的标签
* https://work.weixin.qq.com/api/doc/90000/90135/92117
* </pre>
*
* @param userid the userid
* @param externalUserid the external userid
* @param addTag the add tag
* @param removeTag the remove tag
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp markTag(String userid, String externalUserid, String[] addTag, String[] removeTag) throws WxErrorException;
}

View File

@ -0,0 +1,52 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import java.util.List;
/**
* 微信群机器人消息发送api
* 文档地址https://work.weixin.qq.com/help?doc_id=13376
* 调用地址https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=
*
* @author yr
* @date 2020-8-20
*/
public interface WxCpGroupRobotService {
/**
* 发送text类型的消息
*
* @param content 文本内容最长不超过2048个字节必须是utf8编码
* @param mentionedList userId的列表提醒群中的指定成员(@某个成员)@all表示提醒所有人如果开发者获取不到userId可以使用mentioned_mobile_list
* @param mobileList 手机号列表提醒手机号对应的群成员(@某个成员)@all表示提醒所有人
* @throws WxErrorException 异常
*/
void sendText(String content, List<String> mentionedList, List<String> mobileList) throws WxErrorException;
/**
* 发送markdown类型的消息
*
* @param content markdown内容最长不超过4096个字节必须是utf8编码
* @throws WxErrorException 异常
*/
void sendMarkDown(String content) throws WxErrorException;
/**
* 发送image类型的消息
*
* @param base64 图片内容的base64编码
* @param md5 图片内容base64编码前的md5值
* @throws WxErrorException 异常
*/
void sendImage(String base64, String md5) throws WxErrorException;
/**
* 发送news类型的消息
*
* @param articleList 图文消息支持1到8条图文
* @throws WxErrorException 异常
*/
void sendNews(List<NewArticle> articleList) throws WxErrorException;
}

View File

@ -15,6 +15,22 @@ import java.util.List;
*/
public interface WxCpOaService {
/**
* <pre>提交审批申请
* 调试工具
* 企业可通过审批应用或自建应用Secret调用本接口代应用可见范围内员工在企业微信审批应用内提交指定类型的审批申请
*
* 请求方式POSTHTTPS
* 请求地址 https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token=ACCESS_TOKEN
* 文档地址https://work.weixin.qq.com/api/doc/90000/90135/91853
* </pre>
*
* @param request 请求
* @return 表单提交成功后返回的表单编号
* @throws WxErrorException .
*/
String apply(WxCpOaApplyEventRequest request) throws WxErrorException;
/**
* <pre>
* 获取打卡数据
@ -40,7 +56,7 @@ public interface WxCpOaService {
* @param datetime 需要获取规则的当天日期
* @param userIdList 需要获取打卡规则的用户列表
* @return 打卡规则列表
* @throws WxErrorException
* @throws WxErrorException .
*/
List<WxCpCheckinOption> getCheckinOption(Date datetime, List<String> userIdList) throws WxErrorException;
@ -63,7 +79,7 @@ public interface WxCpOaService {
* @param size 一次请求拉取审批单数量默认值为100上限值为100
* @param filters 筛选条件可对批量拉取的审批申请设置约束条件支持设置多个条件,nullable
* @return WxCpApprovalInfo
* @throws WxErrorException
* @throws WxErrorException .
*/
WxCpApprovalInfo getApprovalInfo(@NonNull Date startTime, @NonNull Date endTime, Integer cursor, Integer size,
List<WxCpApprovalInfoQueryFilter> filters) throws WxErrorException;
@ -74,7 +90,7 @@ public interface WxCpOaService {
* @param startTime 开始时间
* @param endTime 结束时间
* @return WxCpApprovalInfo
* @throws WxErrorException
* @throws WxErrorException .
* @see me.chanjar.weixin.cp.api.WxCpOaService#getApprovalInfo
*/
WxCpApprovalInfo getApprovalInfo(@NonNull Date startTime, @NonNull Date endTime) throws WxErrorException;
@ -90,27 +106,10 @@ public interface WxCpOaService {
*
* @param spNo 审批单编号
* @return WxCpApprovaldetail
* @throws WxErrorException
* @throws WxErrorException .
*/
WxCpApprovalDetailResult getApprovalDetail(@NonNull String spNo) throws WxErrorException;
/**
* <pre>
* 获取审批数据 (已过期, 请使用"批量获取审批单号" && "获取审批申请详情")
* 通过本接口来获取公司一段时间内的审批记录一次拉取调用最多拉取10000个审批记录可以通过多次拉取的方式来满足需求但调用频率不可超过600次/
* API doc : https://work.weixin.qq.com/api/doc#90000/90135/91530
* </pre>
*
* @param startTime 获取审批记录的开始时间
* @param endTime 获取审批记录的结束时间
* @param nextSpnum 第一个拉取的审批单号不填从该时间段的第一个审批单拉取
* @throws WxErrorException
* @see me.chanjar.weixin.cp.api.WxCpOaService#getApprovalInfo
* @see me.chanjar.weixin.cp.api.WxCpOaService#getApprovalDetail
*/
@Deprecated
WxCpApprovalDataResult getApprovalData(Date startTime, Date endTime, Long nextSpnum) throws WxErrorException;
/**
* 获取公费电话拨打记录
*
@ -118,18 +117,19 @@ public interface WxCpOaService {
* @param endTime 查询的结束时间戳
* @param offset 分页查询的偏移量
* @param limit 分页查询的每页大小,默认为100条如该参数大于100则按100处理
* @return
* @throws WxErrorException
* @return .
* @throws WxErrorException .
*/
List<WxCpDialRecord> getDialRecord(Date startTime, Date endTime, Integer offset,
Integer limit) throws WxErrorException;
/**
* 获取审批模板详情
*
* @param templateId 模板ID
* @return
* @throws WxErrorException
* @return .
* @throws WxErrorException .
*/
WxCpTemplateResult getTemplateDetail(@NonNull String templateId)throws WxErrorException;
WxCpTemplateResult getTemplateDetail(@NonNull String templateId) throws WxErrorException;
}

View File

@ -173,6 +173,14 @@ public interface WxCpService {
*/
String post(String url, String postData) throws WxErrorException;
/**
* 当不需要自动带accessToken的时候可以用这个发起post请求
*
* @param url 接口地址
* @param postData 请求body字符串
*/
String postWithoutToken(String url, String postData) throws WxErrorException;
/**
* <pre>
* Service没有实现某个API的时候可以用这个
@ -328,6 +336,13 @@ public interface WxCpService {
WxCpOaService getOAService();
/**
* 获取群机器人消息推送服务
*
* @return 群机器人消息推送服务
*/
WxCpGroupRobotService getGroupRobotService();
/**
* http请求对象
*/

View File

@ -17,7 +17,6 @@ import java.util.List;
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public interface WxCpTagService {
/**
* 创建标签.
* <pre>
@ -32,17 +31,6 @@ public interface WxCpTagService {
*/
String create(String name, Integer id) throws WxErrorException;
/**
* 创建标签.
*
* @param tagName 标签名
* @return 标签id
* @throws WxErrorException .
* @deprecated 建议使用 {@link #create(String, Integer)}其中后面的参数可以为空
*/
@Deprecated
String create(String tagName) throws WxErrorException;
/**
* 更新标签.
*

View File

@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpInviteResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalContactInfo;
import java.util.List;
import java.util.Map;

View File

@ -2,12 +2,11 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.common.base.Joiner;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.StandardSessionManager;
@ -20,6 +19,7 @@ import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.*;
import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult;
import me.chanjar.weixin.cp.bean.WxCpMessage;
@ -52,6 +52,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
private WxCpOaService oaService = new WxCpOaServiceImpl(this);
private WxCpTaskCardService taskCardService = new WxCpTaskCardServiceImpl(this);
private WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(this);
private WxCpGroupRobotService groupRobotService = new WxCpGroupRobotServiceImpl(this);
/**
* 全局的是否正在刷新access token的锁.
@ -110,7 +111,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
synchronized (this.globalAgentJsapiTicketRefreshLock) {
if (this.configStorage.isAgentJsapiTicketExpired()) {
String responseContent = this.get(this.configStorage.getApiUrl(GET_AGENT_CONFIG_TICKET), null);
JsonObject jsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
JsonObject jsonObject = GsonParser.parse(responseContent);
this.configStorage.updateAgentJsapiTicket(jsonObject.get("ticket").getAsString(),
jsonObject.get("expires_in").getAsInt());
}
@ -135,7 +136,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
synchronized (this.globalJsapiTicketRefreshLock) {
if (this.configStorage.isJsapiTicketExpired()) {
String responseContent = this.get(this.configStorage.getApiUrl(GET_JSAPI_TICKET), null);
JsonObject tmpJsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
JsonObject tmpJsonObject = GsonParser.parse(responseContent);
this.configStorage.updateJsapiTicket(tmpJsonObject.get("ticket").getAsString(),
tmpJsonObject.get("expires_in").getAsInt());
}
@ -191,8 +192,8 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
@Override
public String[] getCallbackIp() throws WxErrorException {
String responseContent = get(this.configStorage.getApiUrl(GET_CALLBACK_IP), null);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray();
JsonObject tmpJsonObject = GsonParser.parse(responseContent);
JsonArray jsonArray = tmpJsonObject.get("ip_list").getAsJsonArray();
String[] ips = new String[jsonArray.size()];
for (int i = 0; i < jsonArray.size(); i++) {
ips[i] = jsonArray.get(i).getAsString();
@ -218,6 +219,11 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
return execute(SimplePostRequestExecutor.create(this), url, postData);
}
@Override
public String postWithoutToken(String url, String postData) throws WxErrorException {
return this.executeNormal(SimplePostRequestExecutor.create(this), url, postData);
}
/**
* 向微信端发送请求在这里执行的策略是当发生access_token过期时才去刷新然后重新执行请求而不是全局定时请求.
*/
@ -272,16 +278,12 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
return result;
} catch (WxErrorException e) {
WxError error = e.getError();
/*
* 发生以下情况时尝试刷新access_token
* 40001 获取access_token时AppSecret错误或者access_token无效
* 42001 access_token超时
* 40014 不合法的access_token请开发者认真比对access_token的有效性如是否过期或查看是否正在为恰当的公众号调用接口
*/
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001 || error.getErrorCode() == 40014) {
if (WxConsts.ACCESS_TOKEN_ERROR_CODES.contains(error.getErrorCode())) {
// 强制设置wxCpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
this.configStorage.expireAccessToken();
if (this.getWxCpConfigStorage().autoRefreshToken()) {
log.warn("即将重新获取新的access_token错误代码{},错误信息:{}", error.getErrorCode(), error.getErrorMsg());
return this.execute(executor, uri, data);
}
}
@ -297,6 +299,27 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
}
}
/**
* 普通请求不自动带accessToken
*/
private <T, E> T executeNormal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
try {
T result = executor.execute(uri, data, WxType.CP);
log.debug("\n【请求地址】: {}\n【请求参数】{}\n【响应数据】{}", uri, data, result);
return result;
} catch (WxErrorException e) {
WxError error = e.getError();
if (error.getErrorCode() != 0) {
log.error("\n【请求地址】: {}\n【请求参数】{}\n【错误信息】{}", uri, data, error);
throw new WxErrorException(error, e);
}
return null;
} catch (IOException e) {
log.error("\n【请求地址】: {}\n【请求参数】{}\n【异常信息】{}", uri, data, e.getMessage());
throw new RuntimeException(e);
}
}
@Override
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) {
this.configStorage = wxConfigProvider;
@ -413,6 +436,11 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
return oaService;
}
@Override
public WxCpGroupRobotService getGroupRobotService() {
return groupRobotService;
}
@Override
public WxCpTaskCardService getTaskCardService() {
return taskCardService;

View File

@ -2,11 +2,11 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.common.base.Joiner;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxCpErrorMsgEnum;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.DataUtils;
@ -15,6 +15,7 @@ import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpTpService;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
@ -119,7 +120,7 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
jsonObject.addProperty("auth_code", authCode);
String result = post(configStorage.getApiUrl(GET_PERMANENT_CODE), jsonObject.toString());
jsonObject = new JsonParser().parse(result).getAsJsonObject();
jsonObject = GsonParser.parse(result);
WxCpTpCorp wxCpTpCorp = WxCpTpCorp.fromJson(jsonObject.get("auth_corp_info").getAsJsonObject().toString());
wxCpTpCorp.setPermanentCode(jsonObject.get("permanent_code").getAsString());
return wxCpTpCorp;
@ -222,10 +223,11 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
* 发生以下情况时尝试刷新suite_access_token
* 42009 suite_access_token已过期
*/
if (error.getErrorCode() == 42009) {
if (error.getErrorCode() == WxCpErrorMsgEnum.CODE_42009.getCode()) {
// 强制设置wxCpTpConfigStorage它的suite access token过期了这样在下一次请求里就会刷新suite access token
this.configStorage.expireSuiteAccessToken();
if (this.getWxCpTpConfigStorage().autoRefreshToken()) {
log.warn("即将重新获取新的access_token错误代码{},错误信息:{}", error.getErrorCode(), error.getErrorMsg());
return this.execute(executor, uri, data);
}
}

View File

@ -1,12 +1,12 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpAgentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpAgent;
@ -27,7 +27,7 @@ import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Agent.*;
*/
@RequiredArgsConstructor
public class WxCpAgentServiceImpl implements WxCpAgentService {
private static final JsonParser JSON_PARSER = new JsonParser();
private final WxCpService mainService;
@ -45,7 +45,7 @@ public class WxCpAgentServiceImpl implements WxCpAgentService {
public void set(WxCpAgent agentInfo) throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(AGENT_SET);
String responseContent = this.mainService.post(url, agentInfo.toJson());
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get("errcode").getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.CP));
}
@ -55,7 +55,7 @@ public class WxCpAgentServiceImpl implements WxCpAgentService {
public List<WxCpAgent> list() throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(AGENT_LIST);
String responseContent = this.mainService.get(url, null);
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get("errcode").getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.CP));
}

View File

@ -1,14 +1,13 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonParser;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.cp.api.WxCpChatService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpAppChatMessage;
import me.chanjar.weixin.cp.bean.WxCpChat;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import org.apache.commons.lang3.StringUtils;
@ -25,11 +24,10 @@ import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Chat.*;
*/
@RequiredArgsConstructor
public class WxCpChatServiceImpl implements WxCpChatService {
private static final JsonParser JSON_PARSER = new JsonParser();
private final WxCpService cpService;
@Override
public String chatCreate(String name, String owner, List<String> users, String chatId) throws WxErrorException {
public String create(String name, String owner, List<String> users, String chatId) throws WxErrorException {
Map<String, Object> data = new HashMap<>(4);
if (StringUtils.isNotBlank(name)) {
data.put("name", name);
@ -45,16 +43,11 @@ public class WxCpChatServiceImpl implements WxCpChatService {
}
final String url = this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_CREATE);
String result = this.cpService.post(url, WxGsonBuilder.create().toJson(data));
return new JsonParser().parse(result).getAsJsonObject().get("chatid").getAsString();
return GsonParser.parse(result).get("chatid").getAsString();
}
@Override
public String create(String name, String owner, List<String> users, String chatId) throws WxErrorException {
return this.chatCreate(name, owner, users, chatId);
}
@Override
public void chatUpdate(String chatId, String name, String owner, List<String> usersToAdd, List<String> usersToDelete)
public void update(String chatId, String name, String owner, List<String> usersToAdd, List<String> usersToDelete)
throws WxErrorException {
Map<String, Object> data = new HashMap<>(5);
if (StringUtils.isNotBlank(chatId)) {
@ -78,24 +71,13 @@ public class WxCpChatServiceImpl implements WxCpChatService {
}
@Override
public void update(String chatId, String name, String owner, List<String> usersToAdd, List<String> usersToDelete)
throws WxErrorException {
chatUpdate(chatId, name, owner, usersToAdd, usersToDelete);
}
@Override
public WxCpChat chatGet(String chatId) throws WxErrorException {
public WxCpChat get(String chatId) throws WxErrorException {
final String url = this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_GET_CHATID + chatId);
String result = this.cpService.get(url, null);
final String chatInfo = JSON_PARSER.parse(result).getAsJsonObject().getAsJsonObject("chat_info").toString();
final String chatInfo = GsonParser.parse(result).getAsJsonObject("chat_info").toString();
return WxCpGsonBuilder.create().fromJson(chatInfo, WxCpChat.class);
}
@Override
public WxCpChat get(String chatId) throws WxErrorException {
return this.chatGet(chatId);
}
@Override
public void sendMsg(WxCpAppChatMessage message) throws WxErrorException {
this.cpService.post(this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_SEND), message.toJson());

View File

@ -1,15 +1,14 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpDepartmentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.List;
@ -32,8 +31,8 @@ public class WxCpDepartmentServiceImpl implements WxCpDepartmentService {
public Long create(WxCpDepart depart) throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_CREATE);
String responseContent = this.mainService.post(url, depart.toJson());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("id"));
JsonObject tmpJsonObject = GsonParser.parse(responseContent);
return GsonHelper.getAsLong(tmpJsonObject.get("id"));
}
@Override
@ -56,9 +55,9 @@ public class WxCpDepartmentServiceImpl implements WxCpDepartmentService {
}
String responseContent = this.mainService.get(url, null);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJsonObject = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(tmpJsonElement.getAsJsonObject().get("department"),
.fromJson(tmpJsonObject.get("department"),
new TypeToken<List<WxCpDepart>>() {
}.getType()
);

View File

@ -2,13 +2,16 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxCpErrorMsgEnum;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.bean.external.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.Date;
@ -23,6 +26,69 @@ import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*;
public class WxCpExternalContactServiceImpl implements WxCpExternalContactService {
private final WxCpService mainService;
@Override
public WxCpContactWayResult addContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException {
if (info.getContactWay().getUsers() != null && info.getContactWay().getUsers().size() > 100) {
throw new RuntimeException("「联系我」使用人数默认限制不超过100人(包括部门展开后的人数)");
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_CONTACT_WAY);
String responseContent = this.mainService.post(url, info.getContactWay().toJson());
return WxCpContactWayResult.fromJson(responseContent);
}
@Override
public WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("config_id", configId);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CONTACT_WAY);
String responseContent = this.mainService.post(url, json.toString());
return WxCpContactWayInfo.fromJson(responseContent);
}
@Override
public WxCpBaseResp updateContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException {
if (StringUtils.isBlank(info.getContactWay().getConfigId())) {
throw new RuntimeException("更新「联系我」方式需要指定configId");
}
if (info.getContactWay().getUsers() != null && info.getContactWay().getUsers().size() > 100) {
throw new RuntimeException("「联系我」使用人数默认限制不超过100人(包括部门展开后的人数)");
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_CONTACT_WAY);
String responseContent = this.mainService.post(url, info.getContactWay().toJson());
return WxCpBaseResp.fromJson(responseContent);
}
@Override
public WxCpBaseResp deleteContactWay(@NonNull String configId) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("config_id",configId);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEL_CONTACT_WAY);
String responseContent = this.mainService.post(url, json.toString());
return WxCpBaseResp.fromJson(responseContent);
}
@Override
public WxCpBaseResp closeTempChat(@NonNull String userId, @NonNull String externalUserId) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("userid",userId);
json.addProperty("external_userid",externalUserId);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(CLOSE_TEMP_CHAT);
String responseContent = this.mainService.post(url, json.toString());
return WxCpBaseResp.fromJson(responseContent);
}
@Override
public WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_EXTERNAL_CONTACT + userId);
@ -89,10 +155,10 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
if (ArrayUtils.isNotEmpty(userIds) || ArrayUtils.isNotEmpty(partyIds)) {
JsonObject ownerFilter = new JsonObject();
if (ArrayUtils.isNotEmpty(userIds)) {
json.add("userid", new Gson().toJsonTree(userIds).getAsJsonArray());
json.add("userid_list", new Gson().toJsonTree(userIds).getAsJsonArray());
}
if (ArrayUtils.isNotEmpty(partyIds)) {
json.add("partyid", new Gson().toJsonTree(partyIds).getAsJsonArray());
json.add("partyid_list", new Gson().toJsonTree(partyIds).getAsJsonArray());
}
json.add("owner_filter", ownerFilter);
}
@ -142,7 +208,7 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
json.add("userid_list", new Gson().toJsonTree(userIds).getAsJsonArray());
}
if (ArrayUtils.isNotEmpty(partyIds)) {
json.add("userid_list", new Gson().toJsonTree(partyIds).getAsJsonArray());
json.add("partyid_list", new Gson().toJsonTree(partyIds).getAsJsonArray());
}
json.add("owner_filter", ownerFilter);
}
@ -150,4 +216,83 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
final String result = this.mainService.post(url, json.toString());
return WxCpUserExternalGroupChatStatistic.fromJson(result);
}
@Override
public WxCpMsgTemplateAddResult addMsgTemplate(WxCpMsgTemplate wxCpMsgTemplate) throws WxErrorException {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_MSG_TEMPLATE);
final String result = this.mainService.post(url, wxCpMsgTemplate.toJson());
return WxCpMsgTemplateAddResult.fromJson(result);
}
@Override
public void sendWelcomeMsg(WxCpWelcomeMsg msg) throws WxErrorException {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(SEND_WELCOME_MSG);
this.mainService.post(url, msg.toJson());
}
@Override
public WxCpUserExternalTagGroupList getCorpTagList(String[] tagId) throws WxErrorException {
JsonObject json = new JsonObject();
if(ArrayUtils.isNotEmpty(tagId)){
json.add("tag_id",new Gson().toJsonTree(tagId).getAsJsonArray());
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CORP_TAG_LIST);
final String result = this.mainService.post(url,json.toString());
return WxCpUserExternalTagGroupList.fromJson(result);
}
@Override
public WxCpUserExternalTagGroupInfo addCorpTag(WxCpUserExternalTagGroupInfo tagGroup) throws WxErrorException{
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_CORP_TAG);
final String result = this.mainService.post(url,tagGroup.getTagGroup().toJson());
return WxCpUserExternalTagGroupInfo.fromJson(result);
}
@Override
public WxCpBaseResp editCorpTag(String id, String name, Integer order) throws WxErrorException{
JsonObject json = new JsonObject();
json.addProperty("id",id);
json.addProperty("name",name);
json.addProperty("order",order);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(EDIT_CORP_TAG);
final String result = this.mainService.post(url,json.toString());
return WxCpBaseResp.fromJson(result);
}
@Override
public WxCpBaseResp delCorpTag(String[] tagId, String[] groupId) throws WxErrorException{
JsonObject json = new JsonObject();
if(ArrayUtils.isNotEmpty(tagId)){
json.add("tag_id",new Gson().toJsonTree(tagId).getAsJsonArray());
}
if(ArrayUtils.isNotEmpty(groupId)){
json.add("group_id",new Gson().toJsonTree(groupId).getAsJsonArray());
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEL_CORP_TAG);
final String result = this.mainService.post(url,json.toString());
return WxCpBaseResp.fromJson(result);
}
@Override
public WxCpBaseResp markTag(String userid, String externalUserid, String[] addTag, String[] removeTag)throws WxErrorException{
JsonObject json = new JsonObject();
json.addProperty("userid",userid);
json.addProperty("external_userid",externalUserid);
if(ArrayUtils.isNotEmpty(addTag)){
json.add("add_tag",new Gson().toJsonTree(addTag).getAsJsonArray());
}
if(ArrayUtils.isNotEmpty(removeTag)){
json.add("remove_tag",new Gson().toJsonTree(removeTag).getAsJsonArray());
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(MARK_TAG);
final String result = this.mainService.post(url,json.toString());
return WxCpBaseResp.fromJson(result);
}
}

View File

@ -0,0 +1,65 @@
package me.chanjar.weixin.cp.api.impl;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpGroupRobotService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpGroupRobotMessage;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import java.util.List;
/**
* 微信群机器人消息发送api 实现
*
* @author yr
* @date 2020-08-20
*/
@RequiredArgsConstructor
public class WxCpGroupRobotServiceImpl implements WxCpGroupRobotService {
private final WxCpService cpService;
private String getApiUrl() {
WxCpConfigStorage wxCpConfigStorage = cpService.getWxCpConfigStorage();
return wxCpConfigStorage.getApiUrl(WxCpApiPathConsts.WEBHOOK_SEND) + wxCpConfigStorage.getWebhookKey();
}
@Override
public void sendText(String content, List<String> mentionedList, List<String> mobileList) throws WxErrorException {
WxCpGroupRobotMessage message = new WxCpGroupRobotMessage()
.setMsgType(WxConsts.GroupRobotMsgType.TEXT)
.setContent(content)
.setMentionedList(mentionedList)
.setMentionedMobileList(mobileList);
cpService.postWithoutToken(this.getApiUrl(), message.toJson());
}
@Override
public void sendMarkDown(String content) throws WxErrorException {
WxCpGroupRobotMessage message = new WxCpGroupRobotMessage()
.setMsgType(WxConsts.GroupRobotMsgType.MARKDOWN)
.setContent(content);
cpService.postWithoutToken(this.getApiUrl(), message.toJson());
}
@Override
public void sendImage(String base64, String md5) throws WxErrorException {
WxCpGroupRobotMessage message = new WxCpGroupRobotMessage()
.setMsgType(WxConsts.GroupRobotMsgType.IMAGE)
.setBase64(base64)
.setMd5(md5);
cpService.postWithoutToken(this.getApiUrl(), message.toJson());
}
@Override
public void sendNews(List<NewArticle> articleList) throws WxErrorException {
WxCpGroupRobotMessage message = new WxCpGroupRobotMessage()
.setMsgType(WxConsts.GroupRobotMsgType.NEWS)
.setArticles(articleList);
cpService.postWithoutToken(this.getApiUrl(), message.toJson());
}
}

View File

@ -6,10 +6,8 @@ import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.cp.api.WxCpMediaService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import java.io.File;
import java.io.IOException;

View File

@ -5,7 +5,6 @@ import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpMenuService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Menu.*;

View File

@ -1,24 +1,18 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import me.chanjar.weixin.cp.bean.WxCpUserDetail;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.*;
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.SNSAPI_PRIVATEINFO;
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.SNSAPI_USERINFO;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.OAuth2.*;
/**
@ -74,8 +68,7 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service {
@Override
public WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException {
String responseText = this.mainService.get(String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_USER_INFO), code, agentId), null);
JsonElement je = new JsonParser().parse(responseText);
JsonObject jo = je.getAsJsonObject();
JsonObject jo = GsonParser.parse(responseText);
return WxCpOauth2UserInfo.builder()
.userId(GsonHelper.getString(jo, "UserId"))

View File

@ -1,13 +1,13 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpOaService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.oa.*;
@ -31,6 +31,13 @@ public class WxCpOaServiceImpl implements WxCpOaService {
private static final int MONTH_SECONDS = 30 * 24 * 60 * 60;
private static final int USER_IDS_LIMIT = 100;
@Override
public String apply(WxCpOaApplyEventRequest request) throws WxErrorException {
String responseContent = this.mainService.post(this.mainService.getWxCpConfigStorage().getApiUrl(APPLY_EVENT),
request.toJson());
return GsonParser.parse(responseContent).get("sp_no").getAsString();
}
@Override
public List<WxCpCheckinData> getCheckinData(Integer openCheckinDataType, Date startTime, Date endTime,
List<String> userIdList) throws WxErrorException {
@ -42,10 +49,10 @@ public class WxCpOaServiceImpl implements WxCpOaService {
throw new RuntimeException("用户列表不能为空,不超过 " + USER_IDS_LIMIT + " 个,若用户超过 " + USER_IDS_LIMIT + " 个,请分批获取");
}
long endtimestamp = endTime.getTime() / 1000L;
long starttimestamp = startTime.getTime() / 1000L;
long endTimestamp = endTime.getTime() / 1000L;
long startTimestamp = startTime.getTime() / 1000L;
if (endtimestamp - starttimestamp < 0 || endtimestamp - starttimestamp >= MONTH_SECONDS) {
if (endTimestamp - startTimestamp < 0 || endTimestamp - startTimestamp >= MONTH_SECONDS) {
throw new RuntimeException("获取记录时间跨度不超过一个月");
}
@ -53,8 +60,8 @@ public class WxCpOaServiceImpl implements WxCpOaService {
JsonArray jsonArray = new JsonArray();
jsonObject.addProperty("opencheckindatatype", openCheckinDataType);
jsonObject.addProperty("starttime", starttimestamp);
jsonObject.addProperty("endtime", endtimestamp);
jsonObject.addProperty("starttime", startTimestamp);
jsonObject.addProperty("endtime", endTimestamp);
for (String userid : userIdList) {
jsonArray.add(userid);
@ -64,10 +71,10 @@ public class WxCpOaServiceImpl implements WxCpOaService {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CHECKIN_DATA);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(
tmpJsonElement.getAsJsonObject().get("checkindata"),
tmpJson.get("checkindata"),
new TypeToken<List<WxCpCheckinData>>() {
}.getType()
);
@ -94,11 +101,11 @@ public class WxCpOaServiceImpl implements WxCpOaService {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CHECKIN_OPTION);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(
tmpJsonElement.getAsJsonObject().get("info"),
tmpJson.get("info"),
new TypeToken<List<WxCpCheckinOption>>() {
}.getType()
);
@ -157,20 +164,6 @@ public class WxCpOaServiceImpl implements WxCpOaService {
return WxCpGsonBuilder.create().fromJson(responseContent, WxCpApprovalDetailResult.class);
}
@Override
public WxCpApprovalDataResult getApprovalData(Date startTime, Date endTime, Long nextSpnum) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("starttime", startTime.getTime() / 1000L);
jsonObject.addProperty("endtime", endTime.getTime() / 1000L);
if (nextSpnum != null) {
jsonObject.addProperty("next_spnum", nextSpnum);
}
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_APPROVAL_DATA);
String responseContent = this.mainService.post(url, jsonObject.toString());
return WxCpGsonBuilder.create().fromJson(responseContent, WxCpApprovalDataResult.class);
}
@Override
public List<WxCpDialRecord> getDialRecord(Date startTime, Date endTime, Integer offset, Integer limit)
throws WxErrorException {
@ -202,9 +195,9 @@ public class WxCpOaServiceImpl implements WxCpOaService {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_DIAL_RECORD);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create().fromJson(tmpJsonElement.getAsJsonObject().get("record"),
return WxCpGsonBuilder.create().fromJson(tmpJson.get("record"),
new TypeToken<List<WxCpDialRecord>>() {
}.getType()
);
@ -213,9 +206,9 @@ public class WxCpOaServiceImpl implements WxCpOaService {
@Override
public WxCpTemplateResult getTemplateDetail(@NonNull String templateId) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("template_id",templateId);
jsonObject.addProperty("template_id", templateId);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_TEMPLATE_DETAIL);
String responseContent = this.mainService.post(url, jsonObject.toString());
return WxCpGsonBuilder.create().fromJson(responseContent,WxCpTemplateResult.class);
return WxCpGsonBuilder.create().fromJson(responseContent, WxCpTemplateResult.class);
}
}

View File

@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api.impl;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -1,11 +1,11 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
@ -88,7 +88,7 @@ public class WxCpServiceImpl extends WxCpServiceApacheHttpClientImpl {
// 拿到锁之后再次判断一下最新的token是否过期避免重刷
if (getWxCpConfigStorage().isAgentJsapiTicketExpired()) {
String responseContent = this.get(getWxCpConfigStorage().getApiUrl(GET_AGENT_CONFIG_TICKET), null);
JsonObject jsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
JsonObject jsonObject = GsonParser.parse(responseContent);
getWxCpConfigStorage().updateAgentJsapiTicket(jsonObject.get("ticket").getAsString(),
jsonObject.get("expires_in").getAsInt());
}
@ -112,7 +112,7 @@ public class WxCpServiceImpl extends WxCpServiceApacheHttpClientImpl {
// 拿到锁之后再次判断一下最新的token是否过期避免重刷
if (getWxCpConfigStorage().isJsapiTicketExpired()) {
String responseContent = this.get(getWxCpConfigStorage().getApiUrl(GET_JSAPI_TICKET), null);
JsonObject tmpJsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
JsonObject tmpJsonObject = GsonParser.parse(responseContent);
getWxCpConfigStorage().updateJsapiTicket(tmpJsonObject.get("ticket").getAsString(),
tmpJsonObject.get("expires_in").getAsInt());
}

View File

@ -5,7 +5,7 @@ import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.http.net.SocketHttpConnectionProvider;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api.impl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

View File

@ -4,6 +4,7 @@ import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpTagService;
import me.chanjar.weixin.cp.bean.WxCpTag;
@ -39,18 +40,11 @@ public class WxCpTagServiceImpl implements WxCpTagService {
return this.create(o);
}
@Override
public String create(String tagName) throws WxErrorException {
JsonObject o = new JsonObject();
o.addProperty("tagname", tagName);
return this.create(o);
}
private String create(JsonObject param) throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(TAG_CREATE);
String responseContent = this.mainService.post(url, param.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return tmpJsonElement.getAsJsonObject().get("tagid").getAsString();
JsonObject jsonObject = GsonParser.parse(responseContent);
return jsonObject.get("tagid").getAsString();
}
@Override
@ -72,10 +66,10 @@ public class WxCpTagServiceImpl implements WxCpTagService {
public List<WxCpTag> listAll() throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(TAG_LIST);
String responseContent = this.mainService.get(url, null);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(
tmpJsonElement.getAsJsonObject().get("taglist"),
tmpJson.get("taglist"),
new TypeToken<List<WxCpTag>>() {
}.getType()
);
@ -85,10 +79,10 @@ public class WxCpTagServiceImpl implements WxCpTagService {
public List<WxCpUser> listUsersByTagId(String tagId) throws WxErrorException {
String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(TAG_GET), tagId);
String responseContent = this.mainService.get(url, null);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(
tmpJsonElement.getAsJsonObject().get("userlist"),
tmpJson.get("userlist"),
new TypeToken<List<WxCpUser>>() {
}.getType()
);

View File

@ -5,7 +5,6 @@ import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpTaskCardService;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import java.util.HashMap;
import java.util.List;

View File

@ -2,13 +2,13 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import org.apache.http.Consts;
@ -76,7 +76,7 @@ public class WxCpTpServiceApacheHttpClientImpl extends BaseWxCpTpServiceImpl<Clo
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
jsonObject = new JsonParser().parse(resultContent).getAsJsonObject();
jsonObject = GsonParser.parse(resultContent);
String suiteAccussToken = jsonObject.get("suite_access_token").getAsString();
Integer expiresIn = jsonObject.get("expires_in").getAsInt();
this.configStorage.updateSuiteAccessToken(suiteAccussToken, expiresIn);

View File

@ -5,11 +5,12 @@ import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import me.chanjar.weixin.cp.bean.WxCpInviteResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalContactInfo;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.List;
@ -84,9 +85,9 @@ public class WxCpUserServiceImpl implements WxCpUserService {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(USER_LIST + departId);
String responseContent = this.mainService.get(url, params);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject jsonObject = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(tmpJsonElement.getAsJsonObject().get("userlist"),
.fromJson(jsonObject.get("userlist"),
new TypeToken<List<WxCpUser>>() {
}.getType()
);
@ -107,10 +108,10 @@ public class WxCpUserServiceImpl implements WxCpUserService {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(USER_SIMPLE_LIST + departId);
String responseContent = this.mainService.get(url, params);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
return WxCpGsonBuilder.create()
.fromJson(
tmpJsonElement.getAsJsonObject().get("userlist"),
tmpJson.get("userlist"),
new TypeToken<List<WxCpUser>>() {
}.getType()
);
@ -158,14 +159,14 @@ public class WxCpUserServiceImpl implements WxCpUserService {
}
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
JsonObject tmpJson = GsonParser.parse(responseContent);
Map<String, String> result = Maps.newHashMap();
if (tmpJsonElement.getAsJsonObject().get("openid") != null) {
result.put("openid", tmpJsonElement.getAsJsonObject().get("openid").getAsString());
if (tmpJson.get("openid") != null) {
result.put("openid", tmpJson.get("openid").getAsString());
}
if (tmpJsonElement.getAsJsonObject().get("appid") != null) {
result.put("appid", tmpJsonElement.getAsJsonObject().get("appid").getAsString());
if (tmpJson.get("appid") != null) {
result.put("appid", tmpJson.get("appid").getAsString());
}
return result;
@ -177,8 +178,8 @@ public class WxCpUserServiceImpl implements WxCpUserService {
jsonObject.addProperty("openid", openid);
String url = this.mainService.getWxCpConfigStorage().getApiUrl(USER_CONVERT_TO_USERID);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return tmpJsonElement.getAsJsonObject().get("userid").getAsString();
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("userid").getAsString();
}
@Override
@ -187,8 +188,8 @@ public class WxCpUserServiceImpl implements WxCpUserService {
jsonObject.addProperty("mobile", mobile);
String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_USER_ID);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return tmpJsonElement.getAsJsonObject().get("userid").getAsString();
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("userid").getAsString();
}
@Override

View File

@ -1,5 +1,8 @@
package me.chanjar.weixin.cp.bean;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* <pre>
* 性别枚举
@ -8,7 +11,13 @@ package me.chanjar.weixin.cp.bean;
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Getter
@AllArgsConstructor
public enum Gender {
/**
* 未定义
*/
UNDEFINED("未定义", "0"),
/**
*
*/
@ -18,28 +27,14 @@ public enum Gender {
*/
FEMALE("", "2");
private String genderName;
private String code;
Gender(String genderName, String code) {
this.genderName = genderName;
this.code = code;
}
public String getGenderName() {
return this.genderName;
}
public String getCode() {
return this.code;
}
private final String genderName;
private final String code;
public static Gender fromCode(String code) {
if ("1".equals(code)) {
return Gender.MALE;
}
if ("2".equals(code)) {
return Gender.FEMALE;
for(Gender a: Gender.values()){
if(a.code.equals(code)){
return a;
}
}
return null;

View File

@ -0,0 +1,118 @@
package me.chanjar.weixin.cp.bean;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import java.util.List;
import static me.chanjar.weixin.common.api.WxConsts.GroupRobotMsgType.*;
/**
* 微信群机器人消息
*
* @author yr
* @date 2020-08-20
*/
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Data
public class WxCpGroupRobotMessage {
/**
* 消息类型
*/
private String msgType;
/**
* 文本内容最长不超过2048个字节markdown内容最长不超过4096个字节必须是utf8编码
* 必填
*/
private String content;
/**
* userid的列表提醒群中的指定成员(@某个成员)@all表示提醒所有人如果开发者获取不到userid可以使用mentioned_mobile_list
*/
private List<String> mentionedList;
/**
* 手机号列表提醒手机号对应的群成员(@某个成员)@all表示提醒所有人
*/
private List<String> mentionedMobileList;
/**
* 图片内容的base64编码
*/
private String base64;
/**
* 图片内容base64编码前的md5值
*/
private String md5;
/**
* 图文消息一个图文消息支持1到8条图文
*/
private List<NewArticle> articles;
public String toJson() {
JsonObject messageJson = new JsonObject();
messageJson.addProperty("msgtype", this.getMsgType());
switch (this.getMsgType()) {
case TEXT: {
JsonObject text = new JsonObject();
JsonArray uidJsonArray = new JsonArray();
JsonArray mobileJsonArray = new JsonArray();
text.addProperty("content", this.getContent());
if (this.getMentionedList() != null) {
for (String item : this.getMentionedList()) {
uidJsonArray.add(item);
}
}
if (this.getMentionedMobileList() != null) {
for (String item : this.getMentionedMobileList()) {
mobileJsonArray.add(item);
}
}
text.add("mentioned_list", uidJsonArray);
text.add("mentioned_mobile_list", mobileJsonArray);
messageJson.add("text", text);
break;
}
case MARKDOWN: {
JsonObject text = new JsonObject();
text.addProperty("content", this.getContent());
messageJson.add("markdown", text);
break;
}
case IMAGE: {
JsonObject text = new JsonObject();
text.addProperty("base64", this.getBase64());
text.addProperty("md5", this.getMd5());
messageJson.add("image", text);
break;
}
case NEWS: {
JsonObject text = new JsonObject();
JsonArray array = new JsonArray();
for (NewArticle article : this.getArticles()) {
JsonObject articleJson = new JsonObject();
articleJson.addProperty("title", article.getTitle());
articleJson.addProperty("description", article.getDescription());
articleJson.addProperty("url", article.getUrl());
articleJson.addProperty("picurl", article.getPicUrl());
array.add(articleJson);
}
text.add("articles", array);
messageJson.add("news", text);
break;
}
default:
}
return messageJson.toString();
}
}

View File

@ -1,12 +1,7 @@
package me.chanjar.weixin.cp.bean;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Splitter;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;

View File

@ -8,16 +8,7 @@ import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.XmlUtils;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.cp.bean.outxmlbuilder.ImageBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.NewsBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.TextBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.VideoBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.VoiceBuilder;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
/**

View File

@ -8,13 +8,6 @@ import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;
import me.chanjar.weixin.common.util.XmlUtils;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.cp.bean.outxmlbuilder.ImageBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.NewsBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.TextBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.VideoBuilder;
import me.chanjar.weixin.cp.bean.outxmlbuilder.VoiceBuilder;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
/**

View File

@ -26,11 +26,13 @@ public class WxCpUser implements Serializable {
private Long[] departIds;
private Integer[] orders;
private String position;
private String[] positions;
private String mobile;
private Gender gender;
private String email;
private String avatar;
private String thumbAvatar;
private String mainDepartment;
/**
* 地址长度最大128个字符
@ -88,7 +90,7 @@ public class WxCpUser implements Serializable {
/**
* 属性类型: 0-文本 1-网页
*/
private int type;
private Integer type;
private String name;
private String textValue;
private String webUrl;
@ -103,7 +105,7 @@ public class WxCpUser implements Serializable {
/**
* 属性类型: 0-本文 1-网页 2-小程序.
*/
private int type;
private Integer type;
/**
* 属性名称 需要先确保在管理端有创建改属性否则会忽略.
*/

View File

@ -405,8 +405,7 @@ public class WxCpXmlMessage implements Serializable {
@XStreamAlias("ApprovalInfo")
private ApprovalInfo approvalInfo=new ApprovalInfo();
private ApprovalInfo approvalInfo = new ApprovalInfo();
protected static WxCpXmlMessage fromXml(String xml) {
@ -448,7 +447,8 @@ public class WxCpXmlMessage implements Serializable {
@Data
@XStreamAlias("ScanCodeInfo")
public static class ScanCodeInfo {
public static class ScanCodeInfo implements Serializable {
private static final long serialVersionUID = 7420078330239763395L;
/**
* 扫描类型一般是qrcode.
@ -466,7 +466,8 @@ public class WxCpXmlMessage implements Serializable {
}
@Data
public static class ExtAttr {
public static class ExtAttr implements Serializable {
private static final long serialVersionUID = -3418685294606228837L;
@XStreamImplicit(itemFieldName = "Item")
protected final List<Item> items = new ArrayList<>();
@ -486,7 +487,9 @@ public class WxCpXmlMessage implements Serializable {
@Data
@XStreamAlias("SendPicsInfo")
public static class SendPicsInfo {
public static class SendPicsInfo implements Serializable {
private static final long serialVersionUID = -6549728838848064881L;
@XStreamAlias("PicList")
protected final List<Item> picList = new ArrayList<>();
@ -504,7 +507,8 @@ public class WxCpXmlMessage implements Serializable {
@Data
@XStreamAlias("SendLocationInfo")
public static class SendLocationInfo {
public static class SendLocationInfo implements Serializable {
private static final long serialVersionUID = 6319921071637597406L;
@XStreamAlias("Location_X")
@XStreamConverter(value = XStreamCDataConverter.class)
@ -530,7 +534,8 @@ public class WxCpXmlMessage implements Serializable {
@XStreamAlias("ApprovalInfo")
@Data
public static class ApprovalInfo {
public static class ApprovalInfo implements Serializable {
private static final long serialVersionUID = 8136329462880646091L;
/**
* 审批编号
@ -551,7 +556,7 @@ public class WxCpXmlMessage implements Serializable {
/**
* 审批模板id
*/
@XStreamAlias("templateId")
@XStreamAlias("TemplateId")
private String templateId;
/**
* 审批申请提交时间,Unix时间戳
@ -563,18 +568,20 @@ public class WxCpXmlMessage implements Serializable {
* 申请人信息
*/
@XStreamAlias("Applyer")
private Applyer applyer;
private Applier applier;
/**
* 审批申请单变化类型
*/
@XStreamAlias("StatuChangeEvent")
private Integer statuChangeEvent;
private Integer statusChangeEvent;
@XStreamAlias("Applyer")
@Data
public static class Applyer {
public static class Applier implements Serializable {
private static final long serialVersionUID = -979255011922209018L;
@XStreamAlias("Applyer")
private String UserId;
private String userId;
@XStreamAlias("Party")
private String party;
}

View File

@ -0,0 +1,225 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import me.chanjar.weixin.cp.util.json.WxCpConclusionAdapter;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.List;
/**
* 联系我方式 对象
*
* @author element
*/
@Data
@NoArgsConstructor
public class WxCpContactWayInfo {
@SerializedName("contact_way")
private ContactWay contactWay;
@Getter
@Setter
public static class ContactWay {
/**
* 联系方式的配置id
*/
@SerializedName("config_id")
private String configId;
/**
* <pre>
* 必填
* 联系方式类型,1-单人, 2-多人
* </pre>
*/
private TYPE type;
/**
* <pre>
* 必填
* 场景1-在小程序中联系2-通过二维码联系
* </pre>
*/
private SCENE scene;
/**
* <pre>
* 非必填
* 在小程序中联系时使用的控件样式
* <b>单人样式(type=1)时可选1,2,3</b>
* <b>多人样式(type=2)时可选1,2</b>
* </pre>
*/
private Integer style;
/**
* <pre>
* 非必填
* 联系方式的备注信息用于助记不超过30个字符
* </pre>
*/
private String remark;
/**
* <pre>
* 非必填
* 外部客户添加时是否无需验证默认为true
* </pre>
*/
@SerializedName("skip_verify")
private Boolean skipVerify = Boolean.TRUE;
/**
* <pre>
* 非必填
* 企业自定义的state参数用于区分不同的添加渠道在调用获取外部联系人详情(WxCpExternalContactService.getContactDetail) 时会返回该参数值不超过30个字符
* </pre>
*/
private String state;
/**
* <pre>
* 联系二维码的URL仅在scene为2时返回
* </pre>
*/
@SerializedName("qr_code")
private String qrCode;
/**
* <pre>
* 使用该联系方式的用户userID列表在type为1时为必填且只能有一个
* </pre>
*/
@SerializedName("user")
private List<String> users;
/**
* <pre>
* 非必填
* 使用该联系方式的部门id列表只在type为2时有效
* </pre>
*/
@SerializedName("party")
private List<String> parties;
/**
* <pre>
* 非必填
* 是否临时会话模式true表示使用临时会话模式默认为false
* </pre>
*/
@SerializedName("is_temp")
private Boolean isTemp = Boolean.FALSE;
/**
* <pre>
* 非必填
* 临时会话二维码有效期以秒为单位该参数仅在is_temp为true时有效默认7天
* </pre>
*/
@SerializedName("expires_in")
private Integer expiresIn;
/**
* <pre>
* 非必填
* 临时会话有效期以秒为单位该参数仅在is_temp为true时有效默认为添加好友后24小时
* </pre>
*/
@SerializedName("chat_expires_in")
private Integer chatExpiresIn;
/**
* <pre>
* 非必填
* 可进行临时会话的客户unionid该参数仅在is_temp为true时有效如不指定则不进行限制
* </pre>
*/
@SerializedName("unionid")
private String unionId;
/**
* <pre>
* 非必填
* 结束语会话结束时自动发送给客户可参考结束语定义仅在is_temp为true时有效
* </pre>
*/
private Conclusion conclusions;
public static WxCpContactWayInfo.ContactWay fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpContactWayInfo.ContactWay.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
/**
* 结束语定义
*/
@Data
@JsonAdapter(WxCpConclusionAdapter.class)
public static class Conclusion {
private String textContent;
private String imgMediaId;
private String imgPicUrl;
private String linkTitle;
private String linkPicUrl;
private String linkDesc;
private String linkUrl;
private String miniProgramTitle;
private String miniProgramPicMediaId;
private String miniProgramAppId;
private String miniProgramPage;
}
}
public static WxCpContactWayInfo fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpContactWayInfo.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
public enum TYPE {
/**
* 单人
*/
@SerializedName("1")
SINGLE,
/**
* 多人
*/
@SerializedName("2")
MULTI;
}
public enum SCENE {
/**
* 在小程序中联系
*/
@SerializedName("1")
MINIPROGRAM,
/**
* 通过二维码联系
*/
@SerializedName("2")
QRCODE;
}
}

Some files were not shown because too many files have changed in this diff Show More