IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> cocos creator 原生平台接入google登录、支付 -> 正文阅读

[游戏开发]cocos creator 原生平台接入google登录、支付

一、google登录

google登录接入文档 https://developers.google.com/identity/sign-in/android/start-integrating

  • 准备工作
    1.首先准备一个google账号。
    2.测试机需要挂VPN,需要安装Google Play 服务、Google服务框架、Google Play 商店,
    很重要,很重要,很重要!!!直接影响我们后面调试是否成功。

    3.在Google Cloud Platform后台创建一个项目。

    • 导航菜单选择API和服务
      在这里插入图片描述
    • 左边API和服务菜单栏选择凭据,然后创建Oauth客户端ID
      在这里插入图片描述
      注意: SHA-1证书指纹可以通过cmd运行以下命令生成;keystone文件可以在Android Studio中生成,或者你已经有keystone文件了;keystone就是我们所说的证书,令牌这一类的文件;
      keytool -keystore [你的keystone文件路径] -list -v
      
    • 这时我们已经有OAuth 客户端ID
      在这里插入图片描述
      以上红色框内为自动创建的客户端ID,在集成登录功能时需要填入这个客户端ID。
  • 开始集成google登录
    此时我们应该已经通过cocos creator build成功了Android包了。(这里我使用的是cocos creator2.4.4)。

    • 在我们的应用级build.gradle文件中,将Google Play 服务声明为依赖项
      apply plugin: 'com.android.application'
      	...
      	dependencies {
      		...
      		implementation 'com.google.android.gms:play-services-auth:19.0.0'
      	}
      
    • 上代码
      GoogleSign.java如下
    package org.googleApi;
    import android.content.Intent;
    import android.net.Uri;
    import android.util.Log;
    
    import com.google.android.gms.auth.api.signin.GoogleSignIn;
    import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
    import com.google.android.gms.auth.api.signin.GoogleSignInClient;
    import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
    import com.google.android.gms.common.api.ApiException;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.Task;
    
    import org.cocos2dx.javascript.AppActivity;
    import org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge;
    
    public class GoogleSign {
    
        private static final String TAG = "GoogleSign";
        private static final int RC_SIGN_IN = 9001;
        // google后台自动创建的 Web client(Auto-created for Google Sign-in)
        private static final String server_client_id = "222518010353-gqvt7f9c94lsjr223b0b72kt7bg8skjr.apps.googleusercontent.com";
    
        // Client used to sign in with Google APIs
        public GoogleSignInClient mGoogleSignInClient;
    
        private static AppActivity this_tmp;
    
        public void init(AppActivity context) {
            Log.d(TAG, "init");
            this.this_tmp = context;
        }
    
        public void onCreate() {
            Log.d(TAG, "onCreate.");
            // Configure sign-in to request the user's ID, email address, and basic
            // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
            GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestIdToken(server_client_id)
                    .requestEmail()
                    .build();
            // Build a GoogleSignInClient with the options specified by gso.
            mGoogleSignInClient = GoogleSignIn.getClient(this_tmp, gso);
        }
    
        public void onStart() {
            Log.d(TAG, "onStart.");
            // Check for existing Google Sign In account, if the user is already signed in
            // the GoogleSignInAccount will be non-null.
            // GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this_tmp);
            // updateUI(account);
        }
    
        // 静默登录
        public void silentSignIn() {
            Log.d(TAG, "signInSilently()");
            mGoogleSignInClient.silentSignIn().addOnCompleteListener(this_tmp,
                    new OnCompleteListener<GoogleSignInAccount>() {
                        @Override
                        public void onComplete(Task<GoogleSignInAccount> task) {
                            if (task.isSuccessful()) {
                                Log.d(TAG, "signInSilently(): success");
    
                            } else {
                                Log.d(TAG, "signInSilently(): failure", task.getException());
    
                            }
                        }
                    });
        }
        // 意图登录
        public void logIn() {
            Log.d(TAG, "logIn.");
            Intent signInIntent = mGoogleSignInClient.getSignInIntent();
            this_tmp.startActivityForResult(signInIntent, RC_SIGN_IN);
        }
    
        public void logOut() {
            Log.d(TAG, "signOut()");
            mGoogleSignInClient.signOut().addOnCompleteListener(this_tmp,
                    new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(Task<Void> task) {
                            if (task.isSuccessful()) {
                                Log.d(TAG, "signOut(): success");
    
                            } else {
                                Log.d(TAG, "signOut(): failure");
    
                            }
                        }
                    });
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            Log.d(TAG, "onActivityResult: requestCode = " + requestCode);
            Log.d(TAG, "onActivityResult: resultCode = " + resultCode);
            Log.d(TAG, "onActivityResult: data = " + data);
    
            // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
            if (requestCode == RC_SIGN_IN) {
                // The Task returned from this call is always completed, no need to attach
                // a listener.
                Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
                try {
                    GoogleSignInAccount account = task.getResult(ApiException.class);
                    String idToken = account.getIdToken();
                    System.out.println("idToken = " + idToken);
                    // 返回js层 验证token
    
                    loginRes(account.getDisplayName(), account.getEmail(), idToken);
    
                    // Signed in successfully, show authenticated UI.
                    // updateUI(account);
                } catch (ApiException e) {
                    // The ApiException status code indicates the detailed failure reason.
                    // Please refer to the GoogleSignInStatusCodes class reference for more information.
                    Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
                    // updateUI(null);
    
                    loginRes(null, null, null);
                }
            }
        }
    
        private void loginRes(final String pName, final String pEmail, final String idToken) {
            this_tmp.runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    String value = "window.NativeJSBridgeIns.googleLoginRes(\"" + pName + "\",\"" + pEmail + "\",\"" + idToken + "\");";
                    System.out.println("evalstring: " + value);
                    Cocos2dxJavascriptJavaBridge.evalString(value);
                }
            });
        }
    
        private void updateUI(GoogleSignInAccount acct) {
            Log.d(TAG, "updateUI.");
            System.out.println(acct);
            if(acct != null) { // 登录成功
                String personName = acct.getDisplayName();
                String personGivenName = acct.getGivenName();
                String personFamilyName = acct.getFamilyName();
                String personEmail = acct.getEmail();
                String personId = acct.getId();
                Uri personPhoto = acct.getPhotoUrl();
                Log.d(TAG, "updateUI: personName = " + personName);
                Log.d(TAG, "updateUI: personGivenName = " + personGivenName);
                Log.d(TAG, "updateUI: personFamilyName = " + personFamilyName);
                Log.d(TAG, "updateUI: personEmail = " + personEmail);
                Log.d(TAG, "updateUI: personId = " + personId);
                Log.d(TAG, "updateUI: personPhoto = " + personPhoto);
    
                this_tmp.runOnGLThread(new Runnable() {
                    @Override
                    public void run() {
                        Cocos2dxJavascriptJavaBridge.evalString(String.format(
                                "window.SignIn();"
                        ));
                    }
                });
            }
            else {
                Log.d(TAG, "updateUI: err = " + "登录失败");
            }
        }
    
        public void onResume() {
            Log.d(TAG, "onResume()");
            // silentSignIn();
        }
    }
    

    在AppActivity.java的onCreate方法中进行new及init,在onActivityResult中调用GoogleSign.java的onActivityResult方法,在我们进行了登录操作后,这个方法可以监听到登录的信息。如需要验证idToken则在这里将idToken返回到JS层,JS层再将idToken发给游戏服务器进行校验。至此,登录集成完毕。

