接入google play有段时间了,今天抽空留个备份,回忆下心酸的历程

网上已经有很多资料,google爸爸也提供了很多文档。但是对于刚接触的我来说,信息量太大,有点杂乱的感觉。其实整理清楚,那么就非常简单了。这里细节也不详细写了,主要理清楚一些概念。

一、注册google账号,付钱成为开发者人员

二、进入Google Play Console创建你的应用,同时填写一些信息。(APP基本信息,隐私权政策网址等)

三、注意一条信息【让 Google 管理并保护您的应用签名密钥(推荐)!!】谨慎选择!如果同意的话,那么则无法取消了。

这个协议会造成Google针对你提交的签名文件A生成Google保管的另外一个签名文件B,并且B签名文件只会提供给你

MD5、SHA-1、SHA-256一些信息。而没有.jks这样的签名文件!

你的APP提交Google Play后,会剥离你的签名文件,用B签名再给APP打包一次。

这意味着你签名的APP跟从Google Play下载后的APP签名是不一致的!

这会造成一些困扰,比如APP内置版本更新功能、一些SDK无法使用。(如微信SDK是根据签名文件申请的)等等

同时提交还有个坑!安卓一般分发市场,会用到一些第三方加固软件。如果同意该协议,则提交Google Play的APK包不能加固,只能用原始的A签名打包,否则上架后下载安装是白屏的!!!

OK,上面都是一些坑,血泪史啊。悔不当初有没有!但是呢,后续我发现一些优点,也让我非常眼馋。毕竟从同意这个协议开始,就没办法回头了。

优点:

1、google play统计数据。如果是APP内置版本更新功能,是无法统计这个数据的

2、Android App Bundle。这个东西很流弊,很舒坦。google市场根据用户的手机信息,给用户生成合适的apk包。之前不论什么型号的手机,都是下载一个apk包。但是对大屏手机来说,我不需要小屏的资源,32位手机不需要64位资源,OK,删除不需要的。然后发现APK缩小了很多。

这里可能觉得差别不大,因为我打包的时候

安装包缩小了非常多。至于x86 mip是什么,这里暂时不讲解

四、App需要在首页显示隐私权政策网址,需要用户点击是否接受。没有此功能,提交审核会被拒绝

五、是否付费应用。也只有一次选择机会。此处的付费应用代表在gp市场是否免费还是付费下载。应用内付费不在此列

六、如果APP有内置付费内容,则需要先在控制台定义商品

商品ID非常重要。google pay是根据此id来付费结算购买的。ID可以用json存储到app项目中,自己判断,也可以后台给你。

七、google pay(支付)先理清楚概念,再上代码,代码注释非常清楚。谷歌支付跟ios支付流程非常相似

1、订阅 subs,详情百度

2、一次性购买 inapp。根据商品ID下单,如果此商品已被购买且未被消耗,则下单失败、付款成功回调、消耗

接入支付,可以参考以下链接

3、谷歌支付下单时候,额外参数最好是后台给予的订单ID

https://developer.android.com/google/play/billing/billing_integrate.html?hl=zh-cn

https://developer.android.com/google/play/billing/billing_reference.html?hl=zh-cn#getSkuDetails

代码

