如何通过 FacebookUtil link 解析现有用户

How to link existing Parse User via FacebookUtil

我已经尝试了很多来实现 link Facebook 的现有解析用户。

我正在使用 swift 3.

但我找不到解决方案

我的状态是

  1. 我已经没有 link Facebook 帐户。

  2. 我想通过 facebookUtilslink 我的帐户

  3. 我的应用有 "Sign In or SignUp Facebook" 按钮

  4. 它的工作原理如下

我的问题是

  1. 我点击 Facebook 登录按钮后没有登录。这意味着我没有 PFUser.current()

这是我正在尝试做的事情

  1. 通过 facebookGraph 获取电子邮件地址 API 并通过查询电子邮件来检查是否是用户

  2. 我试过这样登录

试试吧! PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)

但它不起作用,因为我无法获取密码。它总是返回 nil

  1. 我试过 link PFUser 对象,我通过 1 个查询结果

  2. 我也试过这样的云函数

Parse.Cloud.define("fblink", 函数(请求, 响应) {

var query = new Parse.Query(Parse.User);
query.equalTo("username", request.params.username);

query.first({
  success: function(object) {

       if (!Parse.FacebookUtils.isLinked(object)) {
              Parse.FacebookUtils.link(object, null, {
                success: function(user) {
                  alert("Woohoo, user logged in with Facebook!");
                    response.success(true);   
                },
                error: function(user, error) {
                  alert("User cancelled the Facebook login or did not fully authorize.");
                    response.success(false);   
                }
              });
            }
  },
  error: function(error) {
    console.log("Error: " + error.code + " " + error.message);
  }
});

});

但它不起作用...我认为云函数方法不是这种情况下的解决方案。

我发现了很多与将现有用户合并到 Facebook 授权数据相关的问题。但是我找不到任何解决方案。

希望大家一起找到好的方法。

func fbBtnTapped() {

        //Show Activity indicator
        let spiningActivity = MBProgressHUD.showAdded(to: self.view, animated: true)
        spiningActivity?.labelText = "Loading"
        spiningActivity?.detailsLabelText = "Please Wait"


        let permissions = ["public_profile", "email"]


        PFFacebookUtils.logInInBackground(withReadPermissions: permissions, block: {(user:PFUser?, error:Error?) -> Void in

            if let user = user {
                if user.isNew {
                    print("User signed up and logged in through Facebook!")

                } else {
                    print("User logged in through Facebook!")
                }
            } else {
                print("Uh oh. The user cancelled the Facebook login.")

            }


            if(error != nil)
            {
                spiningActivity?.hide(true)

                print("in FBBUTTONTapped Error")
                // display an error message
                let userMessage = error!.localizedDescription
                let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                myAlert.addAction(okAction)

                self.present(myAlert, animated: true, completion: nil)
                return
            }

            // Load facebook details like userName, email address, profile picture.
            self.loadFacebookUserDetails()


        })



    }

这是我在 loadFacebookUserDetails 中尝试过的。

