前言:

  本文利用 python 作为后端服务器, 且接入的 Google Cloud Pub/Sub 服务作为实时开发者通知, 未记录具体支付流程的代码,只记录了再开发过程中较为耗时,个人认为比较麻烦的坑。

- Google 订阅问题总结:

  - Google 认证服务器;

  - Google 订阅信息验证;

  - Google 续订:

    - Google 接入实时开发者通知;

    - Google 续订测试;

    - Google 升级测试;

    - Google Play 账户与 APP账户唯一绑定;

简述订阅流程与续订流程:

订阅流程:

  用户从 Google Play 下载安装 APP,  通过APP的支付接口调用 Google Play 的支付界面, 成功后,App 获取到 Google 返回的携带 Token,  productId, 与本APP的用户信息, 发送到后端, 进行验证, 验证成功后 发放/开通 相应权限;

续订流程:

  Google 会自动续订, 不进过APP支付, 若续订成功, 会发送通知到安全服务器; 续订失败, 或者其他暂停, 取消, 等等操作, 也会发送通知到安全服务器; 在这里, 我只进行了续订以及恢复续订的监听, 我认为只需要知道他续订成功的状态即可; 其他操作一律视为续订失败, 不对该用户的过期时间进行顺延。 正常过期, 收回权限/商品;

Google 认证服务器:

测试时需要Google 验证服务器来作为安全服务器;

官方文档接入地址: https://developer.android.com/google/play/developer-api

选择 OAuth 2.0 https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Google 订阅信息验证:

官网数据验证地址: https://developers.google.com/android-publisher/api-ref/purchases/subscriptions

校验数据的请求地址:

POST https://www.googleapis.com/androidpublisher/v3/applications/packageName/purchases/subscriptions/subscriptionId/tokens/token:acknowledge

Path parameters:
packageName string 购买此订阅的应用程序的包名称(例如: 'com.some.thing'.) subscriptionId string 购买的订阅ID (例如,'monthly001') token string 购买订阅时提供给用户设备的令牌。

验证后的订单数据 demo:

{
"kind": "androidpublisher#subscriptionPurchase",
"startTimeMillis": long,
"expiryTimeMillis": long,
"autoResumeTimeMillis": long,
"autoRenewing": boolean,
"priceCurrencyCode": string,
"priceAmountMicros": long,
"introductoryPriceInfo": {
"introductoryPriceCurrencyCode": string,
"introductoryPriceAmountMicros": long,
"introductoryPricePeriod": string,
"introductoryPriceCycles": integer
},
"countryCode": string,
"developerPayload": string,
"paymentState": integer,
"cancelReason": integer,
"userCancellationTimeMillis": long,
"cancelSurveyResult": {
"cancelSurveyReason": integer,
"userInputCancelReason": string
},
"orderId": string,
"linkedPurchaseToken": string,
"purchaseType": integer,
"priceChange": {
"newPrice": {
"priceMicros": string,
"currency": string
},
"state": integer
},
"profileName": string,
"emailAddress": string,
"givenName": string,
"familyName": string,
"profileId": string,
"acknowledgementState": integer
}

Google 接入实时开发者通知:

参考文档: https://developer.android.com/google/play/billing/realtime_developer_notifications.html#scale_notification_processing

启用实时开发者通知后,只要现有订阅项目有更新,您就会直接从 Cloud Pub/Sub 收到购买令牌。

实时开发者通知并不提供与订阅项目状态有关的完整信息,例如用户目前是否有权访问订阅内容。收到令牌后,您应该始终使用购买令牌查询 Google Play Developer API,以获取完整信息,并根据用户当前的权限状态更新后端。

通知类型未来可能会发生变化。您应该能够处理无法识别的通知类型,并且您应该始终依赖 Google Play Developer API 来处理关键业务逻辑。

开启实时开发者通知后, 订阅所有类型的操作都会通知到你的服务器上, 很好用。

