In my application I would like add Brand and MPN to existing eBay item via API on C#, so, I run code:
string eCommerceID = (dr["eCommerceID"] ?? "").ToString().Trim();
string upc = (dr["UPC"] ?? "").ToString().Trim();
string manufacturerName = (dr["ManufacturerName"] ?? "").ToString().Trim();
string brandMPN = (dr["BrandMPN"] ?? "").ToString().Trim();
ReviseItemRequestType reviseItemRequestType = new ReviseItemRequestType();
reviseItemRequestType.Version = version;
reviseItemRequestType.Item = new ItemType();
reviseItemRequestType.Item.ItemID = eCommerceID;
reviseItemRequestType.Item.ProductListingDetails = new ProductListingDetailsType();
reviseItemRequestType.Item.ProductListingDetails.UPC = upc;
reviseItemRequestType.Item.ProductListingDetails.BrandMPN = new BrandMPNType();
reviseItemRequestType.Item.ProductListingDetails.BrandMPN.Brand = manufacturerName;
reviseItemRequestType.Item.ProductListingDetails.BrandMPN.MPN = brandMPN;
ReviseItemResponseType reviseItemResponseType = ebayService.ReviseItem(reviseItemRequestType);
but when I execute this code, eBay returns error:
"The item specific Brand is missing. Add Brand to this listing, enter a valid value, and then try again."
What I'm doing wrong?
Appreciate any help. Thanks.
Error:
As the error messages says:
The item specific Brand is missing
Don't use the Item.ProductListingDetails.BrandMPN in your request. Instead you will need to create two Item Specifics called Band and MPN.
<ItemSpecifics>
<NameValueList>
<Name>Brand</Name>
<Value>[BRAND VALUE]</Value>
</NameValueList>
<NameValueList>
<Name>MPN</Name>
<Value>[MPN VALUE]</Value>
</NameValueList>
</ItemSpecifics>
Here is copy paste code snippet of the C# solution.
ItemType itemType = new ItemType(); // = class eBay.Service.Core.Soap.ItemType
Int32 condCodeAsInt = 1000; // upto you to derrive this from your use case.
String myBrandValue = "Some BRAND";
String myMpnValue = "some MPN";
String myUpcValue = "Does not apply";
....
//if condition is "New" or "New with Details" then we need to set extra REQUIRED fields
if (condCodeAsInt == 1000 || condCodeAsInt == 1500)
{
//if it is "new" then remove inputted desc text completely REQUIRED
if (condCodeAsInt == 1000)
{
itemType.ConditionDescription = "";
}
// set UPC value HERE, not in ItemSpecifics.
ProductListingDetailsType pldt = new ProductListingDetailsType();
pldt.UPC = myUpcValue;
itemType.ProductListingDetails = pldt;
//init Item specifics ( and set BRAND and MPN )
itemType.ItemSpecifics = new NameValueListTypeCollection();
//brand
NameValueListType nvBrand = new NameValueListType();
nvBrand.Name = "Brand";
StringCollection brandStringCol = new StringCollection();
brandStringCol.Add(myBrandValue);
nvBrand.Value = brandStringCol;
itemType.ItemSpecifics.Add(nvBrand);
//MPN
NameValueListType nvMpn = new NameValueListType();
nvMpn.Name = "MPN";
StringCollection mpnStringCol = new StringCollection();
mpnStringCol.Add(myMpnValue);
nvMpn.Value = mpnStringCol;
itemType.ItemSpecifics.Add(nvMpn);
}
Related
I've managed to create a payment using the C# .NET SDK, however it keeps showing up as 'unapplied' when I check in QBO.
I am providing the Invoice ID and tried to follow their developer API documentation but I been at this so long now that maybe I am missing something?
The following code creates the payment but doesn't 'receive' the payment towards the invoice, is there something I missed or need to do in order for the two to be linked together?
Payment payment = new Payment
{
ProcessPayment = false,
CustomerRef = new ReferenceType { name = customer.DisplayName, Value = customer.Id },
CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
TotalAmt = amount,
TotalAmtSpecified = true
};
if (method == PaymentTypes.Cash)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "1");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{name = paymentType.Name, Value = paymentType.Id};
}
}
if (method == PaymentTypes.DebitCard)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "9");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{ name = paymentType.Name, Value = paymentType.Id };
}
}
if (method == PaymentTypes.CreditCard)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "8");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{ name = paymentType.Name, Value = paymentType.Id };
}
}
List<LinkedTxn> linkedTxns = new List<LinkedTxn>
{
new LinkedTxn()
{
TxnId = invoice.Id,
TxnType = TxnTypeEnum.Invoice.ToString()
},
};
foreach (Line line in invoice.Line)
{
//line.Amount = amount;
//line.AmountSpecified = true;
line.Received = amount;
line.ReceivedSpecified = true;
line.DetailType = LineDetailTypeEnum.PaymentLineDetail;
line.DetailTypeSpecified = true;
line.LinkedTxn = linkedTxns.ToArray();
}
payment.DepositToAccountRef = new ReferenceType() { Value = "5" };
payment.Line = invoice.Line;
payment.PaymentRefNum = reference;
DataService dataService = new DataService(serviceContext);
dataService.Add<Payment>(payment);
This is not an answer. However there's too much to add to the comments. I'm hoping this will be a helpful starting point (if not I'll remove it later).
Firstly I'd suggest refactoring your code and parameterise your variables. Doing so you should be able to preform repeatable testing in isolation.
When you preform the dataService.Add<Payment>(payment), store the response object as it may offer clues on how the request was processed. Alternatively if this is suppressing error messages, you might want to try an use Postman to send HTTP requests. This may help determine what's parameters are missing/ incorrect.
Avoid creating objects that are partially assigned it makes it a lot easier to read 7 work out which properties need to be assigned.
Also if you have a look at Full update a payment section on https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/payment
the json payload has an additional Line with the property TxnType set to CreditMemo. I would assume you'll need to add something like ReceivePayment or CreditCardPayment?
To refactor your code consider:
// TODO - Set variables for testing purposes.
// This can be added as params to a method.
decimal amount = 100;
string reference = "";
string invoiceId = ""; // invoice.Id
string customerDisplayName = ""; //customer.DisplayName
string customerId = ""; //customer.Id
string paymentName = "Cash"; // paymentType.Name
string paymentId = "1"; // paymentType.Id
List<Line> lines = new List<Line>(); // invoice.Line
if(lines.Count() == 0)
{
// TODO: You might want to check there are lines?
throw new ArgumentException("No invoice.");
}
Line[] invoiceLines = lines.Select(m => new Line()
{
AnyIntuitObject = m.AnyIntuitObject,
Amount = m.Amount,
AmountSpecified = m.AmountSpecified,
CustomField = m.CustomField,
Id = m.Id,
LineNum = m.LineNum,
Description = m.Description,
DetailType = LineDetailTypeEnum.PaymentLineDetail, //m.DetailType,
DetailTypeSpecified = true, //m.DetailTypeSpecified,
LinkedTxn = new List<LinkedTxn>
{
new LinkedTxn()
{
TxnId = invoiceId,
TxnType = TxnTypeEnum.Invoice.ToString() // TODO: Should this be ReceivePayment?
},
}.ToArray(), //m.LinkedTxn,
LineEx = m.LineEx,
Received = amount, //m.Received,
ReceivedSpecified = true // m.ReceivedSpecified
}).ToArray();
Payment payment = new Payment
{
ProcessPayment = false,
CustomerRef = new ReferenceType { name = customerDisplayName, Value = customerId },
CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
TotalAmt = amount,
TotalAmtSpecified = true,
DepositToAccountRef = new ReferenceType() { Value = "5" },
Line = invoiceLines, // Variable is for debugging purposes - it should be inline or call a method.
PaymentRefNum = reference,
PaymentMethodRef = new ReferenceType()
{
name = paymentName,
Value = paymentId,
}
};
DataService dataService = new DataService(serviceContext);
Payment results = dataService.Add<Payment>(payment);
var json = JsonConvert.SerializeObject(results);
Console.Write(json); // TODO - Use break point/ or write response somewhere for clues.
I am not able to add or update milestones field for the Features in the Rally. If anyone having the code available using C# to update the same, please share with me. I am searching and doing from last one week with no luck.
When I am trying to add/Update milestones in the Features. I am getting the error as "Could not read: Could not read referenced object null". My code is as follows:-
public DynamicJsonObject UpdateFeaturesbyName(string fea, string bFun)
{
//getting list of Feature.
Request feat = new Request("PortfolioItem/Feature");
feat.Query = new Query("Name", Query.Operator.Equals, fea);
QueryResult TCSResults = restApi.Query(feat);
foreach (var res in TCSResults.Results)
{
var steps = res["Milestones"];
Request tsteps = new Request(steps);
QueryResult tstepsResults = restApi.Query(tsteps);
foreach (var item in tstepsResults.Results)
{
}
if (res.Name == fea)
{
var targetFeature = TCSResults.Results.FirstOrDefault();
DynamicJsonObject toUpdate = new DynamicJsonObject();
//toUpdate["Milestones"] = "";
// CreateResult createResult = restApi.Create(steps._ref, toUpdate);
// String contentRef = steps._ref;
//String contentRef = createResult._ref;
string[] value = null;
string AccCri = string.Empty;
if (!string.IsNullOrWhiteSpace(bFun))
{
value = bFun.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
foreach (string item in value)
{
//if (string.IsNullOrWhiteSpace(AccCri))
// AccCri = item;
//else
// AccCri = AccCri + "<br/>" + item;
if (!string.IsNullOrWhiteSpace(item))
{
//Query for Milestone.
Request ms = new Request("Milestone");
ms.Fetch = new List<string>() { "Name", "ObjectID" };
ms.Query = new Query("Name", Query.Operator.Equals, item);
QueryResult msResults = restApi.Query(ms);
var targetMLResult = msResults.Results.FirstOrDefault();
long MLOID = targetMLResult["ObjectID"];
DynamicJsonObject tarML = restApi.GetByReference("Milestone", MLOID, "Name", "_ref", "DisplayColor");
DynamicJsonObject targetML = new DynamicJsonObject();
targetML["Name"] = tarML["Name"];
//targetML["_ref"] = tarML["_ref"];
targetML["_ref"] = "/milestone/" + Convert.ToString(MLOID);
targetML["DisplayColor"] = tarML["DisplayColor"];
// Grab collection of existing Milestones.
var existingMilestones = targetFeature["Milestones"];
long targetOID = targetFeature["ObjectID"];
// Milestones collection on object is expected to be a System.Collections.ArrayList.
var targetMLArray = existingMilestones;
var tagList2 = targetMLArray["_tagsNameArray"];
tagList2.Add(targetML);//
//targetMLArray.Add(targetML);
targetMLArray["_tagsNameArray"] = tagList2;
toUpdate["Milestones"] = targetMLArray;
OperationResult updateResult = restApi.Update(res._ref, toUpdate);
bool resp = updateResult.Success;
}
}
}
//toUpdate["c_AcceptanceCriteria"] = AccCri;
//OperationResult updateResult = restApi.Update(res._ref, toUpdate);
}
}
var features = TCSResults.Results.Where(p => p.Name == fea).FirstOrDefault();
var featuresref = features._ref;
return features;
}
Now that v3.1.1 of the toolkit has been released you can use the AddToCollection method to do this.
Otherwise, you can still always just update the full collection. The value should be an arraylist of objects with _ref properties.
Check out this example (which adds tasks to defects, but should be very similar to what you're doing): https://github.com/RallyCommunity/rally-dot-net-rest-apps/blob/master/UpdateTaskCollectionOnDefect/addTaskOnDefect.cs
I have an Amazon EC2 instance and I need to be able to create an AMI (image) from it programmatically. I'm trying the following:
CreateImageRequest rq = new CreateImageRequest();
rq.InstanceId = myInstanceID;
rq.Name = instance.KeyName;
rq.Description = "stam";
rq.NoReboot = true;
IAmazonEC2 ec2;
AmazonEC2Config ec2conf = new AmazonEC2Config();
ec2 = AWSClientFactory.CreateAmazonEC2Client(ec2conf);
// CreateImageResponse imageResp;
Amazon.EC2.Model.CreateImageResponse imageResp = null;
try
{
imageResp = ec2.CreateImage(rq);
}
catch (AmazonServiceException ase)
{
MessageBox.Show(ase.Message);
}
The result is always an AmazonServiceException saying that there is a NameResolutionFailure.
How do I overcome this? I tried different possible "name" possibilities but cannot find the right one.
string amiID = ConfigurationManager.AppSettings[AmazonConstants.AwsImageId];
string keyPairName = ConfigurationManager.AppSettings[AmazonConstants.AwsKeyPair];
List<string> groups = new List<string>() { ConfigurationManager.AppSettings[AmazonConstants.AwsSecurityGroupId] };
var launchRequest = new RunInstancesRequest()
{
ImageId = amiID,
InstanceType = ConfigurationManager.AppSettings[AmazonConstants.AwsInstanceType],
MinCount = 1,
MaxCount = 1,
KeyName = keyPairName,
SecurityGroupIds = groups,
SubnetId = ConfigurationManager.AppSettings[AmazonConstants.AwsSubnetId]
};
RunInstancesResponse runInstancesResponse = amazonEc2client.RunInstances(launchRequest);
RunInstancesResult runInstancesResult = runInstancesResponse.RunInstancesResult;
Reservation reservation = runInstancesResult.Reservation;
Problem eventually solved!
it turned out thyat some codelines were doing things which were already done already and removing this part:
IAmazonEC2 ec2;
AmazonEC2Config ec2conf = new AmazonEC2Config();
ec2 = AWSClientFactory.CreateAmazonEC2Client(ec2conf);
// CreateImageResponse imageResp;
Amazon.EC2.Model.CreateImageResponse imageResp = null;
Made things clearer and no wrong repetitions happened! Now it works!
I'm trying to specify a Product/Service list item for invoice line items of invoices that I am importing to QuickBooks Online (QBO) company file and I am getting an error.
Error I receive is:
Intuit.Ipp.Exception.IdsException: InternalServerError ---> Intuit.Ipp.Exception.EndpointNotFoundException: Ids service endpoint was not found.
The exception doesn't give any further breakdown as to if what I'm doing is valid or not.
My unit test method:
[TestMethod()]
public void CreateTest()
{
Entities.Invoice invoice = new Entities.Invoice();
invoice.ReferenceId = Guid.NewGuid().ToString("N").Substring(0, 10);
invoice.CreatedDate = DateTime.Now;
invoice.CustomerId = 1;
invoice.LineItems.Add(new InvoiceLine() { ItemName = "Initial Funding", Description = "Initial Funding", Amount = 5500 });
invoice.LineItems.Add(new InvoiceLine() { ItemName = "Lien Fee", Description = "Lien Fee", Amount = 100 });
IPPRestProfile restProfile = new IPPRestProfile(realmId, accessToken, accessTokenSecret, Intuit.Ipp.Core.IntuitServicesType.QBO, consumerKey, consumerSecret);
IPP.Invoices target = new IPP.Invoices(restProfile);
Intuit.Ipp.Data.Invoice actual = target.Create(invoice);
if (actual != null)
{
Console.WriteLine("QB Invoice ID: {0}", actual.Id);
Console.WriteLine("QB Sync Token: {0}", actual.SyncToken);
Console.WriteLine("================================================");
ObjectDumper.Write(actual, 4);
}
}
The method that the unit test calls:
public Intuit.Ipp.Data.Invoice Create(Entities.Invoice invoice)
{
// Check pre-conditions
if (invoice == null) { throw new ArgumentException("Invoice object is required.", "invoice"); }
var qboInvoice = new Intuit.Ipp.Data.Invoice();
BuildInvoiceEntity(qboInvoice, invoice);
return _Service.Add(qboInvoice) as Intuit.Ipp.Data.Invoice;
}
And finally the build invoice method:
private void BuildInvoiceEntity(Intuit.Ipp.Data.Invoice qboInvoice, Entities.Invoice invoice)
{
if (qboInvoice != null && invoice != null)
{
IQuickBooksHeader header = invoice as IQuickBooksHeader;
if (String.IsNullOrEmpty(header.Id))
{
qboInvoice.DocNumber = invoice.ReferenceId;
qboInvoice.TxnDate = invoice.CreatedDate;
qboInvoice.TxnDateSpecified = true;
// Customer
qboInvoice.CustomerRef = new ReferenceType()
{
type = objectNameEnumType.Customer.ToString(),
Value = invoice.CustomerId.ToString()
};
// AR Account
qboInvoice.ARAccountRef = new ReferenceType()
{
type = objectNameEnumType.Account.ToString(),
name = "Accounts Receivable"
};
}
if (invoice.LineItems.Count > 0)
{
Intuit.Ipp.Data.Line[] invoiceLineCollection = new Intuit.Ipp.Data.Line[invoice.LineItems.Count];
for (int i = 0; i < invoice.LineItems.Count; i++)
{
var line = invoice.LineItems[i];
var qboInvoiceLine = new Intuit.Ipp.Data.Line()
{
Amount = line.Amount,
AmountSpecified = true,
Description = line.Description,
DetailType = LineDetailTypeEnum.SalesItemLineDetail,
DetailTypeSpecified = true,
AnyIntuitObject = new SalesItemLineDetail()
{
ItemRef = new ReferenceType()
{
name = line.ItemName,
},
ItemElementName = ItemChoiceType.UnitPrice,
AnyIntuitObject = line.Amount
}
};
invoiceLineCollection[i] = qboInvoiceLine;
}
qboInvoice.Line = invoiceLineCollection;
}
}
}
If I remove this piece of code from my build method:
ItemRef = new ReferenceType()
{
name = line.ItemName,
},
the invoice is successfully added with the default "Services" list item for the Product/Service of the invoice line items.
The online documentation for the IPP .NET SDK V3 is vague on what to specify for ReferenceType. What is wrong about just specifying the name of the list item? If I'm wrong about how I'm trying to specify a Product/Service list item for invoice line items, what is the correct way?
After days of researching, I never did find an answer as to why I can't just use the name like I wanted to, even though it works that way when specifying an AccountRef. But I digress, here is my solution:
// Hold a collection of QBO items
private ReadOnlyCollection<Item> _Items;
// I set the collection in the constructor only once
public Invoices(Entities.IPPRestProfile restProfile)
{
if (restProfile == null)
throw new ArgumentException("IPPRestProfile object is required.", "restProfile");
OAuthRequestValidator oAuthValidator = new OAuthRequestValidator(restProfile.OAuthAccessToken, restProfile.OAuthAccessTokenSecret,
restProfile.ConsumerKey, restProfile.ConsumerSecret);
ServiceContext context = new ServiceContext(restProfile.RealmId, restProfile.DataSource, oAuthValidator);
_Service = new DataService(context);
_Items = (new QueryService<Item>(context)).ExecuteIdsQuery("SELECT * FROM Item", QueryOperationType.query);
}
Whenever I build my invoice I query the collection for the Id of the item by name:
private void BuildInvoiceEntity(Intuit.Ipp.Data.Invoice qboInvoice, Entities.Invoice invoice)
{
...
// Get the Id value of the item by name
string itemTypeId = _Items.Where(o => o.Name == line.ItemName).FirstOrDefault().Id;
// Specify the Id value in the item reference of the SalesItemLineDetail
var qboInvoiceLine = new Intuit.Ipp.Data.Line()
{
Amount = (decimal)amount,
AmountSpecified = true,
Description = line.Description,
DetailType = LineDetailTypeEnum.SalesItemLineDetail,
DetailTypeSpecified = true,
AnyIntuitObject = new SalesItemLineDetail()
{
ItemRef = new ReferenceType() { Value = itemTypeId },
AnyIntuitObject = (decimal)line.Rate,
ItemElementName = ItemChoiceType.UnitPrice
}
};
...
}
Hopefully this helps point someone in the right direction to a possible better solution.
I'm new to eBay's API, and I'm trying to make an AddItem call. However, I keep getting an error:
Domestic shipping is required if AutoPay is specified
I copied the code in line-for-line from the SDK example code and it compiles and runs just fine, so I feel like there might have been some sort of change on eBay's end.
Here's some of my code:
static ItemType BuildItem()
{
ItemType item = new ItemType();
item.AutoPaySpecified = false;
item.Title = "Test Item";
item.Description = "eBay SDK sample test item";
item.ListingType = ListingTypeCodeType.Chinese;
item.Currency = CurrencyCodeType.USD;
item.StartPrice = new AmountType();
item.StartPrice.Value = 20;
item.StartPrice.currencyID = CurrencyCodeType.USD;
item.ListingDuration = "Days_3";
item.Location = "San Jose";
item.Country = CountryCodeType.US;
CategoryType category = new CategoryType();
category.CategoryID = "11104";
item.PrimaryCategory = category;
item.Quantity = 1;
item.ConditionID = 1000;
item.ItemSpecifics = buildItemSpecifics();
item.PaymentMethods = new BuyerPaymentMethodCodeTypeCollection();
item.PaymentMethods.AddRange(
new BuyerPaymentMethodCodeType[] { BuyerPaymentMethodCodeType.PayPal }
);
item.PayPalEmailAddress = "me#ebay.com";
item.DispatchTimeMax = 1;
item.ShippingDetails = BuildShippingDetails();
item.ReturnPolicy = new ReturnPolicyType();
item.ReturnPolicy.ReturnsAcceptedOption = "ReturnsAccepted";
AmountType amount = new AmountType();
amount.Value = 2.8;
amount.currencyID = CurrencyCodeType.USD;
item.StartPrice = amount;
return item;
}
static NameValueListTypeCollection buildItemSpecifics()
{
NameValueListTypeCollection nvCollection = new NameValueListTypeCollection();
NameValueListType nv1 = new NameValueListType();
nv1.Name = "Platform";
StringCollection nv1Col = new StringCollection();
String[] strArr1 = new string[] { "Microsoft Xbox 360" };
nv1Col.AddRange(strArr1);
nv1.Value = nv1Col;
NameValueListType nv2 = new NameValueListType();
nv2.Name = "Genre";
StringCollection nv2Col = new StringCollection();
String[] strArr2 = new string[] { "Simulation" };
nv2Col.AddRange(strArr2);
nv2.Value = nv2Col;
nvCollection.Add(nv1);
nvCollection.Add(nv2);
return nvCollection;
}
static ShippingDetailsType BuildShippingDetails()
{
ShippingDetailsType sd = new ShippingDetailsType();
sd.ApplyShippingDiscount = true;
AmountType amount = new AmountType();
amount.Value = 2.8;
amount.currencyID = CurrencyCodeType.USD;
sd.PaymentInstructions = "eBay .Net SDK test instructions";
// shipping type and shipping service options
sd.ShippingType = ShippingTypeCodeType.Flat;
ShippingServiceOptionsType shippingOptions = new ShippingServiceOptionsType();
shippingOptions.ShippingService = ShippingServiceCodeType.ShippingMethodStandard.ToString();
amount = new AmountType();
amount.Value = 1;
amount.currencyID = CurrencyCodeType.USD;
shippingOptions.ShippingServiceAdditionalCost = amount;
shippingOptions.ShippingServicePriority = 1;
amount = new AmountType();
amount.Value = 1.0;
amount.currencyID = CurrencyCodeType.USD;
shippingOptions.ShippingInsuranceCost = amount;
sd.ShippingServiceOptions = new ShippingServiceOptionsTypeCollection(
new ShippingServiceOptionsType[] { shippingOptions }
);
return sd;
}
I've tried to set item.AutoPay = false; and item.AutoPaySpecified = false; - neither of those seem to do anything. I've searched the docs for any reference to something about domestic shipping, but I'm not finding anything.
Does anyone have any idea why this might be happening?
Your shippingOptions field is missing a ShippingServiceCost, try changing the line:
shippingOptions.ShippingServiceAdditionalCost = amount;
to
shippingOptions.ShippingServiceCost = amount;
or add an assignment to ShippingServiceCost.
"Domestic shipping is required if AutoPay is specified" seems to mean that some conditional (i.e. depending on the type of shipping) field is missing from the shipping options. I ran into the same error when trying to add all the necessary fields for calculated shipping - without all the fields, eBay interprets it as flat-rate shipping that is missing the ShippingServiceCost field.