effective_orders 2.2.4 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +124 -84
  4. data/app/assets/javascripts/effective_orders/customers.js.coffee +39 -0
  5. data/app/assets/javascripts/effective_orders/providers/{stripe_charges.js.coffee → stripe.js.coffee} +15 -13
  6. data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +73 -0
  7. data/app/assets/stylesheets/effective_orders.scss +2 -1
  8. data/app/assets/stylesheets/effective_orders/_order.scss +16 -8
  9. data/app/assets/stylesheets/effective_orders/_subscriptions.scss +14 -0
  10. data/app/controllers/admin/customers_controller.rb +11 -8
  11. data/app/controllers/admin/order_items_controller.rb +4 -8
  12. data/app/controllers/admin/orders_controller.rb +133 -87
  13. data/app/controllers/effective/carts_controller.rb +18 -8
  14. data/app/controllers/effective/concerns/purchase.rb +39 -0
  15. data/app/controllers/effective/customers_controller.rb +43 -0
  16. data/app/controllers/effective/orders_controller.rb +73 -119
  17. data/app/controllers/effective/providers/app_checkout.rb +3 -1
  18. data/app/controllers/effective/providers/ccbill.rb +4 -6
  19. data/app/controllers/effective/providers/cheque.rb +20 -11
  20. data/app/controllers/effective/providers/free.rb +33 -0
  21. data/app/controllers/effective/providers/mark_as_paid.rb +33 -0
  22. data/app/controllers/effective/providers/moneris.rb +9 -17
  23. data/app/controllers/effective/providers/paypal.rb +4 -6
  24. data/app/controllers/effective/providers/pretend.rb +4 -4
  25. data/app/controllers/effective/providers/refund.rb +39 -0
  26. data/app/controllers/effective/providers/stripe.rb +19 -40
  27. data/app/controllers/effective/providers/stripe_connect.rb +2 -6
  28. data/app/controllers/effective/webhooks_controller.rb +44 -95
  29. data/app/datatables/effective_customers_datatable.rb +21 -29
  30. data/app/datatables/effective_order_items_datatable.rb +77 -79
  31. data/app/datatables/effective_orders_datatable.rb +67 -57
  32. data/app/helpers/effective_carts_helper.rb +17 -14
  33. data/app/helpers/effective_orders_helper.rb +40 -56
  34. data/app/helpers/effective_paypal_helper.rb +3 -3
  35. data/app/helpers/effective_stripe_helper.rb +47 -18
  36. data/app/helpers/effective_subscriptions_helper.rb +79 -0
  37. data/app/mailers/effective/orders_mailer.rb +125 -2
  38. data/app/models/concerns/acts_as_purchasable.rb +23 -33
  39. data/app/models/concerns/acts_as_subscribable.rb +68 -0
  40. data/app/models/concerns/acts_as_subscribable_buyer.rb +22 -0
  41. data/app/models/effective/cart.rb +53 -24
  42. data/app/models/effective/cart_item.rb +6 -12
  43. data/app/models/effective/customer.rb +51 -54
  44. data/app/models/effective/order.rb +160 -147
  45. data/app/models/effective/order_item.rb +18 -21
  46. data/app/models/effective/product.rb +7 -7
  47. data/app/models/effective/providers/ccbill_postback.rb +1 -1
  48. data/app/models/effective/providers/stripe_charge.rb +8 -19
  49. data/app/models/effective/subscripter.rb +230 -0
  50. data/app/models/effective/subscription.rb +27 -76
  51. data/app/models/effective/tax_rate_calculator.rb +10 -7
  52. data/app/views/admin/customers/_actions.html.haml +1 -2
  53. data/app/views/admin/customers/index.html.haml +1 -1
  54. data/app/views/admin/customers/show.html.haml +6 -0
  55. data/app/views/admin/orders/_actions.html.haml +9 -7
  56. data/app/views/admin/orders/_form.html.haml +11 -7
  57. data/app/views/admin/orders/_order_actions.html.haml +2 -1
  58. data/app/views/admin/orders/_order_item_fields.html.haml +1 -1
  59. data/app/views/admin/orders/edit.html.haml +4 -0
  60. data/app/views/admin/orders/index.html.haml +1 -4
  61. data/app/views/admin/orders/new.html.haml +1 -1
  62. data/app/views/admin/orders/show.html.haml +5 -6
  63. data/app/views/effective/carts/_cart.html.haml +2 -2
  64. data/app/views/effective/carts/show.html.haml +2 -2
  65. data/app/views/effective/customers/_customer.html.haml +152 -0
  66. data/app/views/effective/customers/_fields.html.haml +12 -0
  67. data/app/views/effective/customers/_form.html.haml +13 -0
  68. data/app/views/effective/customers/edit.html.haml +3 -0
  69. data/app/views/effective/orders/_checkout_step1.html.haml +8 -15
  70. data/app/views/effective/orders/_checkout_step2.html.haml +34 -21
  71. data/app/views/effective/orders/_order.html.haml +8 -9
  72. data/app/views/effective/orders/_order_actions.html.haml +7 -8
  73. data/app/views/effective/orders/_order_header.html.haml +1 -1
  74. data/app/views/effective/orders/_order_items.html.haml +11 -5
  75. data/app/views/effective/orders/_order_note.html.haml +4 -7
  76. data/app/views/effective/orders/_orders_table.html.haml +26 -26
  77. data/app/views/effective/orders/app_checkout/_form.html.haml +2 -2
  78. data/app/views/effective/orders/ccbill/_form.html.haml +1 -1
  79. data/app/views/effective/orders/cheque/_form.html.haml +3 -1
  80. data/app/views/effective/orders/declined.html.haml +1 -1
  81. data/app/views/effective/orders/{checkout_step1.html.haml → edit.html.haml} +0 -0
  82. data/app/views/effective/orders/free/_form.html.haml +4 -0
  83. data/app/views/effective/orders/index.html.haml +2 -4
  84. data/app/views/effective/orders/mark_as_paid/_form.html.haml +32 -0
  85. data/app/views/effective/orders/moneris/_form.html.haml +6 -6
  86. data/app/views/effective/orders/{checkout_step2.html.haml → new.html.haml} +1 -1
  87. data/app/views/effective/orders/paypal/_form.html.haml +2 -2
  88. data/app/views/effective/orders/pretend/_form.html.haml +2 -2
  89. data/app/views/effective/orders/purchased.html.haml +3 -0
  90. data/app/views/effective/orders/refund/_form.html.haml +32 -0
  91. data/app/views/effective/orders/show.html.haml +4 -1
  92. data/app/views/effective/orders/stripe/_form.html.haml +5 -5
  93. data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
  94. data/app/views/effective/orders_mailer/subscription_payment_failed.html.haml +9 -0
  95. data/app/views/effective/orders_mailer/subscription_payment_succeeded.html.haml +9 -0
  96. data/app/views/effective/orders_mailer/subscription_trial_expired.html.haml +5 -0
  97. data/app/views/effective/orders_mailer/subscription_trial_expiring.html.haml +7 -0
  98. data/app/views/effective/subscriptions/_fields.html.haml +16 -0
  99. data/app/views/effective/subscriptions/_plan.html.haml +21 -0
  100. data/app/views/layouts/effective_orders_mailer_layout.html.haml +6 -8
  101. data/config/effective_orders.rb +41 -20
  102. data/config/routes.rb +48 -48
  103. data/db/migrate/01_create_effective_orders.rb.erb +19 -5
  104. data/lib/effective_orders.rb +78 -42
  105. data/lib/effective_orders/engine.rb +36 -82
  106. data/lib/effective_orders/version.rb +1 -1
  107. data/lib/generators/effective_orders/install_generator.rb +2 -2
  108. data/lib/generators/templates/effective_orders_mailer_preview.rb +39 -4
  109. data/lib/tasks/effective_orders_tasks.rake +42 -0
  110. data/spec/controllers/carts_controller_spec.rb +1 -1
  111. data/spec/controllers/moneris_orders_controller_spec.rb +4 -4
  112. data/spec/controllers/orders_controller_spec.rb +4 -4
  113. data/spec/controllers/stripe_orders_controller_spec.rb +2 -2
  114. data/spec/controllers/webhooks_controller_spec.rb +1 -1
  115. data/spec/dummy/config/initializers/effective_orders.rb +1 -7
  116. data/spec/dummy/db/schema.rb +1 -0
  117. data/spec/dummy/db/test.sqlite3 +0 -0
  118. data/spec/dummy/log/test.log +3 -0
  119. data/spec/models/acts_as_purchasable_spec.rb +0 -56
  120. data/spec/models/customer_spec.rb +3 -3
  121. data/spec/models/order_spec.rb +2 -2
  122. data/spec/spec_helper.rb +1 -1
  123. data/spec/support/factories.rb +2 -1
  124. metadata +37 -49
  125. data/active_admin/effective_carts.rb +0 -14
  126. data/active_admin/effective_orders.rb +0 -112
  127. data/app/assets/javascripts/effective_orders/providers/stripe_subscriptions.js.coffee +0 -28
  128. data/app/controllers/concerns/acts_as_active_admin_controller.rb +0 -69
  129. data/app/controllers/effective/subscriptions_controller.rb +0 -126
  130. data/app/models/effective/datatables/customers.rb +0 -40
  131. data/app/models/effective/datatables/order_items.rb +0 -101
  132. data/app/models/effective/datatables/orders.rb +0 -91
  133. data/app/models/inputs/price_field.rb +0 -63
  134. data/app/models/inputs/price_form_input.rb +0 -7
  135. data/app/models/inputs/price_formtastic_input.rb +0 -9
  136. data/app/models/inputs/price_input.rb +0 -19
  137. data/app/models/inputs/price_simple_form_input.rb +0 -8
  138. data/app/views/admin/orders/_form_mark_as_paid.html.haml +0 -33
  139. data/app/views/admin/orders/_order_payment_details.html.haml +0 -5
  140. data/app/views/admin/orders/mark_as_paid.html.haml +0 -7
  141. data/app/views/effective/orders/stripe/_subscription_fields.html.haml +0 -7
  142. data/app/views/effective/subscriptions/index.html.haml +0 -22
  143. data/app/views/effective/subscriptions/new.html.haml +0 -9
  144. data/app/views/effective/subscriptions/show.html.haml +0 -49
  145. data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +0 -29
  146. data/db/upgrade/03_upgrade_effective_orders_from1x.rb.erb +0 -98
  147. data/db/upgrade/upgrade_price_column_on_table.rb.erb +0 -17
  148. data/lib/generators/effective_orders/upgrade_from03x_generator.rb +0 -31
  149. data/lib/generators/effective_orders/upgrade_from1x_generator.rb +0 -27
  150. data/lib/generators/effective_orders/upgrade_price_column_generator.rb +0 -30
