如何在 C# WCF 中接收 Stripe api webhook

Posted

技术标签:

【中文标题】如何在 C# WCF 中接收 Stripe api webhook【英文标题】:How to receive Stripe api webhook in C# WCF 【发布时间】:2019-11-29 10:56:46 【问题描述】:

我正在尝试从 Stripe 结帐发布请求接收 webhook。但是 Stripe 文档只显示了 ASP.net 的示例代码,而我使用的是 WCF。 https://stripe.com/docs/payments/checkout/fulfillment#webhooks

这是 Stripe 结账的示例请求。


  "created": 1326853478,
  "livemode": false,
  "id": "evt_00000000000000",
  "type": "checkout.session.completed",
  "object": "event",
  "request": null,
  "pending_webhooks": 1,
  "api_version": "2019-05-16",
  "data": 
    "object": 
      "id": "cs_00000000000000",
      "object": "checkout.session",
      "billing_address_collection": null,
      "cancel_url": "https://example.com/cancel",
      "client_reference_id": null,
      "customer": null,
      "customer_email": null,
      "display_items": [
        
          "amount": 1500,
          "currency": "usd",
          "custom": 
            "description": "Comfortable cotton t-shirt",
            "images": null,
            "name": "T-shirt"
          ,
          "quantity": 2,
          "type": "custom"
        
      ],
      "livemode": false,
      "locale": null,
      "payment_intent": "pi_00000000000000",
      "payment_method_types": [
        "card"
      ],
      "submit_type": null,
      "subscription": null,
      "success_url": "https://example.com/success"
    
  

起初我尝试使用 Stripe.Event 类作为参数。

[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
void FromStripeCheckoutWrapped(Event data);

但是所有数据都是空值。 所以,我尝试根据json请求使用我自己的Model类。

    public partial class Temperatures
    
        [DataMember]
        public long Created  get; set; 
        [DataMember]
        public bool Livemode  get; set; 
        [DataMember]
        public string Id  get; set; 
        [DataMember]
        public string Type  get; set; 
        [DataMember]
        public string Object  get; set; 
        [DataMember]
        public object Request  get; set; 
        [DataMember]
        public long PendingWebhooks  get; set; 
        [DataMember]
        public string ApiVersion  get; set; 
        [DataMember]
        public Data Data  get; set; 
     ...

但他们都没有收到正确的数据。

我尝试使用 String 参数接收的最后一件事,就像我在 *** 但在 Java 中发现的问题一样。 How to Receive Webhook from Stripe in Java 他说他可以用这种方式打印数据。但我做不到。

我让它成功的唯一方法是输入 json 请求中写的每一个参数。我也尝试将 WrappedBare 作为 WebMessageBodyStyle

[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
void FromStripeCheckoutWrapped(long created, bool livemode, string id ...);

然后我可以正确获取数据..但是像上面那样做所有事情都太长了。 如何以有效且正确的方式接收 POST 请求? 请同时参考 Java 和 Stripe webhook 文档中的问题。 我只想将 POST 请求读取为 String 对象,而不管请求结构如何,以便我可以解析它。

【问题讨论】:

DataMember 属性上设置 Name 参数以匹配 JSON 中属性名称的大小写。创建创建 @rene 我试过了,但没用.. 请参考以下链接。也许它对你有用。 ***.com/questions/52489002/… 如果您正在寻找最新的 ASP.NET Core MVC 或 ASP.NET Web 表单中的 Stripe checkout 解决方案,请查看演示:techtolia.com/Stripe 【参考方案1】:

当我使用以下 DataContract 类时,反序列化该示例负载没有问题:

[DataContract]
public class Base 

   [DataMember(Name="livemode")]
   public bool Livemode get;set;
   [DataMember(Name="object")]
   public string @Object get;set;
   [DataMember(Name="id")]
   public string Id get;set;


[DataContract]
public class Event:Base

   [DataMember(Name="created")]
   public long Created get;set;   
   [DataMember(Name="type")]
   public string Type get;set;
   [DataMember(Name="data")]
   public EventData Data get;set;


[DataContract]
public class EventData

   [DataMember(Name="object")]
   public EventObject EventObject get;set;


[DataContract]
public class EventObject:Base

   [DataMember(Name="display_items")]
   public Item[] DisplayItems get;set;


[DataContract]
public class Item

   [DataMember(Name="amount")]
   public double Amount get;set;
   [DataMember(Name="currency")]
   public string Currency get;set;

我在本服务合同中使用该 DataContract:

[ServiceContract]
interface IContract 

   [OperationContract]
   [WebInvoke(
        Method = "POST",
        BodyStyle = WebMessageBodyStyle.Bare,
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json)]
   string StripeWebhook(Event data); 

当我为该服务创建实现时:

public class JsonService:IContract 

  public  string StripeWebhook(Event data)
    
    data.Dump("rcvd data");
    return "\"result\":\"success\"";
  

并将其提供给 WebServiceHost:

// keeps the service running
AutoResetEvent are = new AutoResetEvent(false);

void Start() 

  //netsh http add urlacl url=http://+:8000/json user=USERNAME
  using (var serviceHost = new WebServiceHost(typeof(JsonService), new Uri("http://localhost:8000/json")))
  
      serviceHost.AddServiceEndpoint(typeof(IContract), new WebHttpBinding(), "");
      serviceHost.Open();
      are.WaitOne(); // blocks 
      serviceHost.Close();
  

我可以在启动该服务并将 JSON POST 到它后调用它:

void Main()

    new Thread(Start).Start();  
    try 
        var wc = new WebClient();
        wc.Headers.Add("content-type","application/json");
        wc.UploadString("http://localhost:8000/json/Stripewebhook", File.ReadAllText(@"example_json_wcf.json")).Dump("response");
     catch(WebException e) 
       e.Dump("raw");
       using(var ms = new MemoryStream()) 
           e.Response.GetResponseStream().CopyTo(ms);
           Encoding.UTF8.GetString(ms.ToArray()).Dump("error");
       
    
    Console.WriteLine("Now Running. Enter key will stop the service.");
    Console.ReadLine();
    are.Set();

这是我在 LinqPad 中的结果:

记住:

裸露或包裹很重要 在(反)序列化套管问题

如果反序列化失败,请先尝试序列化您的对象树,然后将该结果与您实际需要的结果进行比较。 或者使用许多 JSON 到 POCO 服务中的一种,例如:http://json2csharp.com/(我不隶属于该服务,它恰好是我的 Google 搜索中弹出的第一个)

【讨论】:

非常感谢!实际上我通过 json2csharp 制作了 DataContract 表单,但格式非常不同。我认为问题出在 Model(Datacontract) 结构上。我没有尝试过继承结构。

以上是关于如何在 C# WCF 中接收 Stripe api webhook的主要内容,如果未能解决你的问题,请参考以下文章

在 C# MVC 中使用 Stripe api 兑换促销代码

无法在 wcf c# 中接收 xml 发布请求值

在 Stripe Customer 对象 C# 中访问元数据时遇到问题

如何在 C# 中正确使用 WCF REST API 上的 Stream 将文件(图像/视频/等)上传到服务器?

SOAP(C# WCF) 通过 Zeep 接收整数列表作为参数

C#如何强制等待连接到 WCF 服务