BxXeroModule.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup Xero Xero
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. define('BX_XERO_ACCOUNT_CODE_SALES', 200);
  12. define('BX_XERO_ACCOUNT_CODE_PURCHASES', 300);
  13. define('BX_XERO_ACCOUNT_CODE_ADVERTIXING', 400);
  14. class BxXeroModule extends BxDolModule
  15. {
  16. protected $_oApi;
  17. protected $_oLog;
  18. function __construct($aModule)
  19. {
  20. parent::__construct($aModule);
  21. $this->_oConfig->init($this->_oDb);
  22. bx_import('Api', $aModule);
  23. $this->_oApi = new BxXeroApi($this);
  24. $this->_oLog = $this->_oConfig->getObjectLog();
  25. }
  26. /**
  27. * ACTION METHODS
  28. */
  29. public function actionAuthorize()
  30. {
  31. header('Location: ' . $this->_oApi->authorize());
  32. exit;
  33. }
  34. public function actionCallback()
  35. {
  36. $sCode = bx_process_input(bx_get('code'));
  37. if($sCode === false) {
  38. header('Location: ' . $this->_oConfig->getAuthorizeUrl(1));
  39. exit();
  40. }
  41. if(($sState = bx_get('state')) === false || $sState != $this->_oConfig->getState()) {
  42. $this->_oConfig->unsetState();
  43. header('Location: ' . $this->_oConfig->getAuthorizeUrl(2));
  44. exit();
  45. }
  46. $sUrl = $this->_oApi->callback($sCode);
  47. if($sUrl === false)
  48. $sUrl = $this->_oConfig->getAuthorizeUrl(3);
  49. header('Location: ' . $sUrl);
  50. exit();
  51. }
  52. public function actionWebhook()
  53. {
  54. $sResponse = file_get_contents('php://input');
  55. $sSignatureComputed = base64_encode(hash_hmac('sha256', $sResponse, $this->_oConfig->getWebhookKey(), true));
  56. $sSignatureReceived = isset($_SERVER['HTTP_X_XERO_SIGNATURE']) ? $_SERVER['HTTP_X_XERO_SIGNATURE'] : '';
  57. if(!hash_equals($sSignatureComputed, $sSignatureReceived)) {
  58. @$this->_oLog->write('Get Webhook: Wrong Signature', $sSignatureComputed, $sSignatureReceived);
  59. http_response_code(401);
  60. return;
  61. }
  62. http_response_code(200);
  63. $aResponce = json_decode($sResponse, true);
  64. if(empty($aResponce) || !is_array($aResponce))
  65. return;
  66. foreach($aResponce['events'] as $aEvent) {
  67. $sMethod = '_process' . bx_gen_method_name(strtolower($aEvent['eventType']) . '_' . strtolower($aEvent['eventCategory']));
  68. if(!method_exists($this, $sMethod))
  69. continue;
  70. $this->$sMethod($aEvent['resourceId']);
  71. }
  72. }
  73. public function actionTest()
  74. {
  75. $mixedResult = $this->_oApi->actionTest();
  76. if($mixedResult !== false)
  77. $mixedResult = _t('_bx_xero_txt_organization', $mixedResult);
  78. else
  79. $mixedResult = _t('_bx_xero_txt_err_unknown');
  80. echo $mixedResult;
  81. }
  82. /**
  83. * SERVICE METHODS
  84. */
  85. public function serviceIncludeCssJs()
  86. {
  87. return $this->_oTemplate->getIncludeCssJs();
  88. }
  89. public function serviceIsContact($iProfileId, $bForceCheckApi = false)
  90. {
  91. $oProfile = BxDolProfile::getInstance($iProfileId);
  92. if(!$oProfile)
  93. return false;
  94. $sProfileEmail = $oProfile->getAccountObject()->getEmail();
  95. return $this->isContact($sProfileEmail, $bForceCheckApi);
  96. }
  97. public function serviceAddContact($iProfileId)
  98. {
  99. $oProfile = BxDolProfile::getInstance($iProfileId);
  100. if(!$oProfile)
  101. return false;
  102. $sProfileName = $oProfile->getDisplayName();
  103. $sProfileEmail = $oProfile->getAccountObject()->getEmail();
  104. return $this->_oApi->actionAddContact($iProfileId, $sProfileName, $sProfileEmail);
  105. }
  106. public function serviceAddInvoce($iProfileId, $sName, $fAmount, $iQuantity = 1, $sDueDate = false)
  107. {
  108. $oProfile = BxDolProfile::getInstance($iProfileId);
  109. if(!$oProfile)
  110. return false;
  111. $sProfileEmail = $oProfile->getAccountObject()->getEmail();
  112. return $this->_oApi->actionAddInvoice($sProfileEmail, $sName, $fAmount, $iQuantity, $sDueDate);
  113. }
  114. public function serviceAddInvoceAuto($iProfileId, $sName, $fAmount, $iQuantity = 1, $mixedDueDate = false)
  115. {
  116. $oProfile = BxDolProfile::getInstance($iProfileId);
  117. if(!$oProfile)
  118. return false;
  119. $sProfileEmail = $oProfile->getAccountObject()->getEmail();
  120. if(!$this->isContact($sProfileEmail)) {
  121. $sProfileName = $oProfile->getDisplayName();
  122. if($this->_oApi->actionAddContact($iProfileId, $sProfileName, $sProfileEmail) === false)
  123. return false;
  124. }
  125. return $this->_oApi->actionAddInvoice($sProfileEmail, $sName, $fAmount, $iQuantity, $mixedDueDate);
  126. }
  127. /*
  128. * COMMON METHODS
  129. */
  130. public function getApi()
  131. {
  132. return $this->_oApi;
  133. }
  134. public function isContact($sProfileEmail, $bForceCheckApi = false)
  135. {
  136. if(!$bForceCheckApi && $this->_oDb->isContact($sProfileEmail))
  137. return true;
  138. return $this->_oApi->actionIsContact($sProfileEmail);
  139. }
  140. /*
  141. * INTERNAL METHODS
  142. */
  143. protected function _processCreateInvoice($sId)
  144. {
  145. $oInvoice = $this->_oApi->actionGetInvoice($sId);
  146. $aInvoice = $this->_getInvoiceData($oInvoice);
  147. $this->_oLog->write('Create Invoice: ' . $sId, $aInvoice);
  148. bx_alert($this->_oConfig->getName(), 'invoice_created', 0, 0, array(
  149. 'id' => $sId,
  150. 'invoice' => $aInvoice,
  151. ));
  152. }
  153. protected function _processUpdateInvoice($sId)
  154. {
  155. $oInvoice = $this->_oApi->actionGetInvoice($sId);
  156. $aInvoice = $this->_getInvoiceData($oInvoice);
  157. $this->_oLog->write('Update Invoice: ' . $sId, $aInvoice);
  158. bx_alert($this->_oConfig->getName(), 'invoice_updated', 0, 0, array(
  159. 'id' => $sId,
  160. 'invoice' => $aInvoice,
  161. ));
  162. }
  163. protected function _getInvoiceData($oInvoice)
  164. {
  165. return [
  166. 'id' => $oInvoice->getInvoiceId(),
  167. 'number' => $oInvoice->getInvoiceNumber(),
  168. 'reference' => $oInvoice->getReference(),
  169. 'currency_code' => $oInvoice->getCurrencyCode(),
  170. 'sub_total' => $oInvoice->getSubTotal(),
  171. 'total_tax' => $oInvoice->getTotalTax(),
  172. 'total' => $oInvoice->getTotal(),
  173. 'amount_due' => $oInvoice->getAmountDue(),
  174. 'amount_paid' => $oInvoice->getAmountPaid(),
  175. 'status' => $oInvoice->getStatus(),
  176. ];
  177. }
  178. }
  179. /** @} */