Reputation: 74
I need to add new customers to QuickBooks Online from C#.
I'm struggling to find any working end-to-end samples. Based on this: how to add invoice or sales receipt quickbooks rest api v3.0 I need accessToken, accessTokenSecret, consumerKey, consumerKeySecret, realmId.
Based on this: IPP .NET SDK for QuickBooks v3.0 Create Invoice Error - Bad Request I need accessToken, accessTokenSecret, consumerKey,consumerKeySecret, appToken, companyId.
I only have App Token, Oauth Consumer Key, OAuth consumer Secret, possibly realmId (App ID)
Where do I find the access token, access token secret, realm id and/or company ID?
I don't have a reputation to post images, but the developer settings page on https://developer.intuit.com/Application/Manage/IA?appId=XXX shows the following informations:
App ID: what is this? realm Id, company id?
App Token,OAuth Consumer Key,OAuth Consumer Secret
I'm using the QuickBooks Online REST API v3.0 for .Net
The code follows:
var customer = new Customer();
customer.GivenName = txtFirstName.Text;
customer.FamilyName = txtLastName.Text;
customer.MiddleName = txtMiddleName.Text;
customer.CompanyName = txtCompany.Text;
customer.PrimaryEmailAddr = new EmailAddress() { Address = txtEmail.Text, Default = true };
customer.PrimaryPhone = new TelephoneNumber() { FreeFormNumber = txtPrimaryPhone.Text };
OAuthRequestValidator oauthValidator = new OAuthRequestValidator(accessToken, accessTokenSecret, consumerKey, consumerSecret);
ServiceContext context = new ServiceContext(accessToken, consumerKey, IntuitServicesType.QBO, oauthValidator);
DataService service = new DataService(context);
var c = service.Add(customer);
// do something with c.Id
Upvotes: 2
Views: 5538
Reputation: 84
I'm new to the QuickBooks Online API and had trouble getting the code working for a .NET 5.0 WPF application, so here's some sample code that worked for me:
Install the required QBO dependencies:
WPF Window C# Code:
using Intuit.Ipp.Data;
public partial class MainWindow : Window
{
QuickbooksOnline qbo = new QuickbooksOnline();
public MainWindow()
{
qbo.FindCustomerResponse += HandleFindQBOCustomerResponse;
qbo.FindInvoiceResponse += HandleFindQBOInvoiceResponse;
qbo.FindCreditMemoResponse += HandleFindQBOCreditMemoResponse;
}
private void btnTest_Click(object sender, RoutedEventArgs e)
{
//Get IDs to test from QBO website URL when accessing a record
string customerId = "737";
qbo.FindCustomer(customerId);
string invoiceId = "3198";
qbo.FindInvoice(invoiceId);
string creditMemoId = "3077";
qbo.FindCreditMemo(creditMemoId);
}
private void HandleFindQBOCustomerResponse(object sender, Intuit.Ipp.Data.Customer customer)
{
if (customer == null)
{
MessageBox.Show("Customer not found");
}
else
{
MessageBox.Show(customer.DisplayName);
}
}
private void HandleFindQBOInvoiceResponse(object sender, Intuit.Ipp.Data.Invoice invoice)
{
if (invoice == null)
{
MessageBox.Show("Invoice not found");
}
else
{
MessageBox.Show(invoice.TotalAmt.ToString());
}
}
private void HandleFindQBOCreditMemoResponse(object sender, Intuit.Ipp.Data.CreditMemo creditMemo)
{
if (creditMemo == null)
{
MessageBox.Show("CreditMemo not found");
}
else
{
MessageBox.Show(creditMemo.TotalAmt.ToString());
}
}
}
Quickbooks Online Class:
using System;
using System.Threading.Tasks;
using Intuit.Ipp.Core;
using Intuit.Ipp.Data;
using Intuit.Ipp.Security;
using Intuit.Ipp.DataService;
using System.Windows;
using System.Reflection;
using Intuit.Ipp.OAuth2PlatformClient;
class QuickbooksOnline
{
//Get this information from the OAuth 2.0 Playground: https://developer.intuit.com/app/developer/playground
private string ClientId = "";
private string ClientSecret = "";
private string RedirectURI = "https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl";
private string RealmId = "";
private string AccessToken = "";
private string RefreshToken = "";
private string QBOBaseURL = "https://quickbooks.api.intuit.com/";
private string QBOMinorVersion = "55";
private OAuth2Client OAuthClient;
public event EventHandler<Intuit.Ipp.Data.Customer> FindCustomerResponse;
public event EventHandler<Intuit.Ipp.Data.Invoice> FindInvoiceResponse;
public event EventHandler<Intuit.Ipp.Data.CreditMemo> FindCreditMemoResponse;
public QuickbooksOnline()
{
this.OAuthClient = new OAuth2Client(ClientId, ClientSecret, RedirectURI, "production");
}
public async void FindCustomer(string customerId)
{
OAuth2RequestValidator oAuthValidator = new OAuth2RequestValidator(AccessToken);
ServiceContext serviceContext = new ServiceContext(RealmId, IntuitServicesType.QBO, oAuthValidator);
serviceContext.IppConfiguration.BaseUrl.Qbo = QBOBaseURL;
serviceContext.IppConfiguration.MinorVersion.Qbo = QBOMinorVersion;
DataService service = new DataService(serviceContext);
Customer customer = new Customer();
customer.Id = customerId;
service.OnFindByIdAsyncCompleted += HandlePrivateFindByIdResponse;
service.FindByIdAsync(customer);
}
public void FindInvoice(string invoiceId)
{
OAuth2RequestValidator oAuthValidator = new OAuth2RequestValidator(AccessToken);
ServiceContext serviceContext = new ServiceContext(RealmId, IntuitServicesType.QBO, oAuthValidator);
serviceContext.IppConfiguration.BaseUrl.Qbo = QBOBaseURL;
serviceContext.IppConfiguration.MinorVersion.Qbo = QBOMinorVersion;
DataService service = new DataService(serviceContext);
Intuit.Ipp.Data.Invoice invoice = new Intuit.Ipp.Data.Invoice();
invoice.Id = invoiceId;
service.OnFindByIdAsyncCompleted += HandlePrivateFindByIdResponse;
service.FindByIdAsync(invoice);
}
public void FindCreditMemo(string creditMemoId)
{
OAuth2RequestValidator oAuthValidator = new OAuth2RequestValidator(AccessToken);
ServiceContext serviceContext = new ServiceContext(RealmId, IntuitServicesType.QBO, oAuthValidator);
serviceContext.IppConfiguration.BaseUrl.Qbo = QBOBaseURL;
serviceContext.IppConfiguration.MinorVersion.Qbo = QBOMinorVersion;
DataService service = new DataService(serviceContext);
CreditMemo creditMemo = new CreditMemo();
creditMemo.Id = creditMemoId;
service.OnFindByIdAsyncCompleted += HandlePrivateFindByIdResponse;
service.FindByIdAsync(creditMemo);
}
private async void HandlePrivateFindByIdResponse(object sender, CallCompletedEventArgs<IEntity> entity)
{
// The Intuit.Ipp.DataService.AsyncService class is not public, so that to use reflection
// to get the requestedEntity object and determine the sender type.
// This is useful when the authToken has expired and after refreshing the tokens
// the request has to be sent again.
string entityType = sender.GetType().GetField("requestedEntity", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sender).GetType().FullName;
if (entity.Error != null && entity.Error.Message.Equals("Unauthorized-401"))
{
if (await RefreshTokens())
{
switch (entityType)
{
case "Intuit.Ipp.Data.Customer":
Customer senderCustomer = (Customer)sender.GetType().GetField("requestedEntity", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sender);
FindCustomer(senderCustomer.Id);
break;
case "Intuit.Ipp.Data.Invoice":
Intuit.Ipp.Data.Invoice senderInvoice = (Intuit.Ipp.Data.Invoice)sender.GetType().GetField("requestedEntity", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sender);
FindInvoice(senderInvoice.Id);
break;
case "Intuit.Ipp.Data.CreditMemo":
Intuit.Ipp.Data.CreditMemo senderCreditMemo = (Intuit.Ipp.Data.CreditMemo)sender.GetType().GetField("requestedEntity", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sender);
FindCreditMemo(senderCreditMemo.Id);
break;
}
}
else
{
MessageBox.Show("Error refreshing tokens.");
}
}
else if (entity.Entity != null)
{
switch (entity.Entity.GetType().FullName)
{
case "Intuit.Ipp.Data.Customer":
if (FindCustomerResponse != null)
{
FindCustomerResponse(this, entity.Entity as Intuit.Ipp.Data.Customer);
}
break;
case "Intuit.Ipp.Data.Invoice":
if (FindInvoiceResponse != null)
{
FindInvoiceResponse(this, entity.Entity as Intuit.Ipp.Data.Invoice);
}
break;
case "Intuit.Ipp.Data.CreditMemo":
if (FindCreditMemoResponse != null)
{
FindCreditMemoResponse(this, entity.Entity as Intuit.Ipp.Data.CreditMemo);
}
break;
}
}
else if (entity.Entity == null)
{
switch (entityType)
{
case "Intuit.Ipp.Data.Customer":
if (FindCustomerResponse != null)
{
FindCustomerResponse(this, null);
}
break;
case "Intuit.Ipp.Data.Invoice":
if (FindInvoiceResponse != null)
{
FindInvoiceResponse(this, null);
}
break;
case "Intuit.Ipp.Data.CreditMemo":
if (FindCreditMemoResponse != null)
{
FindCreditMemoResponse(this, null);
}
break;
}
}
}
private async Task<bool> RefreshTokens()
{
var tokenResp = await OAuthClient.RefreshTokenAsync(RefreshToken);
if (tokenResp.AccessToken != null && tokenResp.RefreshToken != null)
{
this.AccessToken = tokenResp.AccessToken;
this.RefreshToken = tokenResp.RefreshToken;
return true;
}
else
{
return false;
}
}
}
Upvotes: 0
Reputation: 2929
Intuit Anywhere Developer Playground provides facility to get accessToken, accessTokenSecret and realmId.
Go to QuickBooks playground by clicking link mentioned below –
https://appcenter.intuit.com/Playground/OAuth/IA
Make sure that you are already logged into your Intuit account.
Fill consumer Key, Consumer Secret and Access Token Duration (120000 seconds).
Click on Connect to QuickBooks icon as shown in the picture. You will be asked to select company. If you have more than one company connected to your sandbox account, choose any according to your requirement. Then click Authorize Button.
You will get Access Token, Access Token Secret, RealmId (Company Id) and DataSource. Now you have all the keys to implement Accounting API. These keys will expire after 120000 seconds.
I have written a blog on how you can add, update, find and delete Customer.
Upvotes: 1
Reputation: 2367
You need to implement the 3 legged oauth flow in your app using C2QB button to get the access token and secret. Please see our sample apps to see how this is implemented. Download the sample app and then configure the consumer key and secret in the config file. Then check how the 3-legged oauth happens.You can try making calls to the V3 API using the local copy of the sample apps too. https://github.com/IntuitDeveloperRelations/ Also refer: https://developer.intuit.com/docs/0025_quickbooksapi/0010_getting_started
Upvotes: 2