@@ -6,10 +6,12 @@ module Effective
6
6
  included do
7
7
  end
8
8
 
9
+ # TODO: Make app checkout work with admin checkout workflow
10
+
9
11
  def app_checkout
10
12
  @order = Order.find(params[:id])
11
13
 
12
- (EffectiveOrders.authorized?(self, :update, @order) rescue false)
14
+ (EffectiveOrders.authorize!(self, :update, @order) rescue false)
13
15
 
14
16
  checkout = EffectiveOrders.app_checkout[:service].call(order: @order)
15
17
  if checkout.success?
@@ -4,18 +4,16 @@ module Effective
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- if respond_to?(:skip_before_action)
8
- skip_before_action :verify_authenticity_token, only: [:ccbill_postback]
9
- else
10
- skip_before_filter :verify_authenticity_token, only: [:ccbill_postback]
11
- end
7
+ skip_before_action :verify_authenticity_token, only: [:ccbill_postback]
12
8
  end
13
9
 
10
+ # TODO: Make ccbill work with admin checkout workflow
11
+
14
12
  def ccbill_postback
15
13
  postback = Effective::Providers::CcbillPostback.new(params)
16
14
  @order ||= Effective::Order.find(postback.order_id)
17
15
 
18
- (EffectiveOrders.authorized?(self, :update, @order) rescue false)
16
+ (EffectiveOrders.authorize!(self, :update, @order) rescue false)
19
17
 