/*** 测试 google pay* https://developer.android.com/google/play/billing/billing_integrate.html?hl=zh-cn* https://developer.android.com/google/play/billing/billing_reference.html?hl=zh-cn#getSkuDetails* https://developer.android.com/google/play/billing/api#consume*/
class GooglePayActivity : BasicActivity3<ActivityGooglePayBinding>(), View.OnClickListener {var mService: IInAppBillingService? = nullvar mServiceConn: ServiceConnection? = nullvar sub_monthly_price: String? = nullvar querySkus: Bundle? = nullval TAG = "Google pay"companion object {fun startActivity(context: Context) {val intent = Intent(context, GooglePayActivity::class.java)context.startActivity(intent)}}override fun onCreate(savedInstanceState: Bundle?) {//与应用内购买结算服务建立连接mServiceConn = object : ServiceConnection {override fun onServiceDisconnected(name: ComponentName) {mService = nullToastUtils.showLongTip("未链接到google play service")}override fun onServiceConnected(name: ComponentName,service: IBinder) {mService = IInAppBillingService.Stub.asInterface(service)val code = mService!!.isBillingSupported(3, packageName, "inapp")LogUtils.e(TAG, "是否支持pay:$code")if (code != 0) {ToastUtils.showLongTip("暂不支持IBinder版本支付")return}if (mService != null) {initRn()getPurchases()} else {LogUtils.e(TAG, "没走initRn()方法")}}}//onCreate 方法中,通过调用 bindService 方法执行绑定。 向方法传递引用应用内购买结算服务的 Intent 和您创建的一个 ServiceConnection 实例,// 并明确地将 Intent 的目标软件包名称设置为 com.android.vending — Google Play 应用的软件包名称。val serviceIntent = Intent("com.android.vending.billing.InAppBillingService.BIND")serviceIntent.`package` = "com.android.vending"bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE)super.onCreate(savedInstanceState)}override fun getLayoutId(): Int {return R.layout.activity_google_pay}override fun initView() {binding.click = this}override fun setData() {}override fun onClick(v: View?) {when (v?.id) {R.id.titleBreak -> {finish()}R.id.tvPlay1 -> {if (mService != null) {getBuyIntent("10006")} else {ToastUtils.showLongTip("未链接到google play service")}}}}private fun initRn() {LogUtils.e(TAG, "initRn==initRn")// 警告:请不要在主线程上调用 getSkuDetails 方法。 调用此方法会触发网络请求,进而阻塞主线程。 请创建单独的线程并从该线程内部调用 getSkuDetails 方法。Thread(Runnable {//在您的应用中,可以使用 In-app Billing Version 3 API 从 Google Play 查询商品详情。 要将请求传递至应用内购买结算服务,// 首先需要创建一个包含商品 ID 字符串 ArrayList 的 Bundle,该字符串带有键“ITEM_ID_LIST”,每个字符串是可购买商品的商品 ID。var skuList = ArrayList<String>()skuList.add("10006")skuList.add("10128")querySkus = Bundle()querySkus!!.putStringArrayList("ITEM_ID_LIST", skuList)//查询可供购买的商品//要从 Google Play 检索此信息,请在 In-app Billing Version 3 API 上调用 getSkuDetails 方法,// 然后将 In-app Billing API 版本(“3”)、发起调用的应用的软件包名称、商品类型(“应用内”)以及您创建的 Bundle 传递给方法。//应用内商品的类型(“inapp”用于一次性购买,“subs”用于订阅)var skuDetails = mService!!.getSkuDetails(3, packageName, "inapp", querySkus)//查询结果将保存在带有键 DETAILS_LIST 的字符串 ArrayList 中。购买信息存储在 JSON 格式的字符串中//将从之前代码段返回的 skuDetails Bundle 中检索您的应用内商品的价格。val response = skuDetails.getInt("RESPONSE_CODE")LogUtils.e(TAG, "response==$response")if (response == 0) {val responseList = skuDetails.getStringArrayList("DETAILS_LIST")LogUtils.e(TAG, "responseList==" + responseList.toString())for (thisResponse in responseList) {/**  返回值  详情见 https://developer.android.com/google/play/billing/billing_reference.html?hl=zh-cn#getSkuDetails  getSkuDetails()方法*/val `object` = JSONObject(thisResponse)val sku = `object`.getString("productId")val price = `object`.getString("price")LogUtils.e(TAG, "price==" + price)if (sku == "sub_monthly")sub_monthly_price = price
//                    else if (sku == "gas") mGasPrice = price}} else {LogUtils.e(TAG, "response===========" + response)}}).start()}//购买//要从您的应用发起订阅请求,请在应用内购买结算服务上调用 getBuyIntent 方法。 将 In-app Billing API 版本(“3”)、发起调用的应用的软件包名称、要购买商品的商品 ID、// 商品类型(“应用内”或“订阅”)以及 developerPayload 字符串传递给方法。 developerPayload 字符串用于指定您想要 Google Play 随购买信息一同发送的任何其他参数。fun getBuyIntent(productId: String) {try {val buyIntentBundle = mService!!.getBuyIntent(3, packageName,productId, "inapp", "zhtttyyzc")//developerPayload 额外参数  可以设置任意  最好服务器设置 增加安全性  比如后台定义的订单idvar code = buyIntentBundle.getInt("RESPONSE_CODE")if (code == 0) {//如果请求成功,返回的 Bundle 将包含响应代码 BILLING_RESPONSE_RESULT_OK (0) 和您可以用于开始购买流程的 PendingIntent。 要从 Google Play 查看所// 有可能的响应代码,请参阅应用内购买结算参考。 接下来,请使用键 BUY_INTENT 从响应 Bundle 中提取 PendingIntent。val pendingIntent = (buyIntentBundle.getParcelable("BUY_INTENT")) as PendingIntent//要完成购买交易,请调用 startIntentSenderForResult 方法并使用您创建的 PendingIntent。 这里用任意值 1001 用于请求代码。startIntentSenderForResult(pendingIntent.intentSender,1001, Intent(), Integer.valueOf(0), Integer.valueOf(0),Integer.valueOf(0))} else {LogUtils.e(TAG, "发起购买失败code:$code")}} catch (e: Exception) {e.printStackTrace()}}//查询已购买商品(未被消耗)//此方法将返回当前归用户所有但未消费的商品,包括购买的商品和通过兑换促销代码获得的商品//未被消耗 无法再次购买fun getPurchases() {Thread(Runnable {val ownedItems = mService!!.getPurchases(3, packageName, "inapp", null)val response = ownedItems.getInt("RESPONSE_CODE")if (response == 0) {val ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST")val purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST")val signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST")for (dataItem in purchaseDataList) {try {val jo = JSONObject(dataItem)val purchaseToken = jo.getString("purchaseToken")//用于消耗val sku = jo.getString("productId")val developerPayload = jo.getString("developerPayload")consumePurchase(purchaseToken)//立即消耗} catch (e: Exception) {e.printStackTrace()}}}}).start()}//消耗fun consumePurchase(purchaseToken: String) {val response = mService!!.consumePurchase(3, packageName, purchaseToken)LogUtils.e(TAG, "消耗 response$response")if (response == 0) {LogUtils.e(TAG, "消耗 succeed")} else {LogUtils.e(TAG, "消耗 失败")}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (requestCode == 1001) {//订单的购买数据是 JSON 格式的字符串,将映射到响应 Intent 中的 INAPP_PURCHASE_DATA 键val responseCode = data?.getIntExtra("RESPONSE_CODE", -1)val purchaseData = data?.getStringExtra("INAPP_PURCHASE_DATA")val dataSignature = data?.getStringExtra("INAPP_DATA_SIGNATURE")if (resultCode == RESULT_OK) {if (responseCode == 0) {try {LogUtils.e(TAG, "支付成功回调结果purchaseData:$purchaseData")val jo = JSONObject(purchaseData)val sku = jo.getString("productId")val purchaseToken = jo.getString("purchaseToken")//用于消耗/*** 开发者指定的字符串,其中包含关于订单的补充信息。当您发出 getBuyIntent 请求时,您可以为此字段指定一个值* 最好是服务器给与的订单ID  进行比对* */val developerPayload = jo.getString("developerPayload")//consumePurchase(purchaseToken)//购买成功 立即消耗} catch (e: JSONException) {LogUtils.e(TAG, "Failed to parse purchase data")e.printStackTrace()}} else {ToastUtils.showLongTip("支付取消")}}}}//安全性建议:在您发送购买请求时,请创建一个可以对此购买请求进行唯一标识的字符串令牌并在 developerPayload 中包含此令牌。您可以将随机生成的字符串作为令牌。 从 Google Play 接收到购买响应时,请确保检查返回的数据签名、orderId 和 developerPayload 字符串。 为了增强安全性,您应在自己安全的服务器上执行检查。 请确保验证 orderId 为您之前未处理的唯一值,且 developerPayload 字符串与您之前通过购买请求发送的令牌相匹配。//重要说明:完成您的 Activity 后,请务必与应用内购买结算服务解除绑定。 如果不解除绑定,开启的服务连接会导致您的设备性能下降。// 此示例说明了如何通过重写 Activity 的 onDestroy 方法对到应用内购买结算的服务连接 mServiceConn 执行解除绑定操作。public override fun onDestroy() {super.onDestroy()if (mService != null) {unbindService(mServiceConn)}}
}
八、Google Play Console渠道

点击对应渠道的管理,如Alpha渠道

可以添加测试人员,输入测试人员的google账号。然后把加入测试的网址发给测试人员,测试人员用google浏览器打开,点击同意加入即可,记得需要先登陆google账号哦。测试人员测试支付,是不需要付费的。

如果测试发现手机调不起google pay?

1、检查手机是否支持谷歌服务

2、检查手机网络是否能科学上网

3、如果APP同意了谷歌签名服务,手机安装的APK包是否跟谷歌市场的签名一致?(这种情况,建议发布个谷歌市场内部测试渠道包,然后从市场下载安装测试)

4、如果排除了已知的可能,那么换个手机试试。手机厂商可能会修改点东西。亲测小米手机某型号怎么都调试不起来,后来换了华为和其他品牌手机,完美调起。

google play以及google pay相关推荐

