licensing's People
Forkers
devlentman1077licensing's Issues
Add support for cancellations
If users cancel the plan, the license should be updated to reflect that in the license message.
Test plan metadata when it is edited
We have to manage plan metadata by hand, and it is very error prone. Our webhook should e-mail us test results (i.e, a sample ID and remote license in decoded form) for the new plan, against a few different subscription states:
trial
active
canceled
etc.
Generate license based on chargbee plan meta_data and subscription id/secret (and fields)
Move web server, endpoint, mailer into this repository
For collecting plan metadata
{
"kind": "oem",
"is_public": true,
"restrictions": "Single-product OEM redistribution. Only for organizations with fewer than 500 employees.",
"features": [
"R_Elite",
"R_Creative",
"R_Performance"
],
"network_grace_minutes": 720,
"subscription_grace_minutes": 28800
}
Create id/secret on Chargbee subscriptions
Update license on customer_changed
No subscription comes through, but we can look up subscriptions by customer id and update all of them.
Re-add test of too-far-future expires date
Somehow this test never got merged into master
Bug in perpetual licensing
The Expires field is required unless a subscription_expiration_date is specified or only ImageResizer v4 is supported
/app/gem/lib/imazen_licensing/v2_remote_license_text.rb:29:in validate' /app/gem/lib/imazen_licensing/validating_hash.rb:7:in
initialize'
/app/gem/lib/imazen_licensing/license_generator.rb:19:in new' /app/gem/lib/imazen_licensing/license_generator.rb:19:in
generate_with_info'
/app/gem/lib/imazen_licensing/license_generator.rb:11:in generate_with_info' /app/app/models/license_handler.rb:107:in
generate_license'
/app/app/models/license_handler.rb:78:in license_summary' /app/app/models/license_handler.rb:111:in
license_hash'
/app/app/models/license_handler.rb:21:in maybe_send_license_email' /app/app/models/license_handler.rb:14:in
call'
/app/app/controllers/chargebee_controller.rb:13:in index' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/basic_implicit_render.rb:6:in
send_action'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:194:in process_action' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/rendering.rb:30:in
process_action'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:42:in block in process_action' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:132:in
run_callbacks'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:41:in process_action' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/rescue.rb:22:in
process_action'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:34:in block in process_action' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in
block in instrument'
/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in instrument' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in
instrument'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:32:in process_action' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/params_wrapper.rb:256:in
process_action'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:134:in process' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:191:in
dispatch'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:252:in dispatch' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:52:in
dispatch'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:34:in serve' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:52:in
block in serve'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in each' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in
serve'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:840:in call' /app/vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/etag.rb:25:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:38:in call' /app/vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/head.rb:12:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in block in call' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in
run_callbacks'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in call' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in call' /app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in
call_app'
/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:26:in block in call' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:71:in
block in tagged'
/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:28:in tagged' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:71:in
tagged'
/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:26:in call' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in call' /app/vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/runtime.rb:22:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in call' /app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/static.rb:127:in call' /app/vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in call' /app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.1/lib/puma/configuration.rb:227:in
call'
/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.1/lib/puma/server.rb:660:in handle_request' /app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.1/lib/puma/server.rb:474:in
process_client'
/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.1/lib/puma/server.rb:334:in block in run' /app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.1/lib/puma/thread_pool.rb:135:in
block in spawn_thread'
<ActionController::Parameters {"id"=>"ev_JD8rbaSRgyaTQsIFC", "occurred_at"=>1572979212, "source"=>"admin_console", "user"=>"[email protected]", "object"=>"event", "api_version"=>"v2", "content"=><ActionController::Parameters {"subscription"=><ActionController::Parameters {"id"=>"J280sqeQZwM55t744", "customer_id"=>"J280sqeQZwM55t744", "plan_id"=>"enterprise-wide-elite-edition-yearly", "plan_quantity"=>1, "plan_unit_price"=>360000, "plan_amount"=>360000, "billing_period"=>1, "billing_period_unit"=>"year", "plan_free_quantity"=>0, "status"=>"active", "current_term_start"=>Sun, 03 Nov 2019 18:17:44 +0000, "current_term_end"=>Tue, 03 Nov 2020 18:17:44 +0000, "next_billing_at"=>Tue, 03 Nov 2020 18:17:44 +0000, "po_number"=>"5000351077", "created_at"=>Fri, 03 Nov 2017 18:17:44 +0000, "started_at"=>Fri, 03 Nov 2017 18:17:44 +0000, "activated_at"=>Fri, 03 Nov 2017 18:17:44 +0000, "updated_at"=>Tue, 05 Nov 2019 18:40:12 +0000, "has_scheduled_changes"=>false, "resource_version"=>1572979212805, "deleted"=>false, "object"=>"subscription", "currency_code"=>"USD", "due_invoices_count"=>1, "due_since"=>1541269064, "total_dues"=>360000, "mrr"=>30000, "exchange_rate"=>1.0, "base_currency_code"=>"USD", "shipping_address"=>{"first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "company"=>"METRO-nom GmbH", "line1"=>"Postfach 1231", "city"=>"Pasewalk", "country"=>"DE", "zip"=>"17302", "validation_status"=>"not_validated", "object"=>"shipping_address"}, "invoice_notes"=>"They purchased a perpetual license; need to set this up properly", "cf_license_id"=>"195815042", "cf_license_hash"=>"5809bc3b2b56b8abfe3ee942a35cb38a8f1b5917215d7bced1afa260aa1e49b4", "cf_perpetual"=>"true", "cancelled_at"=>nil, "trial_start"=>nil, "trial_end"=>nil} permitted: false>, "customer"=>{"id"=>"J280sqeQZwM55t744", "first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "phone"=>"+49 (211) 6886-2308", "company"=>"METRO-nom GmbH", "auto_collection"=>"off", "net_term_days"=>30, "allow_direct_debit"=>false, "created_at"=>1509733064, "taxability"=>"taxable", "updated_at"=>1526403367, "pii_cleared"=>"active", "resource_version"=>1526403367924, "deleted"=>false, "object"=>"customer", "billing_address"=>{"first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "company"=>"METRO Systems GmbH METRO SYSTEMS GMBH", "line1"=>"Metrostrasse 12", "city"=>"Duesseldorf", "country"=>"DE", "zip"=>"40235", "validation_status"=>"not_validated", "object"=>"billing_address"}, "card_status"=>"no_card", "promotional_credits"=>0, "refundable_credits"=>0, "excess_payments"=>0, "unbilled_charges"=>0, "preferred_currency_code"=>"USD", "cf_website"=>"https://metrosystems.net"}} permitted: false>, "event_type"=>"subscription_changed", "webhook_status"=>"scheduled", "webhooks"=>[{"id"=>"whv2_B6HFjARXIcDniFo5", "webhook_status"=>"scheduled", "object"=>"webhook"}], "key"=>"53d583674540ff620c0276ad9d4017aee4b460f36d0273802bbdecbe44da7f6b", "controller"=>"chargebee", "action"=>"index", "chargebee"=>{"id"=>"ev_JD8rbaSRgyaTQsIFC", "occurred_at"=>1572979212, "source"=>"admin_console", "user"=>"[email protected]", "object"=>"event", "api_version"=>"v2", "content"=>{"subscription"=>{"id"=>"J280sqeQZwM55t744", "customer_id"=>"J280sqeQZwM55t744", "plan_id"=>"enterprise-wide-elite-edition-yearly", "plan_quantity"=>1, "plan_unit_price"=>360000, "plan_amount"=>360000, "billing_period"=>1, "billing_period_unit"=>"year", "plan_free_quantity"=>0, "status"=>"active", "current_term_start"=>1572805064, "current_term_end"=>1604427464, "next_billing_at"=>1604427464, "po_number"=>"5000351077", "created_at"=>1509733064, "started_at"=>1509733064, "activated_at"=>1509733064, "updated_at"=>1572979212, "has_scheduled_changes"=>false, "resource_version"=>1572979212805, "deleted"=>false, "object"=>"subscription", "currency_code"=>"USD", "due_invoices_count"=>1, "due_since"=>1541269064, "total_dues"=>360000, "mrr"=>30000, "exchange_rate"=>1.0, "base_currency_code"=>"USD", "shipping_address"=>{"first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "company"=>"METRO-nom GmbH", "line1"=>"Postfach 1231", "city"=>"Pasewalk", "country"=>"DE", "zip"=>"17302", "validation_status"=>"not_validated", "object"=>"shipping_address"}, "invoice_notes"=>"They purchased a perpetual license; need to set this up properly", "cf_license_id"=>"195815042", "cf_license_hash"=>"5809bc3b2b56b8abfe3ee942a35cb38a8f1b5917215d7bced1afa260aa1e49b4", "cf_perpetual"=>"true"}, "customer"=>{"id"=>"J280sqeQZwM55t744", "first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "phone"=>"+49 (211) 6886-2308", "company"=>"METRO-nom GmbH", "auto_collection"=>"off", "net_term_days"=>30, "allow_direct_debit"=>false, "created_at"=>1509733064, "taxability"=>"taxable", "updated_at"=>1526403367, "pii_cleared"=>"active", "resource_version"=>1526403367924, "deleted"=>false, "object"=>"customer", "billing_address"=>{"first_name"=>"Christoph", "last_name"=>"Pelz", "email"=>"[email protected]", "company"=>"METRO Systems GmbH METRO SYSTEMS GMBH", "line1"=>"Metrostrasse 12", "city"=>"Duesseldorf", "country"=>"DE", "zip"=>"40235", "validation_status"=>"not_validated", "object"=>"billing_address"}, "card_status"=>"no_card", "promotional_credits"=>0, "refundable_credits"=>0, "excess_payments"=>0, "unbilled_charges"=>0, "preferred_currency_code"=>"USD", "cf_website"=>"https://metrosystems.net"}}, "event_type"=>"subscription_changed", "webhook_status"=>"scheduled", "webhooks"=>[{"id"=>"whv2_B6HFjARXIcDniFo5", "webhook_status"=>"scheduled", "object"=>"webhook"}]}} permitted: false>
Notify users if they haven't paid via license
Users who have failed credit card attempts should be notified via license message.
Add support for perpetual licenses
ImageResizer subscriptions that are cancelled after 3 years should become Perpetual use licenses for builds released before the cancel date.
ImageResizer subscriptions purchased with the perpetual add-on, or tagged perpetual should also.
Email users if they forgot to enter a domain in a domain-specific license
Currently these cause a license error email to be sent to the admins stating ' A minimum of 1 domain(s) are required to generate this license'
Confim tests under /gem are running on travis
Add multi-user chargebee support
Most companies have separate billing, licensing, and software departments that don't have access to a shared email account.
Adding an an authorized_emails custom field that permits comma or space-delimited addresses.
We should be able to create/send magic links for portal access...
Provide debugging output in plaintext response to webook
If the webhook token is correct, we should display a detailed error message upon failure, or an action log upon success. Plain text is fine.
Chargebee provides an excellent harness for re-executing webhooks and looking at responses, which allows us to troubleshoot real problems quickly. empty responses reduce the utility of the replay and test system available.
Actions we should log
- Whether we used the provided subscription object or re-fetched it, or whether it was nil
- Whether we updated update_license_id_and_hash
- Sending any email
- Uploading a license file
- Skipping one of the above
I think this would be helpful in troubleshooting customer errors and fixing them in real time.
Let's also output ENV['SOURCE_VERSION'] so we know the commit deployed.
Conditional S3 uploading?
Do we want to be uploading licenses to S3 every time a subscription webhook is triggered? I'm not sure if it just overwrites the existing license (which is probably ok), but it seems like a potentially unnecessary step if there are no changes.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.