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.
Related
I am getting the list of Invoice details by Invoice Id.
Now i want to update AmountDue by respective Invoice Id.
i tried by below code:
ByInvoiceId.AmountDue = Convert.ToDecimal(100.00);
public_app_api.Invoices.Update(ByInvoiceId);
but..Error as
"A validation exception occurred"
What's the reason behind and How to solve this?
There are a number of ways to change the amount due on an invoice, however changing the value of the property directly is not one of them.
The amount due on an invoice is driven by the totals of the line items on the invoice minus the total of payments and allocated credit. One way to change the amount due is to change the values of your line items or add/remove some line items. You won't be able to change the invoice if it has been paid/partially paid.
Another way you could change the amount due on an invoice is to add a payment against the invoice or allocate credit from a credit note, prepayment, or overpayment to the invoice
In addition to MJMortimer's answer.
You can't change the line amounts on an AUTHORISED invoice via the c# API. You have to VOID the invoice and create a new one. You can however update DRAFT and SUBMITTED ones by updating the line items.
EDIT: Here is some code to help you. This is create invoice code, but amending one is essentially the same.
public XeroTransferResult CreateInvoices(IEnumerable<InvoiceModel> invoices, string user, string status)
{
_user = XeroApiHelper.User(user);
var invoicestatus = InvoiceStatus.Draft;
if (status == "SUBMITTED")
{
invoicestatus = InvoiceStatus.Submitted;
}
else if (status == "AUTHORISED")
{
invoicestatus = InvoiceStatus.Authorised;
}
var api = XeroApiHelper.CoreApi();
var xinvs = new List<Invoice>();
foreach (var inv in invoices)
{
var items = new List<LineItem>();
foreach (var line in inv.Lines)
{
decimal discount = 0;
if (line.PriceBeforeDiscount != line.Price)
{
discount = (decimal)(1 - line.Price / line.PriceBeforeDiscount) * 100;
}
items.Add(new LineItem
{
AccountCode = line.AccountCode,
Description = line.PublicationName != "N/A" ? line.PublicationName + " - " + line.Description : line.Description,
TaxAmount = (decimal)line.TaxAmount,
Quantity = 1,
UnitAmount = (decimal)line.PriceBeforeDiscount,
DiscountRate = discount,
TaxType = line.XeroCode,
ItemCode = line.ItemCode
});
}
var person = inv.Company.People.FirstOrDefault(p => p.IsAccountContact);
if (person == null)
{
person = inv.Company.People.FirstOrDefault(p => p.IsPrimaryContact);
}
var ninv = new Invoice
{
Number = inv.ClientInvoiceId,
Type = InvoiceType.AccountsReceivable,
Status = invoicestatus,
Reference = inv.Reference,
Contact = new Contact
{
Name = inv.Company.OrganisationName,
//ContactNumber = "MM" + inv.Company.CompanyId.ToString(),
FirstName = person.FirstName,
LastName = person.LastName,
EmailAddress = person.Email,
Phones = new List<Phone>()
{
new Phone {PhoneNumber = person.Telephone, PhoneType = PhoneType.Default},
new Phone {PhoneNumber = person.Mobile, PhoneType = PhoneType.Mobile}
},
Addresses = new List<Address>
{ new Address
{
//AttentionTo = inv.Company.People.FirstOrDefault(p => p.IsAccountContact) == null
//? inv.Company.People.FirstOrDefault(p=> p.IsPrimaryContact).FullName
//: inv.Company.People.FirstOrDefault(p => p.IsAccountContact).FullName,
//AddressLine1 = inv.Company.OrganisationName,
AddressLine1 = inv.Company.Address.Address1,
AddressLine2 = inv.Company.Address.Address2 ?? "",
AddressLine3 = inv.Company.Address.Address3 ?? "",
Region = inv.Company.Address.CountyState,
City = inv.Company.Address.TownCity,
PostalCode = inv.Company.Address.PostCode,
}
}
},
AmountDue = (decimal)inv.TotalAmount,
Date = inv.InvoiceDate,
DueDate = inv.DueDate,
LineItems = items,
LineAmountTypes = LineAmountType.Exclusive
};
if (SessionContext.TransferContactDetailsToXero == false)
{
ninv.Contact = new Contact
{
Id = inv.Company.XeroId ?? Guid.Empty,
Name = inv.Company.OrganisationName
};
}
xinvs.Add(ninv);
}
var success = true;
var xinvresult = new List<Invoice>();
try
{
api.SummarizeErrors(false);
xinvresult = api.Invoices.Create(xinvs).ToList();
}
catch (ValidationException ex)
{
// Something's gone wrong
}
foreach (var inv in xinvresult)
{
var mminvoice = invoices.FirstOrDefault(i => i.ClientInvoiceId == inv.Number);
if (inv.Errors != null && inv.Errors.Count > 0)
{
success = false;
if (mminvoice != null)
{
var errors = new List<XeroError>();
foreach (var err in inv.Errors)
{
errors.Add(new XeroError { ErrorDescription = err.Message });
}
mminvoice.XeroErrors = errors;
}
}
else
{
mminvoice.XeroTransferDate = DateTime.Now;
mminvoice.XeroId = inv.Id;
mminvoice.XeroErrors = new List<XeroError>();
}
}
return new XeroTransferResult
{
Invoices = invoices,
Success = success
};
}
For customer with existing payment profile id(Saved credit card) we are using "createCustomerProfileTransactionController" as follow for authorization.
public createCustomerProfileTransactionResponse AuthorizePaymentProfile(int customerProfileId, int customerPaymentProfileId, decimal amount)
{
createCustomerProfileTransactionResponse response = null;
ApiOperationBase<ANetApiRequest, ANetApiResponse>.RunEnvironment = environment;
// define the merchant information (authentication / transaction id)
ApiOperationBase<ANetApiRequest, ANetApiResponse>.MerchantAuthentication = new merchantAuthenticationType()
{
name = apiLoginID,
ItemElementName = ItemChoiceType.transactionKey,
Item = apiTransactionKey,
};
//construct request
var request = new createCustomerProfileTransactionRequest
{
merchantAuthentication = new merchantAuthenticationType
{
name = apiLoginID,
ItemElementName = ItemChoiceType.transactionKey,
Item = apiTransactionKey
},
transaction = new profileTransactionType
{
Item = new profileTransAuthOnlyType
{
customerProfileId = customerProfileId.ToString(),
customerPaymentProfileId = customerPaymentProfileId.ToString(),
amount = amount
}
},
extraOptions = "x_duplicate_window=1"
};
//Prepare Request
var controller = new createCustomerProfileTransactionController(request);
controller.Execute();
//Send Request to EndPoint
response = controller.GetApiResponse();
return response;
}
And for customer without existing payment profile id we using "createTransactionRequest" as follow for authorization.
public createTransactionResponse AuthorizeOneTimePayment(Card cardInfo, decimal amount)
{
createTransactionResponse response = null;
ApiOperationBase<ANetApiRequest, ANetApiResponse>.RunEnvironment = environment;
//define the merchant information (authentication / transaction id)
ApiOperationBase<ANetApiRequest, ANetApiResponse>.MerchantAuthentication = new merchantAuthenticationType()
{
name = apiLoginID,
ItemElementName = ItemChoiceType.transactionKey,
Item = apiTransactionKey,
};
var creditCard = new creditCardType
{
cardNumber = cardInfo.CardNumber,// "4111111111111111",
expirationDate = cardInfo.ExpirationDate// "0718"
//cardCode=cardInfo.VerificationCode
};
//standard api call to retrieve response
var paymentType = new paymentType { Item = creditCard };
string firstName = string.Empty;
string lastName = string.Empty;
if (!string.IsNullOrWhiteSpace(cardInfo.BillingName))
{
string[] name = GetBillName(cardInfo.BillingName);
firstName = name[0];
lastName = name[1];
}
var transactionRequest = new transactionRequestType
{
transactionType = transactionTypeEnum.authOnlyTransaction.ToString(), // authorize only
amount = amount,
payment = paymentType,
billTo = new customerAddressType
{
firstName = firstName,
lastName = lastName,
address = cardInfo.BillingAddress,
city = cardInfo.BillingCity,
state = cardInfo.BillingState,
zip = cardInfo.BillingZipCode
}
};
var request = new createTransactionRequest { transactionRequest = transactionRequest };
// instantiate the controller that will call the service
var controller = new createTransactionController(request);
controller.Execute();
// get the response from the service (errors contained if any)
response = controller.GetApiResponse();
return response;
}
And following same technique for capture and void a transaction.
My question is can we use "createTransactionRequest" for all transaction like authorize, capture and void a transaction for both customer having payment profile id and one time customer.
I could find any clue in authorize.net on line documentation. Please guide us how to do that.
Yes, you can use createTransactionRequest for Auth/Capture, Auth Only, Prior Auth and Capture, Void and Refund by changing the transactionRequestType and paymentType.
For anyone with the same question, like me, here is the answer.
Note that Order is optional, and obviously profile is optional.
...
var transactionRequest = new transactionRequestType {
transactionType = transactionTypeEnum.authOnlyTransaction.ToString(),
amount = amount,
order = new orderType { invoiceNumber = OrderID, description = desc },
profile = getCustomerPaymentProfile(CustomerProfileId, creditProfileID)
};
...
private customerProfilePaymentType getCustomerPaymentProfile(string CustomerProfileId, string creditProfileID) {
return new customerProfilePaymentType {
customerProfileId = CustomerProfileId,
paymentProfile = new paymentProfile { paymentProfileId = creditProfileID }
};
}
I am using C# implementation of netsuite api from web reference com.netsuite.webservices
I released filter fileSearch.basic by name (you can see it commented) it is working fine.
Please help to write function to achieve all attached files for current user. Something is wrong in this code, it filters nothing and showing me all files as it is without any filter. Please help me.
public static void GetFileAttachmentByCustomerId(string customerId)
{
using (NetSuiteService netSuiteService = GetNetSuiteService())
{
FileSearch fileSearch = new FileSearch();
// this works fine (filter files by name)
//SearchStringField nameSearchParams = new SearchStringField
//{
// #operator = SearchStringFieldOperator.contains,
// operatorSpecified = true,
// searchValue = "some name",
//};
//fileSearch.basic = new FileSearchBasic() { name = nameSearchParams };
// this code not filter files at all
{
RecordRef nsCustomerRef = new RecordRef
{
internalId = customerId,
type = RecordType.customer,
typeSpecified = true,
};
SearchMultiSelectField shopperSearchParam = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new RecordRef[] { nsCustomerRef }
};
fileSearch.shopperJoin = new CustomerSearchBasic { internalId = shopperSearchParam };
}
SearchResult result = netSuiteService.search(fileSearch);
// Get connected objects
{
Customer customer = GetCustomerById(netSuiteService, customerId);
Account account = GetAccountById(netSuiteService, "301395"); //
Folder folder = GetFolderById(netSuiteService, "3962");
}
File file = (File)result.recordList.First();
byte[] fileContent = GetFileContentByInternalId(file.internalId);
}
}
.
Try this:
var nsCustomerRef = new RecordRef
{
internalId = "4",
type = RecordType.employee,
typeSpecified = true,
};
var currentUser = new SearchMultiSelectField()
{
operatorSpecified = true,
#operator = SearchMultiSelectFieldOperator.anyOf,
searchValue = new List<RecordRef>() {nsCustomerRef}.ToArray()
};
var fileSearchBasic = new FileSearchBasic() {owner = currentUser};
var fileSearch = new FileSearch() { basic = fileSearchBasic };
var result = netSuiteService.search(fileSearch);
var file = (File)result.recordList.First();
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 downloaded an example application for using some web services with an online system.
I am not sure if all code below is needed but it is what I got and what I am trying to do is to use the search function.
I start by calling searchCustomer with an ID I have:
partnerRef.internalId = searchCustomer(customerID);
And the code for searchCustomer:
private string searchCustomer(string CustomerID)
{
string InternalID = "";
CustomerSearch custSearch = new CustomerSearch();
CustomerSearchBasic custSearchBasic = new CustomerSearchBasic();
String nameValue = CustomerID;
SearchStringField entityId = null;
entityId = new SearchStringField();
entityId.#operator = SearchStringFieldOperator.contains;
entityId.operatorSpecified = true;
entityId.searchValue = nameValue;
custSearchBasic.entityId = entityId;
String statusKeysValue = "";
SearchMultiSelectField status = null;
if (statusKeysValue != null && !statusKeysValue.Trim().Equals(""))
{
status = new SearchMultiSelectField();
status.#operator = SearchMultiSelectFieldOperator.anyOf;
status.operatorSpecified = true;
string[] nskeys = statusKeysValue.Split(new Char[] { ',' });
RecordRef[] recordRefs = new RecordRef[statusKeysValue.Length];
for (int i = 0; i < nskeys.Length; i++)
{
RecordRef recordRef = new RecordRef();
recordRef.internalId = nskeys[i];
recordRefs[i] = recordRef;
}
status.searchValue = recordRefs;
custSearchBasic.entityStatus = status;
}
custSearch.basic = custSearchBasic;
SearchResult response = _service.search(custSearch);
if (response.status.isSuccess)
{
processCustomerSearchResponse(response);
if (seachMoreResult.status.isSuccess)
{
processCustomerSearchResponse(seachMoreResult);
return InternalID;
}
else
{
_out.error(getStatusDetails(seachMoreResult.status));
}
}
else
{
_out.error(getStatusDetails(response.status));
}
return InternalID;
}
In the code above processCustomerSearchResponse gets called
processCustomerSearchResponse(response);
The code for this function is:
public string processCustomerSearchResponse(SearchResult response)
{
string InternalID = "";
Customer customer;
customer = (Customer)records[0];
InternalID = customer.internalId;
return InternalID;
}
What the original code did was to write some output in the console but I want to return the InternalID instead. When I debug the application InternalID in processCustomerSearchResponse contains the ID I want but I don't know how to pass it to searchCustomer so that function also returns the ID. When I debug searchCustomer InternalID is always null. I am not sure on how to edit the code under response.status.isSuccess
to return the InternalID, any ideas?
Thanks in advance.
When you call processCustomerSearchResponse(response);, you need to store the return value in memory.
Try modifying your code like this:
InternalID = processCustomerSearchResponse(response);