  1. 【Google Play】Google Play 开放式测试 ( 简介 | 发布开放式测试版本 )

    Google Play 上架完整流程 系列文章目录 [Google Play]创建 Google 开发者账号 ( 注册邮箱账号 | 创建开发者账号 ) [Google Play]创建并设置应用 ( 访 ...

  2. (转载)Google Analytics(Google分析)使用技巧

    Google Analytics(Google分析)是Google的一款免费的网站分析服务,自从其诞生以来,即广受好评.Google Analytics功能非常强大,只要在网站的页面上加入一段代码,就 ...

  3. Google发布用于Google Cloud的.Net API

    Google近期宣布针对Google Cloud API的.Net支持.这包括C#绑定和PowerShell cmdlet.还有一个Visual Studio扩展,它允许在Google Compute ...

  4. 【转】在你的博客中添加Google地图(Use Google Map API On Your Bolg)

    在你的博客中添加Google地图(Use Google Map API On Your Bolg) *+申请一组 Google Maps API Key 在使用 Google Maps API 之前, ...

  5. Google play billing(Google play 内支付)

    http://www.bubuko.com/infodetail-930440.html [html] view plaincopy 如billing开发文档所说,要在你的应用中实现In-app Bi ...

  6. python google buffer_python调用Google Protocol Buffer

    写proto文件 package lm; message Person { required int32  id = 1; required string str = 2; optional int3 ...

  7. 怎么样用 Google Analytics 区分 Google Shopping 页的流量

    我们知道 Google Shopping 收费以来,Google Search 页的 PLA 广告和 Google Shopping 页的流量归在了付费搜索(Medium 是 CPC)流量里面了(收费 ...

  8. Geek必备神器 - Google眼镜(Google glass)的十大特色

    日期:2013-3-1  来源:GBin1.com 虽然目前Google眼镜还处于开发状态,但是相信各位Geek对于这个跨时代的产品肯定是十分有兴趣,小编这里手机了10个Google眼镜的特性,希望能 ...

  9. Google play billing(Google play 内支付) 上篇

    写在前面: 最近Google貌似又被全面封杀了,幸好在此之前,把Google play billing弄完了,现在写篇 博客来做下记录.这篇博客一是自己做个记录,二是帮助其他有需要的人.因为现在基本登 ...

  10. 怎么使用Google GSC(原google站长工具)?

    Google GSC即Google search console(原google站长工具)是谷歌的一种免费的网站管理平台,它的功能强大,使用简单,今天Hunk就来分享下怎么使用谷歌GSC. 温馨提示: ...

最新文章

  1. 定义一个员工类(JAVA)
  2. 图像识别工程师 VS The application has requested the Runtime to terminate it in an unusual way.
  3. 1.6 this关键字详解(3种用法)
  4. 折叠屏市场价值在哪里?
  5. 解析《中国互联网软件测试行业2018年度调研报告》
  6. 秋招注意事项和面试通关攻略
  7. Linux USB设备驱动程序设计 和 USB下载线驱动设计
  8. Java多线程学习三十一:ThreadLocal 是用来解决共享资源的多线程访问的问题吗?
  9. 编程吸金榜:你排第几?网友神回应了 !
  10. Trained Ternary Quantization
  11. python爬虫爬取微信_Python爬虫爬取微信小程序
  12. windows双屏显示如何设置
  13. postgresql encode函数
  14. Linux下USB HID device driver研究
  15. Macbook上Gitlab下载代码
  16. python写数字,Python3生成手写体数字方法
  17. ie下载java就花屏,“浏览器花屏的解决方案”的解决方案
  18. 科技观察:通用人工智能已被中央关注
  19. 微信小程序开发-页面跳转的几种方式
  20. node.js爬虫中关村在线电瓶车信息

热门文章

  1. 卷积神经网络与机器视觉,卷积神经网络图像分类
  2. 【C】狐狸找兔子问题
  3. SQL语句写起来太繁琐?你可以试试 MyBatis “动态” SQL
  4. 华为云域名注册_华为云申请个人域名步骤
  5. 13 Java反射机制
  6. JAVA+=运算程序诡异事件
  7. Linux7 下Hadoop集群用户管理方案之五 安装Hadoop集群遇到的坑
  8. Java模拟新浪微博登陆抓取数据
  9. 用户态创建socket来控制arp报文的收发,含编码
  10. ms sql 创建表_使用MS查询创建表组合