I'm getting a Bad Request when I'm sending a POST request to the Klarna API to create a new order.
This is my code for sending the POST request:
Cart = new CartManager(_context, HttpContext.Session).GetCart();
Customer = new CustomerManager(HttpContext.Session).GetCustomer()
OrderViewModel order = new OrderViewModel();
order.Reference = DateTime.Now.ToOADate().ToString().Replace(",", string.Empty);
order.Cart = Cart;
order.Customer = Customer;
string url = ApiHelper.KlarnaApiClient.BaseAddress + "checkout/v3/orders";
KlarnaOrderModel klarnaOrderModel = new KlarnaOrderModel
{
purchase_currency = "SEK",
order_amount = (int)order.Cart.TotalCharge,
order_lines = klarnaOrderLines
};
HttpResponseMessage response = await ApiHelper.KlarnaApiClient.PostAsJsonAsync(
url, klarnaOrderModel);
response.EnsureSuccessStatusCode();
KlarnaOrderModel:
public class KlarnaOrderModel
{
public string purchase_country { get { return "SE"; } }
public string purchase_currency { get; set; }
public string locale { get { return "en-GB"; } }
public int order_amount { get; set; }
public int order_tax_amount { get { return 2500; } }
public List<KlarnaOrderLine> order_lines { get; set; }
public KlarnaMerchantUrls merchant_urls { get { return new Models.KlarnaMerchantUrls(); } }
}
KlarnaOrderLine:
public class KlarnaOrderLine
{
public string name { get; set; }
public int quantity { get; set; }
public int unit_price { get; set; }
public int tax_rate { get { return 2500; } }
public int total_amount { get { return unit_price * quantity; } }
public int total_tax_amount { get { return total_amount / 5 ; } }
}
KlarnaMerchantUrls:
public class KlarnaMerchantUrls
{
public string terms { get { return "https://localhost:44316/shop/terms"; } }
public string checkout { get { return "https://localhost:44316/shop/checkout"; } }
public string confirmation { get { return "https://localhost:44316/shop/checkout/confirmation"; }
public string push { get { return "https://localhost:44316/shop/push"; } }
}
Here is a screenshot:
My code for initializing the API:
KlarnaApiClient = new HttpClient();
KlarnaApiClient.BaseAddress = new Uri("https://api.playground.klarna.com/");
KlarnaApiClient.DefaultRequestHeaders.Accept.Clear();
KlarnaApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
KlarnaApiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{MY KLARNA API KEY UID}:{MY KLARNA API KEY PASSWORD}")));
Related
So I wrote a method of code and it pulls from the database correctly (I am using Dapper), but it doesnt pass off to the next method. Can anyone tell me why and what I am doing wrong? Not quite understanding what I am doing wrong here. I have tried a few different ways including below and making and IEnumerable list. I can see the variables in the logger so I know I am pulling them correctly, just not sure why they arent sending to the CheckSite().
public class UptimeService
{
private readonly ILogger<UptimeService> _logger;
private readonly IWebsiteData _webdb;
private readonly IUptimeData _db;
public UptimeService(IWebsiteData webdb, IUptimeData db ,ILogger<UptimeService> logger)
{
_webdb = webdb;
_logger = logger;
_db= db;
}
public class SiteResponse
{
public int Websiteid { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public bool Status { get; set; }
public long ResponseTime { get; set; }
}
public async Task GetAllWebsites()
{
var websites = await _webdb.GetWebsites();
foreach (var website in websites)
{
_logger.LogInformation($"WEBSITE::::: {website.Url} | {website.Name} | {website.Websiteid}");
CheckSite(website.Url, website.Name, website.Websiteid);
}
return ;
}
public SiteResponse CheckSite(string Url, string Name, int Websiteid)
{
var result = new SiteResponse();
var stopwatch = new Stopwatch();
stopwatch.Start();
var client = new HttpClient();
_logger.LogInformation(
$"TEST URL: {result.Url}");
try
{
var checkingResponse = client.GetAsync(Url).Result;
result.Status = checkingResponse.IsSuccessStatusCode &&
checkingResponse.StatusCode == HttpStatusCode.OK;
}
catch
{
result.Status = false;
// offline
}
stopwatch.Stop();
var elapsed = stopwatch.ElapsedMilliseconds;
result.ResponseTime = elapsed;
if (result.Status)
{
// archive record
RecordToDb(result);
}
else
{
_logger.LogInformation(
$"Status is {result.Status}");
}
return result;
}
public async void RecordToDb(SiteResponse response)
{
var newRecord = new UptimeModel
{
Time = DateTime.Now,
Status = response.Status,
ResponseTime = (int)response.ResponseTime,
Websiteid = response.Websiteid,
Name = response.Name,
};
_logger.LogInformation(
$"Trying to Save {response.Name}");
await _db.InsertUptime(newRecord);
}
}
If the result.Url is empty here:
_logger.LogInformation($"TEST URL: {result.Url}");
that's because it's a new instance of SiteResponse() method.
If it is showing as null, you'll need to create constructors on the class. Here is an example:
public class SiteResponse
{
public SiteResponse(){ }
public SiteResponse(string url){
Url = url;
}
public int Websiteid { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public bool Status { get; set; }
public long ResponseTime { get; set; }
}
and then initialize the new one like:
var result = new SiteResponse(Url);
Based on the comments below, I would refactor to something like this.
public class UptimeService
{
private readonly ILogger<UptimeService> _logger;
private readonly IWebsiteData _webdb;
private readonly IUptimeData _db;
public UptimeService(IWebsiteData webdb, IUptimeData db ,ILogger<UptimeService> logger)
{
_webdb = webdb;
_logger = logger;
_db= db;
}
public class SiteResponse
{
public int Websiteid { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public bool Status { get; set; }
public long ResponseTime { get; set; }
}
public async Task GetAllWebsites()
{
var websites = await _webdb.GetWebsites();
foreach (var website in websites)
{
_logger.LogInformation($"WEBSITE::::: {website.Url} | {website.Name} | {website.Websiteid}");
await CheckSite(website);
}
return ;
}
public async Task CheckSite(SiteResponse siteResponse)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var client = new HttpClient();
_logger.LogInformation(
$"TEST URL: {siteResponse.Url}");
try
{
var checkingResponse = await client.GetAsync(siteResponse.Url);
siteResponse.Status = checkingResponse.IsSuccessStatusCode &&
checkingResponse.StatusCode == HttpStatusCode.OK;
}
catch
{
siteResponse.Status = false;
// offline
}
stopwatch.Stop();
var elapsed = stopwatch.ElapsedMilliseconds;
siteResponse.ResponseTime = elapsed;
if (siteResponse.Status)
{
// archive record
RecordToDb(siteResponse);
}
else
{
_logger.LogInformation(
$"Status is {siteResponse.Status}");
}
return;
}
public async void RecordToDb(SiteResponse response)
{
var newRecord = new UptimeModel
{
Time = DateTime.Now,
Status = response.Status,
ResponseTime = (int)response.ResponseTime,
Websiteid = response.Websiteid,
Name = response.Name,
};
_logger.LogInformation(
$"Trying to Save {response.Name}");
await _db.InsertUptime(newRecord);
}
}
I want to use rest with get method. My code is below;
public class RegisterPage : ContentPage
{
Label label, l4, label2;
public RegisterPage()
{
Button btn = new Button
{
Text = "register"
};
btn.Clicked += Btn_Clicked;
label = new Label();
l4 = new Label();
label2 = new Label();
Content = new StackLayout
{
Children = {
btn,
label,
l4,
label2
}
};
}
private async void Btn_Clicked(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add(Constants.API_KEY_HEADER_KEY, Constants.API_KEY);
string URL = Constants.URL;
var response = await client.GetAsync(URL);
var content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<Models.Result>(content);
label.Text = result.Success.ToString();
l4.Text = result.Error.ToString();
label2.Text = ((RegisteredDevice)result.Retval).Clientuuid + " - " + ((RegisteredDevice)result.Retval).Deviceuuid;
}
}
The url is working good. And my content value has json string. But the serialization is not working.
var result = JsonConvert.DeserializeObject(content);
This code doesn't deserilize.
My model is;
public class Result
{
private object retval = null;
private bool success = false;
private Error error = null;
internal Error Error
{
get { return error; }
set { error = value; }
}
public bool Success
{
get { return success; }
set { success = value; }
}
public object Retval
{
get { return retval; }
set { retval = value; }
}
}
Json:
{
"result":{
"retail":{
"#xsi.type":"registeredDevice",
"clientuuid":"28asgargb-acfe-41dfgsdg51",
"deviceuuid":123456
},
"success":true
}
}
I think the problem comes from :
private object retval = null;
So for me the best way to construct serialization objects in C# is to use this web site :
http://json2csharp.com/
This will tell you if your json is correct and he will generate the classes you need for you, here the classes generated by json2csharp
public class Retail
{
public string __invalid_name__#xsi.type { get; set; }
public string clientuuid { get; set; }
public int deviceuuid { get; set; }
}
public class Result
{
public Retail retail { get; set; }
public bool success { get; set; }
}
public class RootObject
{
public Result result { get; set; }
}
Request Class Structure:
public class QueryParams {
public List<QueryParam> QueryParam { get; set; }
}
public class QueryParam {
public string Parameter { get; set; }
}
Service is Expecting in below format:
<typ:queryParams>
<typ:queryParam>
<typ:parameter>BUSINESS_CATEGORY</typ:parameter>
</typ:queryParam>
<typ:queryParam>
<typ:parameter>CATEGORY</typ:parameter>
</typ:queryParam>
</typ:queryParams>
How i can form the request?
using QueryParams = System.Collections.Generic.List<QueryParam>;
public class QueryParam {
public string Parameter { get; set; }
public QueryParam(string para) {
Parameter = para;
}
}
public class Program
{
public static void Main()
{
var Qp = new QueryParams() {
new QueryParam("BUSINESS_CATEGORY"),
new QueryParam("CATEGORY")
};
string QpXml = ToXml(Qp);
// Use your XML from here on
}
private static string ToXml(QueryParams Qp) {
StringBuilder Sb = new StringBuilder();
Sb.AppendLine("<typ:queryParams>");
foreach (var q in Qp) {
Sb.AppendLine("<typ:queryParam>");
Sb.AppendLine("<typ:parameter>" + q.Parameter + "</typ:parameter>");
Sb.AppendLine("</typ:queryParam>");
}
Sb.AppendLine("</typ:queryParams>");
return Sb.ToString();
}
}
See this .NET Fiddle
How can I pass an entire defined class through a WCF service? I have the class defined on both the service and client side. I keep getting an error:
Best overloaded method match has some invalid arguments.
The whole class was copied from the client-side to the service-side.
Client side calling:
TransferProxy.PutTransferOnService(Transfer);
Defined on service:
[OperationContract]
bool PutTransferOnService(TypeTransfer Transfer);
I don't want to access individual items on the class from the client, I just want to move the WHOLE populated object through and do processing on the server side.
[DataContract]
public class TypeTransfer
{
private string userID;
private string transferNum;
private DateTime effectiveDate;
private int unitCount;
private int skuCount;
private string reason;
private string localStatus;
private string destStatus;
private string carrier;
private string sourceStore;
private string destinationStore;
private string inSeal;
private string outSeal;
[DataMember]
private List<TypeSOQ> correspondingSOQ = new List<TypeSOQ>();
[DataMember]
private List<TypeProductList> ProductList = new List<TypeProductList>();
public TypeTransfer() { }
// Function adds single item to transfer object
public void AddItem(int ProductID, string SKU, string PrimarySKU, string SCC, string ProductDescription, int TransferQty)
{
ProductList.Add(new TypeProductList
{
productID = ProductID,
sku = SKU,
primaryUPC = PrimarySKU,
scc = SCC,
description = ProductDescription,
transferQty = TransferQty
});
}
// Add SOQ to transfer object (can support multiple SOQ's)
public void AddSOQ(TypeSOQ soq)
{
correspondingSOQ.Add(soq);
}
// Function returns number of skus in Product List
public int GetSKUTotal()
{
return ProductList.Count();
}
// Function returns total number of items in transfer
public int GetItemTotal()
{
int itemtotal = 0;
for (int i = 0; i < ProductList.Count(); i++)
{
itemtotal += ProductList[i].transferQty;
}
return itemtotal;
}
// Return entire SOQ list
public List<TypeSOQ> GetSOQs()
{
return correspondingSOQ;
}
// Returns full product list in transfer object
public List<TypeProductList> GetProductList()
{
return ProductList;
}
[DataMember]
public string UserID
{
get { return userID; }
set { userID = value; }
}
[DataMember]
public string TransferNum
{
get { return transferNum; }
set { transferNum = value; }
}
[DataMember]
public DateTime EffectiveDate
{
get { return effectiveDate; }
set { effectiveDate = value; }
}
[DataMember]
public int UnitCount
{
get { return unitCount; }
set { unitCount = value; }
}
[DataMember]
public string Reason
{
get { return reason; }
set { reason = value; }
}
[DataMember]
public string LocalStatus
{
get { return localStatus; }
set { localStatus = value; }
}
[DataMember]
public string DestStatus
{
get { return destStatus; }
set { destStatus = value; }
}
[DataMember]
public string Carrier
{
get { return carrier; }
set { carrier = value; }
}
[DataMember]
public string SourceStore
{
get { return sourceStore; }
set { sourceStore = value; }
}
[DataMember]
public string DestStore
{
get { return destinationStore; }
set { destinationStore = value; }
}
[DataMember]
public string InSeal
{
get { return inSeal; }
set { inSeal = value; }
}
[DataMember]
public string OutSeal
{
get { return outSeal; }
set { outSeal = value; }
}
[DataMember]
public int SKUCount
{
get { return skuCount; }
set { skuCount = value; }
}
}
You said - The whole class was copied from the client-side to the service-side.
You don't need to copy your class to server side. just define your class in a separate library and give reference of that same library to both client and server.
public class OrderXml
{
public enum DeliveryType { FTP, Email, HDD, Tape, Aspera, MLT };
public class Order
{
public int UserId { get; private set; }
public int OrderBinId { get; private set; }
public int TenantId { get; private set; }
public Delivery Delivery { get; set; }
public Recipient Recipient { get; private set; }
public string[] AssetDmGuids { get; set; }
public Order(int orderBinId, string[] assetDmGuids, DeliveryType type, int recipientId, string recipientName)
{
Delivery = new Delivery(type);
Recipient = new Recipient(recipientId, recipientName);
// UserId = SessionHelper.Instance.GetUserId();
// TenantId = SessionHelper.Instance.GetTenantID().ToString();
OrderBinId = orderBinId;
AssetDmGuids = assetDmGuids;
}
public void GetXml()
{
}
}
public class Recipient
{
int _id;
string _name = string.Empty;
public Recipient(int id, string name)
{
this._id = id;
this._name = name;
}
public int Id { get { return _id; } }
public string Name { get { return _name; } }
}
public class Delivery
{
DeliveryType _deliveryType;
string _ftpLocation = string.Empty;
string _ftpPath = string.Empty;
string[] _emailAddresses;
string _deliveryAddress = string.Empty;
string _deliveryComments = string.Empty;
string _asperaLocation = string.Empty;
public string FtpPath
{
get { return _ftpPath; }
set { _ftpPath = value; }
}
public string[] EmailAddresses
{
get { return _emailAddresses; }
set { _emailAddresses = value; }
}
public string DeliveryAddress
{
get { return _deliveryAddress; }
set { _deliveryAddress = value; }
}
public string DeliveryComments
{
get { return _deliveryComments; }
set { _deliveryComments = value; }
}
public string AsperaLocation
{
get { return _asperaLocation; }
set { _asperaLocation = value; }
}
public string FtpLocation
{
get { return _ftpLocation; }
set { _ftpLocation = value; }
}
public Delivery(DeliveryType type)
{
_deliveryType = type;
}
}
public static void Main()
{
Order ord = new Order(1, new string[] { "123", "124", "125" }, DeliveryType.Tape, 1, "vh1");
}
}
public XmlDocument GetXml()
{
XmlDocument retValue = new XmlDocument();
try
{
XmlSerializer xs = new XmlSerializer(this.GetType());
Stream stream = new MemoryStream();
xs.Serialize( stream, toSerialize );
stream.Position = 0;
retValue.Load( stream );
}
catch (Exception ex)
{
}
return retValue;
}