20
18
  if @order.present? && postback.verified?
21
19
  if @order.purchased?
@@ -5,25 +5,34 @@ module Effective
5
5
 
6
6
  def pay_by_cheque
7
7
  @order ||= Order.find(params[:id])
8
+ @page_title = 'Payment Required'
9
+
10
+ EffectiveOrders.authorize!(self, :update, @order)
8
11
 
9
12
  @order.purchase_state = EffectiveOrders::PENDING
10
13
  @order.payment_provider = 'cheque'
11
14
 
12
- EffectiveOrders.authorized?(self, :update, @order)
15
+ begin
16
+ @order.save!
17
+ @order.send_pending_order_invoice_to_buyer!
13
18
 
14
- @page_title = 'Payment Required'
19
+ Effective::Cart.where(user_id: @order.user_id).destroy_all
15
20
 
16
- if @order.save
17
- @order.send_pending_order_invoice_to_buyer!
18
- current_cart.try(:destroy)
19
- flash.now[:success] = 'Successfully indicated order will be payed by cheque.'
20
- else
21
+ message = "Successfully indicated order will be payed by cheque. A pending order invoice has been sent to #{@order.user.email}"
22
+
23
+ # When posted from admin form, there will be a redirect url
24
+ if params[:purchased_url].present?
25
+ flash[:success] = message
26
+ redirect_to params[:purchased_url].gsub(':id', @order.to_param.to_s)
27
+ else
28
+ # Otherwise this is the user flow
29
+ flash.now[:success] = message
30
+ render 'effective/orders/cheque/pay_by_cheque'
31
+ end
32
+ rescue => e
21
33
  flash[:danger] = "Unable to save your order: #{@order.errors.full_messages.to_sentence}. Please try again."
