Summary: Ref PHI1166. I'm documenting our dependencies, and we have approximately 5,000 lines of external code to support WePay as a Phortune provider. We don't use it, I'm almost certain it doesn't work, and we have no plans to use it in the near future. If we did pursue it, I'd probably just wrap the API in a 100-line `WePayFuture` anyway since 5K lines of dependencies to make a couple method calls is ridiculous.
Test Plan: Grepped for `wepay`, `httpful`, `restful`.
Reviewers: amckinley
Reviewed By: amckinley
Subscribers: aurelijus
Differential Revision: https://secure.phabricator.com/D20521
Summary: Ref T13250. See D20149. In a number of cases, we use `setQueryParams()` immediately after URI construction. To simplify this slightly, let the constructor take parameters, similar to `HTTPSFuture`.
Test Plan: See inlines.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T13250
Differential Revision: https://secure.phabricator.com/D20151
Summary: Ref T13244. See PHI1052. Our error handling for Stripe errors isn't great right now. We can give users a bit more information, and a less jarring UI.
Test Plan:
Before (this is in developer mode, production doesn't get a stack trace):
{F6197394}
After:
{F6197397}
- Tried all the invalid test codes listed here: https://stripe.com/docs/testing#cards
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T13244
Differential Revision: https://secure.phabricator.com/D20132
Summary:
Ref T4340. Some "Register/Login" and "Link External Account" buttons are forms which submit to third-party sites. Whitelist these targets when pages render an OAuth form.
Safari, at least, also prevents a redirect to a third-party domain after a form submission to the local domain, so when we first redirect locally (as with Twitter and other OAuth1 providers) we need to authorize an additional URI.
Test Plan: Clicked all my registration buttons locally without hitting CSP issues.
Maniphest Tasks: T4340
Differential Revision: https://secure.phabricator.com/D19159
Summary:
See PHI399. Ref T4340. This header provides an additional layer of protection against various attacks, including XSS attacks which embed inline `<script ...>` or `onhover="..."` content into the document.
**style-src**: The "unsafe-inline" directive affects both `style="..."` and `<style>`. We use a lot of `style="..."`, some very legitimately, so we can't realistically get away from this any time soon. We only use one `<style>` (for monospaced font preferences) but can't disable `<style>` without disabling `style="..."`.
**img-src**: We use "data:" URIs to inline small images into CSS, and there's a significant performance benefit from doing this. There doesn't seem to be a way to allow "data" URIs in CSS without allowing them in the document itself.
**script-src** and **frame-src**: For a small number of flows (Recaptcha, Stripe) we embed external javascript, some of which embeds child elements (or additional resources) into the document. We now whitelist these narrowly on the respective pages.
This won't work with Quicksand, so I've blacklisted it for now.
**connect-src**: We need to include `'self'` for AJAX to work, and any websocket URIs.
**Clickjacking**: We now have three layers of protection:
- X-Frame-Options: works in older browsers.
- `frame-ancestors 'none'`: does the same thing.
- Explicit framebust in JX.Stratcom after initialization: works in ancient IE.
We could probably drop the explicit framebust but it wasn't difficult to retain.
**script tags**: We previously used an inline `<script>` tag to start Javelin. I've moved this to `<data data-javelin-init ...>` tags, which seems to work properly.
**`__DEV__`**: We previously used an inline `<script>` tag to set the `__DEV__` mode flag. I tried using the "initialization" tags for this, but they fire too late. I moved it to `<html data-developer-mode="1">`, which seems OK everywhere.
**CSP Scope**: Only the CSP header on the original request appears to matter -- you can't refine the scope by emitting headers on CSS/JS. To reduce confusion, I disabled the headers on those response types. More headers could be disabled, although we're likely already deep in the land of diminishing returns.
**Initialization**: The initialization sequence has changed slightly. Previously, we waited for the <script> in bottom of the document to evaluate. Now, we go fishing for tags when domcontentready fires.
Test Plan:
- Browsed around in Firefox, Safari and Chrome looking for console warnings. Interacted with various Javascript behaviors. Enabled Quicksand.
- Disabled all the framebusting, launched a clickjacking attack, verified that each layer of protection is individually effective.
- Verified that the XHProf iframe in Darkconsole and the PHPAST frame layout work properly.
- Enabled notifications, verified no complaints about connecting to Aphlict.
- Hit `__DEV__` mode warnings based on the new data attribute.
- Tried to do sketchy stuff with `data:` URIs and SVGs. This works but doesn't seem to be able to do anything dangerous.
- Went through the Stripe and Recaptcha workflows.
- Dumped and examined the CSP headers with `curl`, etc.
- Added a raw <script> tag to a page (as though I'd found an XSS attack), verified it was no longer executed.
Maniphest Tasks: T4340
Differential Revision: https://secure.phabricator.com/D19143
Summary: Noticed a couple of typos in the docs, and then things got out of hand.
Test Plan:
- Stared at the words until my eyes watered and the letters began to swim on the screen.
- Consulted a dictionary.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, yelirekim, PHID-OPKG-gm6ozazyms6q6i22gyam
Differential Revision: https://secure.phabricator.com/D18693
Summary: Use `PhutilClassMapQuery` where appropriate.
Test Plan: Browsed around the UI to verify things seemed somewhat working.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D13429
Summary: All classes should extend from some other class. See D13275 for some explanation.
Test Plan: `arc unit`
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D13283
Summary: Use `__CLASS__` instead of hard-coding class names. Depends on D12605.
Test Plan: Eyeball it.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: hach-que, Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D12806
Summary:
Fixes T7424. Ref T6308.
Currently, there's no option to just add a card directly from the autopay UI. Add a button so this works.
Also, chip away at T6308 a bit. This isn't perfect but looks a little less out of place.
Test Plan:
{F327637}
- Added a payment method, then set it as autopay.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6308, T7424
Differential Revision: https://secure.phabricator.com/D11935
Summary: Ref T2787. Allow merchants to flag orders for review. For now, all orders are flagged for review. Eventually, I could imagine Herald rules for coarse things (e.g., require review of all orders over $1,000, or require review of all orders by users not on a whitelist) and maybe examining fraud data for the providers which support it.
Test Plan: {F215848}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10675
Summary:
Ref T2787. Currently, we dump the user back into the application. Instead, give them a confirmation screen and then let them continue.
Also fix a couple of unit tests I adjusted the underlying behavior of somewhat-recently in libphutil.
Test Plan: {F215498}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10672
Summary: Ref T2787. These don't necessarily do a ton yet, but we can get PayPal out of hold, at least.
Test Plan: Updated charges from all providers. Cleared a PayPal hold.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10670
Summary:
Ref T2787. When Paypal comes back to us with funds on hold, dead-end the transaction but handle it properly.
Generally, smooth out the user interaction on weird states.
Implement refudnds/cancels for Paypal.
Test Plan: {F215230}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10667
Summary:
Ref T2787. Currently, we kill a cart and dead-end the workflow on a charge failure.
Instead, fail the charge and reset the cart so the user can try using a valid payment instrument like a normal checkout workflow would.
Some shakiness/smoothing on WePay for the moment; PayPal is still made up since we don't have a "Hold" state yet.
Test Plan: {F215214}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10666
Summary:
Ref T2787. This has some rough edges but basically works.
- Users can cancel orders that are in incomplete states (or in complete states, if the application allows them to -- for example, some future application might allow cancellation of billed-but-not-shipped orders).
- Merchant controllers can partially or fully refund orders from any state after payment.
Test Plan: This is still rough around the edges, but issued Stripe and WePay refunds.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: chad, epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10664
Summary:
Ref T2787.
- Allow merchants to disable payment providers.
- Show more useful information about providers on the payments page.
- Make test vs live more clear.
- Show merchant status.
- Add a description to merchants to flesh them out a bit -- the merchant areas of responsibilities seem to be fitting well with accounts, etc.
Test Plan: {F215109}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10662
Summary: Ref T2787. Uses the real icons. Straightens out the add payment flow a tiny bit.
Test Plan: {F214922}
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10654
Summary:
Ref T2787. Builds on D10649 by rebining existing objects (carts, charges, etc) to merchantPHIDs and providerPHIDs instead of an implicit global merchant and weird global artifacts (providerType / providerKey).
Basically:
- When you create something that users can pay for, you specify a merchant to control where the payment goes.
- Accounts are install-wide, but payment methods are bound to merchants. This seems to do a reasonable job of balancing usability and technical concerns.
- Replace a bunch of weird links between objects with standard PHIDs.
- Improve "add payment method" flow.
Test Plan: Went through the Fund flow with Stripe and WePay, funding an initiative.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10652
Summary:
Ref T2787. Instead of making providers global configuration, make them a thing on merchants with web configuration.
Payment methods and some of the pyament workflow needs to be retooled a bit after this, but this seemed like a reasonable cutoff point for this diff.
Test Plan: See screenshots.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10649
Summary: Ref T2787. Like Stripe, this one is pretty easy to get working correctly on the "good" path and fataling out in a safe way on bad paths.
Test Plan: Funded an initiative with Balanced.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10645
Summary:
Ref T2787. For test charges, Paypal is putting the charge in a "payment review" state. Dealing with this state requires way more infrastructure than other providers: we're supposed to pause delivery, then poll Paypal every 6 hours to see if the review has resolved.
Since I can't seem to generate normal test charges, I can't test Paypal for now. Disable it until we have more infrastructure.
(This diff gets us further along, up to the point where I hit this issue.)
Test Plan: Read documentation, rolled eyes.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10644
Summary:
Ref T2787. This basically already works correctly since the hard logic is external to the provider on API providers. Tweak a couple of things.
Failures still just fail the cart completely, for now.
Test Plan: Completed a charge with Stripe.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10640
Summary:
Ref T2787. This doesn't get all the edge cases quite correct, but is generally a safe, complete payment workflow:
- Shares the actual charging state logic.
- Makes it appropriately stateful with locking and transactions.
- Gets the main flow correct.
- Detects failure cases, just tends to blow up rather than help the user resolve them.
Test Plan:
- Charged with WePay.
- Charged with Infinite Free Money.
- Resumed an abandoned cart.
- Hit all failure states where we just dead-end the cart. Not ideal, but (seemingly) complete/safe/correct.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10639
Summary:
Ref T2787. Phortune currently stores a bunch of stuff as `...inUSDCents`. This ends up being pretty cumbersome and I worry it will create a huge headache down the road (and possibly not that far off if we do Coinbase/Bitcoin soon). Even now, it's more of a pain than I figured it would be.
Instead:
- Provide an application-level serialization mechanism.
- Provide currency serialization.
- Store currency in an abstract way (currently, as "1.23 USD") that can handle currencies in the future.
- Change all `...inUSDCents` to `..asCurrency`.
- This generally simplifies all the application code.
- Also remove some columns which don't make sense or don't make sense anymore. Notably, `Product` is going to get more abstract and mostly be provided by applications.
Test Plan:
- Created a new product.
- Purchased a product.
- Backed an initiative.
- Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10633
Summary:
Via HackerOne. Chrome (at least) interprets backslashes like forward slashes, so a redirect to "/\evil.com" is the same as a redirect to "//evil.com".
- Reject local URIs with backslashes (we never generate these).
- Fully-qualify all "Location:" redirects.
- Require external redirects to be marked explicitly.
Test Plan:
- Expanded existing test coverage.
- Verified that neither Diffusion nor Phriction can generate URIs with backslashes (they are escaped in Diffusion, and removed by slugging in Phriction).
- Logged in with Facebook (OAuth2 submits a form to the external site, and isn't affected) and Twitter (OAuth1 redirects, and is affected).
- Went through some local redirects (login, save-an-object).
- Verified file still work.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Differential Revision: https://secure.phabricator.com/D10291
Summary: Ref T2787. There were some mega-uggo buttons and such; reduce the uggo-ness by a hair.
Test Plan: {F179686}
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10006
Summary:
Ref T2787. Carts need a status so we can tell if they've been purchased. Also kind of get WePay working as a one-time provider, and let charges not have a methodPHID (they won't for one-time providers).
All the status stuff is still super crazy rough and you can do things like start a checkout, add a bunch of stuff to your cart, complete the checkout, and have Phabricator think you paid for all the stuff you added. But this is fine for now since you can't actually edit carts, and also none of this is at all usable anyway. I'll refine some of the workflows in future diffs, for now I'm just getting things hooked up and technically working.
Test Plan:
- Purcahsed a cart and got a sort of status/done screen instead of a "your money is gone" exception.
- Went through the WePay flow and got a successful test checkout.
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10003
Summary: Ref T2787. Makes charges a real object, allows providers to apply them. We are now (just barely) capable of stealing users' money.
Test Plan: {F179584}
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10002
Summary:
Ref T2787. Make carts and purchases real objects, with storage, that kind-of work.
Roughly, the idea here is that applications create "purchases" (like "1 large t-shirt") and add them to "carts" (a user can have a lot of different carts at the same time), then hand things off to Phortune to deal with actualy charging a card. Roughly this works like Paypal or other similar systems do, except Phortune is the thing the user gets handed off to.
This doesn't do anything interesting/useful yet.
Also fix some bugs and update some UI.
Test Plan: Added a product to a cart, saw it in cart screen.
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: epriestley
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D10001
Summary: Ref T5655. Some discussion in D9839. Generally speaking, `Phabricator{$name}Application` is clearer than `PhabricatorApplication{$name}`.
Test Plan:
# Pinned and uninstalled some applications.
# Applied patch and performed migrations.
# Verified that the pinned applications were still pinned and that the uninstalled applications were still uninstalled.
# Performed a sanity check on the database contents.
Reviewers: btrahan, epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: hach-que, epriestley, Korvin
Maniphest Tasks: T5655
Differential Revision: https://secure.phabricator.com/D9982
Summary: Ran `arc lint --apply-patches --everything` over rP, mainly to change double quotes to single quotes where appropriate. These changes also validate that the `ArcanistXHPASTLinter::LINT_DOUBLE_QUOTE` rule is working as expected.
Test Plan: Eyeballed it.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin, hach-que
Differential Revision: https://secure.phabricator.com/D9431
Summary:
There are quite a few tests in Arcanist, libphutil and Phabricator that do something similar to `$this->assertEqual(false, ...)` or `$this->assertEqual(true, ...)`.
This is unnecessarily verbose and it would be cleaner if we had `assertFalse` and `assertTrue` methods.
Test Plan: I contemplated adding a unit test for the `getCallerInfo` method but wasn't sure if it was required / where it should live.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley
CC: Korvin, epriestley, aran
Differential Revision: https://secure.phabricator.com/D8460
Summary:
Ref T2787.
I //think// we could also use WePay as a recurring payment provider, but this is somewhat messy (OAuth + requires account) -- basically it's "add a WePay account" instead of "add a credit card".
The WePay checkout workflow is a bit upsell-y but basically reasonable.
I like that their API just has a `request($method, $params)` method instead of 30,000 lines of methods for each request type. I did hit one bug; I'll send a pull for that.
Test Plan: Got as far as the charge callback in testing; the rest isn't implemented for any provider yet.
Reviewers: btrahan, vrana, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5982
Summary:
Ref T2787. See discussion in D5834.
- Replace `PhortuneUtil` with `PhortuneCurrency`, which feels a little better and more flexible / future-proof.
- Add unit tests.
- Display prices explicitly as "$... USD".
Test Plan: Hit product list, cart, purchase flow, verified displays.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5841
Summary:
Paypal doesn't let us capture cards in a PCI-free way like Stripe and Balanced do, but we can provide a "pay with paypal" option at checkout. (For subscriptions, we'll have to invoice monthly to retain control over billing, but this doesn't seem wildly unreasonable.) The bitcoin provider MtGox works in a similar way, as do some other providers we might some day want to implement.
This adds:
- Hooks to providers so they can offer "pay once at checkout" workflows.
- Hooks so providers can have controllers, for redirect-based third-party workflows.
- Basic Paypal integration using the "Express Checkout Merchant API", which seems like the best fit for our use case. This only goes as far as shoving the user through the payment flow; we don't actually capture payments yet (paypal has around 35 different APIs, but this one seems to be the only PCI-free one which wouldn't give users an awful experience).
This diff is fairly checkpointey, but Phortune doesn't really bill anything yet anyway. Ref T2787.
Test Plan: Ran through Paypal sandbox workflow; "paid" for stuff.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5834
Summary: Provide a bare implementation so that you can add PhortuneTestProvider as a payment method. Ref 2787.
Test Plan: Added "cards" through the test provider.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5772
Summary:
This has no real behavioral changes (except better error handling), it just factors things out to be a bit cleaner. In particular:
- Move more shared form behaviors into the common JS form component.
- Move more error handling into shared pathways.
- Make the specialized Stripe / Balanced methods do less work.
This needs some more polish for nontrival errors (especially on the Balanced side) but none of the error behavior is worse than it was and a lot of it is much better.
Ref T2787.
Test Plan: Hit all invalid form errors, added valid payment methods with Stripe and Balacned.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5771
Summary:
Allows Balanced payment methods to be added. This works essentially the same way as Stripe, except everything is a little bit different.
Slightly more stuff could be shared, but I feel //mostly// good about this. I'll probably do a bit more cleanup next. Some of the error handling is messy, in particular.
Ref T2787.
Test Plan: Added Balanced and Stripe payment methods.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5765
Summary:
General cleanup and separation into generic vs Stripe blocks of code.
- There was an old CC form view for Stripe stuff that I never cleaned up; clean that up.
- Move non-Stripe CC form rendering into a base class (Balanced can reuse it).
- Move non-Stripe CC form JS into a shareable class.
- Simplify JS a bit (JX.Workflow can add extra parameters to a request, so we don't need hidden inputs).
- Genericize CSS.
- Depend on Stripe JS directly, if they're down we're not going to be able to add cards anyway.
Ref T2787.
Test Plan: Hit all Stripe errors and added new cards.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5758
Summary:
Ref T2787. For payment methods that allow you to add a billable method (i.e., a credit card), move all the logic into the provider. In particular:
- Providers may (Stripe, Balanced) or may not (Paypal, MtGox) allow you to add rebillable payment methods. Providers which don't allow rebillable methods will appear at checkout instead and we'll just invoice you every month if you don't use a rebillable method.
- Providers which permit creation of rebillable methods handle their own data entry, since this will be per-provider.
- "Add Payment Method" now prompts you to choose a provider. This is super ugly and barely-usable for the moment. When there's only one choice, we'll auto-select it in the future.
Test Plan: Added new Stripe payment methods; hit all the Stripe errors.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5756
Summary: Abstract out the Stripiness of payment providers so we can add a Test provider (and maybe MtGox / Balanced / Paypal / etc). Ref T2787.
Test Plan: Ran unit tests.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2787
Differential Revision: https://secure.phabricator.com/D5752