首页 > 解决方案 > Unity 中的自定义 OAuth 链接到 Parse Server

问题描述

我正在使用 Unity 和 Parse Server,现在希望能够将用户与 OAuth 链接。

到目前为止,这是我正在尝试的,但没有运气。

[System.Serializable]
public class DGUOAuth
{
    public string dguId = "";
    public string access_token = "";
}

DGUOAuth auth = new DGUOAuth()
{
   access_token = "F12w06Ddqx1k5qj75JQWRZmzh16Zgf05wHExNnHAnh8",
   dguId = "25-1999"
};

System.Threading.CancellationToken canceltoken;

Dictionary<string, object> data = new Dictionary<string, object>();
data.Add("authData", auth);

Debug.Log("Ready for linking the user!");

DataManager.user.LinkWithAsync("DGU", data, canceltoken).ContinueWith(t =>
{
   if (t.IsFaulted)
   {
       Debug.Log("Faulted: " + t.Exception);
       // Errors from Parse Cloud and network interactions
       using (IEnumerator<Exception> enumerator = t.Exception.InnerExceptions.GetEnumerator())
       {
           if (enumerator.MoveNext())
           {
               ParseException error = (ParseException)enumerator.Current;
               Debug.Log(error.Message);
               // error.Message will contain an error message
               // error.Code will return "OtherCause"
           }
       }
   }
   else
   {
       Debug.Log("User is linked");
   }
});

什么都没有发生,我只得到“准备链接用户!” 但在那之后没有日志?!和 Unity的文档LinkWithAsync几乎不存在......

真的希望有人可以帮助我。任何帮助表示赞赏并提前感谢:-)

- - - 编辑 - - -

现在,Debug.Log在之后添加一个t.isFaulted并获取此日志:

System.AggregateException:发生一个或多个错误。---> System.ArgumentException:无法编码 DGUOAuth 类型的对象

不知道如何解决这个问题。我在 Parse 服务器日志中没有收到任何错误日志。

标签: c#unity3doauth-2.0parse-platform

解决方案


问题

错误基本上来自JsonUtility.Encode

public static string Encode(IDictionary<string, object> dict)
{
    if (dict == null)
        throw new ArgumentNullException();
    if (dict.Count == 0)
        return "{}";
    StringBuilder builder = new StringBuilder("{");
    foreach (KeyValuePair<string, object> pair in dict)
    {
        builder.Append(Encode(pair.Key));
        builder.Append(":");
        builder.Append(Encode(pair.Value));
        builder.Append(",");
    }
    builder[builder.Length - 1] = '}';
    return builder.ToString();
}

然后在哪里builder.Append(Encode(pair.Value));尝试调用Encode(object)

    public static string Encode(object obj)
    {
        if (obj is IDictionary<string, object> dict)
            return Encode(dict);
        if (obj is IList<object> list)
            return Encode(list);
        if (obj is string str)
        {
            str = escapePattern.Replace(str, m =>
            {
                switch (m.Value[0])
                {
                    case '\\':
                        return "\\\\";
                    case '\"':
                        return "\\\"";
                    case '\b':
                        return "\\b";
                    case '\f':
                        return "\\f";
                    case '\n':
                        return "\\n";
                    case '\r':
                        return "\\r";
                    case '\t':
                        return "\\t";
                    default:
                        return "\\u" + ((ushort) m.Value[0]).ToString("x4");
                }
            });
            return "\"" + str + "\"";
        }
        if (obj is null)
            return "null";
        if (obj is bool)
            return (bool) obj ? "true" : "false";
        if (!obj.GetType().GetTypeInfo().IsPrimitive)
            throw new ArgumentException("Unable to encode objects of type " + obj.GetType());
        return Convert.ToString(obj, CultureInfo.InvariantCulture);
    }

所以在根本不知道那件事的情况下,它看起来只是期望一个只能是类型的IDictionary<string, object>地方value

  • IDictionary<string, object>(其中值类型再次基于相同的类型限制)
  • IList<object>(其中元素类型再次受到相同的限制)
  • string
  • bool
  • 原始类型(int, short, ulong, float, 等)

您给定的课程DGUOAuth既不是这些 => ArgumentException


解决方案

所以我根本不会使用你的DGUOAuth类,而只是直接构造相应的字典

var data = new Dictionary<string, object>
{
    {"authData" , "{\"access_token\" : \"F12w06Ddqx1k5qj75JQWRZmzh16Zgf05wHExNnHAnh8\", \"dguId\" : \"25-1999\"}"}
};

或者如果你想

var data = new Dictionary<string, object>
{
    {"authData" , new Dictionary<string, object>
                  {
                      {"access_token", "F12w06Ddqx1k5qj75JQWRZmzh16Zgf05wHExNnHAnh8"}, 
                      {"dguId", "25-1999"}
                  }
    }
};

当然,如果需要,您也可以从变量中动态填写值。

另一种方法是确保您DGUOAuth返回这样的字典

[System.Serializable]
public class DGUOAuth
{
    public string dguId = "";
    public string access_token = "";

    public DGUOauth(string id, string token)
    {
        dguId = id;
        access_token = token;
    }

    public IDictionary<string, object> ToDictionary()
    {
        return new Dictionary<string, object>
        {
            {"access_token", access_token}, 
            {"dguId", dguId}
        };
    }
}

然后像这样使用它

var data = new Dictionary<string, object>
{
    {"authData", new DGUOauth("25-1999", "F12w06Ddqx1k5qj75JQWRZmzh16Zgf05wHExNnHAnh8").ToDictionary()}
};

或者实际上实现了相应的接口IDictionary<string, object>,在我看来,这对于这个小任务来说太过分了。


我什至不确定您是否需要该字段名称authData,或者它是否只是期望

var data = new Dictionary<string, object>
{
   {"access_token", "F12w06Ddqx1k5qj75JQWRZmzh16Zgf05wHExNnHAnh8"}, 
   {"dguId", "25-1999"}
};

但这是你必须尝试的。


推荐阅读