silverapp/silver

Poor (out-dated) documentation and lack of a clear application flow

thevahidal opened this issue · 10 comments

Hey guys,
we've been looking for something like this library for a while and finally we found silver which we really appreciate your work.
but the problem is that the documentation is not really helpful and everytime we ran into a problem it takes us a lot to figure out how to solve it. (for example braintree payment processor is outdated and we basically forked it, changed a lot of things!)

I'm aware of the fact that changing and improving the docs will take a long time, and since we're in a hurry here, we would appreciate it if you could answer some of our questions here.

(before start asking questions assume that we have a platform with only one provider which is us, and we have some pricing plans, and we basically want our user subscribe to a plan a pay the price, that's it nothing too fancy.)

1. can you explain the whole process of what we want to accomplish (above)? the order of api calls and etc? (priority: high)
2. why do pricing plans need authentication? (priority: low)
3. how is that every authenticated user can activate a subscription via the activate subscription endpoint? Doesn't it supposed to get handled by super admin access or automatically by silver? (priority: high)
4. why is that even though we specified the price and all info in the plan, when creating a subscription we need to again give all of them to the subscription entries? (priority: medium)

Hey @thevahidal , thanks for addressing your concerns.

Yes, the documentation is not up to date and not so well written.
If you've dealt with certain pain points it would help to mention / document them. It's a chicken and egg problem really: contributors won't join if the documentation is not good enough, and the documentation won't be improved if there are no contributors.
At the moment Silver has no active contributors, if you don't count me... but I limit my contributions to bugfixes, and handling Issues and PRs. So please consider contributing if you are making use of the project.

At Presslabs we are using the Braintree Payment Processor just fine, what is outdated about it?

I think a couple of questions (2. and 3.) are pretty similar in nature. We have a second application that solves the authentication/permission problems and is an intermediate between the Billing App and the customers / business logic. If this does not fit your platform, you can write your extra business logic code in the same Billing App where Silver is included (which is mostly how Silver was intended to be used).

For 1., assuming you've already created a provider and plans:

  • Create a Customer: POST /api/customers/
  • Create a Subscription: POST /api/customers/<customer_id>/subscriptions/
  • Activate the Subscription: POST /api/customers/<customer_id>/subscriptions/<subscription_id>/activate/

From there invoices will be automatically generated if you've setup Silver correctly. See here.

  • GET /api/invoices/?customer=<customer_id> (invoices can be substituted with proformas or documents)

  • Create a transaction for the customer: POST /api/customers/<customer_id>/transactions/
    You should also create a PaymentMethod beforehand for the customer either via python code (with a hook after a customer is created for example) or via the API.
    The transaction payload will return a pay_url field. That's where you want to redirect the customer.

4. I'm not sure what you mean here.
There are these things called MeteredFeatures that can be attached to Plans. They are used to describe the non-fixed fees of a plan. If you were to model a mobile phone subscription, then you'd have a base fee for the Plan and you could have a MeteredFeature to charge extra internet traffic for example.

Subscriptions have logs of these MeteredFeatures, called MeteredFeatureUnitsLogs. They log how many units of that MeteredFeature have been consumed during a billing interval (a month for example).

You can send a PATCH request to /api/customers/<customer_id>/subscriptions/<subscription_id>/metered_features/<metered_feature_product_code> to add or override the consumed units of a specific MeteredFeature. Other than that the Subscription doesn't require mentioning any other details that have been already mentioned in a plan (unless it allows you to override those details for specific a Subscription).

More info

The API has been partially specified for testing (in a python, but declarative way) in this directory: https://github.com/silverapp/silver/tree/master/silver/tests/api/specs. You can look there to understand the API structure, especially for invoices, their entries and transactions... specs for the other resources are for API output-only.

In the end I encourage you to try and upstream your improvements / changes to the project and related projects (Braintree).

Thanks for your answer,
I'll look into it.

Hey man,
I did all the steps you mentioned (create customer, subscription, ...) and when i try to issue an invoice, i see this error in celery logs:
[2020-02-24 09:49:56,727: WARNING/ForkPoolWorker-9] <ErrorResult 'Unknown or expired payment_method_nonce.' at 7f506ba28950> [2020-02-24 09:49:56,727: WARNING/ForkPoolWorker-9] Couldn't charge Braintree transaction.: {'message': 'Unknown or expired payment_method_nonce.', 'errors': ['91565'], 'customer_id': 6, 'card_verification': None} [2020-02-24 09:49:56,727: ERROR/ForkPoolWorker-9] ['91565']

Does the invoice issue fail? How does the PaymentMethod look (payment_method.__dict__)?
You can also see https://developers.braintreepayments.com/reference/general/validation-errors/all/php#code-91565.

No the invoice issue work just fine.
I saw that braintree doc but the question is where we get the payment_method_nonce?

This is the created transaction Data:
{ "error_codes": [ "91565" ], "requested_at": "2020-02-24T09:49:55.425207" }

oh, my bad, i creating an invoice instead of subscription!

The payment_method_nonce is something the paying customer obtains from Braintree, after submitting his payment information (when redirected to the transaction's pay_url).

See the Braintree documentation for an overview of the entire flow: https://developers.braintreepayments.com/start/overview#how-it-works

oh, my bad, i creating an invoice instead of subscription!

But the problem is that no invoice is created automatically, though when i create an invoice, a transaction was build automatically then i assume my celery is working!

Make sure the subscription is active. The subscription has a few methods you can use for debugging as well:
subscription.should_be_billed(billing_date=date(...)) - tells you if the subscription should generate an invoice
subscription.cycle_end_date(billing_date=date(...)) - tells you the end of the current billing cycle

Where billing_date can be today or some arbitrary date.