iOS第三方验证简单接入Game Center

本文详细介绍了iOS平台下GameCenter的集成步骤与注意事项,包括取消沙箱机制后的配置方法、登录逻辑实现及常见问题解决技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本文源链接:http://blog.csdn.net/qq393830887/article/details/54023218

关键

开启Game Center
1. 从2016年开始,Game Center已经取消了沙箱机制
2. 要开启Game Center,需要在iTunes Connect的Game Center处,新建一个排行榜或者成就。这个我觉得就是苹果的bug,虽然也能理解,否则的话当连入Game Center的时候,会收到error,权限没开?建完之后就可以删除的了
3. 要是取消Game Center登陆3次,虽然会收到回调,但是由于view为空,无法继续弹出登陆界面,得让玩家自己去Game Center手动登陆才行(坑爹的潜规则)

Game Center官网网址

代码

#import <GameKit/GameKit.h>

@implementation GameCenterSdkController
{
    // 记录上次的账号,用于确认是否有登出操作
    NSString* _lastPlayerId;
    // 保证只初始化一次
    BOOL _hasInit;
    // 判断是否登陆过一次了
    BOOL _hasLoginOnce;
}

//初始化
-(void)initsdk
{
    NSLog(@"初始化 init");
    //一般要在这里增加回调监听

    if (self->_hasInit)
    {
        [self sendMessageToUnity:"init" code:1 data:@"想要再次验证Game Center,请切到后台再切回来,或者重启游戏。"];

        return;
    }
    self->_hasInit = true;

    [self registerForAuthenticationNotification];
    [self setAuthenticateLocalPlayer];
}

//注销
- (void)logout
{
    NSLog(@"注销 logout");

    // 苹果没有主动登出一说
    [self sendMessageToUnity:"logout" code:0 data:@""];
}

//登陆
- (void)login
{
    NSLog(@"登陆 login");

    [self getSignature];

}

//帐号管理
- (void)userCenter
{
    NSLog(@"帐号管理 userCenter");
}

-(BOOL) isAuthenticated
{
    return [[GKLocalPlayer localPlayer] isAuthenticated];
}

-(NSString*) getLocalPlayerId
{
    if ([self isAuthenticated])
    {
        return [GKLocalPlayer localPlayer].playerID;
    }

    return nil;
}


// 这玩意只有第一次执行的时候会触发回调
-(void) setAuthenticateLocalPlayer
{
    NSLog(@"setAuthenticateLocalPlayer");

    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

    [localPlayer setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error)
    {
        [self authenticateCallback:viewcontroller Error:error];
    })];
}

// 这玩意每次切换到桌面再切回来还会被调用一次,有点像支付
-(void) authenticateCallback:(UIViewController*)viewcontroller Error:(NSError*)error
{
    NSLog(@"authenticateCallback");

    if (viewcontroller != nil)
    {
        NSLog(@"打开Game Center验证界面。");

        [self.rootViewController  presentViewController:viewcontroller animated:YES completion:nil];
    }
    else
    {
        // 登出再登陆的,说明已经初始化过了
        if (self->_hasLoginOnce)
        {
            return;
        }

        // 切到后台,登出,再切回来,依旧是空viewcontroller,空error,非常神奇
        if ([self isAuthenticated])
        {
            self->_hasLoginOnce = true;

            [self sendMessageToUnity:"init" code:0 data:@""];
        }
        else
        {
            if (error)
            {
                [self sendMessageToUnity:"init" code:1 data:[NSString stringWithFormat:@"code=%ld description=%@", (long)error.code, error.description]];
            }
            else
            {
                [self sendMessageToUnity:"init" code:1 data:@"Game Center登出了或者未知错误"];
            }
        }
    }
}


-(void) getSignature
{
    // 如果还没有登录,特殊处理
    if (![self isAuthenticated])
    {
        [self sendMessageToUnity:"login" code:2 data:@"玩家还没有登录GameCenter,切到后台再切回来登陆,或者去Game Center登陆。"];

        return;
    }

    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    [localPlayer generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error)
    {

        if(error != nil)
        {
            [self sendMessageToUnity:"login" code:2 data:[NSString stringWithFormat:@"code=%ld description=%@", (long)error.code, error.description]];

            return;
        }


        NSString* url = [publicKeyUrl absoluteString];
        NSString* sig = [NSString stringWithFormat:@"%@", [signature base64EncodedStringWithOptions: 0]];
        NSString* slt = [NSString stringWithFormat:@"%@", [salt base64EncodedStringWithOptions: 0]];
        NSString* stamp = [NSString stringWithFormat:@"%llu", timestamp];
        NSString* playerId = [GKLocalPlayer localPlayer].playerID;
        NSString* bundleId = [NSBundle mainBundle].bundleIdentifier;

        NSString* data = [NSString stringWithFormat:@"%@|%@|%@|%@|%@|%@", playerId, sig, slt, stamp, url, bundleId];
        NSLog(@"%@", data);

        [self sendMessageToUnity:"login" code:0 data:data];
    }];
}

-(void) registerForAuthenticationNotification
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver: self selector:@selector(authenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil];
}

// 这玩意会比authenticationHandler早回调
-(void) authenticationChanged
{
    NSLog(@"authenticationChanged");

    // 登出了或者切换了账号
    if (self->_lastPlayerId != nil)
    {
        [self logout];



    }
    self->_lastPlayerId = [self getLocalPlayerId];
}
@end
  • 其实关键在于generateIdentityVerificationSignatureWithCompletionHandler获取的数据如何验证,有空我在弄一下吧
  • setAuthenticateHandler有点像支付,第一次调用的时候会触发handler,然后每次后台切换回来也会触发
  • 退出账号这里有问题,authenticateCallback无法正确判断,只能通过GKPlayerAuthenticationDidChangeNotificationName

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值