开启的步骤如下:

  - 1. 前往 Google Cloud Platform (GCP) 创建 Pub/Sub 项目:

    进入 GCP 的控制台如图点击 创建主题

      

  

  - 2.  在创建的主题中, 添加服务账号到发布商的权限中;

    

  - 3. 前往 Google Play 管理中心开启实时开发者通知:

    - 3.1 打开 Google Play 管理中心

    - 3.2 选择您的 Android 应用。

    - 3.3 依次转到开发工具 > 服务和 API 页面

    - 3.4 ... 看图

    

  - 4. 在主题中创建订阅, 选择 push 类型的订阅进行创建, 创建前需要验证网域所有权; 若果未验证成功, 则在创建订阅的时候 Google 会报 400 的错误;

    - 4.1 使用 Search Console 完成网站验证流程。请务必注册网址的 https:// 版本。 这里我选择的是 HTML 验证; 当这里验证成功后不要急于去创建订阅, 请先完成下面的步骤;

    - 4.2 授予网域对订阅所属的 GCP 项目的访问权限

      - 4.2.1 转到 API 和服务凭据 (APIs & Services Credentials) Console 页面。https://console.cloud.google.com/apis/credentials?_ga=2.15358897.-641556672.1562576238

      - 4.2.2 请选择您的项目

      - 4.2.3 选择网域验证标签页

      - 4.2.4 选择添加网域

      - 4.2.5 输入相应网域,然后选择添加网域

      - 4.2.6 创建订阅

    - 4.3 可以选择任意一个被验证过了的网域配置为 端点;

本文未选择 pull 类型的订阅;

通知消息的数据类型:

属性名称    值    说明
version string 此通知的版本。最初,此值将为“1.0”。此版本与其他版本字段不同。
notificationType int
通知的类型。它可以具有以下值: (1) SUBSCRIPTION_RECOVERED - 从帐号保留状态恢复了订阅。
(2) SUBSCRIPTION_RENEWED - 续订了处于活动状态的订阅。
(3) SUBSCRIPTION_CANCELED - 自愿或非自愿地取消了订阅。如果是自愿取消,在用户取消时发送。
(4) SUBSCRIPTION_PURCHASED - 购买了新的订阅。
(5) SUBSCRIPTION_ON_HOLD - 订阅已进入帐号保留状态(如已启用)。
(6) SUBSCRIPTION_IN_GRACE_PERIOD - 订阅已进入宽限期(如已启用)。
(7) SUBSCRIPTION_RESTARTED - 用户已通过“Play”>“帐号”>“订阅”重新激活其订阅(需要选择使用订阅恢复功能)。
(8) SUBSCRIPTION_PRICE_CHANGE_CONFIRMED - 用户已成功确认订阅价格变动。
(9) SUBSCRIPTION_DEFERRED - 订阅的续订时间点已延期。
(12) SUBSCRIPTION_REVOKED - 用户在有效时间结束前已撤消订阅。
(13) SUBSCRIPTION_EXPIRED - 订阅已过期。

purchaseToken string 购买订阅时向用户设备提供的令牌。
subscriptionId string 所购买订阅的 ID(例如“monthly001”)。

Google Play 账户与 APP账户唯一绑定:

pass

Google 续订暂停订阅等测试需要注意的点:

- 续订测试

  1. 订阅到期后, 自动成功续期;

- 暂停测试

1. 订阅暂停后, 当前续费结束后, 取消访问权限;
2. 暂停期结束后, 自动续费成功;
3. 暂停期间, 主动从Google Play恢复订阅成功;
4. 暂停期间, 主动从App订阅 恢复订阅成功;
5. 恢复订阅后, 自动续订成功;

- 升级测试

  1. 低级订阅升级高级订阅时, 低级订阅应该取消权限

