Unity 中的自定义 OAuth 链接到 Parse Server

Custom OAuth in Unity linking to Parse Server

我正在将 Unity 与 Parse Server 结合使用,现在希望能够 link 一个具有 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");
   }
});

没有任何反应,我只收到“为 link 用户做好准备!”但在那之后没有日志?! LinkWithAsync 和 Unity 的文档几乎不存在...

真的希望有人能帮我解决这个问题。感谢任何帮助,并提前致谢:-)

----- 编辑 -----

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

System.AggregateException: One or more errors occurred. ---> System.ArgumentException: Unable to encode objects of type DGUOAuth

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

问题

错误基本上来自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
  • 原始类型(intshortulongfloat 等)

你给出的 class DGUOAuth 都不是这些 => ArgumentException.


解决方案

所以我根本不会使用你的 DGUOAuth class 而是简单地根据字典直接构造为

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 returns 这样的字典,如果您需要大量传递它或通过检查器配置它,这对您来说可能更容易

[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"}
};

但这是您必须尝试的事情。