连接QuickBooks Online实现于IOS App数据同步功能的个人记录
公司项目需要用WebService与QBO实现后台数据同步,由于国内没有做过类似第三方产品接口的资料,前前后后找了N久,终于实现功能,现把实现功能步骤贴上来分享:
QBO开发者地址(主要用于创建QBO的APP和获取KEY和Token)
https://developer.intuit.com/
QBO后台数据管理地址(存放常见的Invoice,Customer等数据)
https://qbo.intuit.com/qbo28/login?webredir
QBO官方参考文档地址
https://developer.intuit.com/docs/0100_accounting/0000_release_notes
1. 获取token的key和secret,在QBO开发者地址的My APPs中点击右上角Create New APP来创建一个新的App,选择Select APIs,然后勾选Accounting和Payments,创建后进入控制台界面,有三个Deveolpment、Production、AppCards三个选项卡。
Development:用与开发者模式下测试,在Development下只能连接到SandBox。SandBox可以在顶栏 右边栏下拉菜单找到。
Production:用于连接 QBO后台数据管理 地址中的数据
APPCards:用来发布你创建的APP的后台管理卡片
2.Token的Key和Secret在Development/Production的Keys栏下,分别是OAuth Consumer Key和OAuth Consumer Secret
3.获取二次Token的Key和Secret,
参照以下地址中的步骤:
https://developer.intuit.com/docs/0050_quickbooks_api/0020_authentication_and_authorization/connect_from_within_your_app
在Connect from within your app栏可以找到具体操作步骤
需要以下三个地址:Intuit OAuth Service URLs
- Request token URL is: https://oauth.intuit.com/oauth/v1/get_request_token
- User authorization URL is: https://appcenter.intuit.com/Connect/Begin
- Access Token Request URL is: https://oauth.intuit.com/oauth/v1/get_access_token
得到返回的三个参数:分别是
- realmId
- oauth_verifier
- oauth_token
在认证时候,如果是用Development的Key和Secret,是会默认连接到Sandbox的数据的,所以想看到公共的 QBO后台数据管理 中的数据,需要用Production中的Key和Secret。
获得二次Token的Key和Secret后,就可以通过SDK或REST API的方式连接到QBO来获取和推送数据了。
一、SDK方式同步QBO:
官方SDK文档:
http://developer.qbapi.com/Quickbooks-Online-API-QuickStart.aspx
官方SDK下载:
https://www.nuget.org/packages/IppDotNetSdkForQuickBooksApiV3/
如果需要.NET连接QBO的后台示例代码,也可以在以下URL中找到
http://developer.qbapi.com/Connect-to-Quickbooks-Online.aspx#
1.添加引用:
using DevDefined.OAuth.Consumer;
using DevDefined.OAuth.Framework;
using Intuit.Ipp.Core;
using Intuit.Ipp.DataService;
using Intuit.Ipp.Security;
2.定义GetServiceContext方法,用于返回ServiceContext
public static ServiceContext GetServiceContext(string AccessToken, string AccessTokenSecret, string CompanyId)
{
OAuthRequestValidator oauthValidator = new OAuthRequestValidator(AccessToken, AccessTokenSecret, consumerKey, consumerSecret);
ServiceContext context = new ServiceContext(CompanyId, IntuitServicesType.QBO, oauthValidator);
context.IppConfiguration.BaseUrl.Qbo = "https://quickbooks.api.intuit.com/";
return context;
}
consumerKey和consumerSecret是QBO开发者地址中Production下的OAuth Consumer Key和OAuth Consumer Secret
GetServiceContext方法中的参数,AccessToken、AccessTokenSecret和CompanyId分别是二次Token中返回的oauth_token、oauth_verifier和realmId
3.创建QBO连接:
public static DataService ConnectToQBO(string AccessToken, string AccessTokenSecret, string CompanyId)
{
OAuthRequestValidator oauthValidator = new OAuthRequestValidator(AccessToken, AccessTokenSecret, consumerKey, consumerSecret);
ServiceContext context = GetServiceContext(AccessToken, AccessTokenSecret, CompanyId);
DataService dataService = new DataService(context);
return dataService;
}
4.查询QBO对应的信息:
返回Invoice信息:
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
List<Invoice> invoiceList = dataService.FindAll(new Invoice(), 1, 100).ToList();
5.根据条件查询QBO信息:
1)方法一:
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Invoice invoice = dataService.FindAll(new Invoice()).Where(a => a.Id == request.Invoice.QBOId).SingleOrDefault();
2)方法二:
ServiceContext context = QBOCommonUtility.GetServiceContext(AccessToken, AccessTokenSecret, CompanyId);
QueryService<Invoice> queryService = new QueryService<Invoice>(context);
string query = string.Format("SELECT * FROM Invoice where Id='{0}'",id);
IEnumerable<Invoice> invoices = queryService.ExecuteIdsQuery(query);
6.插入一个新的Customer到QBO
public static Customer InsertQBOCustomer(QBOCustomerRequest request)
{
string AccessToken = request.AccessToken;
string AccessTokenSecret= request.AccessSecret;
string CompanyId = request.CompanyId;
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Customer customer = new Customer();
//Mandatory Fields
customer.Title = request.Customer.Title == null ? "" : request.Customer.Title;
customer.GivenName = request.Customer.GivenName == null ? "" : request.Customer.GivenName;
customer.MiddleName = request.Customer.MiddleName == null ? "" : request.Customer.MiddleName;
customer.FamilyName = request.Customer.FamilyName == null ? "" : request.Customer.FamilyName;
customer.Notes = request.Customer.Notes == null ? "" : request.Customer.Notes;
customer.Suffix = request.Customer.Suffix == null ? "" : request.Customer.Suffix;
customer.FullyQualifiedName = request.Customer.FullyQualifiedName == null ? "" : request.Customer.FullyQualifiedName;
customer.CompanyName = request.Customer.CompanyName == null ? "" : request.Customer.CompanyName;
customer.DisplayName = request.Customer.DisplayName == null ? "" : request.Customer.DisplayName;
if (request.Customer.BillAddr!=null)
{
customer.BillAddr = new PhysicalAddress();
customer.BillAddr.City = request.Customer.BillAddr.City == null ? "" : request.Customer.BillAddr.City;
customer.BillAddr.Country = request.Customer.BillAddr.Country == null ? "" : request.Customer.BillAddr.Country;
customer.BillAddr.CountrySubDivisionCode = request.Customer.BillAddr.CountrySubDivisionCode == null ? "" : request.Customer.BillAddr.CountrySubDivisionCode;
customer.BillAddr.Line1 = request.Customer.BillAddr.Line1 == null ? "" : request.Customer.BillAddr.Line1;
customer.BillAddr.PostalCode = request.Customer.BillAddr.PostalCode == null ? "" : request.Customer.BillAddr.PostalCode;
}
if(request.Customer.PrimaryPhone!=null)
{
customer.PrimaryPhone = new TelephoneNumber();
customer.PrimaryPhone.FreeFormNumber = request.Customer.PrimaryPhone.FreeFormNumber == null ? "" : request.Customer.PrimaryPhone.FreeFormNumber;
}
if(request.Customer.PrimaryEmailAddr!=null)
{
customer.PrimaryEmailAddr = new EmailAddress();
customer.PrimaryEmailAddr.Address = request.Customer.PrimaryEmailAddr.Address == null ? "" : request.Customer.PrimaryEmailAddr.Address;
}
Customer resultCustomer = dataService.Add(customer) as Customer;
return resultCustomer;
}
8.插入新的Invoice到QBO
internal static Invoice CreateInvoice(QBOInvoiceRequest request, Customer customer)
{
try
{
string AccessToken = request.AccessToken;
string AccessTokenSecret = request.AccessTokenSecret;
string CompanyId = request.Invoice.QBOCompanyId;
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Item item = dataService.FindAll(new Item(), 1, 1).SingleOrDefault();
Invoice invoice = new Invoice();
//Mandatory fields
invoice.DocNumber = Guid.NewGuid().ToString("N").Substring(0, 10);
invoice.TxnDate = Convert.ToDateTime(request.Invoice.InvoiceDate);//DateTime.Today.Date;//
invoice.TxnDateSpecified = true;
invoice.CustomerRef = new ReferenceType()
{
name = customer.GivenName,
Value = customer.Id
};
Line line = new Line();
line.Amount = request.Invoice.Amount;//request.Invoice.Amount;//10000;
line.DetailType = LineDetailTypeEnum.DescriptionOnly;
line.AmountSpecified = true;
line.Description = "Desc Invoice";
line.DetailType = LineDetailTypeEnum.SalesItemLineDetail;
line.DetailTypeSpecified = true;
SalesItemLineDetail lineSalesItemLineDetail = new SalesItemLineDetail();
//Line Sales Item Line Detail - ItemRef
lineSalesItemLineDetail.ItemRef = new ReferenceType()
{
name = item.Name,
Value = item.Id
};
//Line Sales Item Line Detail - UnitPrice
lineSalesItemLineDetail.AnyIntuitObject = 0m;
lineSalesItemLineDetail.ItemElementName = ItemChoiceType.UnitPrice;
//Line Sales Item Line Detail - Qty
lineSalesItemLineDetail.Qty = 0;
lineSalesItemLineDetail.QtySpecified = true;
//Line Sales Item Line Detail - TaxCodeRef
//For US companies, this can be 'TAX' or 'NON'
lineSalesItemLineDetail.TaxCodeRef = new ReferenceType()
{
Value = "NON"
};
//Line Sales Item Line Detail - ServiceDate
lineSalesItemLineDetail.ServiceDate = DateTime.Now.Date;
lineSalesItemLineDetail.ServiceDateSpecified = true;
//Assign Sales Item Line Detail to Line Item
line.AnyIntuitObject = lineSalesItemLineDetail;
//Assign Line Item to Invoice
invoice.Line = new Line[] { line };
Invoice addInvoice = dataService.Add(invoice) as Invoice;
return addInvoice;
//Invoice invoice1 = invoiceList[0];
//invoice1.CustomerRef = invoice.CustomerRef;
//Invoice addInvoice1 = dataService.Update(invoice1);
//Batch batch = dataService.CreateNewBatch();
//batch.Add(invoice, "bId1", OperationEnum.create);
//batch.Execute();
}
catch (ValidationException exception)
{
Console.WriteLine("Message:{0}, ErrorCode:{1}", exception.Message, exception.ErrorCode);
foreach (IdsError idsError in exception.InnerExceptions)
{
Console.WriteLine("ErrorCode:{0}, Message:{1}, Element:{2}, Detail:{3}", idsError.ErrorCode, idsError.Message,
idsError.Element, idsError.Detail);
}
return null;
}
}
9.更新Customer到QBO
public static Customer UpdateQBOCustomer(QBOCustomerRequest request, string id)
{
string AccessToken = request.AccessToken;
string AccessTokenSecret = request.AccessSecret;
string CompanyId = request.CompanyId;
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Customer customer = GetQBOCustomerById(AccessToken, AccessTokenSecret, CompanyId, id);
Customer resultCustomer = new Customer();//dataService.FindById(customer) as Customer;
if (customer != null)
{
bool isChanged = false;
if (customer.DisplayName != request.Customer.DisplayName)
{
customer.DisplayName = request.Customer.DisplayName == null ? "" : request.Customer.DisplayName;
customer.GivenName = request.Customer.GivenName == null ? "" : request.Customer.GivenName;
customer.MiddleName = request.Customer.MiddleName == null ? "" : request.Customer.MiddleName;
customer.FamilyName = request.Customer.FamilyName == null ? "" : request.Customer.FamilyName;
isChanged = true;
}
if (request.Customer.PrimaryPhone != null)
{
if (customer.PrimaryPhone == null)
{
customer.PrimaryPhone = new TelephoneNumber();
}
if(customer.PrimaryPhone.FreeFormNumber != request.Customer.PrimaryPhone.FreeFormNumber)
{
customer.PrimaryPhone.FreeFormNumber = request.Customer.PrimaryPhone.FreeFormNumber == null ? "" : request.Customer.PrimaryPhone.FreeFormNumber;
isChanged = true;
}
}
if(customer.CompanyName != request.Customer.CompanyName)
{
customer.CompanyName = request.Customer.CompanyName == null ? "" : request.Customer.CompanyName;
isChanged = true;
}
if (request.Customer.PrimaryEmailAddr != null)
{
if(customer.PrimaryEmailAddr == null)
{
customer.PrimaryEmailAddr = new EmailAddress();
}
if(customer.PrimaryEmailAddr.Address != request.Customer.PrimaryEmailAddr.Address)
{
customer.PrimaryEmailAddr.Address = request.Customer.PrimaryEmailAddr.Address == null ? "" : request.Customer.PrimaryEmailAddr.Address;
isChanged = true;
}
}
if (customer.Title != request.Customer.Title)
{
customer.Title = request.Customer.Title == null ? "" : request.Customer.Title;
isChanged = true;
}
if(customer.Notes != request.Customer.Notes)
{
customer.Notes = request.Customer.Notes == null ? "" : request.Customer.Notes;
isChanged = true;
}
if(isChanged)
{
resultCustomer = dataService.Update(customer) as Customer;
}
return resultCustomer;
}
return customer;
}
10.更新Invoice信息到QBO
internal static Invoice UpdateInvoice(QBOInvoiceRequest request, Customer customer)
{
string AccessToken = request.AccessToken;
string AccessTokenSecret = request.AccessTokenSecret;
string CompanyId = request.Invoice.QBOCompanyId;
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Invoice invoice = dataService.FindAll(new Invoice()).Where(a => a.Id == request.Invoice.QBOId).SingleOrDefault();
if (invoice == null)
{
return null;
}
invoice.CustomerRef.Value = customer.Id;
invoice.TxnDate = Convert.ToDateTime(request.Invoice.InvoiceDate);
Line line = invoice.Line[0];
line.Amount = request.Invoice.Amount;
var termStr = request.Invoice.Term;
int termDays = CommonUtility.getTermDays(termStr);
string dueDate = DateTime.Parse(request.Invoice.InvoiceDate).AddDays(termDays).ToString(Constants.FORMAT_MONTH_DAY_YEAR);
invoice.DueDate = Convert.ToDateTime(dueDate);
if (invoice.BillEmail == null)
{
invoice.BillEmail = new EmailAddress();
invoice.BillEmail.DefaultSpecified = true;
invoice.BillEmail.Address = request.Invoice.ContactEmail;
}
invoice.PrivateNote = request.Invoice.Note;
Item item = dataService.FindAll(new Item(), 1, 1).SingleOrDefault();
SalesItemLineDetail lineSalesItemLineDetail = new SalesItemLineDetail();
//Line Sales Item Line Detail - ItemRef
lineSalesItemLineDetail.ItemRef = new ReferenceType()
{
name = item.Name,
Value = item.Id
};
//Line Sales Item Line Detail - UnitPrice
lineSalesItemLineDetail.AnyIntuitObject = 0m;
lineSalesItemLineDetail.ItemElementName = ItemChoiceType.UnitPrice;
//Line Sales Item Line Detail - Qty
lineSalesItemLineDetail.Qty = 0;
lineSalesItemLineDetail.QtySpecified = true;
//Line Sales Item Line Detail - TaxCodeRef
//For US companies, this can be 'TAX' or 'NON'
lineSalesItemLineDetail.TaxCodeRef = new ReferenceType()
{
Value = "NON"
};
//Line Sales Item Line Detail - ServiceDate
lineSalesItemLineDetail.ServiceDate = DateTime.Now.Date;
lineSalesItemLineDetail.ServiceDateSpecified = true;
//Assign Sales Item Line Detail to Line Item
line.AnyIntuitObject = lineSalesItemLineDetail;
Invoice updateInvoice = dataService.Update(invoice);
return updateInvoice;
}
11.删除QBO中的Invoice信息
public static bool DeleteInvoice(string invoiceid, string AccessToken, string AccessTokenSecret, string CompanyId)
{
DataService dataService = QBOCommonUtility.ConnectToQBO(AccessToken, AccessTokenSecret, CompanyId);
Invoice invoice = dataService.FindAll(new Invoice()).Where(a => a.Id == invoiceid).SingleOrDefault();
Invoice updateInvoice = dataService.Delete(invoice);
return true;
}
二、REST API方式连接QBO
参考文档和API接口地址:
https://developer.intuit.com/docs/api/accounting/invoice
官方API测试地址:
https://developer.intuit.com/v2/apiexplorer?apiname=V3QBO#?id=Account
1.REST API 查询:
public static string ExecuteV3Query(string AccessToken, string AccessTokenSecret, string CompanyId, string Query)
{
string encodeQuery = System.Web.HttpUtility.UrlEncode(Query);
string uri = string.Format("https://quickbooks.api.intuit.com/v3/company/{0}/query?query={1}&minorversion=4", CompanyId, Query);
HttpWebRequest httpWebRequest = WebRequest.Create(uri) as HttpWebRequest;
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(consumerKey, consumerSecret, AccessToken, AccessTokenSecret, httpWebRequest, null));
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
using(Stream data = httpWebResponse.GetResponseStream())
{
return new StreamReader(data).ReadToEnd();
}
}
参数中的Query字符串是用来传递SQL语句的比如“select * from Invoice”
private static string GetDevDefinedOAuthHeader(string consumerkey,string consumerSecret,string accessToken,string accessTokenSecret,HttpWebRequest webRequest,string requestBody)
{
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = consumerkey,
SignatureMethod = SignatureMethod.HmacSha1,
ConsumerSecret = consumerSecret,
UseHeaderForOAuthParameters = true
};
//We already have OAuth tokens, so OAuth URIs below are not used - set to example.com
OAuthSession oSession = new OAuthSession(consumerContext, "https://www.example.com", "https://www.example.com", "https://www.example.com");
oSession.AccessToken = new TokenBase
{
Token = accessToken,
ConsumerKey = consumerKey,
TokenSecret = accessTokenSecret
};
IConsumerRequest consumerRequest = oSession.Request();
consumerRequest = ConsumerRequestExtensions.ForMethod(consumerRequest, webRequest.Method);
if(requestBody!=null)
{
consumerRequest = consumerRequest.Post().WithRawContentType(webRequest.ContentType).WithRawContent(System.Text.Encoding.ASCII.GetBytes(requestBody));
}
consumerRequest = ConsumerRequestExtensions.ForUri(consumerRequest, webRequest.RequestUri);
consumerRequest = consumerRequest.SignWithToken();
return consumerRequest.Context.GenerateOAuthParametersForHeader();
}
2.REST API 新建Invoice
1)连接QBO的新建函数:
public static string ExecuteV3InvoiceInsert(string AccessToken, string AccessTokenSecret, string CompanyId,string body)
{
string uri = string.Format("https://quickbooks.api.intuit.com/v3/company/{0}/invoice?minorversion=4", CompanyId);
HttpWebRequest httpWebRequest = WebRequest.Create(uri) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(consumerKey, consumerSecret, AccessToken, AccessTokenSecret, httpWebRequest, null));
byte[] formData = UTF8Encoding.UTF8.GetBytes(body);
httpWebRequest.ContentLength = formData.Length;
using (Stream postStream = httpWebRequest.GetRequestStream())
{
postStream.Write(formData, 0, formData.Length);
}
string response = string.Empty;
try
{
WebResponse webResponse = httpWebRequest.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
response = responseReader.ReadToEnd();
}
}
}
return response;
}
catch(Exception ex)
{
return "";
}
}
2)逻辑层调用ExecuteV3InvoiceInsert函数:
internal static BOSmobileService.DataObjects.RefInvoice CreateInvoiceAPI(QBOInvoiceRequest request, Customer customer)
{
string AccessToken = request.AccessToken;
string AccessTokenSecret = request.AccessTokenSecret;
string CompanyId = request.Invoice.QBOCompanyId;
var amount = request.Invoice.Amount;
var invoiceDate = request.Invoice.InvoiceDate;
var termStr = request.Invoice.Term;
int termDays = CommonUtility.getTermDays(termStr);
string dueDate = DateTime.Parse(invoiceDate).AddDays(termDays).ToString(Constants.FORMAT_MONTH_DAY_YEAR);
var contactEmail = request.Invoice.ContactEmail;
var note = request.Invoice.Note;
string body = GetParams(invoiceDate, dueDate, note, amount.ToString(), customer.Id, contactEmail);
string refStr = QBOCommonUtility.ExecuteV3InvoiceInsert(AccessToken, AccessTokenSecret, CompanyId, body);
BOSmobileService.DataObjects.RefInvoice invocie = Newtonsoft.Json.JsonConvert.DeserializeObject<BOSmobileService.DataObjects.RefInvoice>(refStr);
return invocie;
}
public static string GetParams(string invoiceDate, string dueDate, string note, string amount, string customerId, string contactEmail)
{
StringBuilder sb = new StringBuilder();
sb.Append("{\"TxnDate\":\"");
sb.Append(invoiceDate);
sb.Append("\",\"DueDate\":\"");
sb.Append(dueDate);
sb.Append("\",\"PrivateNote\":\"");
sb.Append(note);
sb.Append("\",\"Line\":[{\"Amount\":");
sb.Append(amount);
sb.Append(",\"DetailType\": \"SalesItemLineDetail\",\"SalesItemLineDetail\": {\"ItemRef\": {\"value\": \"1\",\"name\": \"Sales\"}}}],\"CustomerRef\": {\"value\": \"");
sb.Append(customerId);
sb.Append("\"},\"BillEmail\": {\"Address\":\"");
sb.Append(contactEmail);
sb.Append("\"}}");
return sb.ToString();
}
3. REST API删除Invoice
public static bool DeleteInvoiceAPI(string invoiceid, string AccessToken, string AccessTokenSecret, string CompanyId)
{
StringBuilder sb = new StringBuilder();
sb.Append("{\"Id\": \"");
sb.Append(invoiceid);
sb.Append("\",\"SyncToken\": \"3\"}");
string body = sb.ToString();//string.Format("{\"Id\": \"{0}\",\"SyncToken\": \"3\"}",invoiceid);
string refStr = QBOCommonUtility.ExecuteV3InvoiceDelete(AccessToken, AccessTokenSecret, CompanyId, body);
return true;
}
public static string ExecuteV3InvoiceDelete(string AccessToken, string AccessTokenSecret, string CompanyId, string body)
{
string uri = string.Format("https://quickbooks.api.intuit.com/v3/company/{0}/invoice?operation=delete&minorversion=4", CompanyId);
HttpWebRequest httpWebRequest = WebRequest.Create(uri) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(consumerKey, consumerSecret, AccessToken, AccessTokenSecret, httpWebRequest, null));
byte[] formData = UTF8Encoding.UTF8.GetBytes(body);
httpWebRequest.ContentLength = formData.Length;
using (Stream postStream = httpWebRequest.GetRequestStream())
{
postStream.Write(formData, 0, formData.Length);
}
string response = string.Empty;
try
{
WebResponse webResponse = httpWebRequest.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
response = responseReader.ReadToEnd();
}
}
}
return response;
}
catch (Exception ex)
{
return "Error";
}
}
4. 创建Payment(创建与Invoice的Amount金额数目相对应Payment等同于把Invoice设置成Paid状态)
public static string MarkInvoicePaid(string invoiceid, string customerId, decimal amount, string AccessToken, string AccessTokenSecret, string CompanyId)
{
StringBuilder sb = new StringBuilder();
sb.Append("{\"CustomerRef\":{\"value\": \"");
sb.Append(customerId);
sb.Append("\"},\"TotalAmt\": ");
sb.Append(amount.ToString());
sb.Append(",\"Line\": [{\"Amount\": ");
sb.Append(amount.ToString());
sb.Append(",\"LinkedTxn\": [{\"TxnId\": \"");
sb.Append(invoiceid);
sb.Append("\",\"TxnType\": \"Invoice\"}]}]}");
string body = sb.ToString();
string response = QBOCommonUtility.ExecuteV3InvoicePayment(AccessToken, AccessTokenSecret, CompanyId, body);
return response;
}
internal static string ExecuteV3InvoicePayment(string AccessToken, string AccessTokenSecret, string CompanyId, string body)
{
string uri = string.Format("https://quickbooks.api.intuit.com/v3/company/{0}/payment?minorversion=4", CompanyId);
HttpWebRequest httpWebRequest = WebRequest.Create(uri) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(consumerKey, consumerSecret, AccessToken, AccessTokenSecret, httpWebRequest, null));
byte[] formData = UTF8Encoding.UTF8.GetBytes(body);
httpWebRequest.ContentLength = formData.Length;
using (Stream postStream = httpWebRequest.GetRequestStream())
{
postStream.Write(formData, 0, formData.Length);
}
string response = string.Empty;
try
{
WebResponse webResponse = httpWebRequest.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
response = responseReader.ReadToEnd();
}
}
}
return response;
}
catch (Exception ex)
{
return "Error";
}
}
连接QuickBooks Online实现于IOS App数据同步功能的个人记录的更多相关文章
- iOS App引导页功能实现
一.写作原因 以前都没有想着来写点东西,今天遇到件事情让我决定每次还是要做记录.因为以前自己可以轻松的完成pod spec的配置,但是今天在做的时候还是忘了遇到了很多坑.pod spec配置遇到的坑不 ...
- Navicat premium对数据库的结构同步和数据同步功能
一.在目标数据库新建一个相同的数据库名. 二.工具-->结构同步. 三.填写源数据库和目标数据库. 四.点击比对 五.点击部署 六.点击运行 七.点击关闭.此时源数据库的结构已经同步到目标数据库 ...
- iOS - App 上架审核被原因拒总结
1.未遵守苹果 iOS APP 数据储存指导方针 如果你的 App 有离线数据下载功能,尤其需要关注这一点.因为离线数据一般占用存储空间比较大,可以被重新下载和重建,但是用户往往希望系统存储空间紧时也 ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 能支撑10万以上客户端的数据同步下载问题
庞大的业务系统,特别是需要有离线作业操作支持的核心业务系统,需要有强大的基础数据同步功能,基础数据有在增加.有在变动.有在失效,同时有大量的客户端全天侯的在连接服务器.不间断的在处理核心数据. 经过2 ...
- Oracle和Elasticsearch数据同步
Python编写Oracle和Elasticsearch数据同步脚本 标签: elasticsearchoraclecx_Oraclepython数据同步 Python知识库 一.版本 Pyth ...
- Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步
摘自:http://blog.csdn.net/javaee_sunny/article/details/53439980 目录(?)[-] Oracle 10g 物化视图语法如下 实例演示 主要步骤 ...
- 高可用数据同步方案-SqlServer迁移Mysql实战
简介 随着业务量的上升,以前的架构已经不满足业务的发展,数据作为业务中最重要的一环,需要有更好的架构作为支撑.目前我司有sql server转mysql的需求,所以结合当前业务,我挑选了阿里云开源的一 ...
- 用canal监控binlog并实现mysql定制同步数据的功能
业务背景 写任何工具都不能脱离实际业务的背景.开始这个项目的时候是因为现有的项目中数据分布太零碎,零零散散的分布在好几个数据库中,没有统一的数据库来收集这些数据.这种情况下想做一个大而全的会员中心系统 ...
- 环境篇:数据同步工具DataX
环境篇:数据同步工具DataX 1 概述 https://github.com/alibaba/DataX DataX是什么? DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 ...
随机推荐
- MAC与HMAC的介绍及其在AWS和Azure中的应用
MAC 在密码学中,(消息认证码)Message Authentication Code是用来认证消息的比较短的信息.换言之,MAC用来保证消息的数据完整性和消息的数据源认证. MAC由消息本身和一个 ...
- js每天进步一点点4
输入数字的验证
- Windows Azure Virtual Machine (24) Azure VM支持多网卡功能
<Windows Azure Platform 系列文章目录> Update 2016-03-30 一个VM的多张网卡可以在一个VNet的同一个Subnet子网下,笔者亲自测试过了. 如果 ...
- tornado--SESSION框架,一致性hash,分布式存储
预备知识 tornado框架session要自己写 cookie存储在客户端浏览器上,session数据放在服务器上 session依赖cookie 扩展tornado,返回请求前自定义session ...
- ReflectionHelper
public static T GetInstance<T>(Assembly assembly, string fullNamespace) { return (T)assembly.C ...
- jquery的promise实践--连续加载图片
在javascript设计模式实践之代理模式--图片预加载中用代理模式实现了图片预加载功能. 现在就更进一步,完成一个能够一张一张的连续图片加载的功能. 功能: 1.一张一张加载图片. 2.加载错误, ...
- Linux下快速设定ip bond
在计算机网路普及的初期,很多OS系统都使用的为单网卡方式,即一个网卡使用一个IP地址.随着网络要求的不断提高,我们可以对多个网卡进行绑定聚合当一个逻辑网络接口来使用,从而大幅提升服务器的网络吞吐(I/ ...
- Java动态程序设计:反射介绍
使用运行的类的信息使你的程序设计更加灵活 反射授予了你的代码访问装载进JVM内的Java类的内部信息的权限,并且允许你编写在程序执行期间与所选择的类的一同工作的代码,而不是在源代码中.这种机制使得反射 ...
- PHP导入excel数据到MYSQL
这里介绍一个直接将excel文件导入mysql的例子.我花了一晚上的时间测试,无论导入简繁体都不会出现乱码,非常好用.PHP-ExcelReader,下载地址: http://sourceforge. ...
- Widget的点击事件
本文实现Widget中的按钮点击事件,点击一次下面的按钮,上面的数字减少1. 首先是Manifest文件: <?xml version="1.0" encoding=&quo ...