...
 
Commits (4)
......@@ -20,7 +20,14 @@ class connect implements Interfaces\Api
$connectManager = new Stripe\Connect\Manager();
$account = $connectManager->getByUser($user);
try {
$account = $connectManager->getByUser($user);
} catch (\Exception $e) {
return Factory::response([
'status' => 'error',
'message' => 'There was an error returning the usd account',
]);
}
return Factory::response([
'account' => $account->export(),
......
<?php
/**
*
*/
namespace Minds\Controllers\api\v2\payments\stripe\connect;
use Minds\Api\Factory;
use Minds\Common\Cookie;
use Minds\Core\Di\Di;
use Minds\Core\Config;
use Minds\Core\Session;
use Minds\Interfaces;
use Minds\Core\Payments\Stripe;
class photoid implements Interfaces\Api
{
public function get($pages)
{
return Factory::response([]);
}
public function post($pages)
{
$user = Session::getLoggedInUser();
$connectManager = new Stripe\Connect\Manager();
$account = $connectManager->getByUser($user);
$fp = fopen($_FILES['file']['tmp_name'], 'r');
$connectManager->addPhotoId($account, $fp);
return Factory::response([ 'account_id' => $account->getId() ]);
}
public function put($pages)
{
return Factory::response([]);
}
public function delete($pages)
{
return Factory::response([]);
}
}
<?php
/**
*
*/
namespace Minds\Controllers\api\v2\payments\stripe\connect;
use Minds\Api\Factory;
use Minds\Common\Cookie;
use Minds\Core\Di\Di;
use Minds\Core\Config;
use Minds\Core\Session;
use Minds\Interfaces;
use Minds\Core\Payments\Stripe;
class terms implements Interfaces\Api
{
public function get($pages)
{
return Factory::response([]);
}
public function post($pages)
{
return Factory::response([]);
}
public function put($pages)
{
$user = Session::getLoggedInUser();
$connectManager = new Stripe\Connect\Manager();
$account = $connectManager->getByUser($user);
$account->setIp($_SERVER['HTTP_X_FORWARDED_FOR']);
$connectManager->acceptTos($account);
return Factory::response([]);
}
public function delete($pages)
{
return Factory::response([]);
}
}
......@@ -95,6 +95,24 @@ class Account
/** @var string $status */
private $status = "processing";
/** @var Balance $totalBalance */
private $totalBalance;
/** @var Balance $pendingBalance */
private $pendingBalance;
/** @var string $payoutInterval */
private $payoutInterval;
/** @var int $payoutDelay */
private $payoutDelay;
/** @var int $payoutAnchor */
private $payoutAnchor;
/** @var string $requirement */
private $requirement;
/** @var array $exportable */
private $exportable = [
'guid',
......@@ -118,6 +136,10 @@ class Account
'status',
'verified',
'bankAccount',
'payoutInterval',
'payoutDelay',
'payoutAnchor',
'requirement',
];
/**
......@@ -146,6 +168,14 @@ class Account
$export[$field] = $this->$field;
}
if ($this->totalBalance) {
$export['totalBalance'] = $this->totalBalance->export();
}
if ($this->pendingBalance) {
$export['pendingBalance'] = $this->pendingBalance->export();
}
return $export;
}
}
<?php
/**
* Stripe Connect Balance
*/
namespace Minds\Core\Payments\Stripe\Connect;
use Minds\Traits\MagicAttributes;
/**
* @method Balance getAmount(): int
* @method Balance getCurrency(): string
*/
class Balance
{
use MagicAttributes;
/** @var int $amount */
private $amount;
/** @var string $currency */
private $currency;
/**
* Expose to public API
* @return array
*/
public function export(array $extend = []) : array
{
return [
'amount' => (int) $this->amount,
'currency' => $this->currency,
];
}
}
......@@ -6,6 +6,8 @@ use Minds\Core\Entities\Actions\Save;
use Minds\Core\Payments\Stripe\Connect\Delegates\NotificationDelegate;
use Minds\Core\Payments\Stripe\Currencies;
use Minds\Core\Payments\Stripe\Instances\AccountInstance;
use Minds\Core\Payments\Stripe\Instances\BalanceInstance;
use Minds\Core\Payments\Stripe\Instances\FileInstance;
use Stripe;
use Minds\Entities\User;
......@@ -20,14 +22,24 @@ class Manager
/** @var AccountInstance $accountInstance */
private $accountInstance;
/** @var BalanceInstance $balanceInstance */
private $balanceInstance;
/** @var FileInstance $fileInstance */
private $fileInstance;
public function __construct(
Save $save = null,
NotificationDelegate $notificationDelegate = null,
AccountInstance $accountInstance = null
AccountInstance $accountInstance = null,
BalanceInstance $balanceInstance = null,
FileInstance $fileInstance = null
) {
$this->save = $save ?: new Save();
$this->notificationDelegate = $notificationDelegate ?: new NotificationDelegate();
$this->accountInstance = $accountInstance ?: new AccountInstance();
$this->balanceInstance = $balanceInstance ?: new BalanceInstance();
$this->fileInstance = $fileInstance ?: new FileInstance();
}
/**
......@@ -167,6 +179,27 @@ class Manager
return $stripeAccount->id;
}
/**
* Updates a stripe connect account
* @param $account
* @return bool
* @throws \Exception
*/
public function acceptTos(Account $account) : bool
{
try {
$this->accountInstance->update($account->getId(), [
'tos_acceptance' => [
'date' => time(),
'ip' => $account->getIp(),
],
]);
return true;
} catch (\Exception $e) {
return false;
}
}
/**
* Add a bank account to stripe account
* @param Account $account
......@@ -195,12 +228,26 @@ class Manager
return true;
}
/**
* Add photo Id
* @param Account $account
* @param resource $file
* @return bool
*/
public function addPhotoId(Account $account, $file) : bool
{
return (bool) $this->fileInstance->create([
'purpose' => 'identity_document',
'file' => $file,
], [ 'stripe_account' => $account->getId() ]);
}
/**
* Return a stripe account
* @param string $id
* @return Account
*/
public function getByAccountId(string $id) : Account
public function getByAccountId(string $id) : ?Account
{
try {
$result = $this->accountInstance->retrieve($id);
......@@ -223,20 +270,30 @@ class Manager
->setBankAccount($result->external_accounts->data[0])
->setAccountNumber($result->external_accounts->data[0]['last4'])
->setRoutingNumber($result->external_accounts->data[0]['routing_number'])
->setDestination('bank');
->setDestination('bank')
->setPayoutInterval($result->settings->payouts->schedule->interval)
->setPayoutDelay($result->settings->payouts->schedule->delay_days)
->setPayoutAnchor($result->settings->payouts->schedule->monthly_anchor);
//verifiction check
if ($result->legal_entity->verification->status === 'verified') {
$account->setVerified(true);
}
if ($result->verification->disabled_reason == 'fields_needed') {
if ($result->verification->fields_needed[0] == 'legal_entity.verification.document') {
$account->setStatus('awaiting-document');
if (!$account->getVerified()) {
switch ($result->requirements->disabled_reason) {
case 'requirements.past_due':
$account->setRequirement($result->requirements->currently_due[0]);
break;
}
}
$account->setTotalBalance($this->getBalanceById($result->id, 'available'));
$account->setPendingBalance($this->getBalanceById($result->id, 'pending'));
return $account;
} catch (Stripe\Error\Permission $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
......@@ -256,6 +313,20 @@ class Manager
return $this->getByAccountId($merchant['id']);
}
/**
* Get balance by ID
* @param string $id
* @return Balance
*/
public function getBalanceById(string $id, string $type) : Balance
{
$stripeBalance = $this->balanceInstance->retrieve([ 'stripe_account' => $id ]);
$balance = new Balance();
$balance->setAmount($stripeBalance->$type[0]->amount)
->setCurrency($stripeBalance->$type[0]->currency);
return $balance;
}
/**
* Delete a merchant accont
* @param Account $account
......
<?php
namespace Minds\Core\Payments\Stripe\Instances;
use Minds\Common\StaticToInstance;
use Minds\Core\Config\Config;
use Minds\Core\Di\Di;
/**
* @method BalanceInstance create()
* @method BalanceInstance retrieve()
*/
class BalanceInstance extends StaticToInstance
{
public function __construct(Config $config = null)
{
$config = $config ?? Di::_()->get('Config');
\Stripe\Stripe::setApiKey($config->get('payments')['stripe']['api_key']);
$this->setClass(new \Stripe\Balance);
}
}
<?php
namespace Minds\Core\Payments\Stripe\Instances;
use Minds\Common\StaticToInstance;
use Minds\Core\Config\Config;
use Minds\Core\Di\Di;
/**
* @method FileInstance create()
*/
class FileInstance extends StaticToInstance
{
public function __construct(Config $config = null)
{
$config = $config ?? Di::_()->get('Config');
\Stripe\Stripe::setApiKey($config->get('payments')['stripe']['api_key']);
$this->setClass(new \Stripe\File);
}
}
......@@ -266,6 +266,9 @@ class Manager
throw new \Exception("Not implemented ETH yet");
break;
case 'usd':
if (!$this->receiver->getMerchant() || $this->receiver->getMerchant()['id']) {
throw new \Exception("This channel is not able to receive USD at the moment");
}
$intent = new PaymentIntent();
$intent
->setUserGuid($this->sender->getGuid())
......
......@@ -7,6 +7,8 @@ use Minds\Core\Payments\Stripe\Connect\Account;
use Minds\Core\Entities\Actions\Save;
use Minds\Core\Payments\Stripe\Connect\Delegates\NotificationDelegate;
use Minds\Core\Payments\Stripe\Instances\AccountInstance;
use Minds\Core\Payments\Stripe\Instances\BalanceInstance;
use Minds\Core\Payments\Stripe\Instances\FileInstance;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
......@@ -16,13 +18,17 @@ class ManagerSpec extends ObjectBehavior
private $save;
private $notificationDelegate;
private $accountInstance;
private $balanceInstance;
private $fileInstance;
public function let(Save $save, NotificationDelegate $notificationDelegate, AccountInstance $accountInstance)
public function let(Save $save, NotificationDelegate $notificationDelegate, AccountInstance $accountInstance, BalanceInstance $balanceInstance, FileInstance $fileInstance)
{
$this->beConstructedWith($save, $notificationDelegate, $accountInstance);
$this->beConstructedWith($save, $notificationDelegate, $accountInstance, $balanceInstance, $fileInstance);
$this->save = $save;
$this->notificationDelegate = $notificationDelegate;
$this->accountInstance = $accountInstance;
$this->balanceInstance = $balanceInstance;
$this->fileInstance = $fileInstance;
}
public function it_is_initializable()
......@@ -126,6 +132,31 @@ class ManagerSpec extends ObjectBehavior
'verification' => (object) [
'disabled_reason' => null,
],
'settings' => (object) [
'payouts' => (object) [
'schedule' => (object) [
'interval' => 1,
'delay_days' => 2,
'monthly_anchor' => 31,
],
],
],
]);
$this->balanceInstance->retrieve([ 'stripe_account' => 'acc_123'])
->willReturn((object) [
'pending' => [
(object) [
'amount' => 100,
'currency' => 'GBP',
],
],
'available' => [
(object) [
'amount' => 100,
'currency' => 'GBP',
],
],
]);
$account = $this->getByAccountId('acc_123');
......@@ -181,6 +212,31 @@ class ManagerSpec extends ObjectBehavior
'verification' => (object) [
'disabled_reason' => null,
],
'settings' => (object) [
'payouts' => (object) [
'schedule' => (object) [
'interval' => 1,
'delay_days' => 2,
'monthly_anchor' => 31,
]
]
]
]);
$this->balanceInstance->retrieve([ 'stripe_account' => 'acc_123'])
->willReturn((object) [
'pending' => [
(object) [
'amount' => 100,
'currency' => 'GBP',
],
],
'available' => [
(object) [
'amount' => 100,
'currency' => 'GBP',
],
],
]);
$user = new User();
......