如何创建多级 json 并将其作为 Web 请求传递?

How do I create multi level json and pass it as a web request?

我正在尝试连接到 api 并向其传递 json 请求。我不确定如何格式化 json 数据,所以我发现 post 建议 json2csharp.com.

因此,我使用 http://json2csharp.com/ 创建了 json 请求数据所需的 classes:

curl -v -X POST \
  -H "Authorization: APIKEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "sale",
    "amount": 1112,
    "tax_amount": 100,
    "shipping_amount": 100,
    "currency": "USD",
    "description": "test transaction",
    "order_id": "someOrderID",
    "po_number": "somePONumber",
    "ip_address": "4.2.2.2",
    "email_receipt": false,
    "email_address": "user@home.com",
    "create_vault_record": true,
    "payment_method": {
        "card": {
          "entry_type": "keyed",
          "number": "4012000098765439",
          "expiration_date": "12/20",
          "cvc": "999",
          "cardholder_authentication": {
            "condition": "...",
            "eci": "...",
            "cavv": "...",
            "xid": "...",
          }
        }
        ... or ...
        "customer": {
          "id": "b798ls2q9qq646ksu070",
          "payment_method_type": "card",
          "payment_method_id": "b798ls2q9qq646ksu080",
          "billing_address_id": "b798ls2q9qq646ksu07g",
          "shipping_address_id": "b798ls2q9qq646ksu07g"
        }
        ... or ...
        "terminal": {
          "id": "<terminal id>"
          "expiration_date": "12/20",
          "cvc": "999",
          "print_receipt": "both"
          "signature_required": true
        }
        ... or ...
        "token": "<tokenizer token goes here>",
        ... or ...
        "ach": {
          "routing_number": "490000018",
          "account_number": "999999", 
          "sec_code": "ccd",
          "account_type": "checking",
          "check_number":"1223",
          "accountholder_authentication": {
            "dl_state": "IL",
            "dl_number": "r500123123"
          }
          ... or ...
        "apm": {
          "type": "alipay",
          "merchant_redirect_url": "http://merchantwebsite.com/",
          "locale": "en-US",
          "mobile_view": false
        }
      }
    },
    "billing_address" : {
        "first_name": "John",
        "last_name": "Smith",
        "company": "Test Company",
        "address_line_1": "123 Some St",
        "city": "Wheaton",
        "state": "IL",
        "postal_code": "60187",
        "country": "US",
        "phone": "5555555555",
        "fax": "5555555555",
        "email": "help@website.com"
    },
    "shipping_address" : {
        "first_name": "John",
        "last_name": "Smith",
        "company": "Test Company",
        "address_line_1": "123 Some St",
        "city": "Wheaton",
        "state": "IL",
        "postal_code": "60187",
        "country": "US",
        "phone": "5555555555",
        "fax": "5555555555",
        "email": "help@website.com"
    }
}'   \
"URL_GOES_HERE/transaction"

以下是网站的结果:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
  public class ApiRequest
  {
    public class ProcessorSpecific
    {
    }

    public class Card
    {
      public string id { get; set; }
      public string card_type { get; set; }
      public string first_six { get; set; }
      public string last_four { get; set; }
      public string masked_card { get; set; }
      public string expiration_date { get; set; }
      public string status { get; set; }
      public string auth_code { get; set; }
      public string processor_response_code { get; set; }
      public string processor_response_text { get; set; }
      public string processor_type { get; set; }
      public string processor_id { get; set; }
      public string avs_response_code { get; set; }
      public string cvv_response_code { get; set; }
      public ProcessorSpecific processor_specific { get; set; }
      public DateTime created_at { get; set; }
      public DateTime updated_at { get; set; }
    }

    public class Response
    {
      public Card card { get; set; }
    }

    public class BillingAddress
    {
      public string first_name { get; set; }
      public string last_name { get; set; }
      public string company { get; set; }
      public string address_line_1 { get; set; }
      public string address_line_2 { get; set; }
      public string city { get; set; }
      public string state { get; set; }
      public string postal_code { get; set; }
      public string country { get; set; }
      public string phone { get; set; }
      public string fax { get; set; }
      public string email { get; set; }
    }

    public class ShippingAddress
    {
      public string first_name { get; set; }
      public string last_name { get; set; }
      public string company { get; set; }
      public string address_line_1 { get; set; }
      public string address_line_2 { get; set; }
      public string city { get; set; }
      public string state { get; set; }
      public string postal_code { get; set; }
      public string country { get; set; }
      public string phone { get; set; }
      public string fax { get; set; }
      public string email { get; set; }
    }

    public class Data
    {
      public string id { get; set; }
      public string type { get; set; }
      public int amount { get; set; }
      public int tax_amount { get; set; }
      public bool tax_exempt { get; set; }
      public int shipping_amount { get; set; }
      public int discount_amount { get; set; }
      public string payment_adjustment_type { get; set; }
      public int payment_adjustment_value { get; set; }
      public string currency { get; set; }
      public string description { get; set; }
      public string order_id { get; set; }
      public string po_number { get; set; }
      public string ip_address { get; set; }
      public bool email_receipt { get; set; }
      public string email_address { get; set; }
      public string payment_method { get; set; }
      public Response response { get; set; }
      public string status { get; set; }
      public int response_code { get; set; }
      public string customer_id { get; set; }
      public BillingAddress billing_address { get; set; }
      public ShippingAddress shipping_address { get; set; }
      public DateTime created_at { get; set; }
      public DateTime updated_at { get; set; }
    }

    public class RootObject
    {
      public string status { get; set; }
      public string msg { get; set; }
      public Data data { get; set; }
    }
  }
}

