【问题标题】:Google Dynamic Links with .NET使用 .NET 的 Google 动态链接
【发布时间】:2018-11-12 04:59:14
【问题描述】:

我正在尝试让 google firebase 动态链接在我的 .net 核心项目上工作,我的代码如下

public static async Task<string> GetShortLink(string longLink)
{
    var service = AuthenticateServiceAccount("gayan@empite.com", "Opt/Keys/quallogi-keys.json", new[] { "https://www.googleapis.com/auth/firebase" });
    var request = service.ManagedShortLinks.Create(new CreateManagedShortLinkRequest
    {
        DynamicLinkInfo = new DynamicLinkInfo
        {
            //DynamicLinkDomain = "https://quallogi.page.link",
            DomainUriPrefix = "quallogi.page.link",
            AnalyticsInfo = new AnalyticsInfo(),
            IosInfo = new IosInfo(),
            Link = "https://github.com/distriqt/ANE-Firebase/wiki/DynamicLinks---Create-Dynamic-Links",

        },

        Suffix = new Suffix { Option = "SHORT" },
        Name = "shortlink",


    });
    var response = await request.ExecuteAsync();
    return response.PreviewLink;
}

public static FirebaseDynamicLinksService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
{
    try
    {
        if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
            throw new Exception("Path to the service account credentials file is required.");
        if (!File.Exists(serviceAccountCredentialFilePath))
            throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
        if (string.IsNullOrEmpty(serviceAccountEmail))
            throw new Exception("ServiceAccountEmail is required.");

        if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
        {
            GoogleCredential credential;
            using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
            {
                credential = GoogleCredential.FromStream(stream)
                     .CreateScoped(scopes);
            }

            return new FirebaseDynamicLinksService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Firebasedynamiclinks Service account Authentication Sample",
            });
        }
        else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
        {

            var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
            var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
            {
                Scopes = scopes
            }.FromCertificate(certificate));

            return new FirebaseDynamicLinksService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Firebasedynamiclinks Authentication Sample",
            });
        }
        else
        {
            throw new Exception("Unsupported Service accounts credentials.");
        }

    }
    catch (Exception ex)
    {
        throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
    }
}

但是当我运行代码时,谷歌会抛出异常

Google.Apis.Requests.RequestError 遇到内部错误。 [500] 错误 [ 消息 [遇到内部错误。] 位置 [ - ] 原因[backendError] 域[全局] ]

出了什么问题?

【问题讨论】:

    标签: c# firebase .net-core firebase-dynamic-links


    【解决方案1】:

    我有点惊讶你能做到这一点。目前,这个库有两个问题:

    1. 当使用 ManagedShortLinks 时,它会如所述那样爆炸。但是,如果您处理第二个问题,它只会到目前为止。
    2. ETag 成员未修饰,按原样进行序列化。您将看到如下错误:
    Google.Apis.Requests.RequestError
    Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info.android_info': Cannot find field.
    Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info.ios_info': Cannot find field.
    Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info': Cannot find field.
    Invalid JSON payload received. Unknown name "ETag" at 'suffix': Cannot find field.
    Invalid JSON payload received. Unknown name "ETag": Cannot find field. [400]
    

    我还没有找到解决 ManagedShortLinks 的方法。但是,ShortLinks 会起作用。我会告诉你我是怎么做到的。

           public async Task<string> GetDeepLink(Invitation inv)
           {
               var playId = _configurationProvider.GetSetting(AppSettingNames.GooglePlayAppId);
               var iosId = _configurationProvider.GetSetting(AppSettingNames.AppleAppStoreAppId);
               var domain = _configurationProvider.GetSetting(AppSettingNames.GoogleFirebaseDynamicLinkDomain);
    
               NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);
    
               queryString["Key1"] = "value1";
    
               var mslReq = new CreateShortDynamicLinkRequest();
               mslReq.DynamicLinkInfo = new DynamicLinkInfo();
               mslReq.DynamicLinkInfo.AndroidInfo = new AndroidInfo() { AndroidPackageName = playId };
               mslReq.DynamicLinkInfo.IosInfo = new IosInfo() { IosAppStoreId = iosId, IosBundleId = playId };
               mslReq.DynamicLinkInfo.DomainUriPrefix = $"https://{domain}";
               mslReq.DynamicLinkInfo.Link = $"https://www.example.com/?{queryString}";
               mslReq.Suffix = new Suffix() { Option = "SHORT" };
               var json = JsonConvert.SerializeObject(mslReq, Formatting.Indented, new CreateShortDynamicLinkRequestConverter());
    
               var request = _firebaseDynamicLinksService.ShortLinks.Create(new CreateShortDynamicLinkRequest());
    
               request.ModifyRequest = message =>
                   message.Content = new StringContent(json, Encoding.UTF8, "application/json");
    
               var res = await request.ExecuteAsync();
               return res.ShortLink;
           }
    

    这取决于CreateShortDynamicLinkRequestConverter:

        public class CreateShortDynamicLinkRequestConverter : JsonConverter
        {
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                serializer.NullValueHandling = NullValueHandling.Ignore;
                var t = JToken.FromObject(value);
                var modified = t.RemoveFields("ETag");
    
                modified.WriteTo(writer);
            }
    
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }
    
            public override bool CanConvert(Type objectType)
            {
                return true;
            }
    
            public override bool CanRead => false;
        }
    

    这又取决于RemoveFields

            // source: https://stackoverflow.com/a/31581951/773673
            public static JToken RemoveFields(this JToken token, params string[] fields)
            {
                JContainer container = token as JContainer;
                if (container == null) return token;
    
                List<JToken> removeList = new List<JToken>();
                foreach (JToken el in container.Children())
                {
                    JProperty p = el as JProperty;
                    if (p != null && (fields.Contains(p.Name)))
                    {
                        removeList.Add(el);
                    }
                    el.RemoveFields(fields);
                }
    
                foreach (JToken el in removeList)
                {
                    el.Remove();
                }
    
                return token;
            }
    

    归根结底,这里最大的问题是ETag 成员缺乏装饰。我们需要解决这个问题。我相信在使用public NewtonsoftJsonSerializer(JsonSerializerSettings settings) 构造函数实例化服务时自定义BaseClientService.Initializer.Serializer 将允许您指定要使用的Converters,但是当我开始工作时我停止了。真正解决这个问题的方法是简单地装饰 ETag 成员不参与序列化(前提是不会破坏其他任何东西!)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 2020-10-08
      相关资源
      最近更新 更多