美文网首页
海外sdk开发篇之谷歌

海外sdk开发篇之谷歌

作者: fridayy_CWeitao | 来源:发表于2024-07-11 12:45 被阅读0次

    本文介绍本人安卓接入谷歌授权登录、支付以及后台设置相关的流程步骤,可能有些不是必要的,或者流程不是最精简的。

    不过基于我的步骤我这边出包测试是ok的,所以记录一下,也给大伙做一个参考查漏补缺。

    ____________________________________________________________________________________________________________________

    文档链接

    登录:点击!!

    支付:点击!!

    ____________________________________________________________________________________________________________________

    后台创建步骤:

    简述:需要先创建google cloud项目,其中有个配置文件需要发给服务端来做登录支付校验。后创建firebase项目,它在创建的时候会提示关联google cloud项目,然后根据google cloud和firebase的设置生成google-service.json文件给客户端打包用。

    1.创建google cloud项目

    a.输入项目名称,最好带上地区项目等标识方便后期查阅

    b.进入api和服务功能,选择启动api和服务,搜索“Google Play Android Developer API”并启用

    c.进入IAM和管理,选择服务账号并创建,完成后点击生成的邮箱进入帐号详情,点击秘钥-添加秘钥-创建新秘钥-JSON,会生成一个JSON文件给服务端配置,用于登录支付时候的校验。

    d.api和服务中的OAuth权限请求页面暂时不确定是否必须,创建了之后会给出请求api的域名和测试用户,可以开了试试。

    2.创建firebase项目

    a.添加项目,并且选择关联1中创建的google cloud项目,如图会自己弹出已有的google cloud项目,并且选择它。

    会自己跳出google cloud项目

    b.一阵下一步之后创建完成,进入项目后添加安卓项目,需要输入包名,其他可以先忽略,填了也没事。这里需要注意的一点是包名和签名是全平台唯一的,也就是说在这个项目创建了包名1和签名1的项目后,再创建一个包名1和签名1的项目会提示签名1已经被使用了,后创建的会失效。我这边采坑的地方是游戏项目一开始找的代理,后面代理合同结束后迁移回来,但是代理方不给keystore签名,也不给迁移回来firebase、google cloud等项目,google后台的签名相当于是不能用了的状态。最终没解决,把谷歌登录给屏蔽了 =。=因此也不要随意废弃这些后台创建的项目,以及掌握好keystore等资源。

    c.安卓应用创建完成后进入设置,可以添加签名的SHA-1,SHA-256指纹,修改应用名称,以及生成goole-service.json。这里我们先进入构建-Authentication,选择开始,添加谷歌,选择启用并且保存。

    d.下载google-service.json

    3.回到google cloud

    会看到api和服务-凭据中显示了Oauth2.0 客户端id,我们需要复制的是Web client对应的客户端id用来进行客户端配置(这个会在后面代码中描述),如果ios的应用也需要支持谷歌登录的话,可以在这里添加:创建凭据-Oauth客户端ID-IOS-输入ios的bundle id,app store id等信息后创建。

    客户端的string.xml需要配置的是这个web client id

    4.前往google play console

    a.默认已经创建好了应用,进入主页的用户和权限,这里选择邀请新用户,电子邮件地址就是1中创建的IAM中的邮箱地址,也可以在上面截图中的服务账号中看到,邮箱的后缀有google cloud的项目名称.iam.gserviceaccount.com。把这个邮箱复制下来邀请,然后给与对应的应用的权限,权限内容是所有(特别注意是财务数据这个权限是必须的,否则支付会有问题)

    b.支付的白名单在设置-许可测试中添加,选择LICENSED。

    至此后台配置相关应该已经完成了,可以进入接入sdk并且出包测试环节。


    SDK接入步骤之登录

    1.

    res/values/string.xml中添加<string name="server_client_id">CP_SERVER_CLIENT_ID</string>,这个值就是3中截图描述的web client id。

    2.

    把firebase项目生成的google-service.json放到项目中

    3.

    拉起谷歌登录(不知道怎么插入代码块 就直接贴代码了):

    GoogleSignInOptions googleSignInOptions =new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)

    .requestIdToken(activity.getString(R.string.server_client_id))

    .build();

    GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(activity, googleSignInOptions);

    Intent signInIntent = googleSignInClient.getSignInIntent();

    activity.startActivityForResult(signInIntent, FlowConst.Googele.RC_GET_TOKEN);

    这里拉起的谷歌的授权登录,然后在activity的onActivityResult中会回调授权结果

    if (requestCode == FlowConst.Googele.RC_GET_TOKEN){

    Task task = GoogleSignIn.getSignedInAccountFromIntent(data);

        try{

    GoogleSignInAccount account = task.getResult(ApiException.class);

            String idToken = account.getIdToken();

            String uid = account.getId();

        }catch (ApiException e){

            e.printStackTrace();

        }

    }

    这里从授权结果中获取到了谷歌的id和token,把id和token发给服务端做校验,通过的话进行后续环节,然后这边也有一些错误码,可以点击这里来查看对应的问题是什么。常见的问题就是签名不对,因为谷歌的后台,没设置过的话会有2个签名,1个是上传校验用的,通常是自己的keystore,1个是给用户下载的时候签名的,这个是商店下载最终的keystore签名,可以把2个都添加在firebase上重新生成google-service.json。或者在谷歌后台传过包之后把签名都设置成自己的。


    sdk接入步骤之支付

    按照官方文档接入的话大致也没啥问题,这里简单描述一下步骤

    建议:

    一些需要实现的listener直接由class来implements,然后按照逻辑顺序写在class中

    需要实现的有这几个:

    BillingClientStateListener, PurchasesUpdatedListener, ProductDetailsResponseListener, ConsumeResponseListener, AcknowledgePurchaseResponseListener

    那我们开始:

    1.需要一个billingClient:

    BillingClient.newBuilder(mActivity).setListener(this).enablePendingPurchases().build();

    2.连接google服务

    billingClient.startConnection(this);  //this->BillingClientStateListener

    3.连接上google服务的情况下查询商品,这里需要区分是普通的商品还是订阅商品

    List productList =new ArrayList();

    productList.add(

    QueryProductDetailsParams.Product.newBuilder().

    setProductId(sdkProductId).

    setProductType(isProductSubs? BillingClient.ProductType.SUBS: BillingClient.ProductType.INAPP).

    build());

    QueryProductDetailsParams queryProductDetailsParams =

    QueryProductDetailsParams.newBuilder().

    setProductList(productList).

    build();

    billingClient.queryProductDetailsAsync(queryProductDetailsParams, this);  //this->ProductDetailsResponseListener

    4.查询到订单了之后拉起支付

    需要productId对应的商品对象,可以在ProductDetailsResponseListener的回调onProductDetailsResponse中根据productId来匹配,它的参数中会返回一个商品对象的list。

    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){

    for (ProductDetails details : list){

    if (details.getProductId().equals(sdkProductId)){

    //这里从ProductDetail的list中匹配到了商品的对象(下述代码中的details),然后拉起支付,接口也需要区分是不是订阅商品

    List productDetailsParamsList =new ArrayList();

    if (isProductSubs) {

    productDetailsParamsList.add(

    BillingFlowParams.ProductDetailsParams.newBuilder().

    setProductDetails(details).

    setOfferToken(details.getSubscriptionOfferDetails().toString()).

    build()

    );

    }else{

    productDetailsParamsList.add(

    BillingFlowParams.ProductDetailsParams.newBuilder().

    setProductDetails(details).

    build()

    );

    }

    BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder().

    setProductDetailsParamsList(productDetailsParamsList).

    setObfuscatedAccountId(String.format("%s|%s", FlowLogin.getInstance().getUserId(), sdkOrderId)).    

    //上面这里的accountid我设置了用户的uid和订单id,用户补单的时候校验用户

    build();

    BillingResult billingResult = billingClient.launchBillingFlow(mActivity, billingFlowParams);

    //这里的billingResult 可以获取它的支付结果来判断是否支付成功:billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK

    5.支付回调在onPurchasesUpdated中

    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list !=null){

    for (Purchase purchase : list){

    //这里处理purchase的订单

    //由于上面步骤设置了setObfuscatedAccountId

    //所以这里可以取出来判断当前用户是否是订单支付的用户:purchase.getAccountIdentifiers().getObfuscatedAccountId()

    //支付token:purchase.getPurchaseToken()

    //发给服务端来获取校验结果

        }

    }else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {

    //这里是用户取消了

    }else{

    //这里可以获取到错误信息(billingResult.getResponseCode(), billingResult.getDebugMessage())

    }

    6.根据服务端校验的结果来结束订单

    //token为上一步中获取到的支付token,这个非订阅商品

    ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(token).build();

    billingClient.consumeAsync(consumeParams, this); //this->ConsumeResponseListener

    //订阅商品

    AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()

    .setPurchaseToken(token)

    .build();

    billingClient.acknowledgePurchase(acknowledgePurchaseParams, this);    //this->AcknowledgePurchaseResponseListener

    7.消耗订单回调

    非订阅:onConsumeResponse

    订阅:onAcknowledgePurchaseResponse

    8.补单查询

    QueryPurchasesParams params = QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build();

    billingClient.queryPurchasesAsync(params, PurchasesResponseListener)

    这里是查询了非订阅的商品补单

    在PurchasesResponseListener的回调onQueryPurchasesResponse中

    需要遍历Purchase的list来对未消耗的订单进行查询,如果服务端确认已经发货的话可以按照支付步骤中的流程来结束订单

    这里也可以在Purchase的list中的对象中取得拉起支付的时候传的purchase.getAccountIdentifiers().getObfuscatedAccountId()

    根据玩家的uid是否匹配存的值来进行补单,因为接口会返回谷歌帐号对应的账单,所以需要做好区分别发货发错地方了

    坑点:

    非订阅商品也有2个类型,区别是一个可以重复购买,一个是终生只能购买一次,这个需要做好区分。

    然后也要做好一些容错处理


    ok,到这里就over了 祝大家接入顺利。

    相关文章

      网友评论

          本文标题:海外sdk开发篇之谷歌

          本文链接:https://www.haomeiwen.com/subject/zdrzcjtx.html