baxi 6 天之前
父節點
當前提交
b911faca45
共有 3 個文件被更改,包括 39 次插入 和 35 次删除
  1. 0 2
      native/engine/ios/CMakeLists.txt
  2. 6 4
      native/engine/ios/FACEBOOK.md
  3. 33 29
      native/engine/ios/service/FBWrapper.mm

+ 0 - 2
native/engine/ios/CMakeLists.txt

@@ -21,8 +21,6 @@ cc_ios_after_target(${EXECUTABLE_NAME})
 
 target_sources(${EXECUTABLE_NAME} PRIVATE ${CC_PROJECT_DIR}/service/FBWrapper.mm)
 set_source_files_properties(${CC_PROJECT_DIR}/service/FBWrapper.mm PROPERTIES COMPILE_FLAGS "-fobjc-arc")
-# Read existing ATT status on iOS 14+ without prompting; still support iOS 12.
-target_link_libraries(${EXECUTABLE_NAME} "-weak_framework AppTrackingTransparency")
 target_sources(${EXECUTABLE_NAME} PRIVATE ${CC_PROJECT_DIR}/service/CocosIOSPlatformBridge.mm)
 set_source_files_properties(${CC_PROJECT_DIR}/service/CocosIOSPlatformBridge.mm PROPERTIES COMPILE_FLAGS "-fobjc-arc")
 set_target_properties(${EXECUTABLE_NAME} PROPERTIES

+ 6 - 4
native/engine/ios/FACEBOOK.md

@@ -9,7 +9,7 @@ AppDelegate 直接持有 FBWrapper 单例,无需在 service.json 再次注册
 1. 直接维护本目录的 `Info.plist`,然后在 Creator 构建并生成 Xcode 工程。sdk-manager 已弃用,不依赖构建面板配置。
    `FacebookAppID`、`FacebookClientToken` 已沿用 Android 当前配置;`FacebookAutoLogAppEventsEnabled` 为 `false`,与 Android 一致。
    修改 App ID 时,必须同时更新 `CFBundleURLTypes` 中的 `fb<AppID>`。保留 `LSApplicationQueriesSchemes` 中的 `fbapi`、`fbauth2` 和 `fb-messenger-share-api`。
-   登录不请求 ATT 授权;只读取已有授权状态,拒绝或尚未授权不会阻断 Facebook 授权。
+   登录不请求 ATT 授权,也不由业务代码检查或修改 ATT 状态;交给 Facebook SDK 处理。
 2. 安装 CocoaPods 后,在本目录执行(替换为生成工程的实际绝对路径):
 
    ```sh
@@ -43,10 +43,12 @@ FBWrapper 的注册入口使用不捕获 self 或局部变量的全局 Block,
 
 ## 登录结果与后端
 
-安装了 Facebook App(fbapi 和 fbauth2 检测通过)时启用 `FBSDKAppSwitchEnabled`,由官方 SDK 优先尝试 App 登录。
+参考用户提供的 Unity 工程 `Libraries/FacebookSDK/SDK/Editor/iOS/FBUnityInterface.mm`:
+安装了 Facebook App(fbapi 和 fbauth2 检测通过)时,与 Unity `startLogin` 一致,创建 FBSDKLoginManager 并调用 `logInWithPermissions:fromViewController:nil handler:`。
 没有安装时使用 `FBSDKLoginTrackingLimited` + `FBSDKAppSwitchDisabled`,直接进入 Limited Login 网页。
-有 App 且系统已允许追踪时可以使用普通登录;拒绝、受限或尚未授权时使用 Limited Login,不弹 ATT,不拦截授权。
-iOS 14–16 只同步真实的已有 ATT 状态;iOS 17+ 由 SDK 自行读取。取消登录保持取消,不自动再次弹出另一个登录窗口。
+不再由 Cocos 依据 ATT 提前切换模式,也不读写追踪开关。普通入口的实际登录模式和跳转方式由 SDK 决定。
+两条分支共用成功、取消和失败回调,并读取本次结果的 Access Token 或 Authentication Token;JWT 的 nonce 从实际 Authentication Token 读取。
+取消登录保持取消,不自动再次弹出另一个登录窗口。
 
 安装 App 不等于一定能够跳 App:SDK 18.1.1 还检查 Meta 的普通/受限登录 Fast App Switch 功能开关。
 若功能未开放或跳转失败,SDK 会回退网页;Limited Login 会进入 limited.facebook.com。客户端不能保证或绕过这些条件。

+ 33 - 29
native/engine/ios/service/FBWrapper.mm

@@ -2,7 +2,6 @@
 // Swift-generated headers need these protocol definitions when compiled as Objective-C++.
 #import <SafariServices/SafariServices.h>
 #import <AuthenticationServices/AuthenticationServices.h>
-#import <AppTrackingTransparency/AppTrackingTransparency.h>
 #import <FBSDKCoreKit/FBSDKCoreKit.h>
 #import <FBSDKCoreKit/FBSDKCoreKit-Swift.h>
 #import <FBSDKLoginKit/FBSDKLoginKit.h>
@@ -130,33 +129,12 @@
 
     BOOL hasFacebookApp = [UIApplication.sharedApplication canOpenURL:[NSURL URLWithString:@"fbapi://"]] &&
         [UIApplication.sharedApplication canOpenURL:[NSURL URLWithString:@"fbauth2://"]];
-    BOOL trackingAllowed = [FBSDKSettings sharedSettings].isAdvertiserTrackingEnabled;
-    if (@available(iOS 14.0, *)) {
-        // Read only. Login must never prompt for ATT or be blocked by a denial.
-        trackingAllowed = ATTrackingManager.trackingAuthorizationStatus == ATTrackingManagerAuthorizationStatusAuthorized;
-        if (@available(iOS 17.0, *)) {
-            // SDK reads ATT itself.
-        } else {
-            [FBSDKSettings sharedSettings].isAdvertiserTrackingEnabled = trackingAllowed;
-        }
-    }
-
-    // Prefer the installed app. Without existing tracking consent, native login
-    // can still use Limited Login when Meta enables Limited Login App Switch.
-    // No installed app always uses Limited Login in the browser.
-    FBSDKLoginTracking tracking = hasFacebookApp && trackingAllowed
-        ? FBSDKLoginTrackingEnabled : FBSDKLoginTrackingLimited;
-    NSString *nonce = NSUUID.UUID.UUIDString;
-    FBSDKLoginConfiguration *config = [[FBSDKLoginConfiguration alloc]
-        initWithPermissions:@[@"public_profile", @"email"] tracking:tracking nonce:nonce
-        appSwitch:hasFacebookApp ? FBSDKAppSwitchEnabled : FBSDKAppSwitchDisabled];
-    if (!config) {
-        [self reply:request data:nil cancelled:NO error:@"Facebook 登录配置创建失败。"];
-        return;
-    }
+    NSArray<NSString *> *permissions = @[@"public_profile", @"email"];
+    // Match Unity FBUnityInterface: create a manager for this login and let the
+    // SDK handle the standard flow. Retain it through the asynchronous callback.
+    self.loginManager = [[FBSDKLoginManager alloc] init];
     self.loginPending = YES;
-    [self.loginManager logInFromViewController:self.presenter configuration:config
-        completion:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
+    void (^loginHandler)(FBSDKLoginManagerLoginResult *, NSError *) = ^(FBSDKLoginManagerLoginResult *result, NSError *error) {
         dispatch_async(dispatch_get_main_queue(), ^{
             self.loginPending = NO;
             if (error || result.isCancelled) {
@@ -165,16 +143,42 @@
             }
             NSString *accessToken = result.token.tokenString;
             NSString *authenticationToken = result.authenticationToken.tokenString;
-            if (tracking == FBSDKLoginTrackingEnabled && accessToken.length) {
+            if (accessToken.length) {
                 [self reply:request data:@{@"accessToken": accessToken, @"tokenType": @"access"} cancelled:NO error:nil];
             } else if (authenticationToken.length) {
+                // The standard entry point generates its own nonce. Return the
+                // SDK token's nonce, never an unrelated locally generated value.
+                NSString *nonce = result.authenticationToken.nonce;
+                if (!nonce.length) {
+                    [self reply:request data:nil cancelled:NO error:@"Facebook 身份令牌缺少 nonce。"];
+                    return;
+                }
                 [self reply:request data:@{@"authenticationToken": authenticationToken,
                     @"tokenType": @"authentication", @"nonce": nonce} cancelled:NO error:nil];
             } else {
                 [self reply:request data:nil cancelled:NO error:@"Facebook 登录未返回有效令牌。"];
             }
         });
-    }];
+    };
+
+    if (hasFacebookApp) {
+        // Same entry point as Unity startLogin:scope:isPublishPermLogin:.
+        // nil asks the SDK to find its presenting view controller automatically.
+        [self.loginManager logInWithPermissions:permissions
+                            fromViewController:nil
+                                       handler:loginHandler];
+    } else {
+        // Same configuration-based entry point as Unity loginWithTrackingPreference:.
+        FBSDKLoginConfiguration *config = [[FBSDKLoginConfiguration alloc]
+            initWithPermissions:permissions tracking:FBSDKLoginTrackingLimited
+            nonce:NSUUID.UUID.UUIDString appSwitch:FBSDKAppSwitchDisabled];
+        if (!config) {
+            self.loginPending = NO;
+            [self reply:request data:nil cancelled:NO error:@"Facebook 登录配置创建失败。"];
+            return;
+        }
+        [self.loginManager logInFromViewController:nil configuration:config completion:loginHandler];
+    }
 }
 
 - (void)share:(NSDictionary *)request params:(NSDictionary *)params {