22
- redirect_to effective_orders.order_path(@order)
23
- return
34
+ redirect_to params[:declined_url].presence || effective_orders.order_path(@order)
24
35
  end
25
-
26
- render 'effective/orders/cheque/pay_by_cheque'
27
36
  end
28
37
  end
29
38
  end
@@ -0,0 +1,33 @@
1
+ module Effective
2
+ module Providers
3
+ module Free
4
+ extend ActiveSupport::Concern
5
+
6
+ def free
7
+ @order ||= Order.find(params[:id])
8
+
9
+ EffectiveOrders.authorize!(self, :update, @order)
10
+
11
+ unless @order.free?
12
+ flash[:danger] = 'Unable to process free order with a non-zero total'
13
+ redirect_to effective_orders.order_path(@order)
14
+ return
15
+ end
16
+
17
+ order_purchased(
18
+ details: 'free order. no payment required.',
19
+ provider: 'free',
20
+ card: 'none',
21
+ purchased_url: params[:purchased_url],
22
+ declined_url: params[:declined_url],
23
+ email: false
24
+ )
25
+ end
26
+
27
+ def free_params
28
+ params.require(:effective_order).permit(:purchased_url, :declined_url)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Effective
2
+ module Providers
3
+ module MarkAsPaid
4
+ extend ActiveSupport::Concern
5
+
6
+ def mark_as_paid
7
+ @order ||= Order.find(params[:id])
8
+
9
+ EffectiveOrders.authorize!(self, :update, @order)
10
+ EffectiveOrders.authorize!(self, :admin, :effective_orders)
11
+
12
+ @order.assign_attributes(mark_as_paid_params.except(:payment, :payment_provider, :payment_card))
13
+
14
+ order_purchased(
15
+ details: mark_as_paid_params[:payment],
16
+ provider: mark_as_paid_params[:payment_provider],
17
+ card: mark_as_paid_params[:payment_card],
18
+ email: @order.send_mark_as_paid_email_to_buyer?,
19
+ skip_buyer_validations: true,
20
+ purchased_url: params[:purchased_url].presence || effective_orders.admin_order_path(@order),
21
+ declined_url: params[:declined_url].presence || effective_orders.admin_order_path(@order)
22
+ )
23
+ end
24
+
25
+ def mark_as_paid_params
26
+ params.require(:effective_order).permit(
27
+ :payment, :payment_provider, :payment_card, :note_to_buyer, :send_mark_as_paid_email_to_buyer
28
+ )
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -4,24 +4,20 @@ module Effective
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- if respond_to?(:prepend_before_action)
8
- prepend_before_action :find_authenticity_token_from_moneris, only: [:moneris_postback]
9
- else
10
- prepend_before_filter :find_authenticity_token_from_moneris, only: [:moneris_postback]
11
- end
7
+ skip_before_action :verify_authenticity_token, only: [:moneris_postback]
12
8
  end
13
9
 
14
10
  def moneris_postback
15
11
  @order ||= Effective::Order.find(params[:response_order_id])
16
12
 
17
- (EffectiveOrders.authorized?(self, :update, @order) rescue false)
13
+ (EffectiveOrders.authorize!(self, :update, @order) rescue false)
18
14
 
19
15
  # Delete the Purchased and Declined Redirect URLs
20
- purchased_redirect_url = params.delete(:rvar_purchased_redirect_url)
21
- declined_redirect_url = params.delete(:rvar_declined_redirect_url)
16
+ purchased_url = params.delete(:rvar_purchased_url)
17
+ declined_url = params.delete(:rvar_declined_url)
22
18
 
23
19
  if @order.purchased? # Fallback to a success condition of the Order is already purchased
24
- order_purchased(details: params, provider: 'moneris', card: params[:card], redirect_url: purchased_redirect_url)
20
+ order_purchased(details: params, provider: 'moneris', card: params[:card], purchased_url: purchased_url)
25
21
  return
26
22
  end
27
23
 
@@ -31,12 +27,12 @@ module Effective
31
27
  response_code = verify_params[:response_code].to_i # Sometimes moneris sends us the string 'null'
32
28
 
33
29
  if response_code > 0 && response_code < 50 # Less than 50 means a successful validation
34
- order_purchased(details: params.merge(verify_params), provider: 'moneris', card: params[:card], redirect_url: purchased_redirect_url)
30
+ order_purchased(details: params.merge(verify_params), provider: 'moneris', card: params[:card], purchased_url: purchased_url)
35
31
  else