到目前为止,这是我的代码:

private void button1_Click(object sender, EventArgs e)
{
  var urlx = "https://xxxxx.xxxxxxx.com/api/";
  var usr = "xxxxxxxxxxx";
  var pwd = "xxxx";

  // replace with the TEST class to pass in the required JSON request
  // BaSysRequest item = new BaSysRequest();
  // item.username = usr;
  // item.password = pwd;

  string request = JsonConvert.SerializeObject(item);

  Uri url = new Uri(string.Format(urlx));

  string response = Post(url, request);

  if (response != null)
  {
    Console.WriteLine(response);
  }
  else
  {
    Console.WriteLine("nothing");

  }

}


public string Post(Uri url, string value)
{
  var request = HttpWebRequest.Create(url);
  var byteData = Encoding.ASCII.GetBytes(value);
  request.ContentType = "application/json";
  request.Method = "POST";

  try
  {
    using (var stream = request.GetRequestStream())
    {
      stream.Write(byteData, 0, byteData.Length);
    }
    var response = (HttpWebResponse)request.GetResponse();
    var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

    return responseString;
  }
  catch (WebException e)
  {
    return null;
  }
}

public string Get(Uri url)
{
  var request = HttpWebRequest.Create(url);
  request.ContentType = "application/json";
  request.Method = "GET";

  try
  {
    var response = (HttpWebResponse)request.GetResponse();
    var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

    return responseString;
  }
  catch (WebException e)
  {
    return null;
  }
}

如何填充 ApiRequest 并传入 class?我是否为 json 数据正确创建了 class?

有什么建议吗?

由于付款方式可以是不同的类型,因此请利用泛型

public class TransactionRequest<T> {
    public string type { get; set; }
    public long amount { get; set; }
    public long tax_amount { get; set; }
    public long shipping_amount { get; set; }
    public string currency { get; set; }
    public string description { get; set; }
    public string order_id { get; set; }
    public string po_number { get; set; }
    public string ip_address { get; set; }
    public bool email_receipt { get; set; }
    public string email_address { get; set; }
    public bool create_vault_record { get; set; }
    public Dictionary<string, T> payment_method { get; set; }
    public Address billing_address { get; set; }
    public Address shipping_address { get; set; }
}

public class Address {
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string company { get; set; }
    public string address_line_1 { get; set; }
    public string address_line_2 { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string postal_code { get; set; }
    public string country { get; set; }
    public string phone { get; set; }
    public string fax { get; set; }
    public string email { get; set; }
}

以上class基于原题中的示例请求

为每一种可能的支付类型创建一个可以与通用类型一起使用的匹配模型定义

例如点赞卡片

public partial class Card {
    public string entry_type { get; set; }
    public string number { get; set; }
    public string expiration_date { get; set; }
    public long cvc { get; set; }
    public CardholderAuthentication cardholder_authentication { get; set; }
}

public partial class CardholderAuthentication {
    public string condition { get; set; }
    public string eci { get; set; }
    public string cavv { get; set; }
    public string xid { get; set; }
}

从那里开始,只需构建请求并发布到所需的 URL

例如

static Lazy<HttpClient> client = new Lazy<HttpClient>();

private async void button1_Click(object sender, EventArgs e) {
    var urlx = "https://xxxxx.xxxxxxx.com/api/";
    var usr = "xxxxxxxxxxx";
    var pwd = "xxxx";

    Card card = new Card();
    //populate as needed

    TransactionRequest<Card> item = new TransactionRequest<Card>();
    //populate as needed

    //set payment method accordingly
    item.payment_method["card"] = card;

    Uri url = new Uri(string.Format(urlx));

    string response = await PostAsync(url, item);
    if (response != null) {
        Console.WriteLine(response);
    } else {
        Console.WriteLine("nothing");
    }
}

public async Task<string> PostAsync<T>(Uri url, T value) {
    try {
        string json = JsonConvert.SerializeObject(value);
        var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
        var response = await client.Value.PostAsync(url, content);
        var responseString = await response.Content.ReadAsStringAsync();
        return responseString;
    } catch (Exception e) {
        //TODO: log error
        return null;
    }
}

这是使用 HttpClient 执行 post 的一种快速但肮脏的方法:

    private HttpResponseMessage Post(string url, string path, object content)
    {
        string serialized = JsonConvert.SerializeObject(content);
        StringContent stringContent = new StringContent(serialized, Encoding.UTF8, "application/json");

        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri(url);
        HttpResponseMessage response = Task.Run(() => client.PostAsync(path, stringContent)).Result;
        client.Dispose();

        return response;
    }