最近开发公司的第三个app时,要获取Google支付订单的信息,至于如何在Google Developer开发后台创建项目,如何关联Google Cloud consle项目,如何启用Google Play Android Developer API。如何选择“ 创建OAuth 2.0客户端ID”。获取clientId,clientSecret,refreshTokenk可参考,https://blog.csdn.net/liaodehong/article/details/83274207?spm=1001.2014.3001.5506。
先通过Oauth客户端的方式拿到Access Token,
@Value("${google.pay.clientId: }")
private String clientId;
@Value("${google.pay.clientSecret: }")
private String clientSecret;
@Value("${google.pay.refreshToken: }")
private String refreshToken;
private String getAccessToken() {
String accessToken =
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("grant_type", "refresh_token");
paramMap.add("client_id", clientId);
paramMap.add("client_secret", clientSecret);
paramMap.add("refresh_token", refreshToken);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(paramMap, header);
ResponseEntity<JSONObject> response = restTemplate.postForEntity(UrlConstants.GOOGLE_PAY_ACCESS_TOKEN, httpEntity, JSONObject.class);
if (response.getStatusCode().value() != 200) {
throw new OwServiceException(97400,
"get google token server exception", false);
}
GooglePayAccessTokenModel model = response.getBody().toJavaObject(GooglePayAccessTokenModel.class);
if (StringUtils.isBlank(model.getAccess_token())) {
throw new OwServiceException(97400,
"google pay accessToken is empty", false);
}
accessToken = model.getAccess_token();
return accessToken;
}
拿到Access Token后,调获取订单详情的API
"https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{app包名}/purchases/products/{productId}/tokens/{purchaseToken}?access_token={access_token}" ;
结果报
401:permissionDenied。The current user has insufficient permissions to perform the requested operation.
之前开发的2个APP集成的查询Google支付订单都正常,之前的2个有一个也是自己完全配置的,第三个app完全是按照前2个搞的,然后检查各种配置,都是对的,没什么问题,按该错误百度和Google搜索,
根据搜索到的解决方案,试了以下方案,都没解决,还是报上述问题
1.添加服务账号,则授权服务账号,添加应用,勾选财务的模块,邀请账号进来,设置账号权限。(同时,原来的app项目虽然有服务账号,但代码中并没有用到,都是用的Oauth客户端Id来鉴权的,所以对这个方案我一开始都是犹豫的,试了好几个方案不行,才试了这个方案,同时当时并没有理解为什么要有服务账号,原来和Ouath客户端Id一样,都是调用Google api的一种鉴权方式,2个使用哪个都行,无论是客户端还是服务端,但是由于搜索到的资料几乎都是说的服务账号解决这个问题,也是有所动摇Oauth的方式能不能获取订单信息,)
2.重新保存商品和重新添加一件商品
3.重新创建OAuth 2.0客户端ID,获取新的clientId,clientSecret,refreshToken,
4.服务账号的配置和原来查询支付成功的服务账号配置一样
5.删除原来google play账号关联的api项目,重新关联,
6.以及其他网上搜到的方案
上述方案都没解决我的问题,搞了2天几乎都要放弃了,奇怪问你出在哪里了,看了众多资料后,最后突然意识到,
拿到clientId,clientSecret后,获取Code,最后生成的refreshToken是让老的同事在原来2个成功app所在的Google账号浏览器生成的,因为某些原因,第三个出问题的app和原来app的Google账号、开发者账号、电脑、网络、环境等都是隔离的,想着Oauth客户端ID获取的token没有服务账号,所谓Oauth客户端ID的服务账号其实就是Google开发者账号,用其他项目的谷歌账号也即开发者账号获取refreshToken,再去请求其他项目鉴权,肯定报401:permissionDenied,The current user has insufficient permissions to perform the requested operation.想通这一点,然后换到出问题app所在的电脑及所在的Google账号浏览器,重新获取code和生成refreshToken,再试,问题解决,获取到了订单信息,欣喜若狂。自己所猜想是对的,其实一开始就应该想到的,只是这个refreshToken一直都是他人帮忙生成的,就没考虑那么多,走了那么多弯路。想想解决方案也不难,竟然搞了2天,还尝试各种其他方案。
事后总结:
1.服务账号和OAuth 2.0客户端ID都可以获取AccessToken,都可以用来调用Google api,比如获取普通支付订单信息,订阅订单信息,退款订单信息等等。
2.用OAuth 2.0客户端ID就不用去创建服务账号,当然与服务账号有关的授权、配置等操作也不用做
3.google play账号关联的api项目要单独创建,不要关联app项目,OAuth 2.0客户端ID要创建在关联的api项目,不要关联在app所在的项目,
4.获取code和生成refreshToken,要用app所在的Google play开发中心的谷歌账号,我就是用其他项目所在的谷歌账号导致报上述问题。
5.生成refreshToken时,关联的api项目的Oauth 同意屏幕一定是发布版,不能是测试版,否则会生成refreshToken失败。