36
- order_declined(details: params.merge(verify_params), provider: 'moneris', card: params[:card], redirect_url: declined_redirect_url)
32
+ order_declined(details: params.merge(verify_params), provider: 'moneris', card: params[:card], declined_url: declined_url)
37
33
  end
38
34
  else
39
- order_declined(details: params, provider: 'moneris', card: params[:card], redirect_url: declined_redirect_url)
35
+ order_declined(details: params, provider: 'moneris', card: params[:card], declined_url: declined_url)
40
36
  end
41
37
  end
42
38
 
@@ -47,11 +43,7 @@ module Effective
47
43
  end
48
44
 
49
45
  def send_moneris_verify_request(verify_key)
50
- `curl -F ps_store_id='#{EffectiveOrders.moneris[:ps_store_id]}' -F hpp_key='#{EffectiveOrders.moneris[:hpp_key]}' -F transactionKey='#{verify_key}' --referer #{effective_orders.moneris_postback_url} #{EffectiveOrders.moneris[:verify_url]}`
51
- end
52
-
53
- def find_authenticity_token_from_moneris
54
- params[:authenticity_token] = params.delete(:rvar_authenticity_token)
46
+ `curl -F ps_store_id='#{EffectiveOrders.moneris[:ps_store_id]}' -F hpp_key='#{EffectiveOrders.moneris[:hpp_key]}' -F transactionKey='#{verify_key}' --referer #{effective_orders.moneris_postback_orders_url} #{EffectiveOrders.moneris[:verify_url]}`
55
47
  end
56
48
 
57
49
  end
@@ -4,17 +4,15 @@ module Effective
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- if respond_to?(:skip_before_action)
8
- skip_before_action :verify_authenticity_token, :only => [:paypal_postback]
9
- else
10
- skip_before_filter :verify_authenticity_token, :only => [:paypal_postback]
11
- end
7
+ skip_before_action :verify_authenticity_token, only: [:paypal_postback]
12
8
  end
13
9
 
10
+ # TODO: Make paypal postback work with admin checkout workflow
11
+
14
12
  def paypal_postback
15
13
  @order ||= Effective::Order.where(id: (params[:invoice].to_i rescue 0)).first
16
14
 
17
- (EffectiveOrders.authorized?(self, :update, @order) rescue false)
15
+ (EffectiveOrders.authorize!(self, :update, @order) rescue false)
18
16
 
19
17
  if @order.present?
20
18
  if @order.purchased?
@@ -3,17 +3,17 @@ module Effective
3
3
  module Pretend
4
4
  extend ActiveSupport::Concern
5
5
 
6
- def pretend_purchase
6
+ def pretend
7
7
  @order ||= Order.find(params[:id])
8
8
 
9
- EffectiveOrders.authorized?(self, :update, @order)
9
+ EffectiveOrders.authorize!(self, :update, @order)
10
10
 
11
11
  order_purchased(
12
12
  details: 'for pretend',
13
13
  provider: 'pretend',
14
14
  card: 'none',
15
- redirect_url: params[:purchased_redirect_url],
16
- declined_redirect_url: params[:declined_redirect_url]
15
+ purchased_url: params[:purchased_url],
16
+ declined_url: params[:declined_url]
17
17
  )
18
18
  end
19
19
 
@@ -0,0 +1,39 @@
1
+ module Effective
2
+ module Providers
3
+ module Refund
4
+ extend ActiveSupport::Concern
5
+
6
+ def refund
7
+ @order ||= Order.find(params[:id])
8
+
9
+ EffectiveOrders.authorize!(self, :update, @order)
10
+ EffectiveOrders.authorize!(self, :admin, :effective_orders)
11
+
12
+ unless @order.refund?
13
+ flash[:danger] = 'Unable to process refund with a non-negative total'
14
+ redirect_to effective_orders.admin_order_path(@order)
15
+ return
16
+ end
17
+
18
+ @order.assign_attributes(refund_params.except(:payment, :payment_provider, :payment_card))
19
+
20
+ order_purchased(
21
+ details: refund_params[:payment],
22
+ provider: refund_params[:payment_provider],
23
+ card: refund_params[:payment_card],
24
+ email: @order.send_mark_as_paid_email_to_buyer?,
25
+ skip_buyer_validations: true,
26
+ purchased_url: params[:purchased_url].presence || effective_orders.admin_order_path(@order),
27
+ declined_url: params[:declined_url].presence || effective_orders.admin_order_path(@order)
28
+ )
29
+ end
30
+
31
+ def refund_params
32
+ params.require(:effective_order).permit(
33
+ :payment, :payment_provider, :payment_card, :note_to_buyer, :send_mark_as_paid_email_to_buyer
34
+ )
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -3,23 +3,26 @@ module Effective
3
3
  module Stripe
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ # TODO: Make stripe charge work with admin checkout workflow, purchased_url and declined_url
7
+ # Make it save the customer and not require typing in a CC every time.
8
+
6
9
  def stripe_charge
