| @@ -4,16 +4,13 @@ import cn.binarywang.wx.miniapp.api.*; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | ||||
| import cn.binarywang.wx.miniapp.config.WxMaConfig; | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||
| import com.google.common.base.Joiner; | import com.google.common.base.Joiner; | ||||
| import com.google.gson.Gson; | |||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.error.WxError; | import me.chanjar.weixin.common.error.WxError; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.DataUtils; | import me.chanjar.weixin.common.util.DataUtils; | ||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | |||||
| 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.http.*; | |||||
| import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | ||||
| import org.apache.http.HttpHost; | import org.apache.http.HttpHost; | ||||
| @@ -55,6 +52,8 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| private int retrySleepMillis = 1000; | private int retrySleepMillis = 1000; | ||||
| private int maxRetryTimes = 5; | private int maxRetryTimes = 5; | ||||
| protected static final Gson GSON = new Gson(); | |||||
| @Override | @Override | ||||
| public CloseableHttpClient getRequestHttpClient() { | public CloseableHttpClient getRequestHttpClient() { | ||||
| return httpClient; | return httpClient; | ||||
| @@ -237,6 +237,7 @@ public class WxMpMemberCardServiceImpl implements WxMpMemberCardService { | |||||
| jsonObject.addProperty("code", code); | jsonObject.addProperty("code", code); | ||||
| String responseContent = this.getWxMpService().post(MEMBER_CARD_USER_INFO_GET, jsonObject.toString()); | String responseContent = this.getWxMpService().post(MEMBER_CARD_USER_INFO_GET, jsonObject.toString()); | ||||
| log.debug("{}",responseContent); | |||||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
| return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, | return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, | ||||
| new TypeToken<WxMpMemberCardUserInfoResult>() { | new TypeToken<WxMpMemberCardUserInfoResult>() { | ||||
| @@ -22,8 +22,8 @@ public class WxMpMemberCardServiceImplTest { | |||||
| @Inject | @Inject | ||||
| protected WxMpService wxService; | protected WxMpService wxService; | ||||
| private String cardId = "p2iQk1kUixiypVJ1lJYIT-_fMdUg"; | |||||
| private String code = "201808290001"; | |||||
| private String cardId = "p2iQk1g2d03JXhVRDY5fZRVr236A"; | |||||
| private String code = "435223630779"; | |||||
| private String openId = "o2iQk1u5X-XIJkatmAK1Q8VVuS90"; | private String openId = "o2iQk1u5X-XIJkatmAK1Q8VVuS90"; | ||||
| @Test | @Test | ||||
| @@ -1,8 +1,5 @@ | |||||
| package me.chanjar.weixin.open.api; | package me.chanjar.weixin.open.api; | ||||
| import java.util.List; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
| @@ -13,6 +10,8 @@ import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult; | |||||
| import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult; | import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult; | ||||
| import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; | import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; | ||||
| import java.util.List; | |||||
| /** | /** | ||||
| * @author <a href="https://github.com/007gzs">007</a> | * @author <a href="https://github.com/007gzs">007</a> | ||||
| */ | */ | ||||
| @@ -41,7 +40,13 @@ public interface WxOpenComponentService { | |||||
| WxMpService getWxMpServiceByAppid(String appid); | WxMpService getWxMpServiceByAppid(String appid); | ||||
| WxMaService getWxMaServiceByAppid(String appid); | |||||
| /** | |||||
| * 获取指定appid的开放平台小程序服务(继承一般小程序服务能力) | |||||
| * | |||||
| * @param appid | |||||
| * @return | |||||
| */ | |||||
| WxOpenMaService getWxMaServiceByAppid(String appid); | |||||
| WxOpenConfigStorage getWxOpenConfigStorage(); | WxOpenConfigStorage getWxOpenConfigStorage(); | ||||
| @@ -0,0 +1,335 @@ | |||||
| package me.chanjar.weixin.open.api; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaOpenCommitExtInfo; | |||||
| import me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage; | |||||
| import me.chanjar.weixin.open.bean.result.*; | |||||
| import java.io.File; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * <pre> | |||||
| * 微信开放平台代小程序实现服务能力 | |||||
| * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489144594_DhNoV&token=&lang=zh_CN | |||||
| * </pre> | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| public interface WxOpenMaService extends WxMaService { | |||||
| /** | |||||
| * 设置小程序服务器域名 | |||||
| * | |||||
| * <pre> | |||||
| * 授权给第三方的小程序,其服务器域名只可以为第三方的服务器,当小程序通过第三方发布代码上线后,小程序原先自己配置的服务器域名将被删除, | |||||
| * 只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加第三方自身的域名。 | |||||
| * 提示:需要先将域名登记到第三方平台的小程序服务器域名中,才可以调用接口进行配置 | |||||
| * </pre> | |||||
| */ | |||||
| String API_MODIFY_DOMAIN = "https://api.weixin.qq.com/wxa/modify_domain"; | |||||
| /** | |||||
| * 设置小程序业务域名(仅供第三方代小程序调用) | |||||
| * <pre> | |||||
| * 授权给第三方的小程序,其业务域名只可以为第三方的服务器,当小程序通过第三方发布代码上线后,小程序原先自己配置的业务域名将被删除, | |||||
| * 只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加业务域名。 | |||||
| * 提示: | |||||
| * 1、需要先将域名登记到第三方平台的小程序业务域名中,才可以调用接口进行配置。 | |||||
| * 2、为授权的小程序配置域名时支持配置子域名,例如第三方登记的业务域名如为qq.com,则可以直接将qq.com及其子域名(如xxx.qq.com)也配置到授权的小程序中。 | |||||
| * </pre> | |||||
| */ | |||||
| String API_SET_WEBVIEW_DOMAIN = "https://api.weixin.qq.com/wxa/setwebviewdomain"; | |||||
| /** | |||||
| * 获取帐号基本信息 | |||||
| * <pre> | |||||
| * GET请求 | |||||
| * 注意:需要使用1.3环节获取到的新创建小程序appid及authorization_code换取authorizer_refresh_token进而得到authorizer_access_token。 | |||||
| * </pre> | |||||
| */ | |||||
| String API_GET_ACCOUNT_BASICINFO = "https://api.weixin.qq.com/cgi-bin/account/getaccountbasicinfo"; | |||||
| /** | |||||
| * 绑定微信用户为小程序体验者 | |||||
| */ | |||||
| String API_BIND_TESTER = "https://api.weixin.qq.com/wxa/bind_tester"; | |||||
| /** | |||||
| * 解除绑定微信用户为小程序体验者 | |||||
| */ | |||||
| String API_UNBIND_TESTER = "https://api.weixin.qq.com/wxa/unbind_tester"; | |||||
| /** | |||||
| * 获取体验者列表 | |||||
| */ | |||||
| String API_GET_TESTERLIST = "https://api.weixin.qq.com/wxa/memberauth"; | |||||
| /** | |||||
| * 以下接口为三方平台代小程序实现的代码管理功能 | |||||
| * <p> | |||||
| * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=fe774228c66725425675810097f9e48d0737a4bf&lang=zh_CN | |||||
| * </p> | |||||
| */ | |||||
| /** | |||||
| * 1. 为授权的小程序帐号上传小程序代码 | |||||
| */ | |||||
| String API_CODE_COMMIT = "https://api.weixin.qq.com/wxa/commit"; | |||||
| /** | |||||
| * 2. 获取体验小程序的体验二维码 | |||||
| */ | |||||
| String API_TEST_QRCODE = "https://api.weixin.qq.com/wxa/get_qrcode"; | |||||
| /** | |||||
| * 3. 获取授权小程序帐号的可选类目 | |||||
| */ | |||||
| String API_GET_CATEGORY = "https://api.weixin.qq.com/wxa/get_category"; | |||||
| /** | |||||
| * 4. 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) | |||||
| */ | |||||
| String API_GET_PAGE = "https://api.weixin.qq.com/wxa/get_page"; | |||||
| /** | |||||
| * 5. 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) | |||||
| */ | |||||
| String API_SUBMIT_AUDIT = "https://api.weixin.qq.com/wxa/submit_audit"; | |||||
| /** | |||||
| * 7. 查询某个指定版本的审核状态(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_GET_AUDIT_STATUS = "https://api.weixin.qq.com/wxa/get_auditstatus"; | |||||
| /** | |||||
| * 8. 查询最新一次提交的审核状态(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_GET_LATEST_AUDIT_STATUS = "https://api.weixin.qq.com/wxa/get_latest_auditstatus"; | |||||
| /** | |||||
| * 9. 发布已通过审核的小程序(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_RELEASE = "https://api.weixin.qq.com/wxa/release"; | |||||
| /** | |||||
| * 10. 修改小程序线上代码的可见状态(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_CHANGE_VISITSTATUS = "https://api.weixin.qq.com/wxa/change_visitstatus"; | |||||
| /** | |||||
| * 11.小程序版本回退(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_REVERT_CODE_RELEASE = "https://api.weixin.qq.com/wxa/revertcoderelease"; | |||||
| /** | |||||
| * 12.查询当前设置的最低基础库版本及各版本用户占比 (仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_GET_WEAPP_SUPPORT_VERSION = "https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion"; | |||||
| /** | |||||
| * 13.设置最低基础库版本(仅供第三方代小程序调用) | |||||
| */ | |||||
| String API_SET_WEAPP_SUPPORT_VERSION = "https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion"; | |||||
| /** | |||||
| * 14.设置小程序“扫普通链接二维码打开小程序”能力 | |||||
| * <p> | |||||
| * TODO 暂时不实现 | |||||
| * </p> | |||||
| */ | |||||
| /** | |||||
| * 15.小程序审核撤回 | |||||
| * <p> | |||||
| * 单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次。 | |||||
| * </p> | |||||
| */ | |||||
| String API_UNDO_CODE_AUDIT = "https://api.weixin.qq.com/wxa/undocodeaudit"; | |||||
| /** | |||||
| * 16.1 小程序分阶段发布-分阶段发布接口 | |||||
| */ | |||||
| String API_GRAY_RELEASE = "https://api.weixin.qq.com/wxa/grayrelease"; | |||||
| /** | |||||
| * 16.2 小程序分阶段发布-取消分阶段发布 | |||||
| */ | |||||
| String API_REVERT_GRAY_RELEASE = "https://api.weixin.qq.com/wxa/revertgrayrelease"; | |||||
| /** | |||||
| * 16.3 小程序分阶段发布-查询当前分阶段发布详情 | |||||
| */ | |||||
| String API_GET_GRAY_RELEASE_PLAN = "https://api.weixin.qq.com/wxa/getgrayreleaseplan"; | |||||
| /** | |||||
| * 获得小程序的域名配置信息 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| WxOpenMaDomainResult getDomain() throws WxErrorException; | |||||
| /** | |||||
| * 修改域名 | |||||
| * | |||||
| * @param action delete删除, set覆盖, get获取 | |||||
| * @param requestdomainList | |||||
| * @param wsrequestdomainList | |||||
| * @param uploaddomainList | |||||
| * @param downloaddomainList | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| WxOpenMaDomainResult modifyDomain(String action, List<String> requestdomainList, List<String> wsrequestdomainList, List<String> uploaddomainList, List<String> downloaddomainList) throws WxErrorException; | |||||
| /** | |||||
| * 获取小程序的业务域名 | |||||
| * | |||||
| * @return 直接返回字符串 | |||||
| */ | |||||
| String getWebViewDomain() throws WxErrorException; | |||||
| /** | |||||
| * 设置小程序的业务域名 | |||||
| * | |||||
| * @param action add添加, delete删除, set覆盖 | |||||
| * @param domainList | |||||
| * @return 直接返回字符串 | |||||
| */ | |||||
| String setWebViewDomain(String action, List<String> domainList) throws WxErrorException; | |||||
| /** | |||||
| * 获取小程序的信息 | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String getAccountBasicInfo() throws WxErrorException; | |||||
| /** | |||||
| * 绑定小程序体验者 | |||||
| * | |||||
| * @param wechatid 体验者微信号(不是openid) | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String bindTester(String wechatid) throws WxErrorException; | |||||
| /** | |||||
| * 解除绑定小程序体验者 | |||||
| * | |||||
| * @param wechatid 体验者微信号(不是openid) | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String unbindTester(String wechatid) throws WxErrorException; | |||||
| /** | |||||
| * 获得体验者列表 | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| WxOpenMaTesterListResult getTesterList() throws WxErrorException; | |||||
| /** | |||||
| * 1、为授权的小程序帐号上传小程序代码 | |||||
| * | |||||
| * @param templateId 代码模板ID | |||||
| * @param userVersion 用户定义版本 | |||||
| * @param userDesc 用户定义版本描述 | |||||
| * @param extInfo 第三方自定义的配置 | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String codeCommit(Long templateId, String userVersion, String userDesc, WxMaOpenCommitExtInfo extInfo) throws WxErrorException; | |||||
| /** | |||||
| * 获取体验小程序的体验二维码 | |||||
| * | |||||
| * @param pagePath | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| File getTestQrcode(String pagePath, Map<String, String> params) throws WxErrorException; | |||||
| /** | |||||
| * 获取授权小程序帐号的可选类目 | |||||
| * <p> | |||||
| * 注意:该接口可获取已设置的二级类目及用于代码审核的可选三级类目。 | |||||
| * </p> | |||||
| * | |||||
| * @return WxOpenMaCategoryListResult | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| WxOpenMaCategoryListResult getCategoryList() throws WxErrorException; | |||||
| /** | |||||
| * 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| WxOpenMaPageListResult getPageList() throws WxErrorException; | |||||
| /** | |||||
| * 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) | |||||
| * | |||||
| * @param submitAuditMessage | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| WxOpenMaSubmitAuditResult submitAudit(WxOpenMaSubmitAuditMessage submitAuditMessage) throws WxErrorException; | |||||
| /** | |||||
| * 查询某个指定版本的审核状态(仅供第三方代小程序调用) | |||||
| * | |||||
| * @param auditid | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String getAuditStatus(Long auditid) throws WxErrorException; | |||||
| /** | |||||
| * 查询最新一次提交的审核状态(仅供第三方代小程序调用) | |||||
| * | |||||
| * @param auditid | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String getLatestAuditStatus(Long auditid) throws WxErrorException; | |||||
| /** | |||||
| * 发布已通过审核的小程序(仅供第三方代小程序调用) | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String releaesAudited() throws WxErrorException; | |||||
| /** | |||||
| * 11. 小程序版本回退(仅供第三方代小程序调用) | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String revertCodeReleaes() throws WxErrorException; | |||||
| /** | |||||
| * 15. 小程序审核撤回 | |||||
| * <p> | |||||
| * 单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次。 | |||||
| * </p> | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| String undoCodeAudit() throws WxErrorException; | |||||
| } | |||||
| @@ -1,14 +1,5 @@ | |||||
| package me.chanjar.weixin.open.api.impl; | package me.chanjar.weixin.open.api.impl; | ||||
| import java.util.Hashtable; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | ||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| @@ -22,6 +13,7 @@ import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | ||||
| import me.chanjar.weixin.open.api.WxOpenComponentService; | import me.chanjar.weixin.open.api.WxOpenComponentService; | ||||
| import me.chanjar.weixin.open.api.WxOpenConfigStorage; | import me.chanjar.weixin.open.api.WxOpenConfigStorage; | ||||
| import me.chanjar.weixin.open.api.WxOpenMaService; | |||||
| import me.chanjar.weixin.open.api.WxOpenService; | import me.chanjar.weixin.open.api.WxOpenService; | ||||
| import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken; | import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken; | ||||
| import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken; | import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken; | ||||
| @@ -32,13 +24,20 @@ import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult; | |||||
| import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult; | import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult; | ||||
| import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; | import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; | ||||
| import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; | import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| 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> | * @author <a href="https://github.com/007gzs">007</a> | ||||
| */ | */ | ||||
| public class WxOpenComponentServiceImpl implements WxOpenComponentService { | public class WxOpenComponentServiceImpl implements WxOpenComponentService { | ||||
| private static final JsonParser JSON_PARSER = new JsonParser(); | 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, WxOpenMaService> WX_OPEN_MA_SERVICE_MAP = new Hashtable<>(); | |||||
| private static final Map<String, WxMpService> WX_OPEN_MP_SERVICE_MAP = new Hashtable<>(); | private static final Map<String, WxMpService> WX_OPEN_MP_SERVICE_MAP = new Hashtable<>(); | ||||
| protected final Logger log = LoggerFactory.getLogger(this.getClass()); | protected final Logger log = LoggerFactory.getLogger(this.getClass()); | ||||
| @@ -65,18 +64,18 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public WxMaService getWxMaServiceByAppid(String appId) { | |||||
| WxMaService wxMaService = WX_OPEN_MA_SERVICE_MAP.get(appId); | |||||
| if (wxMaService == null) { | |||||
| public WxOpenMaService getWxMaServiceByAppid(String appId) { | |||||
| WxOpenMaService wxOpenMaService = WX_OPEN_MA_SERVICE_MAP.get(appId); | |||||
| if (wxOpenMaService == null) { | |||||
| synchronized (WX_OPEN_MA_SERVICE_MAP) { | synchronized (WX_OPEN_MA_SERVICE_MAP) { | ||||
| wxMaService = WX_OPEN_MA_SERVICE_MAP.get(appId); | |||||
| if (wxMaService == null) { | |||||
| wxMaService = new WxOpenMaServiceImpl(this, appId, getWxOpenConfigStorage().getWxMaConfig(appId)); | |||||
| WX_OPEN_MA_SERVICE_MAP.put(appId, wxMaService); | |||||
| wxOpenMaService = WX_OPEN_MA_SERVICE_MAP.get(appId); | |||||
| if (wxOpenMaService == null) { | |||||
| wxOpenMaService = new WxOpenMaServiceImpl(this, appId, getWxOpenConfigStorage().getWxMaConfig(appId)); | |||||
| WX_OPEN_MA_SERVICE_MAP.put(appId, wxOpenMaService); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return wxMaService; | |||||
| return wxOpenMaService; | |||||
| } | } | ||||
| public WxOpenService getWxOpenService() { | public WxOpenService getWxOpenService() { | ||||
| @@ -1,16 +1,34 @@ | |||||
| package me.chanjar.weixin.open.api.impl; | 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.api.impl.WxMaServiceImpl; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | ||||
| import cn.binarywang.wx.miniapp.config.WxMaConfig; | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||
| import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||||
| import com.google.gson.JsonArray; | |||||
| import com.google.gson.JsonObject; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.open.api.WxOpenComponentService; | import me.chanjar.weixin.open.api.WxOpenComponentService; | ||||
| import me.chanjar.weixin.open.api.WxOpenMaService; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaOpenCommitExtInfo; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam; | |||||
| import me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage; | |||||
| import me.chanjar.weixin.open.bean.result.*; | |||||
| import me.chanjar.weixin.open.util.requestexecuter.ma.MaQrCodeRequestExecutor; | |||||
| import java.io.File; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | /** | ||||
| * @author <a href="https://github.com/007gzs">007</a> | * @author <a href="https://github.com/007gzs">007</a> | ||||
| * <pre> | |||||
| * 增加开放平台代小程序管理服务能力 | |||||
| * 说明:这里让这个服务公开便于调用者模拟本地测试服务 | |||||
| * </pre> | |||||
| * @author yqx | |||||
| * @date 2018-09-12 | |||||
| */ | */ | ||||
| /* package */ class WxOpenMaServiceImpl extends WxMaServiceImpl { | |||||
| public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaService { | |||||
| private WxOpenComponentService wxOpenComponentService; | private WxOpenComponentService wxOpenComponentService; | ||||
| private WxMaConfig wxMaConfig; | private WxMaConfig wxMaConfig; | ||||
| private String appId; | private String appId; | ||||
| @@ -26,6 +44,7 @@ import me.chanjar.weixin.open.api.WxOpenComponentService; | |||||
| public WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException { | public WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException { | ||||
| return wxOpenComponentService.miniappJscode2Session(appId, jsCode); | return wxOpenComponentService.miniappJscode2Session(appId, jsCode); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public WxMaConfig getWxMaConfig() { | public WxMaConfig getWxMaConfig() { | ||||
| return wxMaConfig; | return wxMaConfig; | ||||
| @@ -35,4 +54,293 @@ import me.chanjar.weixin.open.api.WxOpenComponentService; | |||||
| public String getAccessToken(boolean forceRefresh) throws WxErrorException { | public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||
| return wxOpenComponentService.getAuthorizerAccessToken(appId, forceRefresh); | return wxOpenComponentService.getAuthorizerAccessToken(appId, forceRefresh); | ||||
| } | } | ||||
| /** | |||||
| * 获得小程序的域名配置信息 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public WxOpenMaDomainResult getDomain() throws WxErrorException { | |||||
| return modifyDomain("get", null, null, null, null); | |||||
| } | |||||
| /** | |||||
| * 修改服务器域名 | |||||
| * | |||||
| * @param action delete删除, set覆盖, get获取 | |||||
| * @param requestdomainList | |||||
| * @param wsrequestdomainList | |||||
| * @param uploaddomainList | |||||
| * @param downloaddomainList | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public WxOpenMaDomainResult modifyDomain(String action, List<String> requestdomainList, List<String> wsrequestdomainList, List<String> uploaddomainList, List<String> downloaddomainList) throws WxErrorException { | |||||
| // if (!"get".equals(action) && (requestdomainList == null || wsrequestdomainList == null || uploaddomainList == null || downloaddomainList == null)) { | |||||
| // throw new WxErrorException(WxError.builder().errorCode(44004).errorMsg("域名参数不能为空").build()); | |||||
| // } | |||||
| JsonObject requestJson = new JsonObject(); | |||||
| requestJson.addProperty("action", action); | |||||
| if (!"get".equals(action)) { | |||||
| requestJson.add("requestdomain", toJsonArray(requestdomainList)); | |||||
| requestJson.add("wsrequestdomain", toJsonArray(wsrequestdomainList)); | |||||
| requestJson.add("uploaddomain", toJsonArray(uploaddomainList)); | |||||
| requestJson.add("downloaddomain", toJsonArray(downloaddomainList)); | |||||
| } | |||||
| String response = post(API_MODIFY_DOMAIN, GSON.toJson(requestJson)); | |||||
| return WxMaGsonBuilder.create().fromJson(response, WxOpenMaDomainResult.class); | |||||
| } | |||||
| /** | |||||
| * 获取小程序的业务域名 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public String getWebViewDomain() throws WxErrorException { | |||||
| return setWebViewDomain("get", null); | |||||
| } | |||||
| /** | |||||
| * 设置小程序的业务域名 | |||||
| * | |||||
| * @param action add添加, delete删除, set覆盖 | |||||
| * @param domainList | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public String setWebViewDomain(String action, List<String> domainList) throws WxErrorException { | |||||
| JsonObject requestJson = new JsonObject(); | |||||
| requestJson.addProperty("action", action); | |||||
| if (!"get".equals(action)) { | |||||
| requestJson.add("webviewdomain", toJsonArray(domainList)); | |||||
| } | |||||
| String response = post(API_SET_WEBVIEW_DOMAIN, GSON.toJson(requestJson)); | |||||
| //TODO 转化为对象返回 | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 获取小程序的信息,GET请求 | |||||
| * <pre> | |||||
| * 注意:这里不能直接用小程序的access_token | |||||
| * //TODO 待调整 | |||||
| * </pre> | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String getAccountBasicInfo() throws WxErrorException { | |||||
| String response = get(API_GET_ACCOUNT_BASICINFO, ""); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 绑定小程序体验者 | |||||
| * | |||||
| * @param wechatid 体验者微信号(不是openid) | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String bindTester(String wechatid) throws WxErrorException { | |||||
| JsonObject paramJson = new JsonObject(); | |||||
| paramJson.addProperty("wechatid", wechatid); | |||||
| String response = post(API_BIND_TESTER, GSON.toJson(paramJson)); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 解除绑定小程序体验者 | |||||
| * | |||||
| * @param wechatid 体验者微信号(不是openid) | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String unbindTester(String wechatid) throws WxErrorException { | |||||
| JsonObject paramJson = new JsonObject(); | |||||
| paramJson.addProperty("wechatid", wechatid); | |||||
| String response = post(API_UNBIND_TESTER, GSON.toJson(paramJson)); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 获得体验者列表 | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public WxOpenMaTesterListResult getTesterList() throws WxErrorException { | |||||
| JsonObject paramJson = new JsonObject(); | |||||
| paramJson.addProperty("action", "get_experiencer"); | |||||
| String response = post(API_GET_TESTERLIST, GSON.toJson(paramJson)); | |||||
| return WxMaGsonBuilder.create().fromJson(response, WxOpenMaTesterListResult.class); | |||||
| } | |||||
| /** | |||||
| * 1、为授权的小程序帐号上传小程序代码 | |||||
| * | |||||
| * @param templateId 代码模板ID | |||||
| * @param userVersion 用户定义版本 | |||||
| * @param userDesc 用户定义版本描述 | |||||
| * @param extInfo 第三方自定义的配置 | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String codeCommit(Long templateId, String userVersion, String userDesc, WxMaOpenCommitExtInfo extInfo) throws WxErrorException { | |||||
| JsonObject params = new JsonObject(); | |||||
| params.addProperty("template_id", templateId); | |||||
| params.addProperty("user_version", userVersion); | |||||
| params.addProperty("user_desc", userDesc); | |||||
| //注意:ext_json必须是字符串类型 | |||||
| params.addProperty("ext_json", GSON.toJson(extInfo)); | |||||
| String response = post(API_CODE_COMMIT, GSON.toJson(params)); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 获取体验小程序的体验二维码 | |||||
| * | |||||
| * @param pagePath | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public File getTestQrcode(String pagePath, Map<String, String> params) throws WxErrorException { | |||||
| WxMaQrcodeParam qrcodeParam = WxMaQrcodeParam.create(pagePath); | |||||
| qrcodeParam.addPageParam(params); | |||||
| return execute(MaQrCodeRequestExecutor.create(getRequestHttp()), API_TEST_QRCODE, qrcodeParam); | |||||
| } | |||||
| /** | |||||
| * 获取授权小程序帐号的可选类目 | |||||
| * <p> | |||||
| * 注意:该接口可获取已设置的二级类目及用于代码审核的可选三级类目。 | |||||
| * </p> | |||||
| * | |||||
| * @return WxOpenMaCategoryListResult | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public WxOpenMaCategoryListResult getCategoryList() throws WxErrorException { | |||||
| String response = get(API_GET_CATEGORY, null); | |||||
| return WxMaGsonBuilder.create().fromJson(response, WxOpenMaCategoryListResult.class); | |||||
| } | |||||
| /** | |||||
| * 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public WxOpenMaPageListResult getPageList() throws WxErrorException { | |||||
| String response = get(API_GET_PAGE, null); | |||||
| return WxMaGsonBuilder.create().fromJson(response, WxOpenMaPageListResult.class); | |||||
| } | |||||
| /** | |||||
| * 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) | |||||
| * | |||||
| * @param submitAuditMessage | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public WxOpenMaSubmitAuditResult submitAudit(WxOpenMaSubmitAuditMessage submitAuditMessage) throws WxErrorException { | |||||
| String response = post(API_SUBMIT_AUDIT, GSON.toJson(submitAuditMessage)); | |||||
| return WxMaGsonBuilder.create().fromJson(response, WxOpenMaSubmitAuditResult.class); | |||||
| } | |||||
| /** | |||||
| * 7. 查询某个指定版本的审核状态(仅供第三方代小程序调用) | |||||
| * | |||||
| * @param auditid | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String getAuditStatus(Long auditid) throws WxErrorException { | |||||
| JsonObject params = new JsonObject(); | |||||
| params.addProperty("auditid", auditid); | |||||
| String response = post(API_GET_AUDIT_STATUS, GSON.toJson(params)); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 8. 查询最新一次提交的审核状态(仅供第三方代小程序调用) | |||||
| * | |||||
| * @param auditid | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String getLatestAuditStatus(Long auditid) throws WxErrorException { | |||||
| String response = get(API_GET_LATEST_AUDIT_STATUS, null); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 9. 发布已通过审核的小程序(仅供第三方代小程序调用) | |||||
| * <p> | |||||
| * 请填写空的数据包,POST的json数据包为空即可。 | |||||
| * </p> | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String releaesAudited() throws WxErrorException { | |||||
| JsonObject params = new JsonObject(); | |||||
| String response = post(API_RELEASE, GSON.toJson(params)); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 11. 小程序版本回退(仅供第三方代小程序调用) | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String revertCodeReleaes() throws WxErrorException { | |||||
| String response = get(API_REVERT_CODE_RELEASE, null); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 15. 小程序审核撤回 | |||||
| * <p> | |||||
| * 单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次。 | |||||
| * </p> | |||||
| * | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| @Override | |||||
| public String undoCodeAudit() throws WxErrorException { | |||||
| String response = get(API_UNDO_CODE_AUDIT, null); | |||||
| return response; | |||||
| } | |||||
| /** | |||||
| * 将字符串对象转化为GsonArray对象 | |||||
| * | |||||
| * @param strList | |||||
| * @return | |||||
| */ | |||||
| private JsonArray toJsonArray(List<String> strList) { | |||||
| JsonArray jsonArray = new JsonArray(); | |||||
| if (strList != null && !strList.isEmpty()) { | |||||
| for (String str : strList) { | |||||
| jsonArray.add(str); | |||||
| } | |||||
| } | |||||
| return jsonArray; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,96 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.io.Serializable; | |||||
| import java.util.ArrayList; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 微信小程序三方平台代上传代码提交额外信息对象 | |||||
| * <p> | |||||
| * 如果代码中已经有配置,则配置的合并规则为:除了pages和tabBar.list直接覆盖原配置,其他都为插入或同级覆盖。 | |||||
| * </p> | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaOpenCommitExtInfo implements Serializable { | |||||
| WxMaOpenCommitExtInfo() { | |||||
| } | |||||
| /** | |||||
| * 授权小程序Appid,可填入商户小程序AppID,以区分不同商户 | |||||
| */ | |||||
| private String extAppid; | |||||
| @SerializedName("ext") | |||||
| private Map<String, Object> extMap; | |||||
| @SerializedName("extPages") | |||||
| private Map<String, WxMaOpenPage> extPages; | |||||
| /** | |||||
| * 页面路径列表(和app.json结构一致) | |||||
| */ | |||||
| @SerializedName("pages") | |||||
| private List<String> pageList; | |||||
| @SerializedName("window") | |||||
| private WxMaOpenWindow window; | |||||
| @SerializedName("networkTimeout") | |||||
| private WxMaOpenNetworkTimeout networkTimeout; | |||||
| @SerializedName("tabBar") | |||||
| private WxMaOpenTabBar tabBar; | |||||
| /** | |||||
| * 添加扩展项 | |||||
| * | |||||
| * @param key | |||||
| * @param value | |||||
| */ | |||||
| public void addExt(String key, String value) { | |||||
| if (extMap == null) | |||||
| extMap = new HashMap<>(); | |||||
| if (StringUtils.isNoneBlank(key, value)) | |||||
| extMap.put(key, value); | |||||
| } | |||||
| /** | |||||
| * 添加扩展页面 | |||||
| * | |||||
| * @param pagePath | |||||
| * @param page | |||||
| */ | |||||
| public void addExtPage(String pagePath, WxMaOpenPage page) { | |||||
| if (extPages == null) | |||||
| extPages = new HashMap<>(); | |||||
| if (StringUtils.isNotBlank(pagePath) && page != null) | |||||
| extPages.put(pagePath, page); | |||||
| } | |||||
| /** | |||||
| * 添加页面 | |||||
| * | |||||
| * @param pagePath | |||||
| */ | |||||
| public void addPage(String pagePath) { | |||||
| if (pageList == null) | |||||
| pageList = new ArrayList<>(); | |||||
| if (StringUtils.isNotBlank(pagePath)) | |||||
| pageList.add(pagePath); | |||||
| } | |||||
| public static WxMaOpenCommitExtInfo INSTANCE() { | |||||
| return new WxMaOpenCommitExtInfo(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaOpenNetworkTimeout implements Serializable { | |||||
| private Integer request; | |||||
| private Integer connectSocket; | |||||
| private Integer uploadFile; | |||||
| private Integer downloadFile; | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaOpenPage implements Serializable { | |||||
| private String navigationBarBackgroundColor; | |||||
| private String navigationBarTextStyle; | |||||
| private String navigationBarTitleText; | |||||
| private String backgroundColor; | |||||
| private String backgroundTextStyle; | |||||
| private Boolean enablePullDownRefresh; | |||||
| private Integer onReachBottomDistance; | |||||
| private Boolean disableScroll; | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import lombok.NonNull; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaOpenTab implements Serializable { | |||||
| @NonNull | |||||
| private String pagePath; | |||||
| @NonNull | |||||
| private String text; | |||||
| private String iconPath; | |||||
| private String selectedIconPath; | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.NonNull; | |||||
| import java.io.Serializable; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * tabBar对象 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class WxMaOpenTabBar implements Serializable { | |||||
| @NonNull | |||||
| private String color; | |||||
| @NonNull | |||||
| private String selectedColor; | |||||
| @NonNull | |||||
| private String backgroundColor; | |||||
| private String borderStyle; | |||||
| @NonNull | |||||
| @SerializedName("list") | |||||
| private List<WxMaOpenTab> tabList; | |||||
| private String position; | |||||
| /** | |||||
| * 添加tab | |||||
| * | |||||
| * @param text | |||||
| * @param pagePath | |||||
| */ | |||||
| public void addTab(String text, String pagePath) { | |||||
| if (tabList == null) | |||||
| tabList = new ArrayList<>(); | |||||
| tabList.add(new WxMaOpenTab(pagePath, text)); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * window对象 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaOpenWindow implements Serializable { | |||||
| private String navigationBarBackgroundColor; | |||||
| private String navigationBarTextStyle; | |||||
| private String navigationBarTitleText; | |||||
| private String navigationStyle; | |||||
| private String backgroundColor; | |||||
| private String backgroundTextStyle; | |||||
| private String backgroundColorTop; | |||||
| private String backgroundColorBottom; | |||||
| private Boolean enablePullDownRefresh; | |||||
| private Integer onReachBottomDistance; | |||||
| } | |||||
| @@ -0,0 +1,86 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| /** | |||||
| * 微信小程序体验二维码参数 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxMaQrcodeParam { | |||||
| WxMaQrcodeParam() { | |||||
| } | |||||
| /** | |||||
| * 页面路径 | |||||
| */ | |||||
| private String pagePath; | |||||
| /** | |||||
| * 页面参数 | |||||
| */ | |||||
| private Map<String, String> pageParams; | |||||
| /** | |||||
| * 添加页面参数 | |||||
| * | |||||
| * @param key | |||||
| * @param value | |||||
| */ | |||||
| public WxMaQrcodeParam addPageParam(String key, String value) { | |||||
| if (StringUtils.isNoneBlank(key, value)) { | |||||
| if (pageParams == null) | |||||
| pageParams = new HashMap<>(); | |||||
| pageParams.put(key, value); | |||||
| } | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * 添加页面参数 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public WxMaQrcodeParam addPageParam(Map<String, String> params) { | |||||
| if (params != null) { | |||||
| if (pageParams == null) | |||||
| pageParams = new HashMap<>(); | |||||
| pageParams.putAll(params); | |||||
| } | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * 组装完整的页面请求路径(带参数) | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| public String getRequestPath() { | |||||
| if (StringUtils.isNotBlank(getPagePath()) && getPageParams() != null && !getPageParams().isEmpty()) { | |||||
| Set<String> keys = getPageParams().keySet(); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (String key : keys) { | |||||
| sb.append("&").append(key).append("=").append(getPageParams().get(key)); | |||||
| } | |||||
| return pagePath + "?" + sb.substring(1); | |||||
| } else { | |||||
| return pagePath; | |||||
| } | |||||
| } | |||||
| public static WxMaQrcodeParam create(String pagePath) { | |||||
| WxMaQrcodeParam instance = new WxMaQrcodeParam(); | |||||
| instance.setPagePath(pagePath); | |||||
| return instance; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 微信小程序分类目录 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaCategory implements Serializable { | |||||
| @SerializedName("first_class") | |||||
| private String firstClass; | |||||
| @SerializedName("second_class") | |||||
| private String secondClass; | |||||
| @SerializedName("third_class") | |||||
| private String thirdClass; | |||||
| @SerializedName("first_id") | |||||
| private Integer firstId; | |||||
| @SerializedName("second_id") | |||||
| private Integer secondId; | |||||
| @SerializedName("third_id") | |||||
| private Integer thirdId; | |||||
| public String toString() { | |||||
| return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,19 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 微信开放平台小程序成员对象 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaMember implements Serializable { | |||||
| /** | |||||
| * 人员对应的唯一字符串 | |||||
| */ | |||||
| private String userstr; | |||||
| } | |||||
| @@ -0,0 +1,60 @@ | |||||
| package me.chanjar.weixin.open.bean.ma; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 三方平台提交小程序代码审核 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaSubmitAudit implements Serializable { | |||||
| /** | |||||
| * 小程序的页面,可通过“获取小程序的第三方提交代码的页面配置”接口获得 | |||||
| */ | |||||
| @SerializedName("address") | |||||
| private String pagePath; | |||||
| /** | |||||
| * 小程序的标签,多个标签用空格分隔,标签不能多于10个,标签长度不超过20 | |||||
| */ | |||||
| @SerializedName("tag") | |||||
| private String tag; | |||||
| /** | |||||
| * 类目名称,可通过“获取授权小程序帐号的可选类目”接口获得 | |||||
| */ | |||||
| @SerializedName("first_class") | |||||
| private String firstClass; | |||||
| @SerializedName("second_class") | |||||
| private String secondClass; | |||||
| @SerializedName("third_class") | |||||
| private String thirdClass; | |||||
| /** | |||||
| * 类目的ID,可通过“获取授权小程序帐号的可选类目”接口获得 | |||||
| */ | |||||
| @SerializedName("first_id") | |||||
| private Integer firstId; | |||||
| @SerializedName("second_id") | |||||
| private Integer secondId; | |||||
| @SerializedName("third_id") | |||||
| private Integer thirdId; | |||||
| /** | |||||
| * 小程序页面的标题,标题长度不超过32 | |||||
| */ | |||||
| @SerializedName("title") | |||||
| private String title; | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| package me.chanjar.weixin.open.bean.message; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import me.chanjar.weixin.open.bean.ma.WxOpenMaSubmitAudit; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信小程序代码包提交审核(仅供第三方开发者代小程序调用) | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/13 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaSubmitAuditMessage implements Serializable { | |||||
| @SerializedName("item_list") | |||||
| private List<WxOpenMaSubmitAudit> itemList; | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| package me.chanjar.weixin.open.bean.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import me.chanjar.weixin.open.bean.ma.WxOpenMaCategory; | |||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信开放平台小程序分类目录列表返回 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaCategoryListResult implements Serializable { | |||||
| private String errcode; | |||||
| private String errmsg; | |||||
| @SerializedName("category_list") | |||||
| List<WxOpenMaCategory> categoryList; | |||||
| public String toString() { | |||||
| return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,33 @@ | |||||
| package me.chanjar.weixin.open.bean.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信开放平台小程序域名设置返回对象 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaDomainResult implements Serializable { | |||||
| private String errcode; | |||||
| private String errmsg; | |||||
| @SerializedName("requestdomain") | |||||
| List<String> requestdomainList; | |||||
| @SerializedName("wsrequestdomain") | |||||
| List<String> wsrequestdomainList; | |||||
| @SerializedName("uploaddomain") | |||||
| List<String> uploaddomainList; | |||||
| @SerializedName("downloaddomain") | |||||
| List<String> downloaddomainList; | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package me.chanjar.weixin.open.bean.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信开放平台小程序第三方提交代码的页面配置列表 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaPageListResult implements Serializable { | |||||
| private String errcode; | |||||
| private String errmsg; | |||||
| @SerializedName("page_list") | |||||
| List<String> pageList; | |||||
| public String toString() { | |||||
| return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| package me.chanjar.weixin.open.bean.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 微信开放平台小程序发布代码审核结果 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaSubmitAuditResult implements Serializable { | |||||
| private String errcode; | |||||
| private String errmsg; | |||||
| /** | |||||
| * 审核编号 | |||||
| */ | |||||
| @SerializedName("auditid") | |||||
| Long auditId; | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| package me.chanjar.weixin.open.bean.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import me.chanjar.weixin.open.bean.ma.WxOpenMaMember; | |||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信开放平台小程序体验者列表返回 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018/9/12 | |||||
| */ | |||||
| @Data | |||||
| public class WxOpenMaTesterListResult implements Serializable { | |||||
| private String errcode; | |||||
| private String errmsg; | |||||
| @SerializedName("members") | |||||
| List<WxOpenMaMember> membersList; | |||||
| public String toString() { | |||||
| return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,68 @@ | |||||
| package me.chanjar.weixin.open.util.requestexecuter.ma; | |||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.fs.FileUtils; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | |||||
| import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; | |||||
| import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.Header; | |||||
| import org.apache.http.HttpHost; | |||||
| import org.apache.http.client.config.RequestConfig; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.client.methods.HttpGet; | |||||
| import org.apache.http.entity.ContentType; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.net.URLEncoder; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018-09-13 | |||||
| */ | |||||
| public class MaQrCodeApacheHttpRequestExecutor extends MaQrCodeRequestExecutor<CloseableHttpClient, HttpHost> { | |||||
| public MaQrCodeApacheHttpRequestExecutor(RequestHttp requestHttp) { | |||||
| super(requestHttp); | |||||
| } | |||||
| @Override | |||||
| public File execute(String uri, WxMaQrcodeParam qrcodeParam) throws WxErrorException, IOException { | |||||
| if (qrcodeParam != null && StringUtils.isNotBlank(qrcodeParam.getPagePath())) { | |||||
| if (uri.indexOf('?') == -1) { | |||||
| uri += '?'; | |||||
| } | |||||
| uri += uri.endsWith("?") | |||||
| ? "path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8") | |||||
| : "&path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8"); | |||||
| } | |||||
| HttpGet httpGet = new HttpGet(uri); | |||||
| if (requestHttp.getRequestHttpProxy() != null) { | |||||
| RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); | |||||
| httpGet.setConfig(config); | |||||
| } | |||||
| try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet); | |||||
| InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) { | |||||
| Header[] contentTypeHeader = response.getHeaders("Content-Type"); | |||||
| if (contentTypeHeader != null && contentTypeHeader.length > 0) { | |||||
| // 出错 | |||||
| if (ContentType.TEXT_PLAIN.getMimeType() | |||||
| .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) { | |||||
| String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||||
| throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); | |||||
| } | |||||
| } | |||||
| return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); | |||||
| } finally { | |||||
| httpGet.releaseConnection(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,62 @@ | |||||
| package me.chanjar.weixin.open.util.requestexecuter.ma; | |||||
| import jodd.http.HttpConnectionProvider; | |||||
| import jodd.http.HttpRequest; | |||||
| import jodd.http.HttpResponse; | |||||
| import jodd.http.ProxyInfo; | |||||
| import jodd.util.MimeTypes; | |||||
| import jodd.util.StringPool; | |||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.fs.FileUtils; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.net.URLEncoder; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018-09-13 | |||||
| */ | |||||
| public class MaQrCodeJoddHttpRequestExecutor extends MaQrCodeRequestExecutor<HttpConnectionProvider, ProxyInfo> { | |||||
| public MaQrCodeJoddHttpRequestExecutor(RequestHttp requestHttp) { | |||||
| super(requestHttp); | |||||
| } | |||||
| @Override | |||||
| public File execute(String uri, WxMaQrcodeParam qrcodeParam) throws WxErrorException, IOException { | |||||
| if (qrcodeParam != null && StringUtils.isNotBlank(qrcodeParam.getPagePath())) { | |||||
| if (uri.indexOf('?') == -1) { | |||||
| uri += '?'; | |||||
| } | |||||
| uri += uri.endsWith("?") | |||||
| ? "path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8") | |||||
| : "&path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8"); | |||||
| } | |||||
| HttpRequest request = HttpRequest.get(uri); | |||||
| if (requestHttp.getRequestHttpProxy() != null) { | |||||
| requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); | |||||
| } | |||||
| request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||||
| HttpResponse response = request.send(); | |||||
| response.charset(StringPool.UTF_8); | |||||
| String contentTypeHeader = response.header("Content-Type"); | |||||
| if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { | |||||
| String responseContent = response.bodyText(); | |||||
| throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); | |||||
| } | |||||
| try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { | |||||
| return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,59 @@ | |||||
| package me.chanjar.weixin.open.util.requestexecuter.ma; | |||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.fs.FileUtils; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | |||||
| import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; | |||||
| import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam; | |||||
| import okhttp3.OkHttpClient; | |||||
| import okhttp3.Request; | |||||
| import okhttp3.Response; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.net.URLEncoder; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @author yqx | |||||
| * @date 2018-09-13 | |||||
| */ | |||||
| public class MaQrCodeOkhttpRequestExecutor extends MaQrCodeRequestExecutor<OkHttpClient, OkHttpProxyInfo> { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| public MaQrCodeOkhttpRequestExecutor(RequestHttp requestHttp) { | |||||
| super(requestHttp); | |||||
| } | |||||
| @Override | |||||
| public File execute(String uri, WxMaQrcodeParam qrcodeParam) throws WxErrorException, IOException { | |||||
| if (qrcodeParam != null && StringUtils.isNotBlank(qrcodeParam.getPagePath())) { | |||||
| if (uri.indexOf('?') == -1) { | |||||
| uri += '?'; | |||||
| } | |||||
| uri += uri.endsWith("?") | |||||
| ? "path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8") | |||||
| : "&path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8"); | |||||
| } | |||||
| OkHttpClient client = requestHttp.getRequestHttpClient(); | |||||
| Request request = new Request.Builder().url(uri).get().build(); | |||||
| Response response = client.newCall(request).execute(); | |||||
| String contentTypeHeader = response.header("Content-Type"); | |||||
| if ("text/plain".equals(contentTypeHeader)) { | |||||
| String responseContent = response.body().string(); | |||||
| throw new WxErrorException(WxError.fromJson(responseContent, WxType.MP)); | |||||
| } | |||||
| try (InputStream inputStream = response.body().byteStream()) { | |||||
| return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| package me.chanjar.weixin.open.util.requestexecuter.ma; | |||||
| 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.bean.ma.WxMaQrcodeParam; | |||||
| import java.io.File; | |||||
| /** | |||||
| * 获得小程序体验QrCode图片 请求执行器 | |||||
| * | |||||
| * @author yqx | |||||
| * @date 2018-09-13 | |||||
| */ | |||||
| public abstract class MaQrCodeRequestExecutor<H, P> implements RequestExecutor<File, WxMaQrcodeParam> { | |||||
| protected RequestHttp<H, P> requestHttp; | |||||
| public MaQrCodeRequestExecutor(RequestHttp requestHttp) { | |||||
| this.requestHttp = requestHttp; | |||||
| } | |||||
| public static RequestExecutor<File, WxMaQrcodeParam> create(RequestHttp requestHttp) throws WxErrorException { | |||||
| switch (requestHttp.getRequestType()) { | |||||
| case APACHE_HTTP: | |||||
| return new MaQrCodeApacheHttpRequestExecutor(requestHttp); | |||||
| case JODD_HTTP: | |||||
| return new MaQrCodeJoddHttpRequestExecutor(requestHttp); | |||||
| case OK_HTTP: | |||||
| return new MaQrCodeOkhttpRequestExecutor(requestHttp); | |||||
| default: | |||||
| throw new WxErrorException(WxError.builder().errorCode(-1).errorMsg("不支持的http框架").build()); | |||||
| } | |||||
| } | |||||
| } | |||||