Stripe.Net 发票 属性 在处理 charge.refund webhook 时为 NULL

Stripe.Net invoice property is NULL when handling charge.refund webhook

我正在使用 Stripe.Net 来处理付款。当我开始测试 "charge.refund" webhook 时,我在后面的代码中得到 NULL 发票 属性 但发票值存在于 Stripe webhook 事件中,我确认发票也存在仪表板。

注意到 Stripe.Net 中的版本与配置的 webhook API 不同。

仪表板 Webhook API 版本:2017-08-15

Stripe.Net版本:16.12.0.0(支持2018-02-06)。

这是 Stripe webhook 事件

这里是破解代码(charge.Invoice.SubscriptionId用空引用破解)

以前有人遇到过这个问题吗?

谢谢

正在查看 source code for the Stripe.Mapper<T>.MapFromJson

// the ResponseJson on a list method is the entire list (as json) returned from stripe.
// the ObjectJson is so we can store only the json for a single object in the list on that entity for
// logging and/or debugging
public static T MapFromJson(string json, string parentToken = null, StripeResponse stripeResponse = null)
{
    var jsonToParse = string.IsNullOrEmpty(parentToken) ? json : JObject.Parse(json).SelectToken(parentToken).ToString();

    var result = JsonConvert.DeserializeObject<T>(jsonToParse);

    // if necessary, we might need to apply the stripe response to nested properties for StripeList<T>
    ApplyStripeResponse(json, stripeResponse, result);

    return result;
}

public static T MapFromJson(StripeResponse stripeResponse, string parentToken = null)
{
    return MapFromJson(stripeResponse.ResponseJson, parentToken, stripeResponse);
}

private static void ApplyStripeResponse(string json, StripeResponse stripeResponse, object obj)
{
    if (stripeResponse == null)
    {
        return;
    }

    foreach (var property in obj.GetType().GetRuntimeProperties())
    {
        if (property.Name == nameof(StripeResponse))
        {
            property.SetValue(obj, stripeResponse);
        }
    }

    stripeResponse.ObjectJson = json;
}

使用 JSON.Net、

反序列化 JSON

事实StripeCharge.Invoice property is marked with [JsonIgnore] attribute

#region Expandable Invoice

/// <summary>
/// ID of the invoice this charge is for if one exists.
/// </summary>
public string InvoiceId { get; set; }

[JsonIgnore]
public StripeInvoice Invoice { get; set; }

[JsonProperty("invoice")]
internal object InternalInvoice
{
    set
    {
        StringOrObject<StripeInvoice>.Map(value, s => this.InvoiceId = s, o => this.Invoice = o);
    }
}
#endregion

最后是 InternalInvoice 属性 是如何通过 StringOrObject<T>

映射的
StringOrObject<StripeInvoice>.Map(value, s => this.InvoiceId = s, o => this.Invoice = o);

可以在class定义中看到

internal static class StringOrObject<T>
    where T : StripeEntityWithId
{
    public static void Map(object value, Action<string> updateId, Action<T> updateObject)
    {
        if (value is JObject)
        {
            T item = ((JToken)value).ToObject<T>();
            updateId(item.Id);
            updateObject(item);
        }
        else if (value is string)
        {
            updateId((string)value);
            updateObject(null);
        }
    }
}

如果传递的值是 string,它将 Invoice 对象 属性 设置为 null

else if (value is string)
{
    updateId((string)value);
    updateObject(null);
}

因此,您描述的行为是根据显示的数据和代码设计的。

您可能需要提取 InvoiceId 并尝试检索它(发票)才能使用其成员。