7
10
  @order ||= Effective::Order.find(stripe_charge_params[:effective_order_id])
8
11
  @stripe_charge = Effective::Providers::StripeCharge.new(stripe_charge_params)
9
12
  @stripe_charge.order = @order
10
13
 
11
- EffectiveOrders.authorized?(self, :update, @order)
14
+ EffectiveOrders.authorize!(self, :update, @order)
12
15
 
13
16
  if @stripe_charge.valid? && (response = process_stripe_charge(@stripe_charge)) != false
14
17
  order_purchased(
15
18
  details: response,
16
19
  provider: (EffectiveOrders.stripe_connect_enabled ? 'stripe_connect' : 'stripe'),
17
- card: (response['charge']['card']['brand'] rescue nil)
20
+ card: (response[:charge]['source']['brand'] rescue nil)
18
21
  )
19
22
  else
20
23
  @page_title = 'Checkout'
21
24
  flash.now[:danger] = @stripe_charge.errors.full_messages.to_sentence
22
- render :checkout_step2
25
+ render :show
23
26
  end
24
27
  end
25
28
 
@@ -28,16 +31,16 @@ module Effective
28
31
  def process_stripe_charge(charge)
29
32
  Effective::Order.transaction do
30
33
  begin
31
- @buyer = Effective::Customer.for_user(charge.order.user)
32
- @buyer.update_card!(charge.token)
34
+ subscripter = Effective::Subscripter.new(user: charge.order.user, stripe_token: charge.stripe_token)
35
+ subscripter.save!
33
36
 
34
37
  if EffectiveOrders.stripe_connect_enabled
35
- return charge_with_stripe_connect(charge, @buyer)
38
+ return charge_with_stripe_connect(charge, subscripter.customer)
36
39
  else
37
- return charge_with_stripe(charge, @buyer)
40
+ return charge_with_stripe(charge, subscripter.customer)
38
41
  end
39
42
  rescue => e
40
- charge.errors.add(:base, "Unable to process order with Stripe. Your credit card has not been charged. Message: \"#{e.message}\".")
43
+ charge.errors.add(:base, "Unable to process order with Stripe. Your credit card has not been charged. Message: \"#{e.message}\".")
41
44
  raise ActiveRecord::Rollback
42
45
  end
43
46
  end
@@ -45,35 +48,15 @@ module Effective
45
48
  false
46
49
  end
47
50
 
48
- def charge_with_stripe(charge, buyer)
49
- results = {subscriptions: {}, charge: nil}
50
-
51
- # Process subscriptions.
52
- charge.subscriptions.each do |subscription|
53
- next if subscription.stripe_plan_id.blank?
54
-
55
- stripe_subscription = if subscription.stripe_coupon_id.present?
56
- buyer.stripe_customer.subscriptions.create({plan: subscription.stripe_plan_id, coupon: subscription.stripe_coupon_id})
57
- else
58
- buyer.stripe_customer.subscriptions.create({plan: subscription.stripe_plan.id})
59
- end
60
-
61
- subscription.stripe_subscription_id = stripe_subscription.id
62
- subscription.save!
51
+ def charge_with_stripe(charge, customer)
52
+ results = { charge: nil }
63
53
 
64
- results[:subscriptions][subscription.stripe_plan_id] = JSON.parse(stripe_subscription.to_json)
65
- end
66
-
67
- # Process regular order_items.
68
- amount = charge.order_items.map { |oi| oi.total }.sum # A positive integer in cents representing how much to charge the card. The minimum amount is 50 cents.
69
- description = "Charge for Order ##{charge.order.to_param}"
70
-
71
- if amount > 0
54
+ if charge.order.total > 0
72
55
  results[:charge] = JSON.parse(::Stripe::Charge.create(
73
- amount: amount,
56
+ amount: charge.order.total,
74
57
  currency: EffectiveOrders.stripe[:currency],
75
- customer: buyer.stripe_customer.id,
76
- description: description
58
+ customer: customer.stripe_customer.id,
59
+ description: "Charge for Order ##{charge.order.to_param}"
77
60
  ).to_json)
78
61
  end
79
62
 
@@ -82,7 +65,7 @@ module Effective
82
65
 
83
66
  def charge_with_stripe_connect(charge, buyer)
84
67
  # Go through and create Stripe::Tokens for each seller
