谷歌支付服务端校验

最近项目要接谷歌支付,如果之前结果国内的微信支付宝支付的话就对支付的流程非常熟悉了,我不必赘述。谷歌/苹果支付跟国内支付不一样的地方在于它不会主动回调业务的服务端,它是通过告诉客户端支付结果由客户端去调业务服务端进行发货之类的逻辑。为了安全性,业务服务端还是有必要去请求谷歌服务器获取订单接口去进一步校验订单状态。由于谷歌支付流程相对复杂,谷歌各种文档太多不好找,本文重点讲述服务端api校验订单的过程,下文所有操作都基于你已经创建好了谷歌应用账号。

谷歌订单校验的方法有两种,第一种是通过谷歌返回给客户端的支付详情,然后通过公钥pulbic key去进行校验;第二种是通过申请api权限获取access_token,通过access_token去请求谷歌的api。相对来说第二种方式显得更加安全一些。下面重点介绍这两种方式。

1.通过public key校验

怎么查看你的public key?

首先你需要移步到谷歌的应用控制台:https://play.google.com/apps/publish

在应用列表中选择你要设置的应用

你就可以在右侧的面板你看到你的public key了。

客户端支付成功之后,谷歌服务器会给他们返回一下几个参数

其中INAPP_PURCHASE_DATA是一个包含订单详情的json,详情如下:
说明:
developerPayload : 这个是客户端的透传参数,建议放置自身的交易流水号(自有服务器的订单号)
purchaseState :支付的结果, 0 (支付了), 1 (取消), 2 (退款)
productId :商品ID
orderId : 谷歌的订单ID (当处于沙箱环境的时候,没有这个字段)

INAPP_DATA_SIGNATURE是校验加密的字符串。INAPP_PURCHASE_DATA,INAPP_DATA_SIGNATURE这两个参数需要客户端透传给服务端。
php校验实例:

 

2.通过api校验

谷歌api接口采用auth2.0设计,在请求api的时候需要传access_token参数,为了获得access_token,您需要申请相关账号,获refreshToken,具体流程详见官方文档。具体步骤如下:

相关账号的创建及申请

官方文档:https://developers.google.com/android-publisher/authorization

2.1 创建一个项目

地址:https://console.developers.google.com/cloud-resource-manager

创建项目完成之后,你需要启用api服务。

搜索:Google Play Android Developer API ,然后点击“启用”

2.2 创建OAuth 客户端 ID

创建成功之后,你将获得clientId和clientSecret。

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
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}
这样就获取了refresh_token,下文中称refreshToken,这个token是一个长久有效的token,需要保存起来。
3. 项目关联
      在2中我们创建了一个API服务,名为: test-api,以及获取了这个api的一系列参数。我们可以创建很多个 api,给不同 api 启用不同的谷歌 api,这里我们要将我们的游戏应用与我们所需要的API服务关联起来。登录Google Play Console, 链接: https://play.google.com/apps/publish,登录之后点击设置按钮 :
点击API权限之后,能在右侧发现我们前面创建的test-api这个项目,点击关联,这样我们就可以用test-api中谷歌提供的接口Google Play Android Developer API来查询这个账号下所有应用的订单信息了 。
4. 参数保存
       要验证订单我们需要以下参数,这些参数可以保存在配置文件中
    • clientId: OAuth 客户端 ID
    • clientSecret: OAuth 客户端密钥
    • redirectURI: 自己填写的重定向地址
    • code
    • refreshToken
5.  验证
      订单来源分两种,一种是商品,一种是订阅,不同来源的订单调用的api是不同的
这里使用商品订单查询接口
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错误,报错如下

产生的原因 1:项目没有关联,或者关联到错误的API项目上了,请看3 项目关联

产生的原因 2:谷歌服务的 BUG,这时候只要在该应用的商店内,随意增加一个内购或者订阅,再看看是不是这个问题就消失了。新增的内购或者订阅可以删除的。

产生的原因3:当前开发客户端处于谷歌沙箱环境,服务端请求的是线上正式环境的接口。

  1. jz说道:

    clientSecret 在什么地方看的,你2-2最后一个图 我在系统里面没有看到

  2. ccyy说道:

    第一种验证方法的 public key是在哪里获取.
    google 开发后台没有找到“服务和API”这个入库

    1. vonn.wang说道:

      检查一下你登陆的账户权限

  3. Hey! I could have sworn I’ve been to this site before
    but after reading through some of the post I realized it’s new to me.
    Anyhow, I’m definitely happy I found it and I’ll be bookmarking and checking back frequently!

  4. mark说道:

    为什么我的redresh_token用了7天之后,就会提示过期?

发表评论

邮箱地址不会被公开。 必填项已用*标注