IAP 订阅后端踩坑总结之 Google 篇的更多相关文章

  1. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  2. k8s踩坑记第1篇--rc无法创建

    六一快乐!!! 什么是k8s,我不想解释,百度资料有很多,本系列只踩坑,不科普. 问题描述: 做Hello World的例子,结果get pods一直显示没有资源? 应用配置代码: apiVersio ...

  3. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  4. Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...

  5. [代码修订版] Python 踩坑之旅进程篇其五打不开的文件

    目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...

  6. Python 踩坑之旅文件系统篇其一文件夹也是个文件

    目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...

  7. k8s踩坑记第2篇--3个IP折磨人的故事

    例子来源于<Kubernetes实践指南>一书.问题依然没有解决,求助大神. 测试环境 Centos 7.0 docker 1.13.1 kubectl v1.5.2 etcd 3.2.1 ...

  8. 美团热修复Robust的踩坑之旅-使用篇

    最近需要在项目中使用热修复框架,在这里以美团的Robust为主写一篇文章总结一下学习的过程. 一直认为要学习一个框架的原理,首先需要让他跑起来,从效果反推回去,这样更容易理解. 一.美团Robust的 ...

  9. ABP框架入门踩坑-配置数据库表前缀

    配置数据库表前缀 ABP踩坑记录-目录 本篇其实和ABP关系并不大,主要是EF Core的一些应用-.-. 起因 支持数据库表前缀应该是很多应用中比较常见的功能,而在ABP中并没直接提供这一功能,所以 ...

随机推荐

  1. 1038 Recover the Smallest Number

    Given a collection of number segments, you are supposed to recover the smallest number from them. Fo ...

  2. C/C++ 实现多线程与线程同步

    多线程中的线程同步可以使用,CreateThread,CreateMutex 互斥锁实现线程同步,通过临界区实现线程同步,Semaphore 基于信号实现线程同步,CreateEvent 事件对象的同 ...

  3. Windows PE第6章 栈与重定位表

    第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...

  4. Linux-鸟菜-5-目录配置-FHS

    Linux-鸟菜-5-目录配置-FHS 这节内容比较休闲,主要就是介绍Linux的目录配置,也就是那些目录通常是干啥的,这个比较重要,需要我们去了解.但是我觉得通常看一遍记不住啥,也就记个大概,主要还 ...

  5. Spring SPI 机制总结

    1.概念: SPI(Service Provider Interface)服务提供接口,简单来说就是用来解耦,实现插件的自由插拔,具体实现方案可参考JDK里的ServiceLoader(加载class ...

  6. selenium之利用cookie绕过验证登录

    方法一 第一步 2.第二步 方法二.重点:1.打开验证码页(登录页面):2.首次登录等待三十秒手工输入账密:3.保存cookie至excel后利用cookie脚本登录 1.导入第三方模块xlwt 2. ...

  7. 视频格式mkv、mp4、avi、flv、mov、wmv、webm特点和区别

    mkv是一种多媒体封装格式,这个封装格式可把多种不同编码的影像及 16 条或以上不同格式的音频和语言不同的字幕封装到一个 Matroska Media 档内. 它也是其中一种开放原始码的多媒体封装格式 ...

  8. [BUAA2021软工助教]结对项目-第二阶段小结

    一.作业链接 结对项目-第二阶段 二.优秀作业推荐 本次博客作业虽然是简单总结,但是以下作业中都不乏有思考.有亮点的精彩内容,推荐给同学们阅读学习. 磨练,结对编程!(中) zzx 和 zzy 同学实 ...

  9. 偷梁换柱:使用mock.patch辅助python单元测试

    最近在搞软工项目的后端测试,重新复习了一下python的mock.patch,并用它简化了对一些复杂逻辑的测试,在此记录 问题描述 本组的项目比较特殊,设计对教务网站的模拟登陆与信息爬取,同时不少接口 ...

  10. [JavaScript之BOM与DOM]

    [JavaScript之BOM与DOM] BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". DOM ( ...