| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- <?php defined('BX_DOL') or die('hack attempt');
- /**
- * Copyright (c) UNA, Inc - https://una.io
- * MIT License - https://opensource.org/licenses/MIT
- *
- * @defgroup StripeConnect Stripe Connect
- * @ingroup TridentModules
- *
- * @{
- */
- define('BX_STRIPE_CONNECT_MODE_LIVE', 'live');
- define('BX_STRIPE_CONNECT_MODE_TEST', 'test');
- define('BX_STRIPE_CONNECT_PMODE_DIRECT', 'direct');
- define('BX_STRIPE_CONNECT_PMODE_PLATFORM', 'platform');
- class BxStripeConnectModule extends BxBaseModGeneralModule
- {
- public function __construct(&$aModule)
- {
- parent::__construct($aModule);
- $this->_oConfig->init($this->_oDb);
- }
- /**
- *
- * SERVICE METHODS
- *
- */
- public function serviceGetSafeServices()
- {
- return array_merge(parent::serviceGetSafeServices(), [
- 'AccountSessionCreate' => '',
- 'AccountCreate' => '',
- 'AccountContinue' => '',
- 'AccountDelete' => ''
- ]);
- }
- public function serviceAccountCreate($iId)
- {
- $CNF = &$this->_oConfig->CNF;
- $sError = _t('_bx_stripe_connect_err_perform');
- if(empty($iId) || $iId != bx_get_logged_profile_id())
- return ['code' => 1, 'message' => $sError];
- $oProfile = BxDolProfile::getInstance($iId);
- if(!$oProfile)
- return ['code' => 1, 'message' => $sError];
- $sAccIdField = $CNF['FIELD_' . strtoupper($this->_oConfig->getMode()) . '_ACCOUNT_ID'];
- $oApi = BxStripeConnectApi::getInstance();
- $oAccount = $oApi->createAccount($oProfile->getAccountObject()->getEmail());
- if(!$oAccount)
- return ['code' => 1, 'message' => $sError];
- $this->_oDb->insertAccount([
- 'profile_id' => $iId,
- $sAccIdField => $oAccount->id
- ]);
- $sRefreshLink = $this->_oConfig->getRefreshLink();
- $sReturnLink = $this->_oConfig->getReturnLink();
- $oAccountLink = $oApi->createAccountLinks($oAccount->id, $sRefreshLink, $sReturnLink);
- if(!$oAccountLink)
- return ['code' => 1, 'message' => $sError];
- return ['code' => 0, 'redirect' => $oAccountLink->url];
- }
- public function serviceAccountContinue($iId)
- {
- $CNF = &$this->_oConfig->CNF;
- $sError = _t('_bx_stripe_connect_err_perform');
- if(empty($iId) || $iId != bx_get_logged_profile_id())
- return ['code' => 1, 'message' => $sError];
- $sModeUc = strtoupper($this->_oConfig->getMode());
- $sAccIdField = $CNF['FIELD_' . $sModeUc . '_ACCOUNT_ID'];
- $sAccDetailsField = $CNF['FIELD_' . $sModeUc . '_DETAILS'];
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iId]);
- if(empty($aAccount) || !is_array($aAccount) || $aAccount[$sAccIdField] == '')
- return ['code' => 1, 'message' => $sError];
- if((int)$aAccount[$sAccDetailsField] != 0)
- return ['code' => 0];
- $sRefreshLink = $this->_oConfig->getRefreshLink();
- $sReturnLink = $this->_oConfig->getReturnLink();
- $oAccountLink = BxStripeConnectApi::getInstance()->createAccountLinks($aAccount[$sAccIdField], $sRefreshLink, $sReturnLink);
- if(!$oAccountLink)
- return ['code' => 1, 'message' => $sError];
- return ['code' => 0, 'redirect' => $oAccountLink->url];
- }
- public function serviceAccountDelete($iId)
- {
- $CNF = &$this->_oConfig->CNF;
- $sError = _t('_bx_stripe_connect_err_perform');
- if(empty($iId) || $iId != bx_get_logged_profile_id())
- return ['code' => 1, 'message' => $sError];
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iId]);
- if(empty($aAccount) || !is_array($aAccount))
- return ['code' => 1, 'message' => $sError];
- $sAccIdField = $CNF['FIELD_' . strtoupper($this->_oConfig->getMode()) . '_ACCOUNT_ID'];
- $oAccount = BxStripeConnectApi::getInstance()->deleteAccount($aAccount[$sAccIdField]);
- if(!$oAccount || !$oAccount->deleted)
- return ['code' => 2, 'message' => _t('_bx_stripe_connect_err_delete')];
- $this->_oDb->deleteAccount([
- 'profile_id' => $iId,
- $sAccIdField => $oAccount->id
- ]);
- return ['code' => 0, 'reload' => 1];
- }
- public function serviceAccountSessionCreate($iProfileId)
- {
- $CNF = &$this->_oConfig->CNF;
- if(!$iProfileId || ($iProfileId != $this->_iProfileId && !isAdmin()))
- $iProfileId = $this->_iProfileId;
- if(!$iProfileId)
- return ['code' => 1];
- $sModeUc = strtoupper($this->_oConfig->getMode());
- $sAccIdField = $CNF['FIELD_' . $sModeUc . '_ACCOUNT_ID'];
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iProfileId]);
- if(empty($aAccount) || !is_array($aAccount) || $aAccount[$sAccIdField] == '')
- return ['code' => 1];
- $oAccountSession = BxStripeConnectApi::getInstance()->createAccountSessions($aAccount[$sAccIdField]);
- if(!$oAccountSession)
- return ['code' => 1];
- return [
- 'code' => 0,
- 'secret' => $oAccountSession->client_secret
- ];
- }
- /**
- * @page service Service Calls
- * @section bx_stripe_connect Stripe Connect
- * @subsection bx_stripe_connect-other Other
- * @subsubsection bx_stripe_connect-get_options_mode get_options_mode
- *
- * @code bx_srv('bx_stripe_connect', 'get_options_mode', [...]); @endcode
- *
- * Get an array with available modes. Is used in forms.
- *
- * @return an array with available modes represented as key => value pairs.
- *
- * @see BxStripeConnectModule::serviceGetOptionsMode
- */
- /**
- * @ref bx_stripe_connect-get_options_mode "get_options_mode"
- */
- public function serviceGetOptionsMode()
- {
- return [
- BX_STRIPE_CONNECT_MODE_LIVE => _t('_bx_stripe_connect_option_mode_live'),
- BX_STRIPE_CONNECT_MODE_TEST => _t('_bx_stripe_connect_option_mode_test'),
- ];
- }
- /**
- * @page service Service Calls
- * @section bx_stripe_connect Stripe Connect
- * @subsection bx_stripe_connect-other Other
- * @subsubsection bx_stripe_connect-get_options_pmode get_options_pmode
- *
- * @code bx_srv('bx_stripe_connect', 'get_options_pmode', [...]); @endcode
- *
- * Get an array with available processing modes for payments. Is used in forms.
- *
- * @return an array with available modes represented as key => value pairs.
- *
- * @see BxStripeConnectModule::serviceGetOptionsPmode
- */
- /**
- * @ref bx_stripe_connect-get_options_pmode "get_options_pmode"
- */
- public function serviceGetOptionsPmode()
- {
- return [
- BX_STRIPE_CONNECT_PMODE_DIRECT => _t('_bx_stripe_connect_option_pmode_direct'),
- //BX_STRIPE_CONNECT_PMODE_PLATFORM => _t('_bx_stripe_connect_option_pmode_platform'),
- ];
- }
- public function serviceGetOptionValueMode($iVendorId, $aParams = [])
- {
- return _t('_bx_stripe_connect_option_mode_' . $this->_oConfig->getMode());
- }
- public function serviceGetOptionValueLiveAccountId($iVendorId, $aParams = [])
- {
- $CNF = &$this->_oConfig->CNF;
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iVendorId]);
- if(empty($aAccount) || !is_array($aAccount))
- return '';
- return $aAccount[$CNF['FIELD_LIVE_ACCOUNT_ID']];
- }
- public function serviceGetOptionValueTestAccountId($iVendorId, $aParams = [])
- {
- $CNF = &$this->_oConfig->CNF;
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iVendorId]);
- if(empty($aAccount) || !is_array($aAccount))
- return '';
- return $aAccount[$CNF['FIELD_TEST_ACCOUNT_ID']];
- }
- public function serviceGetConnectCode($iVendorId, $aParams = [])
- {
- return $this->_oTemplate->getConnectCode($iVendorId, $aParams);
- }
- public function serviceGetBlockPayments()
- {
- if(!isLogged())
- return $this->_bIsApi ? [] : '';
-
- if($this->_bIsApi)
- return [bx_api_get_block('stripe_connect', [
- 'key' => $this->_oConfig->getApiPublicKey(),
- 'embed' => 'payments'
- ])];
- return $this->_oTemplate->getBlockPayments();
- }
- /*
- * Isn't supported with the current SDK. It's still in Beta mode.
- * https://docs.stripe.com/connect/supported-embedded-components/reporting-chart
- */
- public function serviceGetBlockReportingChart()
- {
- if(!isLogged())
- return $this->_bIsApi ? [] : '';
- if($this->_bIsApi)
- return [bx_api_get_block('stripe_connect', [
- 'key' => $this->_oConfig->getApiPublicKey(),
- 'embed' => 'reporting-chart'
- ])];
-
- return $this->_oTemplate->getBlockReportingChart();
- }
- public function serviceGetBlockBalances()
- {
- if(!isLogged())
- return $this->_bIsApi ? [] : '';
- if($this->_bIsApi)
- return [bx_api_get_block('stripe_connect', [
- 'key' => $this->_oConfig->getApiPublicKey(),
- 'embed' => 'balances'
- ])];
- return $this->_oTemplate->getBlockBalances();
- }
- public function serviceGetBlockNotifications()
- {
- if(!isLogged())
- return $this->_bIsApi ? [] : '';
- if($this->_bIsApi)
- return [bx_api_get_block('stripe_connect', [
- 'key' => $this->_oConfig->getApiPublicKey(),
- 'embed' => 'notification-banner'
- ])];
- return $this->_oTemplate->getBlockNotifications();
- }
- /**
- *
- * ACTION METHODS
- *
- */
- public function actionNotify()
- {
- $iResult = $this->_processEvent();
- http_response_code($iResult);
- }
- public function actionAccountCreate()
- {
- return echoJson($this->serviceAccountCreate((int)bx_get('id')));
- }
- public function actionAccountContinue()
- {
- return echoJson($this->serviceAccountContinue((int)bx_get('id')));
- }
- public function actionAccountDelete()
- {
- return echoJson($this->serviceAccountDelete((int)bx_get('id')));
- }
- public function actionAccountSessionCreate($iProfileId)
- {
- return echoJson($this->serviceAccountSessionCreate($iProfileId));
- }
- /**
- *
- * OTHER METHODS
- *
- */
- public function hasAccount($iVendorId)
- {
- return $this->_oDb->hasAccount($iVendorId, $this->_oConfig->getMode());
- }
- public function processAlertStripeV3GetButton($iObject, $iSender, $aParams)
- {
- $CNF = &$this->_oConfig->CNF;
- $iVendorId = 0;
- if(empty($aParams['vendor_id']) || ($iVendorId = (int)$aParams['vendor_id']) == $this->_oConfig->getMainSeller())
- return false;
- $sModeUc = strtoupper($this->_oConfig->getMode());
- $sAccIdField = $CNF['FIELD_' . $sModeUc . '_ACCOUNT_ID'];
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iVendorId]);
- if(empty($aAccount) || !is_array($aAccount) || empty($aAccount[$sAccIdField]))
- return false;
- $aParams['public_key'] = $this->_oConfig->getApiPublicKey();
- $aParams['connected_account_id'] = $aAccount[$sAccIdField];
- return !empty($aParams['public_key']);
- }
- public function processAlertStripeV3CreateSession($iObject, $iSender, $aParams)
- {
- $CNF = &$this->_oConfig->CNF;
- if(empty($aParams['session_params']))
- return false;
- try {
- $sModeUc = strtoupper($this->_oConfig->getMode());
- $sAccIdField = $CNF['FIELD_' . $sModeUc . '_ACCOUNT_ID'];
-
- $iVendorId = (int)$aParams['session_params']['metadata']['vendor'];
- if($iVendorId == $this->_oConfig->getMainSeller())
- return false;
- $aAccount = $this->_oDb->getAccount(['sample' => 'profile_id', 'profile_id' => $iVendorId]);
- if(empty($aAccount) || !is_array($aAccount) || empty($aAccount[$sAccIdField]))
- return false;
- switch($aParams['session_params']['mode']) {
- case 'payment':
- $fAmount = 0;
- foreach($aParams['session_params']['line_items'] as $aLineItem)
- $fAmount += (float)$aLineItem['price_data']['unit_amount'] * (int)$aLineItem['quantity'];
- if($fAmount && ($fAmount = $this->_oConfig->getFee(BX_PAYMENT_TYPE_SINGLE, $iVendorId, $fAmount))) {
- if(!isset($aParams['session_params']['payment_intent_data']))
- $aParams['session_params']['payment_intent_data'] = [];
- $aParams['session_params']['payment_intent_data']['application_fee_amount'] = $fAmount;
- }
- break;
- case 'subscription':
- $fAmount = 0;
- foreach($aParams['session_params']['line_items'] as $aLineItem)
- $fAmount += (float)$aLineItem['price_data']['unit_amount'] * (int)$aLineItem['quantity'];
- if($fAmount && ($fAmount = $this->_oConfig->getFee(BX_PAYMENT_TYPE_RECURRING, $iVendorId, $fAmount))) {
- if(!isset($aParams['session_params']['subscription_data']))
- $aParams['session_params']['subscription_data'] = [];
- $aParams['session_params']['subscription_data']['application_fee_percent'] = $fAmount;
- }
- break;
- }
- $aParams['session_object'] = BxStripeConnectApi::getInstance()->getStripe()->checkout->sessions->create($aParams['session_params'], [
- 'stripe_account' => $aAccount[$sAccIdField]
- ]);
- }
- catch (Exception $oException) {
- $aParams['session_object'] = null;
- return $this->_processException('Create Session Error: ', $oException);
- }
- return !empty($aParams['session_object']);
- }
- protected function _processEvent()
- {
- $sInput = @file_get_contents("php://input");
- $aEvent = json_decode($sInput, true);
- if(empty($aEvent) || !is_array($aEvent))
- return 404;
- $sType = $aEvent['type'];
- if(!in_array($sType, ['account.updated']))
- return 200;
- $this->_log('Webhooks: ' . (!empty($sType) ? $sType : ''));
- $this->_log($aEvent);
- $sMethod = '_processEvent' . bx_gen_method_name($sType, array('.', '_', '-'));
- if(!method_exists($this, $sMethod))
- return 200;
- return $this->$sMethod($aEvent) ? 200 : 403;
- }
- protected function _processEventAccountUpdated(&$aEvent)
- {
- $CNF = $this->_oConfig->CNF;
- $sAccountId = '';
- if(!isset($aEvent['data']['object']['id']) || !($sAccountId = bx_process_input($aEvent['data']['object']['id'])))
- return false;
- $sMode = $this->_oConfig->getMode();
- $sAccDetailsField = $CNF['FIELD_' . strtoupper($sMode) . '_DETAILS'];
- $aAccount = $this->_oDb->getAccount(['sample' => 'account_id', $sMode . '_account_id' => $sAccountId]);
- if((int)$aAccount[$sAccDetailsField] == 0 && $aEvent['data']['object']['details_submitted'])
- return $this->_oDb->updateAccount([$sAccDetailsField => 1], [$CNF['FIELD_ID'] => $aAccount[$CNF['FIELD_ID']]]);
- return true;
- }
- protected function _processException($sMessage, &$oException)
- {
- $aError = $oException->getJsonBody();
- $sMessage = $aError['error']['message'];
- if(empty($sMessage))
- $sMessage = $oException->getMessage();
- $this->_log($sMessage . $aError['error']['message']);
- $this->_log($aError);
- return false;
- }
- protected function _log($sContents)
- {
- if (is_array($sContents))
- $sContents = var_export($sContents, true);
- else if (is_object($sContents))
- $sContents = json_encode($sContents);
- bx_log('bx_stripe_connect', $sContents, BX_LOG_ERR);
- }
- }
- /** @} */
|