二、google支付

google支付接入文档https://developer.android.com/google/play/billing
具体步骤可参考这篇博文https://blog.csdn.net/sxk874890728/article/details/103764096,写的非常详细了。
我这里再强调几个需要注意的点,很重要!很重要!很重要!

  • 准备一个google开发者账号,注册的话需要25美刀;如果是公司项目,可以使用公司的账号将上面准备工作中的google账号邀请为开发者,然后你就不用再花25美刀了。
  • Google Play Console平台根据接入文档配置项目信息,在可以添加应用内商品前需要在内部测试菜单栏上传apk或其他,上传时若出现Google Play 提包错误:“您的APK或Android App Bundle会使用需提供隐私权政策的权限”。需要在应用内容菜单栏的隐私权政策中添加一个网址。
  • 在调试过程中连接谷歌服务器时出现code==3。
    billingResult.getResponseCode() = 3;
    billingResult.getResponseCode() = BillingClient.BillingResponseCode.BILLING_UNAVAILABLE;
    billingResult.getDebugMessage() = "billing service unavailable"
    
    可能原因:手机不支持google支付,可以打开Google Play 商店验证。一般不支持付费协议的话付费的应用列表为空,如果包含付费的应用且点击付费可以拉起付费弹窗,则支持。在验证之前必须完成准备工作中的第二点!
  • 查询商品列表时,返回空。
    List<String> skuList = new ArrayList<>();
    skuList.add("test_1");
    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
    billingClient.querySkuDetailsAsync(params.build(),
            new SkuDetailsResponseListener() {
                @Override
                public void onSkuDetailsResponse(BillingResult billingResult, @Nullable List<SkuDetails> skuDetailsList) {
                    Log.i(TAG, "getResponseCode=" + billingResult.getResponseCode() + ",skuDetailsList =" + skuDetailsList);
                }
         ....
    });
    
    即:Log.i中 getResponseCode=0,查询成功;skuDetailsList=[],列表为空。原因是应用虽然发布但是若还未审核成功。必须要在审核通过之后才能查询到商品信息。

到这里就大功告成了!若有什么疑问或不清楚的地方,欢迎加我QQ:1476212137一起探讨。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 20:04:20  更:2021-07-04 20:04:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 1:24:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码