diff --git a/src/applications/phortune/currency/PhortuneCurrency.php b/src/applications/phortune/currency/PhortuneCurrency.php index fd9ea08f0e..88b9833e4d 100644 --- a/src/applications/phortune/currency/PhortuneCurrency.php +++ b/src/applications/phortune/currency/PhortuneCurrency.php @@ -121,6 +121,13 @@ final class PhortuneCurrency extends Phobject { return $this->currency; } + public function getValueInUSDCents() { + if ($this->currency !== 'USD') { + throw new Exception(pht('Unexpected currency!')); + } + return $this->value; + } + private static function throwFormatException($string) { throw new Exception("Invalid currency format ('{$string}')."); } diff --git a/src/applications/phortune/provider/PhortuneBalancedPaymentProvider.php b/src/applications/phortune/provider/PhortuneBalancedPaymentProvider.php index 41d3f3b4d6..a9204a86a1 100644 --- a/src/applications/phortune/provider/PhortuneBalancedPaymentProvider.php +++ b/src/applications/phortune/provider/PhortuneBalancedPaymentProvider.php @@ -40,7 +40,43 @@ final class PhortuneBalancedPaymentProvider extends PhortunePaymentProvider { protected function executeCharge( PhortunePaymentMethod $method, PhortuneCharge $charge) { - throw new PhortuneNotImplementedException($this); + + $root = dirname(phutil_get_library_root('phabricator')); + require_once $root.'/externals/httpful/bootstrap.php'; + require_once $root.'/externals/restful/bootstrap.php'; + require_once $root.'/externals/balanced-php/bootstrap.php'; + + $price = $charge->getAmountAsCurrency(); + + // Build the string which will appear on the credit card statement. + $charge_as = new PhutilURI(PhabricatorEnv::getProductionURI('/')); + $charge_as = $charge_as->getDomain(); + $charge_as = id(new PhutilUTF8StringTruncator()) + ->setMaximumBytes(22) + ->setTerminator('') + ->truncateString($charge_as); + + try { + Balanced\Settings::$api_key = $this->getSecretKey(); + $card = Balanced\Card::get($method->getMetadataValue('balanced.cardURI')); + $debit = $card->debit($price->getValueInUSDCents(), $charge_as); + } catch (RESTful\Exceptions\HTTPError $error) { + // NOTE: This exception doesn't print anything meaningful if it escapes + // to top level. Replace it with something slightly readable. + throw new Exception($error->response->body->description); + } + + $expect_status = 'succeeded'; + if ($debit->status !== $expect_status) { + throw new Exception( + pht( + 'Debit failed, expected "%s", got "%s".', + $expect_status, + $debit->status)); + } + + $charge->setMetadataValue('balanced.debitURI', $debit->uri); + $charge->save(); } private function getMarketplaceURI() { diff --git a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php index 5a19c928d8..957eeb9cb8 100644 --- a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php +++ b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php @@ -52,7 +52,7 @@ final class PhortuneStripePaymentProvider extends PhortunePaymentProvider { $secret_key = $this->getSecretKey(); $params = array( - 'amount' => $price->getValue(), + 'amount' => $price->getValueInUSDCents(), 'currency' => $price->getCurrency(), 'customer' => $method->getMetadataValue('stripe.customerID'), 'description' => $charge->getPHID(),