mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-11-01 03:25:35 +08:00 
			
		
		
		
	🐛 #2128 【开放平台】 修复公众号在由第三方平台管理时OAuth2Service授权相关报错问题
This commit is contained in:
		| @ -14,11 +14,11 @@ public interface WxOAuth2Service { | |||||||
|   /** |   /** | ||||||
|    * <pre> |    * <pre> | ||||||
|    * 构造oauth2授权的url连接. |    * 构造oauth2授权的url连接. | ||||||
|    * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息 |    * 详情请见: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html | ||||||
|    * </pre> |    * </pre> | ||||||
|    * |    * | ||||||
|    * @param redirectUri 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode |    * @param redirectUri 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode | ||||||
|    * @param scope       scope |    * @param scope       scope,静默:snsapi_base, 带信息授权:snsapi_userinfo | ||||||
|    * @param state       state |    * @param state       state | ||||||
|    * @return url |    * @return url | ||||||
|    */ |    */ | ||||||
|  | |||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package me.chanjar.weixin.common.service; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.experimental.Delegate; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 微信 oauth2服务 装饰器 | ||||||
|  |  * | ||||||
|  |  * @author <a href="https://www.sacoc.cn">广州跨界</a> | ||||||
|  |  */ | ||||||
|  | @AllArgsConstructor | ||||||
|  | public class WxOAuth2ServiceDecorator implements WxOAuth2Service { | ||||||
|  |  | ||||||
|  |   @Delegate | ||||||
|  |   private final WxOAuth2Service wxOAuth2Service; | ||||||
|  | } | ||||||
| @ -7,6 +7,8 @@ import me.chanjar.weixin.mp.bean.guide.WxMpGuideTagInfo; | |||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  |  * 微信导购助手(现在叫对话能力)标签相关接口. | ||||||
|  |  * | ||||||
|  * @author <a href="https://www.sacoc.cn">广州跨界-宋心成</a> |  * @author <a href="https://www.sacoc.cn">广州跨界-宋心成</a> | ||||||
|  * @date 2021/5/13/013 |  * @date 2021/5/13/013 | ||||||
|  */ |  */ | ||||||
|  | |||||||
| @ -106,7 +106,7 @@ public class WxMpGuideTagServiceImpl implements WxMpGuideTagService { | |||||||
|     body.put(ACCOUNT, account); |     body.put(ACCOUNT, account); | ||||||
|     body.put(OPENID, openid); |     body.put(OPENID, openid); | ||||||
|     body.put("push_count", pushCount); |     body.put("push_count", pushCount); | ||||||
|     body.put("tag_value", value); |     body.put("tag_values", value); | ||||||
|     String returnString = this.mpService.post(WxMpApiUrl.Guide.QUERY_GUIDE_BUYER_BY_TAG, body); |     String returnString = this.mpService.post(WxMpApiUrl.Guide.QUERY_GUIDE_BUYER_BY_TAG, body); | ||||||
|     return WxGsonBuilder.create().fromJson(GsonParser.parse(returnString).getAsJsonArray("openid_list"), |     return WxGsonBuilder.create().fromJson(GsonParser.parse(returnString).getAsJsonArray("openid_list"), | ||||||
|       new TypeToken<List<String>>() { |       new TypeToken<List<String>>() { | ||||||
|  | |||||||
| @ -1,8 +1,9 @@ | |||||||
| package me.chanjar.weixin.open.api; | package me.chanjar.weixin.open.api; | ||||||
|  |  | ||||||
| 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.bean.oauth2.WxOAuth2AccessToken; | import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; | ||||||
|  | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.mp.api.WxMpService; | ||||||
| import me.chanjar.weixin.open.bean.WxOpenCreateResult; | import me.chanjar.weixin.open.bean.WxOpenCreateResult; | ||||||
| import me.chanjar.weixin.open.bean.WxOpenGetResult; | import me.chanjar.weixin.open.bean.WxOpenGetResult; | ||||||
| import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate; | import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate; | ||||||
| @ -330,7 +331,10 @@ public interface WxOpenComponentService { | |||||||
|    * @param code  the code |    * @param code  the code | ||||||
|    * @return the wx mp o auth 2 access token |    * @return the wx mp o auth 2 access token | ||||||
|    * @throws WxErrorException the wx error exception |    * @throws WxErrorException the wx error exception | ||||||
|  |    * @see WxMpService#getOAuth2Service() | ||||||
|  |    * @deprecated 2021-05-21: 已修正公众号相关接口,请使用:WxOpenCommpentService.getWxMpServiceByAppid(mpAppId).getOAuth2Service().getAccessToken(code) | ||||||
|    */ |    */ | ||||||
|  |   @Deprecated | ||||||
|   WxOAuth2AccessToken oauth2getAccessToken(String appid, String code) throws WxErrorException; |   WxOAuth2AccessToken oauth2getAccessToken(String appid, String code) throws WxErrorException; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @ -362,7 +366,10 @@ public interface WxOpenComponentService { | |||||||
|    * @param scope       the scope |    * @param scope       the scope | ||||||
|    * @param state       the state |    * @param state       the state | ||||||
|    * @return the string |    * @return the string | ||||||
|  |    * @see WxMpService#getOAuth2Service() | ||||||
|  |    * @deprecated 2021-05-21: 已修正公众号相关接口,请使用:WxOpenCommpentService.getWxMpServiceByAppid(mpAppId).getOAuth2Service().buildAuthorizationUrl(redirectUri, scope, state) | ||||||
|    */ |    */ | ||||||
|  |   @Deprecated | ||||||
|   String oauth2buildAuthorizationUrl(String appid, String redirectUri, String scope, String state); |   String oauth2buildAuthorizationUrl(String appid, String redirectUri, String scope, String state); | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|  | |||||||
| @ -0,0 +1,61 @@ | |||||||
|  | package me.chanjar.weixin.open.api.impl; | ||||||
|  |  | ||||||
|  | import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; | ||||||
|  | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.common.service.WxOAuth2Service; | ||||||
|  | import me.chanjar.weixin.common.service.WxOAuth2ServiceDecorator; | ||||||
|  | import me.chanjar.weixin.common.util.http.URIUtil; | ||||||
|  | import me.chanjar.weixin.mp.config.WxMpConfigStorage; | ||||||
|  | import me.chanjar.weixin.open.api.WxOpenComponentService; | ||||||
|  | import org.apache.commons.lang3.StringUtils; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 微信 第三方平台对于公众号 oauth2 的实现类 | ||||||
|  |  * | ||||||
|  |  * @author <a href="https://www.sacoc.cn">广州跨界</a> | ||||||
|  |  */ | ||||||
|  | public class WxOpenMpOAuth2ServiceImpl extends WxOAuth2ServiceDecorator { | ||||||
|  |  | ||||||
|  |   private final WxOpenComponentService wxOpenComponentService; | ||||||
|  |   private final WxMpConfigStorage wxMpConfigStorage; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   public WxOpenMpOAuth2ServiceImpl(WxOpenComponentService wxOpenComponentService, WxOAuth2Service wxOAuth2Service, WxMpConfigStorage wxMpConfigStorage) { | ||||||
|  |     super(wxOAuth2Service); | ||||||
|  |     this.wxOpenComponentService = wxOpenComponentService; | ||||||
|  |     this.wxMpConfigStorage = wxMpConfigStorage; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 第三方平台代公众号发起网页授权 | ||||||
|  |    * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/Official_Accounts/official_account_website_authorization.html | ||||||
|  |    * | ||||||
|  |    * @param code 微信授权code | ||||||
|  |    * @return 微信用户信息 | ||||||
|  |    * @throws WxErrorException 如果微信接口调用失败将抛出此异常 | ||||||
|  |    */ | ||||||
|  |   @Override | ||||||
|  |   public WxOAuth2AccessToken getAccessToken(String code) throws WxErrorException { | ||||||
|  |     String url = String.format( | ||||||
|  |       WxOpenComponentService.OAUTH2_ACCESS_TOKEN_URL, | ||||||
|  |       wxMpConfigStorage.getAppId(), | ||||||
|  |       code, | ||||||
|  |       wxOpenComponentService.getWxOpenConfigStorage().getComponentAppId() | ||||||
|  |     ); | ||||||
|  |     String responseContent = wxOpenComponentService.get(url); | ||||||
|  |     return WxOAuth2AccessToken.fromJson(responseContent); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public String buildAuthorizationUrl(String redirectUri, String scope, String state) { | ||||||
|  |     return String.format( | ||||||
|  |       WxOpenComponentService.CONNECT_OAUTH2_AUTHORIZE_URL, | ||||||
|  |       wxMpConfigStorage.getAppId(), | ||||||
|  |       URIUtil.encodeURIComponent(redirectUri), | ||||||
|  |       scope, | ||||||
|  |       StringUtils.trimToEmpty(state), | ||||||
|  |       wxOpenComponentService.getWxOpenConfigStorage().getComponentAppId() | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| @ -10,7 +10,6 @@ import me.chanjar.weixin.open.api.WxOpenMpService; | |||||||
| import me.chanjar.weixin.open.bean.mp.FastRegisterResult; | import me.chanjar.weixin.open.bean.mp.FastRegisterResult; | ||||||
|  |  | ||||||
| import java.net.URLEncoder; | import java.net.URLEncoder; | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -22,9 +21,11 @@ public class WxOpenMpServiceImpl extends WxMpServiceImpl implements WxOpenMpServ | |||||||
|   private String appId; |   private String appId; | ||||||
|  |  | ||||||
|   public WxOpenMpServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMpConfigStorage wxMpConfigStorage) { |   public WxOpenMpServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMpConfigStorage wxMpConfigStorage) { | ||||||
|  | //    wxOpenComponentService.oauth2getAccessToken(appId) | ||||||
|     this.wxOpenComponentService = wxOpenComponentService; |     this.wxOpenComponentService = wxOpenComponentService; | ||||||
|     this.appId = appId; |     this.appId = appId; | ||||||
|     this.wxMpConfigStorage = wxMpConfigStorage; |     this.wxMpConfigStorage = wxMpConfigStorage; | ||||||
|  |     setOAuth2Service(new WxOpenMpOAuth2ServiceImpl(wxOpenComponentService, getOAuth2Service(), wxMpConfigStorage)); | ||||||
|     initHttp(); |     initHttp(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -0,0 +1,29 @@ | |||||||
|  | package me.chanjar.weixin.open.api.impl; | ||||||
|  |  | ||||||
|  | import com.google.inject.Inject; | ||||||
|  | import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; | ||||||
|  | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.open.api.WxOpenMpService; | ||||||
|  | import me.chanjar.weixin.open.test.ApiTestModule; | ||||||
|  | import org.testng.annotations.Guice; | ||||||
|  | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
|  | @Guice(modules = ApiTestModule.class) | ||||||
|  | public class WxOpenMpOAuth2ServiceImplTest { | ||||||
|  |  | ||||||
|  |   @Inject | ||||||
|  |   protected WxOpenMpService wxOpenMpService; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void buildAuthorizationUrl() { | ||||||
|  |     String url = wxOpenMpService.getOAuth2Service().buildAuthorizationUrl("https://t.aaxp.cn/api/base/mp/showCode", "snsapi_userinfo", ""); | ||||||
|  |     System.out.println(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void getAccessToken() throws WxErrorException { | ||||||
|  |     WxOAuth2AccessToken result = wxOpenMpService.getOAuth2Service().getAccessToken("041crm0005iFJL1b2l400I0s0k4crm0z"); | ||||||
|  |     System.out.println(result); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,64 @@ | |||||||
|  | package me.chanjar.weixin.open.test; | ||||||
|  |  | ||||||
|  | import com.google.inject.Binder; | ||||||
|  | import com.google.inject.Module; | ||||||
|  | import com.thoughtworks.xstream.XStream; | ||||||
|  | import me.chanjar.weixin.common.error.WxRuntimeException; | ||||||
|  | import me.chanjar.weixin.common.util.xml.XStreamInitializer; | ||||||
|  | import me.chanjar.weixin.open.api.WxOpenMaService; | ||||||
|  | import me.chanjar.weixin.open.api.WxOpenMpService; | ||||||
|  | import me.chanjar.weixin.open.api.WxOpenService; | ||||||
|  | import me.chanjar.weixin.open.api.impl.WxOpenServiceImpl; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStream; | ||||||
|  |  | ||||||
|  | public class ApiTestModule implements Module { | ||||||
|  |   private final Logger log = LoggerFactory.getLogger(this.getClass()); | ||||||
|  |   private static final String TEST_CONFIG_XML = "test-config.xml"; | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void configure(Binder binder) { | ||||||
|  |     try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) { | ||||||
|  |       if (inputStream == null) { | ||||||
|  |         throw new WxRuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到,请参照test-config-sample.xml文件生成"); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream); | ||||||
|  |       WxOpenService service = new WxOpenServiceImpl(); | ||||||
|  |  | ||||||
|  |       service.setWxOpenConfigStorage(config); | ||||||
|  |  | ||||||
|  |       binder.bind(TestConfigStorage.class).toInstance(config); | ||||||
|  |       binder.bind(WxOpenService.class).toInstance(service); | ||||||
|  |  | ||||||
|  |       if (config.getTestMpAppId() != null && !config.getTestMpAppId().isEmpty()) { | ||||||
|  |         //如果配置了测试公众号,则构建公众号服务依赖 | ||||||
|  |         binder.bind(WxOpenMpService.class).toInstance(service.getWxOpenComponentService().getWxMpServiceByAppid(config.getTestMpAppId())); | ||||||
|  |       } else { | ||||||
|  |         log.warn("建议参照参照 test-config-sample.xml 配置测试公众号"); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (config.getTestMaAppId() != null && !config.getTestMaAppId().isEmpty()) { | ||||||
|  |         //如果配置了测试小程序,则构建小程序服务依赖 | ||||||
|  |         binder.bind(WxOpenMaService.class).toInstance(service.getWxOpenComponentService().getWxMaServiceByAppid(config.getTestMaAppId())); | ||||||
|  |       } else { | ||||||
|  |         log.warn("建议参照参照 test-config-sample.xml 配置测试小程序"); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     } catch (IOException e) { | ||||||
|  |       this.log.error(e.getMessage(), e); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @SuppressWarnings("unchecked") | ||||||
|  |   private <T> T fromXml(Class<T> clazz, InputStream is) { | ||||||
|  |     XStream xstream = XStreamInitializer.getInstance(); | ||||||
|  |     xstream.alias("xml", clazz); | ||||||
|  |     xstream.processAnnotations(clazz); | ||||||
|  |     return (T) xstream.fromXML(is); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package me.chanjar.weixin.open.test; | ||||||
|  |  | ||||||
|  | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||||
|  | import lombok.Getter; | ||||||
|  | import lombok.Setter; | ||||||
|  | import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage; | ||||||
|  |  | ||||||
|  | @Getter | ||||||
|  | @Setter | ||||||
|  | @XStreamAlias("xml") | ||||||
|  | public class TestConfigStorage extends WxOpenInMemoryConfigStorage { | ||||||
|  |  | ||||||
|  |   private String testMpAppId; | ||||||
|  |  | ||||||
|  |   private String testMaAppId; | ||||||
|  | } | ||||||
| @ -1,7 +1,10 @@ | |||||||
| <xml> | <xml> | ||||||
|   <componentAppId>第三方平台appID</componentAppId> |   <componentAppId>第三方平台appID</componentAppId> | ||||||
|   <componentSecret>第三方平台appsecret</componentSecret> |   <componentSecret>第三方平台appsecret</componentSecret> | ||||||
|  |   <componentAppSecret>第三方平台appsecret</componentAppSecret> | ||||||
|  |   <componentVerifyTicket>微信服务器推送过来的ticket</componentVerifyTicket> | ||||||
|   <componentToken>第三方平台Token</componentToken> |   <componentToken>第三方平台Token</componentToken> | ||||||
|   <componentAesKey>第三方平台EncodingAESKey</componentAesKey> |   <componentAesKey>第三方平台EncodingAESKey</componentAesKey> | ||||||
|   <appId>测试APPID</appId> |   <testMpAppId>测试公众号</testMpAppId> | ||||||
|  |   <testMaAppId>测试小程序</testMaAppId> | ||||||
| </xml> | </xml> | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 hywr
					hywr