85
- items = charge.order_items.group_by(&:seller)
68
+ items = charge.order_items.group_by { |oi| oi.seller }
86
69
  results = {}
87
70
 
88
71
  # We do all these Tokens first, so if one throws an exception no charges are made
@@ -113,11 +96,7 @@ module Effective
113
96
 
114
97
  # StrongParameters
115
98
  def stripe_charge_params
116
- begin
117
- params.require(:effective_providers_stripe_charge).permit(:token, :effective_order_id)
118
- rescue => e
119
- params[:effective_providers_stripe_charge]
120
- end
99
+ params.require(:effective_providers_stripe_charge).permit(:stripe_token, :effective_order_id)
121
100
  end
122
101
 
123
102
  end
@@ -4,11 +4,7 @@ module Effective
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- if respond_to?(:prepend_before_action)
8
- prepend_before_action :set_stripe_connect_state_params, :only => [:stripe_connect_redirect_uri]
9
- else
10
- prepend_before_filter :set_stripe_connect_state_params, :only => [:stripe_connect_redirect_uri]
11
- end
7
+ prepend_before_action :set_stripe_connect_state_params, only: [:stripe_connect_redirect_uri]
12
8
  end
13
9
 
14
10
  # So this is the postback after Stripe does its oAuth authentication
@@ -18,7 +14,7 @@ module Effective
18
14
  customer = Effective::Customer.for_user(current_user)
19
15
 
20
16
  if token_params['access_token'].present? && customer.present?
21
- if customer.update_attributes(:stripe_connect_access_token => token_params['access_token'])
17
+ if customer.update_attributes(stripe_connect_access_token: token_params['access_token'])
22
18
  flash[:success] = 'Successfully Connected with Stripe Connect'
23
19
  else
24
20
  flash[:danger] = "Unable to update customer: #{customer.errors[:base].first}"
@@ -3,115 +3,64 @@ module Effective
3
3
  protect_from_forgery except: [:stripe]
4
4
  skip_authorization_check if defined?(CanCan)
5
5
 
6
- # Webhook from stripe
7
6
  def stripe
8
- (head(:ok) && return) if (params[:livemode] == false && Rails.env.production?) || params[:object] != 'event' || params[:id].blank?
7
+ @event = (Stripe::Webhook.construct_event(request.body.read, request.env['HTTP_STRIPE_SIGNATURE'], EffectiveOrders.subscription[:webhook_secret]) rescue nil)
8
+ (head(:bad_request) and return) if !@event || (params[:livemode] == false && Rails.env.production?)
9
9
 
10
- # Dont trust the POST, and instead request the actual event from Stripe
11
- @event = Stripe::Event.retrieve(params[:id]) rescue (head(:ok) && return)
10
+ Rails.logger.info "STRIPE WEBHOOK: #{@event.type}"
12
11
 
13
12
  Effective::Customer.transaction do
14
- begin
15
- case @event.type
16
- when 'customer.created' then stripe_customer_created(@event)
17
- when 'customer.deleted' then stripe_customer_deleted(@event)
18
- when 'customer.subscription.created' then stripe_subscription_created(@event)
19
- when 'customer.subscription.deleted' then stripe_subscription_deleted(@event)
20
- when 'invoice.payment_succeeded' then invoice_payment_succeeded(@event)
21
- end
22
- rescue => e
23
- Rails.logger.info "Stripe Webhook Error: #{e.message}"
24
- raise ActiveRecord::Rollback
13
+ case @event.type
14
+ # when 'customer.created'
15
+ # when 'customer.updated'
16
+ # when 'customer.source.created'
17
+ # when 'customer.source.deleted'
18
+ # when 'customer.subscription.created'
19
+ # when 'customer.subscription.updated'
20
+ # when 'invoice.created'
21
+ # when 'invoice.payment_succeeded'
22
+ # when 'invoiceitem.created'
23
+ # when 'invoiceitem.updated'
24
+ # when 'charge.succeeded'
25
+ # when 'charge.failed' # Card declined. 4000 0000 0000 0341
26
+
27
+ when 'invoice.payment_succeeded'
28
+ customer = Effective::Customer.where(stripe_customer_id: @event.data.object.customer).first!
29
+ customer.update_attributes!(status: 'active')
30
+
31
+ send_email(:subscription_payment_succeeded, customer)
32
+ when 'invoice.payment_failed'
33
+ customer = Effective::Customer.where(stripe_customer_id: @event.data.object.customer).first!
34
+ customer.update_attributes!(status: 'past_due')
35
+
36
+ send_email(:subscription_payment_failed, customer)
37
+ when 'customer.subscription.deleted'
38
+ customer = Effective::Customer.where(stripe_customer_id: @event.data.object.customer).first!
39
+ Effective::Subscription.where(customer: customer).destroy_all
40
+ customer.update_attributes!(stripe_subscription_id: nil, status: nil, active_card: nil)
41
+
42
+ send_email(:subscription_canceled, customer)
43
+ else
44
+ Rails.logger.info "[STRIPE WEBHOOK] Unhandled event type #{@event.type}"
25
45
  end
