这个帖子写给不太了解PHP与API开发的人 一、先简单回答两个问题: 1、PHP 可以开发客户端? 答:不可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:服务端的开发。(别去纠结…
June 30, 2020
QuickBooks App 开发教程:PHP 创建你的第一个App, Build your first app
要求:
PHP
- PHP > 5.6
- Composer
- Git Client
1. 克隆Hello World应用程序即可开始
克隆Hello World应用程序是引导构建新的QuickBooks应用程序的最佳方法。它设置您的开发环境,以便您可以使用最新的SDK,通过启用日志记录来提供良好的开发人员体验,并优化您的应用程序以进行生产。
$ git clone https://github.com/IntuitDeveloper/HelloWorld-PHP.git $ cd HelloWorld-PHP $ curl -sS https://getcomposer.org/installer | php $ composer install
要运行Hello World App,您将需要创建和配置一个应用程序以允许在开发人员门户中访问QuickBooks Online 。
2. 在开发人员门户中创建和配置应用
如果您已经在开发人员门户中创建了应用程序,则可以跳过步骤2、3和4。
- 登录到开发人员门户。从右上角的菜单中选择我的应用程序。

- 在“ 我的应用程序”仪表板中,通过单击+创建应用程序按钮创建一个新应用程序。

- 选择“ 在线快速书和付款”。

- 为您的应用命名,从“ 国家”下拉列表中选择您的国家,然后从“ 选择范围”下拉列表中选择“ 会计 ” 。然后点击创建应用。

- 创建应用程序后,您可以从仪表板中查看其详细信息。

- 开发和生产键可以在左侧的边栏中找到。在开发下,选择密钥和OAuth。

- 找到您的客户ID和客户机密。

- 作为此应用程序的开发人员,您必须在客户通过授权流程后使用他们的应用程序重定向客户。对于本教程,我们将Hello World App的用户重定向到回调页面。在“ 重定向URI”部分下设置“ 链接”字段,然后单击“ 保存”。对于世界,您好!示例应用程序,重定向URL为http://localhost:3000/callback。

3. 进行授权流程
要访问QuickBooks公司的数据,QBO用户必须通过授权流程对您的应用程序进行授权。在该过程结束时,您将获得一个访问令牌,该令牌用于发出QBO API请求。要启动授权流程,QBO用户单击“ 连接到QuickBooks”按钮。
创建开发者帐户还会创建一个QuickBooks测试公司(也称为Sandbox公司)。您将使用该Sandbox公司浏览授权流程,以查看其外观。
首先,使用您的客户端ID,客户端密钥和重定向URI配置“ Hello,World”应用程序。编辑config.php文件以添加应用程序的clientId和clientSecret
config.php
<?php return array( 'authorizationRequestUrl' => 'https://appcenter.intuit.com/connect/oauth2', 'tokenEndPointUrl' => 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer', 'client_id' => 'Enter the clietID from Developer Portal', 'client_secret' => 'Enter the clientSecret from Developer Portal', 'oauth_scope' => 'com.intuit.quickbooks.accounting openid profile email phone address', 'oauth_redirect_uri' => 'http://localhost:3000/callback.php', ) ?>
'client_id' => 'Enter the clietID from Developer Portal', 'client_secret' => 'Enter the clientSecret from Developer Portal',
通过在终端上输入以下内容来运行Hello World应用程序:
$ php -S localhost:3000
打开浏览器,键入localhost:3000,就可以开始了。这样的窗口将出现在您的浏览器中:

- 单击“ 连接到QuickBooks”将您的应用程序与Sandbox公司连接。使用您的开发者帐户登录,然后点击授权。

4. 进行首次API调用
单击Authorize之后,将重定向到您之前指定的URI,即http:// localhost:3000 / callback
现在,您可以对连接到的Sandbox QuickBooks公司进行首次API调用,并获取CompanyInfo。单击获取公司信息按钮,您将看到公司信息的结果:
5. 查看代码
下面我们将讨论在HelloWorld PHP示例中使用的逻辑。该的index.php文件将具有主页,发起授权流,使得QBO API请求,并callback.php它处理重定向后QBO用户已授权的应用程序,交易所授权码来获得访问和刷新令牌,然后将控制权回到index.php文件。
- auth_mode:此处为“ oauth2”
- 客户端ID:“应用程序的密钥”标签中的“客户端ID”,请参阅第2步
- 客户端机密:“应用程序的密钥”标签中的“客户端机密”,请参阅步骤2
- RedirectURI:确定将响应发送到的位置。此参数的值必须与应用设置中为此应用列出的值之一完全匹配
- 范围:授予DataService的访问量,即“ com.intuit.quickbooks.accounting”
- baseUrl:此应用程序使用的API端点。
DataService对象将用于构造OAuth2LoginHelper对象。
OAuth2LoginHelper将帮助开发人员完成所有必要的步骤,以检索将应用程序连接到用户的QBO公司所需的访问令牌。
我们使用OAuth2LoginHelper对象在index.php文件中生成授权码URL,然后在浏览器中呈现授权码URL。
<?php require_once(__DIR__ . '/vendor/autoload.php'); use QuickBooksOnline\API\DataService\DataService; $config = include('config.php'); session_start(); $dataService = DataService::Configure(array( 'auth_mode' => 'oauth2', 'ClientID' => $config['client_id'], 'ClientSecret' => $config['client_secret'], 'RedirectURI' => $config['oauth_redirect_uri'], 'scope' => $config['oauth_scope'], 'baseUrl' => "development" )); $OAuth2LoginHelper = $dataService->getOAuth2LoginHelper(); $authUrl = $OAuth2LoginHelper->getAuthorizationCodeURL(); // Store the url in PHP Session Object; $_SESSION['authUrl'] = $authUrl; //set the access token using the auth object if (isset($_SESSION['sessionAccessToken'])) { $accessToken = $_SESSION['sessionAccessToken']; $accessTokenJson = array('token_type' => 'bearer', 'access_token' => $accessToken->getAccessToken(), 'refresh_token' => $accessToken->getRefreshToken(), 'x_refresh_token_expires_in' => $accessToken->getRefreshTokenExpiresAt(), 'expires_in' => $accessToken->getAccessTokenExpiresAt() ); $dataService->updateOAuth2Token($accessToken); $oauthLoginHelper = $dataService -> getOAuth2LoginHelper(); $CompanyInfo = $dataService->getCompanyInfo(); } ?>
说明 callback.php
在向用户显示授权代码URL后,他们将开始对应用程序进行授权,带有realmID的授权代码将返回到我们在config.php文件中指定的RedirectURI。我们会将这些值传递给OAuth2LoginHelper对象以生成我们的令牌。
在此步骤之后,OAuth 2令牌生成步骤被视为已完成。
<?php require_once(__DIR__ . '/vendor/autoload.php'); use QuickBooksOnline\API\DataService\DataService; session_start(); function processCode() { // Create SDK instance $config = include('config.php'); $dataService = DataService::Configure(array( 'auth_mode' => 'oauth2', 'ClientID' => $config['client_id'], 'ClientSecret' => $config['client_secret'], 'RedirectURI' => $config['oauth_redirect_uri'], 'scope' => $config['oauth_scope'], 'baseUrl' => "development" )); $OAuth2LoginHelper = $dataService->getOAuth2LoginHelper(); $parseUrl = parseAuthRedirectUrl($_SERVER['QUERY_STRING']); /* * Update the OAuth2Token */ $accessToken = $OAuth2LoginHelper->exchangeAuthorizationCodeForToken($parseUrl['code'], $parseUrl['realmId']); $dataService->updateOAuth2Token($accessToken); /* * Setting the accessToken for session variable */ $_SESSION['sessionAccessToken'] = $accessToken; } function parseAuthRedirectUrl($url) { parse_str($url,$qsArray); return array( 'code' => $qsArray['code'], 'realmId' => $qsArray['realmId'] ); } $result = processCode(); ?>
附录:
index.php
<?php require_once(__DIR__ . '/vendor/autoload.php'); use QuickBooksOnline\API\DataService\DataService; $config = include('config.php'); session_start(); $dataService = DataService::Configure(array( 'auth_mode' => 'oauth2', 'ClientID' => $config['client_id'], 'ClientSecret' => $config['client_secret'], 'RedirectURI' => $config['oauth_redirect_uri'], 'scope' => $config['oauth_scope'], 'baseUrl' => "development" )); $OAuth2LoginHelper = $dataService->getOAuth2LoginHelper(); $authUrl = $OAuth2LoginHelper->getAuthorizationCodeURL(); // Store the url in PHP Session Object; $_SESSION['authUrl'] = $authUrl; //set the access token using the auth object if (isset($_SESSION['sessionAccessToken'])) { $accessToken = $_SESSION['sessionAccessToken']; $accessTokenJson = array('token_type' => 'bearer', 'access_token' => $accessToken->getAccessToken(), 'refresh_token' => $accessToken->getRefreshToken(), 'x_refresh_token_expires_in' => $accessToken->getRefreshTokenExpiresAt(), 'expires_in' => $accessToken->getAccessTokenExpiresAt() ); $dataService->updateOAuth2Token($accessToken); $oauthLoginHelper = $dataService -> getOAuth2LoginHelper(); $CompanyInfo = $dataService->getCompanyInfo(); } ?> <!DOCTYPE html> <html> <head> <link rel="apple-touch-icon icon shortcut" type="image/png" href="https://plugin.intuitcdn.net/sbg-web-shell-ui/6.3.0/shell/harmony/images/QBOlogo.png"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> <link rel="stylesheet" href="views/common.css"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <script> var url = '<?php echo $authUrl; ?>'; var OAuthCode = function(url) { this.loginPopup = function (parameter) { this.loginPopupUri(parameter); } this.loginPopupUri = function (parameter) { // Launch Popup var parameters = "location=1,width=800,height=650"; parameters += ",left=" + (screen.width - 800) / 2 + ",top=" + (screen.height - 650) / 2; var win = window.open(url, 'connectPopup', parameters); var pollOAuth = window.setInterval(function () { try { if (win.document.URL.indexOf("code") != -1) { window.clearInterval(pollOAuth); win.close(); location.reload(); } } catch (e) { console.log(e) } }, 100); } } var apiCall = function() { this.getCompanyInfo = function() { /* AJAX Request to retrieve getCompanyInfo */ $.ajax({ type: "GET", url: "apiCall.php", }).done(function( msg ) { $( '#apiCall' ).html( msg ); }); } this.refreshToken = function() { $.ajax({ type: "POST", url: "refreshToken.php", }).done(function( msg ) { }); } } var oauth = new OAuthCode(url); var apiCall = new apiCall(); </script> </head> <body> <div class="container"> <h1> <a href="http://developer.intuit.com"> <img src="views/quickbooks_logo_horz.png" id="headerLogo"> </a> </h1> <hr> <div class="well text-center"> <h1>QuickBooks HelloWorld sample application</h1> <h2>Demonstrate Connect to QuickBooks flow and API Request</h2> <br> </div> <p>If there is no access token or the access token is invalid, click the <b>Connect to QuickBooks</b> button below.</p> <pre id="accessToken"> <style="background-color:#efefef;overflow-x:scroll"><?php $displayString = isset($accessTokenJson) ? $accessTokenJson : "No Access Token Generated Yet"; echo json_encode($displayString, JSON_PRETTY_PRINT); ?> </pre> <a class="imgLink" href="#" onclick="oauth.loginPopup()"><img src="views/C2QB_green_btn_lg_default.png" width="178" /></a> <hr /> <h2>Make an API call</h2> <p>If there is no access token or the access token is invalid, click either the <b>Connect to QuickBooks</b> button above.</p> <pre id="apiCall"></pre> <button type="button" class="btn btn-success" onclick="apiCall.getCompanyInfo()">Get Company Info</button> <hr /> </div> </body> </html>
callback.php
<?php require_once(__DIR__ . '/vendor/autoload.php'); use QuickBooksOnline\API\DataService\DataService; session_start(); function processCode() { // Create SDK instance $config = include('config.php'); $dataService = DataService::Configure(array( 'auth_mode' => 'oauth2', 'ClientID' => $config['client_id'], 'ClientSecret' => $config['client_secret'], 'RedirectURI' => $config['oauth_redirect_uri'], 'scope' => $config['oauth_scope'], 'baseUrl' => "development" )); $OAuth2LoginHelper = $dataService->getOAuth2LoginHelper(); $parseUrl = parseAuthRedirectUrl($_SERVER['QUERY_STRING']); /* * Update the OAuth2Token */ $accessToken = $OAuth2LoginHelper->exchangeAuthorizationCodeForToken($parseUrl['code'], $parseUrl['realmId']); $dataService->updateOAuth2Token($accessToken); /* * Setting the accessToken for session variable */ $_SESSION['sessionAccessToken'] = $accessToken; } function parseAuthRedirectUrl($url) { parse_str($url,$qsArray); return array( 'code' => $qsArray['code'], 'realmId' => $qsArray['realmId'] ); } $result = processCode(); ?>
下载:
本文:QuickBooks App 开发教程:PHP 创建你的第一个App, Build your first app