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


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

关键

iOS第三方验证简单接入Game Center_第1张图片
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 

@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

你可能感兴趣的:(iOS,Unity3D开发iOS相关)