Phortune v0
Summary:
Ref T2787. This does very little so far, but makes inroads on accounts and billing. This is mostly just modeled on what Stripe looks like. The objects are:
- **Account**: Has one or more authorized users, who can make manage the account. An example might be "Phacility", and the three of us would be able to manage it. A user may be associated with more than one account (e.g., a corporate account and a personal account) but the UI tries to simplify the common case of a single account.
- **Payment Method**: Something we can get sweet sweet money from; for now, a credit card registered with Stripe. Payment methods are associated with an account.
- **Product**: A good (one time charge) or service (recurring charge). This might be "t-shirt" or "enterprise plan" or "hourly support" or whatever else.
- **Purchase**: Represents a user purchasing a Product for an Account, using a Payment Method. e.g., you bought a shirt, or started a plan, or purchased support.
- **Charge**: Actual charges against payment methods. A Purchase can create more than one charge if it's a plan, or if the first charge fails and we re-bill.
This doesn't fully account for stuff like coupons/discounts yet but they should fit into the model without any issues.
This only implements `Account`, and that only partially.
Test Plan: {F37531}
Reviewers: chad, btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5435
2013-03-28 17:10:34 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
abstract class PhortuneController extends PhabricatorController {
|
|
|
|
|
2014-08-18 22:15:21 +02:00
|
|
|
protected function addAccountCrumb(
|
|
|
|
$crumbs,
|
|
|
|
PhortuneAccount $account,
|
|
|
|
$link = true) {
|
|
|
|
|
2015-01-30 20:28:49 +01:00
|
|
|
$name = $account->getName();
|
2014-08-18 22:15:21 +02:00
|
|
|
$href = null;
|
|
|
|
|
|
|
|
if ($link) {
|
|
|
|
$href = $this->getApplicationURI($account->getID().'/');
|
|
|
|
$crumbs->addTextCrumb($name, $href);
|
|
|
|
} else {
|
|
|
|
$crumbs->addTextCrumb($name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 20:28:49 +01:00
|
|
|
protected function addMerchantCrumb(
|
|
|
|
$crumbs,
|
|
|
|
PhortuneMerchant $merchant,
|
|
|
|
$link = true) {
|
|
|
|
|
|
|
|
$name = $merchant->getName();
|
|
|
|
$href = null;
|
|
|
|
|
|
|
|
$crumbs->addTextCrumb(
|
|
|
|
pht('Merchants'),
|
|
|
|
$this->getApplicationURI('merchant/'));
|
|
|
|
|
|
|
|
if ($link) {
|
|
|
|
$href = $this->getApplicationURI('merchant/'.$merchant->getID().'/');
|
|
|
|
$crumbs->addTextCrumb($name, $href);
|
|
|
|
} else {
|
|
|
|
$crumbs->addTextCrumb($name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:41:59 +02:00
|
|
|
private function loadEnabledProvidersForMerchant(PhortuneMerchant $merchant) {
|
|
|
|
$viewer = $this->getRequest()->getUser();
|
|
|
|
|
|
|
|
$provider_configs = id(new PhortunePaymentProviderConfigQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withMerchantPHIDs(array($merchant->getPHID()))
|
|
|
|
->execute();
|
|
|
|
$providers = mpull($provider_configs, 'buildProvider', 'getID');
|
|
|
|
|
|
|
|
foreach ($providers as $key => $provider) {
|
|
|
|
if (!$provider->isEnabled()) {
|
|
|
|
unset($providers[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $providers;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function loadCreatePaymentMethodProvidersForMerchant(
|
|
|
|
PhortuneMerchant $merchant) {
|
|
|
|
|
|
|
|
$providers = $this->loadEnabledProvidersForMerchant($merchant);
|
|
|
|
foreach ($providers as $key => $provider) {
|
|
|
|
if (!$provider->canCreatePaymentMethods()) {
|
|
|
|
unset($providers[$key]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $providers;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function loadOneTimePaymentProvidersForMerchant(
|
|
|
|
PhortuneMerchant $merchant) {
|
|
|
|
|
|
|
|
$providers = $this->loadEnabledProvidersForMerchant($merchant);
|
|
|
|
foreach ($providers as $key => $provider) {
|
|
|
|
if (!$provider->canProcessOneTimePayments()) {
|
|
|
|
unset($providers[$key]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $providers;
|
|
|
|
}
|
|
|
|
|
Improve Phortune policy behavior
Summary:
Currently, PhortuneAccounts have a very open default policy to allow merchants to see and interact with them.
This has the undesirable side effect of leaking their names in too many places, because all users are allowed to load the handles for the accounts. Although this information is not super sensitive, we shouldn't expose it.
I went through about 5 really messy diffs trying to fix this. It's very complicated because there are a lot of objects and many of them are related to PhortuneAccounts, but PhortuneAccounts are not bound to a specific merchant. This lead to a lot of threading viewers and merchants all over the place through the call stack and some really sketchy diffs with OmnipotentUsers that weren't going anywhere good.
This is the cleanest approach I came up with, by far:
- Introduce the concept of an "Authority", which gives a user more powers as a viewer. For now, since we only have one use case, this is pretty open-ended.
- When a viewer is acting as a merchant, grant them authority through the merchant.
- Have Accounts check if the viewer is acting with merchant authority. This lets us easily implement the rule "merchants can see this stuff" without being too broad.
Then update the Subscription view to respect Merchant Authority.
I partially updated the Cart views to respect it. I'll finish this up in a separate diff, but this seemed like a good checkpoint that introduced the concept without too much extra baggage.
This feels pretty good/clean to me, overall, even ignoring the series of horrible messes I made on my way here.
Test Plan:
- Verified I can see everything I need to as a merchant (modulo un-updated Cart UIs).
- Verified I can see nothing when acting as a normal user.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Differential Revision: https://secure.phabricator.com/D11945
2015-03-03 19:38:25 +01:00
|
|
|
protected function loadMerchantAuthority() {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
|
|
|
$is_merchant = (bool)$request->getURIData('merchantID');
|
|
|
|
if (!$is_merchant) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$merchant = id(new PhortuneMerchantQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withIDs(array($request->getURIData('merchantID')))
|
|
|
|
->requireCapabilities(
|
|
|
|
array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
))
|
|
|
|
->executeOne();
|
|
|
|
if (!$merchant) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$viewer->grantAuthority($merchant);
|
|
|
|
return $merchant;
|
|
|
|
}
|
|
|
|
|
Phortune v0
Summary:
Ref T2787. This does very little so far, but makes inroads on accounts and billing. This is mostly just modeled on what Stripe looks like. The objects are:
- **Account**: Has one or more authorized users, who can make manage the account. An example might be "Phacility", and the three of us would be able to manage it. A user may be associated with more than one account (e.g., a corporate account and a personal account) but the UI tries to simplify the common case of a single account.
- **Payment Method**: Something we can get sweet sweet money from; for now, a credit card registered with Stripe. Payment methods are associated with an account.
- **Product**: A good (one time charge) or service (recurring charge). This might be "t-shirt" or "enterprise plan" or "hourly support" or whatever else.
- **Purchase**: Represents a user purchasing a Product for an Account, using a Payment Method. e.g., you bought a shirt, or started a plan, or purchased support.
- **Charge**: Actual charges against payment methods. A Purchase can create more than one charge if it's a plan, or if the first charge fails and we re-bill.
This doesn't fully account for stuff like coupons/discounts yet but they should fit into the model without any issues.
This only implements `Account`, and that only partially.
Test Plan: {F37531}
Reviewers: chad, btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5435
2013-03-28 17:10:34 +01:00
|
|
|
}
|