This is a guide to creating an eCommerce integration with QuickBooks Online and Payments APIs, showing:
This guide is for developers who want to implement an eCommerce app. The QuickBooks entities used in this exercise are Sales Receipt, Customers, and Items for QuickBooks Online API and Charges and Tokens for Payments API. In order get the most out of this information, you need the following:
developer.intuit.com
enabled for both QuickBooks Online and Payments APIs.For this scenario, your sandbox serves as the QuickBooks company that manages the transaction where Pye’s Cakes buys twenty sprinkler pipes from the merchant with a credit card. All moving parts for this transaction are explored.
For the complete cycle of a merchant service credit card transaction, corresponding QuickBooks sales transactions, and settlement reconciliation to work properly, it is critical that the Payments connection and QuickBooks connection be on the same companyId. This is typically accomplished by
ensuring that when you request an OAuth access token and secret you provide the complete picture of what your user expects your app to be doing with QuickBooks data sources. In your OAuth authorization
implementation, make sure your call to setup() enables both quickbooks
and payments
data sources.
When your user changes their settings to turn ON a new part of your integration with QuickBooks, initiate a subsequent request for a set of OAuth access token and secret to ensure that the correct services are setup on the company for your application. The worst possible situation would be for you to transact credit cards using a payments account set up for one company, while syncing the corresponding business transaction to a completely different QuickBooks company. Reconciliation will fail at best, and at worst, you are transacting for one business using the payments account of another business (albeit owned by the same user) which is fraudulent use of the QuickBooks payments service and can lead to service disruption for the merchant.
Accept order from the customer, request credit card details.
Order: 20 sprinkler pipes at $4 each = $80.00
Use customer information once or save, based on the merchant’s business model. To save, create an account and store detail in Customer object, credit card details in Payments API Cards object (opaque to merchant).
Information in this section shows you how to submit a credit card charge to QuickBooks Payments via the API, without the need to swipe the physical card. There are three steps:
Note
Note
Token is only preferred to avoid PCI compliance requirements. For creating a charge without token creation, please follow the steps mentioned in API Explorer under Charges section.
First, create a token to keep CC info opaque from you, the developer. Become informed about handling credit card information.
https://api.intuit.com/quickbooks/v4/payments/tokens
application/json
Sample Request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "card": { "expYear": "2017", "expMonth": "03", "address": { "region": "NJ", "postalCode": "07079", "streetAddress": "350 Mountain View Dr.", "country": "US", "city": "South Orange" }, "name": "Pye's Cakes", "cvc": "123", "number": "4111111111111111" } } |
View Sample Response
1 2 3 | { "value": "4ALvl3ZJZESJwjiQr6vQQCfDz74=" } |
Now create a charges authorization using the token created in the last section. Life time of a token is 15 minutes and is for one time use. This is the first half of a credit card transaction, with the charges.capture
attribute set to false
, and is used to get authorization that the
merchandise will be paid by the card issuer.
https://api.intuit.com/quickbooks/v4/payments/charges
application/json
Sample Request
1 2 3 4 5 6 | { "amount": "80.00", "currency": "USD", "capture": "false", "token": "4ALvl3ZJZESJwjiQr6vQQCfDz74=" } |
View Sample Response
1 2 3 4 5 6 7 8 9 10 | { "created": "2015-04-23T19:51:48Z", "status": "AUTHORIZED", "amount": "80.00", "currency": "USD", "token": "4ALvl3ZJZESJwjiQr6vQQCfDz74=", "capture": false, "id": "ECZG9D8YZ2WY", "authCode": "817677" } |
At fulfillment time, you capture the charge.
https://api.intuit.com/quickbooks/v4/payments/charges/<id>/capture
ECZG9D8YZ2WY
.application/json
Sample Request
1 2 3 | { amount: 80.00 } |
View Sample Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | { "created": "2015-04-23T19:51:47Z", "status": "CAPTURED", "amount": "80.00", "currency": "USD", "card": { "number": "xxxxxxxxxxxx1111", "name": "Pye's Cakes", "address": { "city": "xxxxxxxxxxxx", "region": "xx", "postalCode": "xxxxx", "streetAddress": "xxxxxxxxxxxxxxxxxxxxx" }, "expMonth": "03", "expYear": "2017" }, "capture": false, "id": "ECZG9D8YZ2WY", "context": { "tax": null, "recurring": false, "deviceInfo": {} }, "authCode": "817677", "captureDetail": { "created": "2015-04-23T19:53:43Z", "amount": "80.00", "context": { "tax": "0.00", "recurring": false, "deviceInfo": {} } } } |
After receiving and processing the credit card create response, create the sales receipt.
Line.SalesItemLineDetail
sub-object.CreditCardPayment.CreditChargeResponse.CCTransId
.When creating the sales receipt, set up the sale to be automatically reconciled with the QuickBooks company account register. After the transaction settles from merchant services, QuickBooks Online automatically creates a deposit in the merchant’s company file.
In order to take advantage of automatic reconciliation, set the following parameters in the salesreceipt create request:
CreditCardPayment.CreditChargeResponse.CCTransId
to the value returned in the original QuickBooks Payments charge response.CreditCardPayment.CrecitChargeInfo.ProcessPayment
to true
. This triggers QuickBooks Online services to store the credit card charge response information, in particular the CCTransId
field that is fundamental to credit card transaction reconciliation. This triggers the notation
Transaction has been processed for the sales receipt on the QuickBooks user interface.TxnSource
toIntuitPayment
. This inserts the transaction into a list of pending deposits to be automatically matched and reconciled with the merchant’s checking account.Note
Note
show production endpoint URLs, but request and response samples use sandbox objects
https://quickbooks.api.intuit.com/v3/company/<realmId>/salesreceipt
application/json
Sample Request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | { "Line": [{ "Id": "1", "LineNum": 1, "Description": "Sprinkler Pipes", "Amount": 80.0, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "17", "name": "Sprinkler Pipes" }, "UnitPrice": 4, "Qty": 20 } }], "CustomerRef": { "value": "15", "name": "Pye's Cakes" }, "CreditCardPayment": { "CreditChargeInfo": { "ProcessPayment": "true" }, "CreditChargeResponse": { "CCTransId": "EKFOR97XK9UD" } }, "TxnSource": "IntuitPayment" } |
View Sample Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | { "SalesReceipt": { "domain": "QBO", "sparse": false, "Id": "192", "SyncToken": "0", "MetaData": { "CreateTime": "2015-04-15T12:59:52-07:00", "LastUpdatedTime": "2015-04-15T12:59:52-07:00" }, "DocNumber": "1053", "TxnDate": "2015-04-15", "Line": [ { "Id": "1", "LineNum": 1, "Description": "Sprinkler Pipes", "Amount": 80.0, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "17", "name": "Sprinkler Pipes" }, "UnitPrice": 4, "Qty": 20, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 80.0, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "15", "name": "Pye's Cakes" }, "BillAddr": { "Id": "15", "Line1": "350 Mountain View Dr.", "City": "South Orange", "CountrySubDivisionCode": "NJ", "PostalCode": "07079", "Lat": "40.7633073", "Long": "-74.2426072" }, "TxnSource": "IntuitPayment", "TotalAmt": 80.0, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "Balance": 0, "CreditCardPayment": { "CreditChargeInfo": { "ProcessPayment": true }, "CreditChargeResponse": { "CCTransId": "EKFOR97XK9UD", "Status": "Completed", "CardSecurityCodeMatch": "NotAvailable", "AvsStreet": "Fail", "AvsZip": "Fail" } }, "DepositToAccountRef": { "value": "4", "name": "Undeposited Funds" } }, "time": "2015-04-15T12:59:53.035-07:00" } |
If you attempt to create this sales receipt without having enabled the Payments data source in your app, you receive the following error.
View Sample Error Response
1 2 3 4 5 6 | { "Fault" => { "Error" => [{ "Message" => "Feature Not Supported Error", "Detail" => "Feature Not Supported Error : true", "code" => "5030", "element" => "ProcessPayment" }], "type" => "ValidationFault" }, "time" => "2015-04-17T12:53:32.542-07:00" |
After the credit card transaction settles, QuickBooks Payments deposits funds into the merchant’s checking account and withdraws the transaction fee. A deposit object and purchase object, respectively, are created on his behalf. You, the developer, do not create these objects. This has the effect of automatically reconciling the transaction in the QuickBooks company account register.
To determine if a deposit object has been created, query deposit objects and parse the response to locate the deposit whose Line.LinkedTxn.TxnId
matches that of the subject salesreceipt object created in the last section.
View Sample Deposit Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | { "Deposit": [ { "DepositToAccountRef": { "value": "35", "name": "Checking" }, "TotalAmt": 80.0, "domain": "QBO", "sparse": false, "Id": "200", "SyncToken": "0", "MetaData": { "CreateTime": "2015-04-20T15:24:02-07:00", "LastUpdatedTime": "2015-04-20T15:24:02-07:00" }, "TxnDate": "2015-04-20", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "PrivateNote": "System-recorded deposit for QuickBooks Payments", "Line": [ { "Amount": 80, "LinkedTxn": [ { "TxnId": "192", "TxnType": "SalesReceipt", "TxnLineId": "0" } ] } ] } ], "time": "2015-04-20T15:25:28.184-07:00" } |
A Purchase object is created on the merchant’s behalf to represent the corresponding fee paid to QuickBooks Payments for the transaction.
View Sample Purchase Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | { "Purchase": { "AccountRef": { "value": "35", "name": "Checking" }, "PaymentType": "Cash", "EntityRef": { "value": "135", "name": "QuickBooks Payments", "type": "Vendor" }, "TotalAmt": 0.28, "PurchaseEx": { "any": [ { "name": "{http://schema.intuit.com/finance/v3}NameValue", "declaredType": "com.intuit.schema.finance.v3.NameValue", "scope": "javax.xml.bind.JAXBElement$GlobalScope", "value": { "Name": "TxnType", "Value": "54" }, "nil": false, "globalScope": true, "typeSubstituted": false } ] }, "domain": "QBO", "sparse": false, "Id": "958", "SyncToken": "0", "MetaData": { "CreateTime": "2015-04-20T15:24:02-07:00", "LastUpdatedTime": "2015-04-20T15:24:02-07:00" }, "CustomField": [], "TxnDate": "2015-04-20", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "PrivateNote": "System-recorded fee for QuickBooks Payments. Fee-name: DiscountRateFee, fee-type: Daily.", "Line": [ { "Id": "1", "Description": "System-recorded fee for QuickBooks Payments. Fee-name: DiscountRateFee, fee-type: Daily.", "Amount": 0.28, "DetailType": "AccountBasedExpenseLineDetail", "AccountBasedExpenseLineDetail": { "AccountRef": { "value": "79", "name": "Bank Service Charges" }, "BillableStatus": "NotBillable", "TaxCodeRef": { "value": "NON" } } } ] }, "time": "2015-04-20T13:15:47.19-07:00" } |
There are two parts to refunding a transaction:
https://api.intuit.com/quickbooks/v4/payments/charges/{id}/refunds
application/json
Sample Request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { "amount": 5.0, "description": "first refund", "id": "", "context": { "deviceInfo": { "macAddress": "", "ipAddress": "", "longitude": "", "phoneNumber": "", "latitude": "", "type": "", "id": "" }, "tax": 0, "recurring": false }, "created": "" } |
Note the id that is returned in this response. You use it in the subsequent request to create a refund receipt.
View Sample Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | { "created": "2021-03-10T21:24:05Z", "status": "ISSUED", "amount": "5.00", "description": "first refund", "id": "XXXXXXXXXXX", "context": { "tax": "0.00", "reconBatchID": "420210310 1Q13249999999977036129AUTO04", "mobile": false, "paymentGroupingCode": "5", "txnAuthorizationStamp": "1615411445", "clientTransID": "amyxswe7", "deviceInfo": { "longitude": "", "latitude": "", "id": "", "type": "", "phoneNumber": "", "macAddress": "", "ipAddress": "" }, "recurring": false }, "type": "REFUND" } |
Now, create the refund receipt request. In order to take advantage of automatic reconciliation later when the payment refund transaction settles from merchant services, set the following parameters in the request:
CreditCardPayment.CreditChargeResponse.CCTransId
to the value returned in the original QuickBooks Payments refund response.CreditCardPayment.CrecitChargeInfo.ProcessPayment
to true
. This triggers QuickBooks Online services to store the credit card charge response information, in particular the CCTransId
field that is fundamental to credit card transaction reconciliation. This triggers the notation
Transaction has been processed for the refund receipt on the QuickBooks user interface.TxnSource
toIntuitPayment
. This inserts the transaction into a list of pending refunds to be automatically matched and reconciled with the merchant’s checking account.In addition,
Line.SalesItemLineDetail
sub-object.CreditCardPayment.CreditChargeResponse.CCTransId
.https://quickbooks.api.intuit.com/v3/company/<realmId>/refundreceipt
application/json
Sample Request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | { "Line": [{ "Id": "1", "LineNum": 1, "Description": "Sprinkler Pipes", "Amount": 80.0, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "17", "name": "Sprinkler Pipes" }, "UnitPrice": 4, "Qty": 20 } }], "CustomerRef": { "value": "15", "name": "Pye's Cakes" }, "CreditCardPayment": { "CreditChargeInfo": { "ProcessPayment": "true" }, "CreditChargeResponse": { "CCTransId": "EKFOR97XK9UD" } }, "TxnSource": "IntuitPayment", "DepositToAccountRef": { "value": "40", "name": "Checking" } } |
View Sample Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | { "RefundReceipt": { "domain": "QBO", "sparse": false, "Id": "930", "SyncToken": "0", "MetaData": { "CreateTime": "2014-04-25T09:40:43-07:00", "LastUpdatedTime": "2014-04-25T09:40:43-07:00" }, "CustomField": [ { "Name": "P.O. Number", "Type": "StringType" }, { "Name": "Sales Rep", "Type": "StringType" } ], "DocNumber": "10033", "TxnDate": "2014-04-25", "DepartmentRef": { "value": "1", "name": "Garden Services" }, "Line": [ { "Id": "1", "LineNum": 1, "Amount": 420, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "33", "name": "Concrete" }, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 420, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "TotalAmt": 420, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "Balance": 0, "PaymentRefNum": "To Print", "DepositToAccountRef": { "value": "40", "name": "Checking" } }, "time": "2014-04-25T09:40:43.687-07:00" } |
QuickBooks Online can manage product inventory. Line items entered on sales, purchase, and refund transactions flow into inventory items to automatically adjust quantity on hand. Additionally, cost and price of individual inventory items are stored so the merchant can track inventory value.
Enable inventory management for the QuickBooks company via Preferences.ProductAndServicesPrefs
. By default, it is not enabled. Set these flags to true:
ForSales
—Show product column on sales formsForPurchase
—Show product column on purchase formsQuantityWithPriceAndRate
—Quantity with price and rate enabled.QuantityOnHand
—Quantity on hand enabled.After enabling inventory management, add individual inventory items as Item objects.
Note
Note
and agreement.
Create an Item object for each inventory item that is tracked. Take care when using categories to define your products—they can add complexity when parsing out the inventory item of interest.
https://quickbooks.api.intuit.com/v3/company/<realmId>/item
application/json
Sample Request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "Name": "Office Supplies", "Description": "This is the sales description.", "Active": true, "Taxable": true, "UnitPrice": 25, "Type": "Inventory", "IncomeAccountRef": { "value": "79", "name": "Sales of Product Income" }, "PurchaseDesc": "This is the purchasing description.", "PurchaseCost": 35, "ExpenseAccountRef": { "value": "80", "name": "Cost of Goods Sold" }, "AssetAccountRef": { "value": "81", "name": "Inventory Asset" }, "TrackQtyOnHand": true, "QtyOnHand": 10, "InvStartDate": "2013-02-19" } |
View Sample Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | { "Item": { "Name": "Office Supplies", "Description": "This is the sales description.", "Active": true, "FullyQualifiedName": "Office Supplies", "Taxable": true, "UnitPrice": 25, "Type": "Inventory", "IncomeAccountRef": { "value": "79", "name": "Sales of Product Income" }, "PurchaseDesc": "This is the purchasing description.", "PurchaseCost": 35, "ExpenseAccountRef": { "value": "80", "name": "Cost of Goods Sold" }, "AssetAccountRef": { "value": "81", "name": "Inventory Asset" }, "TrackQtyOnHand": true, "QtyOnHand": 10, "InvStartDate": "2013-02-19", "domain": "QBO", "sparse": false, "Id": "36", "SyncToken": "0", "MetaData": { "CreateTime": "2015-04-17T15:21:09-07:00", "LastUpdatedTime": "2015-04-17T15:21:10-07:00" } }, "time": "2015-04-17T15:21:09.688-07:00" } |
Your app needs to provide options to allow merchants to manage and track their customers.
Having a customer reference attached to each sales receipt enables the merchant to accurately track customer activity.