func loadFacebookUserDetails()
    {
        MBProgressHUD.hideAllHUDs(for: self.view, animated: true)

        //Show Activity indicator
        let spiningActivity = MBProgressHUD.showAdded(to: self.view, animated: true)
        spiningActivity?.labelText = "Loading"
        spiningActivity?.detailsLabelText = "Wait"


        //Define fields we would like to read from Facebook User Object
        let requestParameters = ["fields": "id, email, first_name, last_name"]
        // me
        let userDetails : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: requestParameters)

        userDetails.start(completionHandler: { (connection, result, error) -> Void in

            if error != nil {


                print("in FBDetailed Error")
                //Display error message
                spiningActivity?.hide(true)

                let userMessage = error!.localizedDescription
                let myAlert = UIAlertController(title:"Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                myAlert.addAction(okAction)

                self.present(myAlert, animated: true, completion: nil)

                PFUser.logOut()

                return

            }

            var userId = String()
            var userName = String()
            var userEmail = String()
            var userFirstName = String()
            var userLastName = String()
            var displayName = String()

            var userObj = PFUser()

            //Extract user fields
            if let dict = result as? [String: AnyObject]
            {
                userId = dict["id"] as! String
                print("User id=\(userId)")
                userEmail = (dict["email"] as? String)!
                print("User email=\(userEmail)")

                userFirstName = dict["first_name"] as! String
                print("User FirstName=\(userFirstName)")
                userLastName = dict["last_name"] as! String
                print("User LastName=\(userLastName)")
            }

            //get Username
            if !userEmail.isEmpty
            {
                PFUser.current()?.email = userEmail
                if let range = userEmail.range(of: "@") {

                    let username = userEmail.substring(to: range.lowerBound)
                    userName = username

                    PFUser.current()?.username = username
                }
            }

            PFFacebookUtils.linkUser(inBackground: PFUser.current()!, with: FBSDKAccessToken.current())


            //Get Facebook profile picture
            let userProfile = "https://graph.facebook.com/" + userId + "/picture?type=large"

            let profilePictureUrl = URL(string:userProfile)
            let profilePictureData = try? Data(contentsOf: profilePictureUrl!)

            //Prepare PFUser object
            if(profilePictureData != nil)
            {
                let profileFileObject = PFFile(data:profilePictureData!)

                //                userObj.setObject(profileFileObject!, forKey: "profileImg")

                if (PFUser.current()?.object(forKey: "profileImg")) == nil{

                    PFUser.current()?.setObject(profileFileObject!, forKey: "profileImg")
                }
            }

            displayName=userFirstName+userLastName
            PFUser.current()?.setObject(displayName, forKey: "displayname")



            //Check If user has already signedup or not
            let query = PFQuery(className: "_User")
            query.whereKey("username", equalTo: userName)
            try! userObj = query.getFirstObject() as! PFUser

//            if userObj.username != nil {
//                
//                print("already signed up")
//                return
//            }
//            print(FBSDKAccessToken.current())



//            try! PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)

            PFFacebookUtils.linkUser(inBackground: PFUser.current()!, with: FBSDKAccessToken.current())


//            userObj.setObject(displayName, forKey: "displayname")

            PFUser.current()?.saveInBackground(block: { (success:Bool, error:Error?) in
                spiningActivity?.hide(true)

                if(error != nil)
                {
                    let userMessage = error!.localizedDescription
                    let myAlert = UIAlertController(title: "Alert2", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                    myAlert.addAction(okAction)

                    self.present(myAlert, animated: true, completion: nil)

                    PFUser.logOut()
                    return
                }

                if(success)
                {
                    if !userId.isEmpty
                    {
                        print(userId)
                        //userId->userName
                        UserDefaults.standard.set(userName, forKey: "username")
                        UserDefaults.standard.synchronize()

                        DispatchQueue.main.async{
                            let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate

                            appDelegate.buildUserInterface()
                        }

                    }

                }
            })
//



        })



    }

如果他不是 Facebook linked 帐户,您将需要 PFUser.current() 帐户才能 link。您的选择是:

1:) 使用您的逻辑通过登录页面登录 facebook。这意味着您在 Users 列中有一个新用户。因此,无论以后如何,基本上都可以用作 parse 登录。您可以只用电子邮件或 Facebook 名称更新用户名(因为默认情况下,Facebook 登录会用 ID 填充用户名)。一旦他进入成功页面,您可以让他填写一个密码,以备日后他选择不使用他的 facebook 帐户时使用。然后欢迎他使用取消link按钮取消link设置页面中的帐户。

@IBAction func unlinkFacebook(_ sender: AnyObject) {
    let user = PFUser.current()
    showHUD(message: "unlinking")
    PFFacebookUtils.unlinkUser(inBackground: user!, block:{
        (succeeded: Bool?, error) -> Void in
        if succeeded! {
            self.simpleAlert(mess: "Your account is no longer associated with your Facebook account.")
            self.hideHUD()

        }else{
            self.simpleAlert(mess: "\(error!.localizedDescription)")
            self.hideHUD()
        }
    })
}

所有未linking 将做的就是清除 authData 列。

2:) 以 parse 用户身份登录,成功登录后请他link 将他的帐户转到 facebook。 func 可能像:

func linkFacebook() {
   let user = PFUser.current()
    showHUD(message: "linking")
    if !PFFacebookUtils.isLinked(with: user!) {
        PFFacebookUtils.linkUser(inBackground:  user!, withReadPermissions: nil, block:{
            (succeeded: Bool?, error) -> Void in
            if succeeded! {
             self.simpleAlert(mess: "Success. You can now log in using your facebook account in future.")
             self.hideHUD()
            }else{
             self.simpleAlert(mess: "\(error!.localizedDescription)")
             self.hideHUD()
            }
        })
    }
}

可以将其放入您的 viewdidLoad 或一个漂亮的按钮中,让用户可以选择是否要 link 他的帐户。请记住,如果您想存储 Facebook 详细信息,您需要调用 Facebook sdk 来更新用户详细信息。

Users table 中唯一填充的列是 authData