合并 Develop,发布3.1.0正式版 (#640)
* #519 修复小程序客服消息 URL 被转义的问题 * 优化单元测试提示信息 * 网页授权url增加&connect_redirect=1参数解决两次重定向跳转问题: https://blog.csdn.net/jiangguilong2000/article/details/79416615 * 修复错误的feeToYuan方法名为fenToYuan * #529 EntPayBankRequest增加默认构造函数 * #529 EntPayBankResult中cmmsAmount的数据类型改为Integer * #528 WxMpUser类增加三个属性:subscribe_scene、 qr_scene 和qr_scene_str * 修复代码 * 发布3.0.1.BETA测试版本 * #533 微信刷卡支付请求类增加缺少的三个参数 * #536 企业号模块增加获取企业号应用相关接口 * 定义《企业号应用》的bean * 增加《获取企业号应用》接口实现 * 增加获取测试企业号应用信息测试类 * #535 修复Tomcat 不能正常关闭的问题,增加线程池shutdown相关的操作 * #541 企业号增加实现管理标签的(获取标签成员)接口 * 定义《企业号应用》的bean * 增加《获取企业号应用》接口实现 * 增加获取测试企业号应用信息测试类 * tag service增加获取标签成员方法 http://qydev.weixin.qq.com/wiki/index.php?title=管理标签 * #534 公众号发送模版消息中的小程序path改回pagepath * 发布3.0.2.BETA测试版本 * #547 开放平台模块 componentAccessToken 增加过期自动刷新 * createOrder方法增加H5支付的支持 * #551 文本卡片消息增加btntext字段 * #550 企业微信删除标签成员接口增加部门列表参数 * 清理无用代码 * #530 微信支付申请退款接口结果类增加单个代金券相关参数 ,并根据官方文档整理其他参数 * #531 小程序WxMaMessage类增加小程序卡片消息相关的几个属性 * #520 企业微信网页授权增加使用user_ticket获取成员详情的接口 * 发布3.0.3.BETA测试版本 * 优化代码 * 完善测试 * #559 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * #560 微信开放平台:增加小程序代码模板库管理 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * #562 小程序增加代码管理相关 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * #563 小程序增加修改服务器地址、成员管理 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * #565 小程序增加数据分析相关 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * #567 微信开放平台增加 HTTP proxy 机制 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * 微信开放平台:增加 HTTP proxy 机制 * #568 修复三方平台多次授权时,RefreshToken 没有刷新的问题 * fix 多次授权时,RefreshToken 没有刷新 * null 判断 * 发布3.0.4.BETA测试版本 * fix code * #569 微信支付几个查询关闭对账下载相关接口增加重载方法,以方便客户端指定更多参数 * #578 微信开放平台增加 WxMaUserService 的实现 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * 微信开放平台:增加 HTTP proxy 机制 * 微信开放平台:增加 WxMaUserService 的实现 * 修复小程序码的相关方法命名:WxCode->WxaCode, WxCodeLimit -> WxaCodeUnlimit * #556 日志信息中如果含有secret值的,将其值隐藏掉 * #585 小程序二维码支持is_hyaline参数生成透明背景二维码 * 发布3.0.5.BETA测试版本 * #584 修复企业付款到银行卡接口签名失败的问题 * 简化代码 * #586 微信支付 WxPayConfig增加支持byte数组方式设置证书 * #581 增加微信公众号错误信息枚举类WxMpErrorMsg,并提供方法,方便根据错误代码查询错误信息内容 * #555 修复微信支付服务商模式支付验证签名失败的问题 * #521 微信支付回调通知类WxPayOrderNotifyResult增加version参数 * #583 企业微信新增人员接口新增字段to_invite * #583 企业微信通讯录管理增加邀请成员接口 * #587 企业微信几个接口增加个人二维码字段 * 修复字符 * 修复单元测试 * 发布3.0.6.BETA测试版本 * 重构WxError相关代码,自动根据代码补充错误中文说明 * 优化微信支付代码 * #584 修复企业付款queryEntPay签名失败问题 * #591 文件上传接口不自动关闭inputStream,由调用方自己控制 * #595 优化WxPayException * 发布3.0.7.BETA测试版本 * 更新pom * 优化代码 * #615 公众号客服消息添加 "发送小程序卡片" 类型 * 优化XStreamTransformer * 微信支付模块jodd-http修改scope * 发布3.0.8.BETA测试版本 * #623 群发接口增加clientmsgid * add author for some files * clean code * 重构规范RequestExecuter代码 * #532 实现微信AI开放接口的三个接口:语音上传、查询识别结果和微信翻译功能 * 发布3.0.9.BETA测试版本 * #516 增加获取Wi-Fi门店列表接口 * #629 修复WxPayOrderNotifyResult解析xml报错问题 * #639 修复小程序代码模版库管理 access_token key 错误 * 发布3.1.0正式版本
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
</parent>
|
||||
<artifactId>weixin-java-open</artifactId>
|
||||
<name>Weixin Java Tools - Open</name>
|
||||
|
||||
@@ -2,19 +2,21 @@ package me.chanjar.weixin.open.api;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate;
|
||||
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
public interface WxOpenComponentService {
|
||||
|
||||
String API_COMPONENT_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
|
||||
String API_CREATE_PREAUTHCODE_URL = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode";
|
||||
String API_QUERY_AUTH_URL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth";
|
||||
@@ -23,7 +25,6 @@ public interface WxOpenComponentService {
|
||||
String API_GET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option";
|
||||
String API_SET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/api_set_authorizer_option";
|
||||
|
||||
|
||||
String COMPONENT_LOGIN_PAGE_URL = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";
|
||||
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect";
|
||||
|
||||
@@ -87,4 +88,48 @@ public interface WxOpenComponentService {
|
||||
|
||||
WxMaJscode2SessionResult miniappJscode2Session(String appId, String jsCode) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 代小程序实现业务
|
||||
* <p>
|
||||
* 小程序代码模版库管理:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1506504150_nMMh6&token=&lang=zh_CN
|
||||
* access_token 为 component_access_token
|
||||
*/
|
||||
String GET_TEMPLATE_DRAFT_LIST_URL = "https://api.weixin.qq.com/wxa/gettemplatedraftlist";
|
||||
String GET_TEMPLATE_LIST_URL = "https://api.weixin.qq.com/wxa/gettemplatelist";
|
||||
String ADD_TO_TEMPLATE_URL = "https://api.weixin.qq.com/wxa/addtotemplate";
|
||||
String DELETE_TEMPLATE_URL = "https://api.weixin.qq.com/wxa/deletetemplate";
|
||||
|
||||
/**
|
||||
* 获取草稿箱内的所有临时代码草稿
|
||||
*
|
||||
* @return 草稿箱代码模板列表(draftId)
|
||||
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档
|
||||
*/
|
||||
List<WxOpenMaCodeTemplate> getTemplateDraftList() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取代码模版库中的所有小程序代码模版
|
||||
*
|
||||
* @return 小程序代码模版列表(templateId)
|
||||
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档
|
||||
*/
|
||||
List<WxOpenMaCodeTemplate> getTemplateList() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 将草稿箱的草稿选为小程序代码模版
|
||||
*
|
||||
* @param draftId 草稿ID,本字段可通过“获取草稿箱内的所有临时代码草稿”接口获得
|
||||
* @throws WxErrorException 操作失败时抛出,具体错误码请看此接口的注释文档
|
||||
* @see #getTemplateDraftList
|
||||
*/
|
||||
void addToTemplate(long draftId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 删除指定小程序代码模版
|
||||
*
|
||||
* @param templateId 要删除的模版ID
|
||||
* @throws WxErrorException 操作失败时抛出,具体错误码请看此接口的注释文档
|
||||
* @see #getTemplateList
|
||||
*/
|
||||
void deleteTemplate(long templateId) throws WxErrorException;
|
||||
}
|
||||
|
||||
@@ -34,8 +34,18 @@ public interface WxOpenConfigStorage {
|
||||
|
||||
boolean isComponentAccessTokenExpired();
|
||||
|
||||
void expireComponentAccessToken();
|
||||
|
||||
void updateComponentAccessTokent(WxOpenComponentAccessToken componentAccessToken);
|
||||
|
||||
String getHttpProxyHost();
|
||||
|
||||
int getHttpProxyPort();
|
||||
|
||||
String getHttpProxyUsername();
|
||||
|
||||
String getHttpProxyPassword();
|
||||
|
||||
WxMpConfigStorage getWxMpConfigStorage(String appId);
|
||||
|
||||
WxMaConfig getWxMaConfig(String appId);
|
||||
@@ -115,5 +125,4 @@ public interface WxOpenConfigStorage {
|
||||
* @param expiresInSeconds 过期时间,以秒为单位
|
||||
*/
|
||||
void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package me.chanjar.weixin.open.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
|
||||
@@ -3,7 +3,10 @@ package me.chanjar.weixin.open.api.impl;
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.crypto.SHA1;
|
||||
import me.chanjar.weixin.common.util.http.URIUtil;
|
||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||
@@ -14,6 +17,7 @@ import me.chanjar.weixin.open.api.WxOpenConfigStorage;
|
||||
import me.chanjar.weixin.open.api.WxOpenService;
|
||||
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
|
||||
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
|
||||
import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate;
|
||||
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
|
||||
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
|
||||
@@ -25,13 +29,14 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
public class WxOpenComponentServiceImpl implements WxOpenComponentService {
|
||||
|
||||
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||
private static final Map<String, WxMaService> WX_OPEN_MA_SERVICE_MAP = new Hashtable<>();
|
||||
private static final Map<String, WxMpService> WX_OPEN_MP_SERVICE_MAP = new Hashtable<>();
|
||||
|
||||
@@ -110,15 +115,64 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
|
||||
}
|
||||
|
||||
private String post(String uri, String postData) throws WxErrorException {
|
||||
return post(uri, postData, "component_access_token");
|
||||
}
|
||||
|
||||
private String post(String uri, String postData, String accessTokenKey) throws WxErrorException {
|
||||
String componentAccessToken = getComponentAccessToken(false);
|
||||
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + "component_access_token=" + componentAccessToken;
|
||||
return getWxOpenService().post(uriWithComponentAccessToken, postData);
|
||||
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + accessTokenKey + "=" + componentAccessToken;
|
||||
try {
|
||||
return getWxOpenService().post(uriWithComponentAccessToken, postData);
|
||||
} 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) {
|
||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
|
||||
this.getWxOpenConfigStorage().expireComponentAccessToken();
|
||||
if (this.getWxOpenConfigStorage().autoRefreshToken()) {
|
||||
return this.post(uri, postData, accessTokenKey);
|
||||
}
|
||||
}
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String get(String uri) throws WxErrorException {
|
||||
return get(uri, "component_access_token");
|
||||
}
|
||||
private String get(String uri, String accessTokenKey) throws WxErrorException {
|
||||
String componentAccessToken = getComponentAccessToken(false);
|
||||
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + "component_access_token=" + componentAccessToken;
|
||||
return getWxOpenService().get(uriWithComponentAccessToken, null);
|
||||
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + accessTokenKey + "=" + componentAccessToken;
|
||||
try {
|
||||
return getWxOpenService().get(uriWithComponentAccessToken, null);
|
||||
} 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) {
|
||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
|
||||
this.getWxOpenConfigStorage().expireComponentAccessToken();
|
||||
if (this.getWxOpenConfigStorage().autoRefreshToken()) {
|
||||
return this.get(uri, accessTokenKey);
|
||||
}
|
||||
}
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,14 +200,6 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
|
||||
if (queryAuth == null || queryAuth.getAuthorizationInfo() == null || queryAuth.getAuthorizationInfo().getAuthorizerAppid() == null) {
|
||||
throw new NullPointerException("getQueryAuth");
|
||||
}
|
||||
WxOpenAuthorizationInfo authorizationInfo = queryAuth.getAuthorizationInfo();
|
||||
if (authorizationInfo.getAuthorizerAccessToken() != null) {
|
||||
getWxOpenConfigStorage().updateAuthorizerAccessToken(authorizationInfo.getAuthorizerAppid(),
|
||||
authorizationInfo.getAuthorizerAccessToken(), authorizationInfo.getExpiresIn());
|
||||
}
|
||||
if (authorizationInfo.getAuthorizerRefreshToken() != null) {
|
||||
getWxOpenConfigStorage().setAuthorizerRefreshToken(authorizationInfo.getAuthorizerAppid(), authorizationInfo.getAuthorizerRefreshToken());
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
return "";
|
||||
@@ -165,7 +211,19 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
|
||||
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
|
||||
jsonObject.addProperty("authorization_code", authorizationCode);
|
||||
String responseContent = post(API_QUERY_AUTH_URL, jsonObject.toString());
|
||||
return WxOpenGsonBuilder.create().fromJson(responseContent, WxOpenQueryAuthResult.class);
|
||||
WxOpenQueryAuthResult queryAuth = WxOpenGsonBuilder.create().fromJson(responseContent, WxOpenQueryAuthResult.class);
|
||||
if (queryAuth == null || queryAuth.getAuthorizationInfo() == null) {
|
||||
return queryAuth;
|
||||
}
|
||||
WxOpenAuthorizationInfo authorizationInfo = queryAuth.getAuthorizationInfo();
|
||||
if (authorizationInfo.getAuthorizerAccessToken() != null) {
|
||||
getWxOpenConfigStorage().updateAuthorizerAccessToken(authorizationInfo.getAuthorizerAppid(),
|
||||
authorizationInfo.getAuthorizerAccessToken(), authorizationInfo.getExpiresIn());
|
||||
}
|
||||
if (authorizationInfo.getAuthorizerRefreshToken() != null) {
|
||||
getWxOpenConfigStorage().setAuthorizerRefreshToken(authorizationInfo.getAuthorizerAppid(), authorizationInfo.getAuthorizerRefreshToken());
|
||||
}
|
||||
return queryAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -245,4 +303,45 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
|
||||
return WxMaJscode2SessionResult.fromJson(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxOpenMaCodeTemplate> getTemplateDraftList() throws WxErrorException {
|
||||
String responseContent = get(GET_TEMPLATE_DRAFT_LIST_URL, "access_token");
|
||||
JsonObject response = JSON_PARSER.parse(StringUtils.defaultString(responseContent, "{}")).getAsJsonObject();
|
||||
boolean hasDraftList = response.has("draft_list");
|
||||
if (hasDraftList) {
|
||||
return WxOpenGsonBuilder.create().fromJson(response.getAsJsonArray("draft_list"),
|
||||
new TypeToken<List<WxOpenMaCodeTemplate>>() {
|
||||
}.getType());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxOpenMaCodeTemplate> getTemplateList() throws WxErrorException {
|
||||
String responseContent = get(GET_TEMPLATE_LIST_URL, "access_token");
|
||||
JsonObject response = JSON_PARSER.parse(StringUtils.defaultString(responseContent, "{}")).getAsJsonObject();
|
||||
boolean hasDraftList = response.has("template_list");
|
||||
if (hasDraftList) {
|
||||
return WxOpenGsonBuilder.create().fromJson(response.getAsJsonArray("template_list"),
|
||||
new TypeToken<List<WxOpenMaCodeTemplate>>() {
|
||||
}.getType());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToTemplate(long draftId) throws WxErrorException {
|
||||
JsonObject param = new JsonObject();
|
||||
param.addProperty("draft_id", draftId);
|
||||
post(ADD_TO_TEMPLATE_URL, param.toString(), "access_token");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTemplate(long templateId) throws WxErrorException {
|
||||
JsonObject param = new JsonObject();
|
||||
param.addProperty("template_id", templateId);
|
||||
post(DELETE_TEMPLATE_URL, param.toString(), "access_token");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,11 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
|
||||
private String componentAccessToken;
|
||||
private long componentExpiresTime;
|
||||
|
||||
private String httpProxyHost;
|
||||
private int httpProxyPort;
|
||||
private String httpProxyUsername;
|
||||
private String httpProxyPassword;
|
||||
|
||||
private Map<String, Token> authorizerRefreshTokens = new Hashtable<>();
|
||||
private Map<String, Token> authorizerAccessTokens = new Hashtable<>();
|
||||
private Map<String, Token> jsapiTickets = new Hashtable<>();
|
||||
@@ -95,11 +100,52 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
|
||||
return System.currentTimeMillis() > componentExpiresTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireComponentAccessToken() {
|
||||
this.componentExpiresTime = 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateComponentAccessTokent(WxOpenComponentAccessToken componentAccessToken) {
|
||||
updateComponentAccessTokent(componentAccessToken.getComponentAccessToken(), componentAccessToken.getExpiresIn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpProxyHost() {
|
||||
return httpProxyHost;
|
||||
}
|
||||
|
||||
public void setHttpProxyHost(String httpProxyHost) {
|
||||
this.httpProxyHost = httpProxyHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHttpProxyPort() {
|
||||
return httpProxyPort;
|
||||
}
|
||||
|
||||
public void setHttpProxyPort(int httpProxyPort) {
|
||||
this.httpProxyPort = httpProxyPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpProxyUsername() {
|
||||
return httpProxyUsername;
|
||||
}
|
||||
|
||||
public void setHttpProxyUsername(String httpProxyUsername) {
|
||||
this.httpProxyUsername = httpProxyUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpProxyPassword() {
|
||||
return httpProxyPassword;
|
||||
}
|
||||
|
||||
public void setHttpProxyPassword(String httpProxyPassword) {
|
||||
this.httpProxyPassword = httpProxyPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpConfigStorage getWxMpConfigStorage(String appId) {
|
||||
return new WxOpenInnerConfigStorage(this, appId);
|
||||
@@ -372,22 +418,22 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
|
||||
|
||||
@Override
|
||||
public String getHttpProxyHost() {
|
||||
return null;
|
||||
return this.wxOpenConfigStorage.getHttpProxyHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHttpProxyPort() {
|
||||
return 0;
|
||||
return this.wxOpenConfigStorage.getHttpProxyPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpProxyUsername() {
|
||||
return null;
|
||||
return this.wxOpenConfigStorage.getHttpProxyUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpProxyPassword() {
|
||||
return null;
|
||||
return this.wxOpenConfigStorage.getHttpProxyPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.util.Pool;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
@@ -15,7 +17,11 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
|
||||
private final static String JSAPI_TICKET_KEY = "wechat_jsapi_ticket:";
|
||||
private final static String CARD_API_TICKET_KEY = "wechat_card_api_ticket:";
|
||||
|
||||
protected final JedisPool jedisPool;
|
||||
protected final Pool<Jedis> jedisPool;
|
||||
/**
|
||||
* redis 存储的 key 的前缀,可为空
|
||||
*/
|
||||
private String keyPrefix;
|
||||
private String componentVerifyTicketKey;
|
||||
private String componentAccessTokenKey;
|
||||
private String authorizerRefreshTokenKey;
|
||||
@@ -23,6 +29,15 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
|
||||
private String jsapiTicketKey;
|
||||
private String cardApiTicket;
|
||||
|
||||
public WxOpenInRedisConfigStorage(Pool<Jedis> jedisPool) {
|
||||
this.jedisPool = jedisPool;
|
||||
}
|
||||
|
||||
public WxOpenInRedisConfigStorage(Pool<Jedis> jedisPool, String keyPrefix) {
|
||||
this.jedisPool = jedisPool;
|
||||
this.keyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
public WxOpenInRedisConfigStorage(JedisPool jedisPool) {
|
||||
this.jedisPool = jedisPool;
|
||||
}
|
||||
@@ -30,10 +45,12 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
|
||||
@Override
|
||||
public void setComponentAppId(String componentAppId) {
|
||||
super.setComponentAppId(componentAppId);
|
||||
this.componentVerifyTicketKey = COMPONENT_VERIFY_TICKET_KEY.concat(componentAppId);
|
||||
this.componentAccessTokenKey = COMPONENT_ACCESS_TOKEN_KEY.concat(componentAppId);
|
||||
this.authorizerRefreshTokenKey = AUTHORIZER_REFRESH_TOKEN_KEY.concat(componentAppId);
|
||||
this.authorizerAccessTokenKey = AUTHORIZER_ACCESS_TOKEN_KEY.concat(componentAppId);
|
||||
String prefix = StringUtils.isBlank(keyPrefix) ? "" :
|
||||
(StringUtils.endsWith(keyPrefix, ":") ? keyPrefix : (keyPrefix + ":"));
|
||||
componentVerifyTicketKey = prefix + COMPONENT_VERIFY_TICKET_KEY.concat(componentAppId);
|
||||
componentAccessTokenKey = prefix + COMPONENT_ACCESS_TOKEN_KEY.concat(componentAppId);
|
||||
authorizerRefreshTokenKey = prefix + AUTHORIZER_REFRESH_TOKEN_KEY.concat(componentAppId);
|
||||
authorizerAccessTokenKey = prefix + AUTHORIZER_ACCESS_TOKEN_KEY.concat(componentAppId);
|
||||
this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(componentAppId);
|
||||
this.cardApiTicket = CARD_API_TICKET_KEY.concat(componentAppId);
|
||||
}
|
||||
@@ -66,6 +83,13 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expireComponentAccessToken(){
|
||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||
jedis.expire(this.componentAccessTokenKey, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds) {
|
||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaUserService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.config.WxMaConfig;
|
||||
import com.google.common.base.Joiner;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.open.api.WxOpenComponentService;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
@@ -38,5 +35,4 @@ import java.util.Map;
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
return wxOpenComponentService.getAuthorizerAccessToken(appId, forceRefresh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import me.chanjar.weixin.common.bean.result.WxError;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.RequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import me.chanjar.weixin.open.api.WxOpenComponentService;
|
||||
@@ -33,8 +33,14 @@ public abstract class WxOpenServiceAbstractImpl<H, P> implements WxOpenService,
|
||||
@Override
|
||||
public void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage) {
|
||||
this.wxOpenConfigStorage = wxOpenConfigStorage;
|
||||
this.initHttp();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 RequestHttp
|
||||
*/
|
||||
public abstract void initHttp();
|
||||
|
||||
protected synchronized <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
|
||||
try {
|
||||
T result = executor.execute(uri, data);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.HttpType;
|
||||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
@@ -14,8 +15,21 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
* @author <a href="https://github.com/007gzs">007</a>
|
||||
*/
|
||||
public class WxOpenServiceApacheHttpClientImpl extends WxOpenServiceAbstractImpl<CloseableHttpClient, HttpHost> {
|
||||
private CloseableHttpClient httpClient = DefaultApacheHttpClientBuilder.get().build();
|
||||
private HttpHost httpProxy = null;
|
||||
private CloseableHttpClient httpClient;
|
||||
private HttpHost httpProxy;
|
||||
|
||||
@Override
|
||||
public void initHttp() {
|
||||
WxOpenConfigStorage configStorage = this.getWxOpenConfigStorage();
|
||||
if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) {
|
||||
this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort());
|
||||
}
|
||||
this.httpClient = DefaultApacheHttpClientBuilder.get()
|
||||
.httpProxyHost(configStorage.getHttpProxyHost())
|
||||
.httpProxyPort(configStorage.getHttpProxyPort())
|
||||
.httpProxyUsername(configStorage.getHttpProxyUsername())
|
||||
.httpProxyPassword(configStorage.getHttpProxyPassword()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseableHttpClient getRequestHttpClient() {
|
||||
@@ -41,5 +55,4 @@ public class WxOpenServiceApacheHttpClientImpl extends WxOpenServiceAbstractImpl
|
||||
public String post(String url, String postData) throws WxErrorException {
|
||||
return execute(SimplePostRequestExecutor.create(this), url, postData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package me.chanjar.weixin.open.bean;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/charmingoh">Charming</a>
|
||||
* @since 2018-04-26 17:10
|
||||
*/
|
||||
@Data
|
||||
public class WxOpenMaCodeTemplate implements Serializable {
|
||||
private static final long serialVersionUID = -3278116984473619010L;
|
||||
/**
|
||||
* 草稿id
|
||||
*/
|
||||
@SerializedName(value = "draftId", alternate = "draft_id")
|
||||
private Long draftId;
|
||||
/**
|
||||
* 模版id
|
||||
*/
|
||||
@SerializedName(value = "templateId", alternate = "template_id")
|
||||
private Long templateId;
|
||||
/**
|
||||
* 模版版本号,开发者自定义字段
|
||||
*/
|
||||
@SerializedName(value = "userVersion", alternate = "user_version")
|
||||
private String userVersion;
|
||||
/**
|
||||
* 模版描述 开发者自定义字段
|
||||
*/
|
||||
@SerializedName(value = "userDesc", alternate = "user_desc")
|
||||
private String userDesc;
|
||||
/**
|
||||
* 开发者上传草稿时间 / 被添加为模版的时间
|
||||
*/
|
||||
@SerializedName(value = "createTime", alternate = "create_time")
|
||||
private Long createTime;
|
||||
}
|
||||
@@ -60,7 +60,6 @@ public class XStreamTransformer {
|
||||
*/
|
||||
private static void registerClass(Class<?> clz) {
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||
|
||||
xstream.processAnnotations(clz);
|
||||
xstream.processAnnotations(getInnerClasses(clz));
|
||||
|
||||
Reference in New Issue
Block a user