mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 10:12:41 +01:00
Kind of generate a bill for users
Summary: Ref T6881. This generates a product, purchase and invoice for users, and there's sort of some UI for them. Stuff it doesn't do yet: - Try to autobill when we have a CC; - actually tell the user they should pay it; - ask the application for anything like "how much should we charge", or tell the application anything like "the user paid". However, these work: - You can //technically// pay the invoices. - You can see the invoices you paid in the past. Test Plan: Used `bin/phriction invoice` to double-bill myself over and over again. Paid one of the invoices. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6881 Differential Revision: https://secure.phabricator.com/D11580
This commit is contained in:
parent
bdb3adeee4
commit
d1e793a292
12 changed files with 380 additions and 32 deletions
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_phortune.phortune_cart
|
||||
ADD subscriptionPHID VARBINARY(64);
|
2
resources/sql/autopatches/20150130.phortune.2.subkey.sql
Normal file
2
resources/sql/autopatches/20150130.phortune.2.subkey.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_phortune.phortune_cart
|
||||
ADD KEY `key_subscription` (subscriptionPHID);
|
|
@ -2811,9 +2811,11 @@ phutil_register_library_map(array(
|
|||
'PhortuneSchemaSpec' => 'applications/phortune/storage/PhortuneSchemaSpec.php',
|
||||
'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php',
|
||||
'PhortuneSubscription' => 'applications/phortune/storage/PhortuneSubscription.php',
|
||||
'PhortuneSubscriptionCart' => 'applications/phortune/cart/PhortuneSubscriptionCart.php',
|
||||
'PhortuneSubscriptionImplementation' => 'applications/phortune/subscription/PhortuneSubscriptionImplementation.php',
|
||||
'PhortuneSubscriptionListController' => 'applications/phortune/controller/PhortuneSubscriptionListController.php',
|
||||
'PhortuneSubscriptionPHIDType' => 'applications/phortune/phid/PhortuneSubscriptionPHIDType.php',
|
||||
'PhortuneSubscriptionProduct' => 'applications/phortune/product/PhortuneSubscriptionProduct.php',
|
||||
'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php',
|
||||
'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php',
|
||||
'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php',
|
||||
|
@ -6169,8 +6171,10 @@ phutil_register_library_map(array(
|
|||
'PhortuneDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhortuneSubscriptionCart' => 'PhortuneCartImplementation',
|
||||
'PhortuneSubscriptionListController' => 'PhortuneController',
|
||||
'PhortuneSubscriptionPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhortuneSubscriptionProduct' => 'PhortuneProductImplementation',
|
||||
'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhortuneSubscriptionTableView' => 'AphrontView',
|
||||
|
|
|
@ -50,6 +50,8 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
|||
=> 'PhortuneSubscriptionListController',
|
||||
'view/(?P<id>\d+)/'
|
||||
=> 'PhortuneSubscriptionViewController',
|
||||
'order/(?P<subscriptionID>\d+)/'
|
||||
=> 'PhortuneCartListController',
|
||||
),
|
||||
'charge/(?:query/(?P<queryKey>[^/]+)/)?'
|
||||
=> 'PhortuneChargeListController',
|
||||
|
@ -90,6 +92,8 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
|||
=> 'PhortuneSubscriptionListController',
|
||||
'view/(?P<id>\d+)/'
|
||||
=> 'PhortuneSubscriptionViewController',
|
||||
'order/(?P<subscriptionID>\d+)/'
|
||||
=> 'PhortuneCartListController',
|
||||
),
|
||||
'(?P<id>\d+)/' => 'PhortuneMerchantViewController',
|
||||
),
|
||||
|
|
89
src/applications/phortune/cart/PhortuneSubscriptionCart.php
Normal file
89
src/applications/phortune/cart/PhortuneSubscriptionCart.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneSubscriptionCart
|
||||
extends PhortuneCartImplementation {
|
||||
|
||||
private $subscriptionPHID;
|
||||
private $subscription;
|
||||
|
||||
public function setSubscriptionPHID($subscription_phid) {
|
||||
$this->subscriptionPHID = $subscription_phid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubscriptionPHID() {
|
||||
return $this->subscriptionPHID;
|
||||
}
|
||||
|
||||
public function setSubscription(PhortuneSubscription $subscription) {
|
||||
$this->subscription = $subscription;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubscription() {
|
||||
return $this->subscription;
|
||||
}
|
||||
|
||||
public function getName(PhortuneCart $cart) {
|
||||
return pht('Subscription');
|
||||
}
|
||||
|
||||
public function willCreateCart(
|
||||
PhabricatorUser $viewer,
|
||||
PhortuneCart $cart) {
|
||||
|
||||
$subscription = $this->getSubscription();
|
||||
if (!$subscription) {
|
||||
throw new Exception(
|
||||
pht('Call setSubscription() before building a cart!'));
|
||||
}
|
||||
|
||||
$cart->setMetadataValue('subscriptionPHID', $subscription->getPHID());
|
||||
}
|
||||
|
||||
public function loadImplementationsForCarts(
|
||||
PhabricatorUser $viewer,
|
||||
array $carts) {
|
||||
|
||||
$phids = array();
|
||||
foreach ($carts as $cart) {
|
||||
$phids[] = $cart->getMetadataValue('subscriptionPHID');
|
||||
}
|
||||
|
||||
$subscriptions = id(new PhortuneSubscriptionQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($phids)
|
||||
->execute();
|
||||
$subscriptions = mpull($subscriptions, null, 'getPHID');
|
||||
|
||||
$objects = array();
|
||||
foreach ($carts as $key => $cart) {
|
||||
$subscription_phid = $cart->getMetadataValue('subscriptionPHID');
|
||||
$subscription = idx($subscriptions, $subscription_phid);
|
||||
if (!$subscription) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$object = id(new PhortuneSubscriptionCart())
|
||||
->setSubscriptionPHID($subscription_phid)
|
||||
->setSubscription($subscription);
|
||||
|
||||
$objects[$key] = $object;
|
||||
}
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
public function getCancelURI(PhortuneCart $cart) {
|
||||
return $this->getSubscription()->getURI();
|
||||
}
|
||||
|
||||
public function getDoneURI(PhortuneCart $cart) {
|
||||
return $this->getSubscription()->getURI();
|
||||
}
|
||||
|
||||
public function getDoneActionName(PhortuneCart $cart) {
|
||||
return pht('Return to Subscription');
|
||||
}
|
||||
|
||||
}
|
|
@ -3,29 +3,35 @@
|
|||
final class PhortuneCartListController
|
||||
extends PhortuneController {
|
||||
|
||||
private $accountID;
|
||||
private $merchantID;
|
||||
private $queryKey;
|
||||
|
||||
private $merchant;
|
||||
private $account;
|
||||
private $subscription;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->merchantID = idx($data, 'merchantID');
|
||||
$this->accountID = idx($data, 'accountID');
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
}
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
$merchant_id = $request->getURIData('merchantID');
|
||||
$account_id = $request->getURIData('accountID');
|
||||
$subscription_id = $request->getURIData('subscriptionID');
|
||||
|
||||
$engine = new PhortuneCartSearchEngine();
|
||||
|
||||
if ($this->merchantID) {
|
||||
if ($subscription_id) {
|
||||
$subscription = id(new PhortuneSubscriptionQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($subscription_id))
|
||||
->executeOne();
|
||||
if (!$subscription) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$this->subscription = $subscription;
|
||||
$engine->setSubscription($subscription);
|
||||
}
|
||||
|
||||
if ($merchant_id) {
|
||||
$merchant = id(new PhortuneMerchantQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($this->merchantID))
|
||||
->withIDs(array($merchant_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
|
@ -37,10 +43,10 @@ final class PhortuneCartListController
|
|||
}
|
||||
$this->merchant = $merchant;
|
||||
$engine->setMerchant($merchant);
|
||||
} else if ($this->accountID) {
|
||||
} else if ($account_id) {
|
||||
$account = id(new PhortuneAccountQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($this->accountID))
|
||||
->withIDs(array($account_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
|
@ -57,7 +63,7 @@ final class PhortuneCartListController
|
|||
}
|
||||
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($this->queryKey)
|
||||
->setQueryKey($request->getURIData('queryKey'))
|
||||
->setSearchEngine($engine)
|
||||
->setNavigation($this->buildSideNavView());
|
||||
|
||||
|
@ -82,27 +88,40 @@ final class PhortuneCartListController
|
|||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$subscription = $this->subscription;
|
||||
|
||||
$merchant = $this->merchant;
|
||||
if ($merchant) {
|
||||
$id = $merchant->getID();
|
||||
$crumbs->addTextCrumb(
|
||||
$merchant->getName(),
|
||||
$this->getApplicationURI("merchant/{$id}/"));
|
||||
$this->addMerchantCrumb($crumbs, $merchant);
|
||||
if (!$subscription) {
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Orders'),
|
||||
$this->getApplicationURI("merchant/orders/{$id}/"));
|
||||
}
|
||||
}
|
||||
|
||||
$account = $this->account;
|
||||
if ($account) {
|
||||
$id = $account->getID();
|
||||
$crumbs->addTextCrumb(
|
||||
$account->getName(),
|
||||
$this->getApplicationURI("{$id}/"));
|
||||
$this->addAccountCrumb($crumbs, $account);
|
||||
if (!$subscription) {
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Orders'),
|
||||
$this->getApplicationURI("{$id}/order/"));
|
||||
}
|
||||
}
|
||||
|
||||
if ($subscription) {
|
||||
if ($merchant) {
|
||||
$subscription_uri = $subscription->getMerchantURI();
|
||||
} else {
|
||||
$subscription_uri = $subscription->getURI();
|
||||
}
|
||||
$crumbs->addTextCrumb(
|
||||
$subscription->getSubscriptionName(),
|
||||
$subscription_uri);
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ final class PhortuneSubscriptionViewController extends PhortuneController {
|
|||
}
|
||||
|
||||
$is_merchant = (bool)$request->getURIData('merchantID');
|
||||
$merchant = $subscription->getMerchant();
|
||||
$account = $subscription->getAccount();
|
||||
|
||||
$title = pht('Subscription: %s', $subscription->getSubscriptionName());
|
||||
|
||||
|
@ -27,9 +29,9 @@ final class PhortuneSubscriptionViewController extends PhortuneController {
|
|||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
if ($is_merchant) {
|
||||
$this->addMerchantCrumb($crumbs, $subscription->getMerchant());
|
||||
$this->addMerchantCrumb($crumbs, $merchant);
|
||||
} else {
|
||||
$this->addAccountCrumb($crumbs, $subscription->getAccount());
|
||||
$this->addAccountCrumb($crumbs, $account);
|
||||
}
|
||||
$crumbs->addTextCrumb(pht('Subscription %d', $subscription->getID()));
|
||||
|
||||
|
@ -46,10 +48,66 @@ final class PhortuneSubscriptionViewController extends PhortuneController {
|
|||
->setHeader($header)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$carts = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withSubscriptionPHIDs(array($subscription->getPHID()))
|
||||
->needPurchases(true)
|
||||
->withStatuses(
|
||||
array(
|
||||
PhortuneCart::STATUS_PURCHASING,
|
||||
PhortuneCart::STATUS_CHARGED,
|
||||
PhortuneCart::STATUS_HOLD,
|
||||
PhortuneCart::STATUS_REVIEW,
|
||||
PhortuneCart::STATUS_PURCHASED,
|
||||
))
|
||||
->execute();
|
||||
|
||||
$phids = array();
|
||||
foreach ($carts as $cart) {
|
||||
$phids[] = $cart->getPHID();
|
||||
foreach ($cart->getPurchases() as $purchase) {
|
||||
$phids[] = $purchase->getPHID();
|
||||
}
|
||||
}
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
|
||||
$invoice_table = id(new PhortuneOrderTableView())
|
||||
->setUser($viewer)
|
||||
->setCarts($carts)
|
||||
->setHandles($handles);
|
||||
|
||||
$account_id = $account->getID();
|
||||
$merchant_id = $merchant->getID();
|
||||
$subscription_id = $subscription->getID();
|
||||
|
||||
if ($is_merchant) {
|
||||
$invoices_uri = $this->getApplicationURI(
|
||||
"merchant/{$merchant_id}/subscription/order/{$subscription_id}/");
|
||||
} else {
|
||||
$invoices_uri = $this->getApplicationURI(
|
||||
"{$account_id}/subscription/order/{$subscription_id}/");
|
||||
}
|
||||
|
||||
$invoice_header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Recent Invoices'))
|
||||
->addActionLink(
|
||||
id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setIcon(
|
||||
id(new PHUIIconView())
|
||||
->setIconFont('fa-list'))
|
||||
->setHref($invoices_uri)
|
||||
->setText(pht('View All Invoices')));
|
||||
|
||||
$invoice_box = id(new PHUIObjectBoxView())
|
||||
->setHeader($invoice_header)
|
||||
->appendChild($invoice_table);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$object_box,
|
||||
$invoice_box,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneSubscriptionProduct
|
||||
extends PhortuneProductImplementation {
|
||||
|
||||
private $viewer;
|
||||
private $subscriptionPHID;
|
||||
private $subscription;
|
||||
|
||||
public function setSubscriptionPHID($subscription_phid) {
|
||||
$this->subscriptionPHID = $subscription_phid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubscriptionPHID() {
|
||||
return $this->subscriptionPHID;
|
||||
}
|
||||
|
||||
public function setSubscription(PhortuneSubscription $subscription) {
|
||||
$this->subscription = $subscription;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubscription() {
|
||||
return $this->subscription;
|
||||
}
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getViewer() {
|
||||
return $this->viewer;
|
||||
}
|
||||
|
||||
public function getRef() {
|
||||
return $this->getSubscriptionPHID();
|
||||
}
|
||||
|
||||
public function getName(PhortuneProduct $product) {
|
||||
return $this->getSubscription()->getSubscriptionName();
|
||||
}
|
||||
|
||||
public function getPriceAsCurrency(PhortuneProduct $product) {
|
||||
return PhortuneCurrency::newEmptyCurrency();
|
||||
}
|
||||
|
||||
public function didPurchaseProduct(
|
||||
PhortuneProduct $product,
|
||||
PhortunePurchase $purchase) {
|
||||
// TODO: Callback the subscription.
|
||||
return;
|
||||
}
|
||||
|
||||
public function didRefundProduct(
|
||||
PhortuneProduct $product,
|
||||
PhortunePurchase $purchase,
|
||||
PhortuneCurrency $amount) {
|
||||
// TODO: Callback the subscription.
|
||||
return;
|
||||
}
|
||||
|
||||
public function loadImplementationsForRefs(
|
||||
PhabricatorUser $viewer,
|
||||
array $refs) {
|
||||
|
||||
$subscriptions = id(new PhortuneSubscriptionQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($refs)
|
||||
->execute();
|
||||
$subscriptions = mpull($subscriptions, null, 'getPHID');
|
||||
|
||||
$objects = array();
|
||||
foreach ($refs as $ref) {
|
||||
$subscription = idx($subscriptions, $ref);
|
||||
if (!$subscription) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$objects[] = id(new PhortuneSubscriptionProduct())
|
||||
->setViewer($viewer)
|
||||
->setSubscriptionPHID($ref)
|
||||
->setSubscription($subscription);
|
||||
}
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ final class PhortuneCartQuery
|
|||
private $phids;
|
||||
private $accountPHIDs;
|
||||
private $merchantPHIDs;
|
||||
private $subscriptionPHIDs;
|
||||
private $statuses;
|
||||
|
||||
private $needPurchases;
|
||||
|
@ -31,6 +32,11 @@ final class PhortuneCartQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withSubscriptionPHIDs(array $subscription_phids) {
|
||||
$this->subscriptionPHIDs = $subscription_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withStatuses(array $statuses) {
|
||||
$this->statuses = $statuses;
|
||||
return $this;
|
||||
|
@ -158,6 +164,13 @@ final class PhortuneCartQuery
|
|||
$this->merchantPHIDs);
|
||||
}
|
||||
|
||||
if ($this->subscriptionPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'cart.subscriptionPHID IN (%Ls)',
|
||||
$this->subscriptionPHIDs);
|
||||
}
|
||||
|
||||
if ($this->statuses !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
|
|
|
@ -5,6 +5,7 @@ final class PhortuneCartSearchEngine
|
|||
|
||||
private $merchant;
|
||||
private $account;
|
||||
private $subscription;
|
||||
|
||||
public function setAccount(PhortuneAccount $account) {
|
||||
$this->account = $account;
|
||||
|
@ -24,6 +25,15 @@ final class PhortuneCartSearchEngine
|
|||
return $this->merchant;
|
||||
}
|
||||
|
||||
public function setSubscription(PhortuneSubscription $subscription) {
|
||||
$this->subscription = $subscription;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubscription() {
|
||||
return $this->subscription;
|
||||
}
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Phortune Orders');
|
||||
}
|
||||
|
@ -83,6 +93,11 @@ final class PhortuneCartSearchEngine
|
|||
}
|
||||
}
|
||||
|
||||
$subscription = $this->getSubscription();
|
||||
if ($subscription) {
|
||||
$query->withSubscriptionPHIDs(array($subscription->getPHID()));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ final class PhortuneCart extends PhortuneDAO
|
|||
protected $accountPHID;
|
||||
protected $authorPHID;
|
||||
protected $merchantPHID;
|
||||
protected $subscriptionPHID;
|
||||
protected $cartClass;
|
||||
protected $status;
|
||||
protected $metadata = array();
|
||||
|
@ -518,6 +519,7 @@ final class PhortuneCart extends PhortuneDAO
|
|||
'status' => 'text32',
|
||||
'cartClass' => 'text128',
|
||||
'mailKey' => 'bytes20',
|
||||
'subscriptionPHID' => 'phid?',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_account' => array(
|
||||
|
@ -526,6 +528,9 @@ final class PhortuneCart extends PhortuneDAO
|
|||
'key_merchant' => array(
|
||||
'columns' => array('merchantPHID'),
|
||||
),
|
||||
'key_subscription' => array(
|
||||
'columns' => array('subscriptionPHID'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
|
|
@ -8,8 +8,55 @@ final class PhortuneSubscriptionWorker extends PhabricatorWorker {
|
|||
$range = $this->getBillingPeriodRange($subscription);
|
||||
list($last_epoch, $next_epoch) = $range;
|
||||
|
||||
// TODO: Actual billing.
|
||||
echo "Bill from {$last_epoch} to {$next_epoch}.\n";
|
||||
$account = $subscription->getAccount();
|
||||
$merchant = $subscription->getMerchant();
|
||||
|
||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||
|
||||
$product = id(new PhortuneProductQuery())
|
||||
->setViewer($viewer)
|
||||
->withClassAndRef('PhortuneSubscriptionProduct', $subscription->getPHID())
|
||||
->executeOne();
|
||||
|
||||
$cart_implementation = id(new PhortuneSubscriptionCart())
|
||||
->setSubscription($subscription);
|
||||
|
||||
|
||||
// TODO: This isn't really ideal. It would be better to use an application
|
||||
// actor than the original author of the subscription. In particular, if
|
||||
// someone initiates a subscription, adds some other account managers, and
|
||||
// later leaves the company, they'll continue "acting" here indefinitely.
|
||||
// However, for now, some of the stuff later in the pipeline requires a
|
||||
// valid actor with a real PHID. The subscription should eventually be
|
||||
// able to create these invoices "as" the application it is acting on
|
||||
// behalf of.
|
||||
$actor = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($subscription->getAuthorPHID()))
|
||||
->executeOne();
|
||||
if (!$actor) {
|
||||
throw new Exception(pht('Failed to load actor to bill subscription!'));
|
||||
}
|
||||
|
||||
$cart = $account->newCart($actor, $cart_implementation, $merchant);
|
||||
|
||||
$purchase = $cart->newPurchase($actor, $product);
|
||||
|
||||
// TODO: Consider allowing subscriptions to cost an amount other than one
|
||||
// dollar and twenty-three cents.
|
||||
$currency = PhortuneCurrency::newFromUserInput($actor, '1.23 USD');
|
||||
|
||||
$purchase
|
||||
->setBasePriceAsCurrency($currency)
|
||||
->setMetadataValue('subscriptionPHID', $subscription->getPHID())
|
||||
->save();
|
||||
|
||||
$cart->setSubscriptionPHID($subscription->getPHID());
|
||||
$cart->activateCart();
|
||||
|
||||
// TODO: Autocharge this, etc.; this is still mostly faked up.
|
||||
echo 'Okay, made a cart here: ';
|
||||
echo $cart->getCheckoutURI()."\n\n";
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue