后端对谷歌支付进行验证的时候遇到些问题,为了方便以后查阅,记录整个过程
很多图都挂了,现在也不太喜欢 CSDN,有需要的直接到 github 上看吧
1 前述
-
本文讲述后端使用谷歌
api
验证支付的过程 -
流程: 前端支付完毕之后会获取
token
,将token
发送至后端,后端将此token
发向google
进行查询,如果是正常有效的token
,谷歌会返回对应订单的详细信息,验证通过后再通知前端进行消费(也可以前端先消费再通知后端验证发货) -
个人博客来源: 谷歌支付验证
2 前期准备
2-1 创建api项目
- 进入https://console.developers.google.com/cloud-resource-manager, 点击
创建项目
- 填写项目名称后,项目就创建完成了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3az5xEJ-1653925412950)(leanote://file/getImage?fileId=5bbc4aefef2b2c3be5000000)] - 创建完成之后,需要启用所需要的
api服务
,点击启用API和服务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8MrW2Un-1653925412951)(leanote://file/getImage?fileId=5bbc4ba8ef2b2c3be5000001)] - 搜索
Google Play Android Developer API
,我们将使用这个API服务来查询订单,点击启用它
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZG7URQGL-1653925412952)(leanote://file/getImage?fileId=5bbc4bdaef2b2c3be5000002)] - 点击创建凭据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e0MfYNzD-1653925412952)(leanote://file/getImage?fileId=5bbc4c20ef2b2c3be5000003)] - 实际上是跳转到
test-api
这个项目的凭据创建了,点击信息中心
,可以看到API
列表中出现了Google Play Android Developer API
,还有请求次数,错误,错误率等信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tR4NpIKo-1653925412953)(leanote://file/getImage?fileId=5bbc4c7eef2b2c3be5000004)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2vN6xO6G-1653925412953)(leanote://file/getImage?fileId=5bbc4cefef2b2c3be5000005)]
2-2 创建OAuth客户端ID
- 接下来准备创建
OAuth客户端ID
,点击凭据
- 先填写
OAuth同意屏幕
,应用名称那一行可以随便填写,反正是给自己看的,填完应用名称
之后,还需要填已授权的网域
,然后点击最下方的保存
按钮 已授权的网域
最好填写要发起请求的后台所用的域名,假设我的后台为sdk.keylala.cn
,则此处填写keylala.cn
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSQL4YJt-1653925412954)(leanote://file/getImage?fileId=5bbc4eedef2b2c3be5000008)]- 准备创建
OAuth客户端ID
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvyWgrxh-1653925412955)(leanote://file/getImage?fileId=5bbc4de8ef2b2c3be5000007)] - 填写的内容
- 应用类型选择: 网页应用
- 名称:随意填写了
- 已获授权的 JavaScript 来源:
https://keylala.cn
- 已获授权的重定向 URI:
https://keylala.cn
,这个随便,比如写成https://keylala.cn/callback
,不一定需要这个接口真实存在的,但一定要记着这个URI
,后文中我们称之为redirectURI
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxleHSow-1653925412955)(leanote://file/getImage?fileId=5bbc53feef2b2c3be5000009)]
- 点击
创建
按钮,获得客户端ID和客户端密钥,下文中分别称为clientId
和clientSecret
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7gyUSUf-1653925412956)(leanote://file/getImage?fileId=5bbc5485ef2b2c3be500000a)]
2-3 获取 code
- 请将下方
url
中的redirect_uri
和client_id
填写上2-2
中获取的参数
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=...
&client_id=...
- 放到浏览器上(此时不要关闭之前的页面, 此浏览器需要登录谷歌开发者账号,且不能点退出),另起一个页面标签,复制上去,点击允许
- 这时候会跳转到
redirect_uri
开头的地址,如果redirect_uri
是胡乱填的,这里会出现一个404
页面或者无法访问的提示,不过没关系,请将地址栏中的地址复制下来,把code=4/xxxxx
的值取出来,这里就获得了code
的值。 code
的值类似这样的一长串:4/eWdxD7b-YSQ5CNNb-c2iI83KQx19.wp6198ti5Zc7dJ3UXOl0T3aRLxQmbwI
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UPtFIknd-1653925412957)(leanote://file/getImage?fileId=5bbc56d8ef2b2c3be500000b)]
2-4 获取 refresh_token
- 发送**
POST
**请求到https://accounts.google.com/o/oauth2/token
- 参数:
- grant_type=authorization_code
- code={2-3获得的code值}
- client_id={2-2获得的clientId}
- client_secret={2-2获得的clientSecret}
- redirect_uri={2-2填写的redirectURI}
- 这里使用
Postman
工具发送请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ehmx0PgV-1653925412957)(leanote://file/getImage?fileId=5bbc5904ef2b2c3be500000c)] - 这样就获取了
refresh_token
,下文中称refreshToken
,这个token
是一个长久有效的token
,可以保存起来
3 项目关联
- 在
2
中我们创建了一个API
服务,名为:test-api
,以及获取了这个api
的一系列参数 - 我们可以创建很多个api,给不同api启用不同的谷歌api
- 这里我们要将我们的游戏应用与我们所需要的
API
服务关联起来 - 登录
Google Play Console
, 链接: https://play.google.com/apps/publish,登录之后点击设置
按钮
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m3exUcS7-1653925412957)(leanote://file/getImage?fileId=5bbc5bafef2b2c3be500000d)] - 点击
API权限
之后,能在右侧发现我们前面创建的test-api
这个项目,点击关联
,这样我们就可以用test-api
中谷歌提供的接口Google Play Android Developer API
来查询这个账号下所有应用的订单信息了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dr3wWCgq-1653925412958)(leanote://file/getImage?fileId=5bbc5c72ef2b2c3be500000e)]
4 参数保存
- 要验证订单我们需要以下参数,这些参数可以保存在后台中
- clientId: OAuth 客户端ID
- clientSecret: OAuth 客户端密钥
- redirectURI: 自己填写的重定向地址
- code
- refreshToken
5 验证
- 订单来源分两种,一种是商品,一种是订阅,不同来源的订单调用的
api
是不同的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOHc0ZhM-1653925412959)(leanote://file/getImage?fileId=5bbc6061ef2b2c3be500000f)] - 商品订单查询接口: https://developers.google.com/android-publisher/api-ref/purchases/products/get
- 订阅订单查询接口: https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get
- 这里使用
商品订单查询接口
5-1 获取 access_token
-
通过前面获取的
refreshToken
来获得access_token
-
代码中使用**
POST
**方式调用https://accounts.google.com/o/oauth2/token
-
参数:
- grant_type : refresh_token
- client_id
- client_secret
- refresh_token
-
返回值:
{ "access_token" : "ya29.AHES3ZQ_MbZCwac9TBWIbjW5ixxxxxxxxx2", "token_type" : "Bearer", "expires_in" : 3600, }
5-2 查询订单信息
-
使用**
GET
**方法调用以下接口:
https://www.googleapis.com/androidpublisher/v3/applications/packageName
/purchases/products/productId
/tokens/token
?access_token=access_token
-
packageName: 该应用的包名, 比如
com.test.xxx
-
productId: 商品ID,即内购ID
-
token: 充值的时候,前端获取的
token
值 -
access_token: 在
5-1
中获取的 -
如果订单是有效的,会返回如下内容:
{ "kind": "androidpublisher#productPurchase", "purchaseTimeMillis": "1539054135375", // 支付时间, 毫秒 "purchaseState": 0, // 是否付费: 0 已支付, 1 取消 "consumptionState": 0, // 是否被消费: 0 未消费, 1 已消费 "developerPayload": "xxxxx", // 开发者透传参数 "orderId": "GPA.3337-xxxx-xxxx-xxxx", // 谷歌订单号 "purchaseType": 0 // 支付类型: 0 测试, 1 真实 }
-
如果订单是无效的,会返回以下内容:
{ "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "Invalid Value" } ], "code": 400, "message": "Invalid Value" } }
5-3 403错误
-
在测试过程中,遇到了
403
错误,报错如下{ "error": { "errors": [{ "domain": "androidpublisher", "reason": "projectNotLinked", "message": "The project id used to call the Google Play Developer API has not been linked in the Google Play Developer Console." }], "code": 403, "message": "The project id used to call the Google Play Developer API has not been linked in the Google Play Developer Console." } }
-
产生的原因1:项目没有关联,或者关联到错误的
API
项目上了,请看3 项目关联
-
产生的原因2:谷歌服务的BUG,这时候只要在该应用的商店内,随意增加一个内购或者订阅,再看看是不是这个问题就消失了。新增的内购或者订阅可以删除的。