Skip to content

jsil3601/QuickBooksSharp

 
 

Repository files navigation

QuickBooksSharp

Modern, async first, .NET client for QuickBooks Online Accounting API

This project was created because the official .NET client provided by Intuit is hard to work with and based on outdated .NET patterns.

https://developer.intuit.com/app/developer/qbo/docs/develop

Build

https://www.nuget.org/packages/QuickBooksSharp/

Install-Package QuickBooksSharp

  • TargetFramework = netstandard2.1
  • The object model is generated via the XSD.
  • Minor version is currently pinned to version 65

OAuth authentication

Generate URL to redirect user for approval of connection:

var authService = new AuthenticationService();
var scopes = new[] { "com.intuit.quickbooks.accounting" };
string redirectUrl = "https://myapp.com/quickbooks/authresult";
string state = Guid.NewGuid().ToString();
string url = authService.GenerateAuthorizationPromptUrl(clientId, scopes, redirectUrl, state);
// Redirect the user to redirectUrl so that they can approve the connection

Exchange code for token

[HttpGet]
public async Task<IActionResult> AuthResult(string code, long realmId, string state)
{
    //validate state parameter
    var authService = new AuthenticationService();
    string clientId = //get from config
    string clientSecret = //get from config
    var result = await authService.GetOAuthTokenAsync(clientId, clientSecret, code, redirectUrl);
    //persit access token and refresh token
    ...
}

Refresh token

var authService = new AuthenticationService();
var result = await authService.RefreshOAuthTokenAsync(clientId, clientSecret, refreshToken);
//persit access token and refresh token

Get User Info

var authService = new AuthenticationService();
var userInfo = await authService.GetUserInfo(accessToken, useSandbox: true);
//persit access token and refresh token

Instantiating the DataService

var dataService = new DataService(accessToken, realmId, useSandbox: true);

Creating / Updating entities

var result = await dataService.PostAsync(new Customer
            {
                DisplayName = "Chandler Bing",
                Suffix = "Jr",
                Title = "Mr",
                MiddleName = "Muriel",
                FamilyName = "Bing",
                GivenName = "Chandler",
            });
//result.Response is of type Customer
var customer = result.Response;

//Sparse update some properties
result = await dataService.PostAsync(new Customer
            {
                Id = customer.Id,
                SyncToken = customer.SyncToken,
                GivenName = "Ross",
                sparse = true
            });

//Update all properties
customer = result.Response;
customer.FamilyName = "Geller";
customer.sparse = false;
result = await dataService.PostAsync(customer);

Delete entities

  var result = await dataService.PostAsync(new Invoice { Id = "123", SyncToken = syncToken }, OperationEnum.delete);

Querying entities

var result = await dataService.QueryAsync<Customer>("SELECT * FROM Customer")
//res.Response.Entities is of type Customer[]
var customers = res.Response.Entities;

Querying reports

var report = await dataService.GetReportAsync("ProfitAndLoss", new()
            {
                { "accounting_method", "Accrual" },
                { "date_macro", "Last Fiscal Year" }
            });
string reportName = report.Header.ReportName;

Change Data Capture (CDC)

var result = await dataService.GetCDCAsync(DateTimeOffset.UtcNow.AddDays(-10), "Customer,Invoice");
var queryResponses = result.Response.QueryResponse; //type QueryResponse[]
var customers = queryResponses[0].IntuitObjects.Cast<Customer>();
var invoices = queryResponses[1].IntuitObjects.Cast<Invoice>();

Batch

//Delete 30 bills in a batch
var bills = (await dataService.QueryAsync<Bill>("SELECT * FROM Bill MAXRESULTS 30")).Response.Entities;
var response = await dataService.BatchAsync(new IntuitBatchRequest
{
    BatchItemRequest = bills.Select(b => new BatchItemRequest
    {
        bId = Guid.NewGuid().ToString(),
        operation = OperationEnum.delete,
        Bill = new Bill
        {
            Id = b.Id,
            SyncToken = b.SyncToken
        }
    }).ToArray()
});

//Issue multiple queries in a batch
var response = await dataService.BatchAsync(new IntuitBatchRequest
{
    BatchItemRequest = new[]
    {
            new BatchItemRequest
            {
                bId = Guid.NewGuid().ToString(),
                Query = "SELECT * FROM Bill MAXRESULTS 30",
            },
            new BatchItemRequest
            {
                bId = Guid.NewGuid().ToString(),
                Query = "SELECT * FROM Invoice MAXRESULTS 30",
            }
    }
});

Verifying webhooks

[HttpPost]
[IgnoreAntiforgeryToken]
[AllowAnonymous]
public async Task<IActionResult> Webhook()
{
    string signature = Request.Headers["intuit-signature"].ToString();
    string webhookVerifierToken = //get from config
    string requestBodyJSON = await base.ReadBodyToEndAsync();
    if (!Helper.IsAuthenticWebhook(signature, webhookVerifierToken, requestBodyJSON))
        return BadRequest();
        //return HTTP error status

    //Process webhook
    WebhookEvent notification = JsonSerializer.Deserialize<WebhookEvent>(requestBodyJSON, QuickBooksHttpClient.JsonSerializerOptions);
}

Download Invoice PDF

    var invoiceId = "1023";
    var invoidePdfStream = await dataService.GetInvoicePDF(invoiceId);

About

.NET client for QuickBooks Online API

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%