26
46
  end
27
47
 
28
- head :ok # Always return success
48
+ head(:ok)
29
49
  end
30
50
 
31
51
  private
32
52
 
33
- def stripe_customer_created(event)
34
- stripe_customer = event.data.object
35
- user = ::User.where(email: stripe_customer.email).first
36
-
37
- if user.present?
38
- customer = Effective::Customer.for_user(user) # This is a first_or_create
39
- customer.stripe_customer_id = stripe_customer.id
40
- customer.save!
41
- end
42
- end
43
-
44
- def stripe_customer_deleted(event)
45
- stripe_customer = event.data.object
46
- user = ::User.where(email: stripe_customer.email).first
47
-
48
- if user.present?
49
- customer = Effective::Customer.where(user_id: user.id).first
50
- customer.destroy! if customer
51
- end
52
- end
53
-
54
- def stripe_subscription_created(event)
55
- stripe_subscription = event.data.object
56
- @customer = Effective::Customer.where(stripe_customer_id: stripe_subscription.customer).first
57
-
58
- if @customer.present?
59
- subscription = @customer.subscriptions.where(stripe_plan_id: stripe_subscription.plan.id).first_or_initialize
60
-
61
- subscription.stripe_subscription_id = stripe_subscription.id
62
- subscription.stripe_plan_id = (stripe_subscription.plan.id rescue nil)
63
- subscription.stripe_coupon_id = stripe_subscription.discount.coupon.id if (stripe_subscription.discount.present? rescue false)
64
-
65
- subscription.save!
66
-
67
- unless subscription.purchased?
68
- # Now we have to purchase it
69
- @order = Effective::Order.new(subscription, user: @customer.user)
70
- @order.purchase!(details: "Webhook #{event.id}", provider: 'stripe', validate: false)
71
- end
72
-
73
- end
74
- end
75
-
76
- def stripe_subscription_deleted(event)
77
- stripe_subscription = event.data.object
78
- @customer = Effective::Customer.where(stripe_customer_id: stripe_subscription.customer).first
79
-
80
- if @customer.present?
81
- @customer.subscriptions.find { |subscription| subscription.stripe_plan_id == stripe_subscription.plan.id }.try(:destroy)
82
- subscription_deleted_callback(event)
53
+ def send_email(email, *mailer_args)
54
+ if EffectiveOrders.mailer[:delayed_job_deliver] && EffectiveOrders.mailer[:deliver_method] == :deliver_later
55
+ Effective::OrdersMailer.delay.public_send(email, *mailer_args)
56
+ elsif EffectiveOrders.mailer[:deliver_method].present?
57
+ Effective::OrdersMailer.public_send(email, *mailer_args).public_send(EffectiveOrders.mailer[:deliver_method])
58
+ else
59
+ Effective::OrdersMailer.public_send(email, *mailer_args).deliver_now
83
60
  end
84
- end
85
61
 
86
- def invoice_payment_succeeded(event)
87
- @customer = Effective::Customer.where(stripe_customer_id: event.data.object.customer).first
88
-
89
- check_for_subscription_renewal(event) if @customer.present?
62
+ true
90
63
  end
91
64
 
92
- def check_for_subscription_renewal(event)
93
- invoice_payment = event.data.object
94
- subscription_payments = invoice_payment.lines.select { |line_item| line_item.type == 'subscription' }
95
-
96
- if subscription_payments.present?
97
- customer = Stripe::Customer.retrieve(invoice_payment.customer)
98
- subscription_payments.each do |subscription_payment|
99
- subscription_renewed_callback(event) if stripe_subscription_renewed?(customer, subscription_payment)
100
- end
101
- end
102
- end
103
-
104
- def stripe_subscription_renewed?(customer, subscription_payment)
105
- subscription = customer.subscriptions.retrieve(subscription_payment.id) rescue nil # API client raises error when object not found
106
- subscription.present? && subscription.status == 'active' && subscription.start < (subscription_payment.period.start - 1.day)
107
- end
108
-
109
- def subscription_deleted_callback(_event)
110
- # Can be overridden in Effective::WebhooksController within a Rails application
111
- end
112
-
113
- def subscription_renewed_callback(_event)
114
- # Can be overridden in Effective::WebhooksController within a Rails application
115
- end
116
65
  end
117
66
  end