effective_orders 4.5.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 (135) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +1004 -0
  4. data/app/assets/images/effective_orders/stripe.png +0 -0
  5. data/app/assets/javascripts/effective_orders.js +6 -0
  6. data/app/assets/javascripts/effective_orders/customers.js.coffee +32 -0
  7. data/app/assets/javascripts/effective_orders/providers/stripe.js.coffee +77 -0
  8. data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +81 -0
  9. data/app/assets/stylesheets/effective_orders.scss +2 -0
  10. data/app/assets/stylesheets/effective_orders/_cart.scss +4 -0
  11. data/app/assets/stylesheets/effective_orders/_order.scss +58 -0
  12. data/app/controllers/admin/customers_controller.rb +24 -0
  13. data/app/controllers/admin/order_items_controller.rb +16 -0
  14. data/app/controllers/admin/orders_controller.rb +223 -0
  15. data/app/controllers/effective/carts_controller.rb +85 -0
  16. data/app/controllers/effective/concerns/purchase.rb +62 -0
  17. data/app/controllers/effective/customers_controller.rb +20 -0
  18. data/app/controllers/effective/orders_controller.rb +162 -0
  19. data/app/controllers/effective/providers/cheque.rb +22 -0
  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 +60 -0
  23. data/app/controllers/effective/providers/paypal.rb +33 -0
  24. data/app/controllers/effective/providers/phone.rb +22 -0
  25. data/app/controllers/effective/providers/pretend.rb +26 -0
  26. data/app/controllers/effective/providers/refund.rb +33 -0
  27. data/app/controllers/effective/providers/stripe.rb +72 -0
  28. data/app/controllers/effective/subscripter_controller.rb +18 -0
  29. data/app/controllers/effective/webhooks_controller.rb +109 -0
  30. data/app/datatables/admin/effective_customers_datatable.rb +22 -0
  31. data/app/datatables/admin/effective_orders_datatable.rb +100 -0
  32. data/app/datatables/effective_orders_datatable.rb +79 -0
  33. data/app/helpers/effective_carts_helper.rb +113 -0
  34. data/app/helpers/effective_orders_helper.rb +143 -0
  35. data/app/helpers/effective_paypal_helper.rb +49 -0
  36. data/app/helpers/effective_stripe_helper.rb +85 -0
  37. data/app/helpers/effective_subscriptions_helper.rb +34 -0
  38. data/app/mailers/effective/orders_mailer.rb +196 -0
  39. data/app/models/concerns/acts_as_purchasable.rb +118 -0
  40. data/app/models/concerns/acts_as_subscribable.rb +90 -0
  41. data/app/models/concerns/acts_as_subscribable_buyer.rb +49 -0
  42. data/app/models/effective/access_denied.rb +17 -0
  43. data/app/models/effective/cart.rb +88 -0
  44. data/app/models/effective/cart_item.rb +40 -0
  45. data/app/models/effective/customer.rb +92 -0
  46. data/app/models/effective/order.rb +541 -0
  47. data/app/models/effective/order_item.rb +63 -0
  48. data/app/models/effective/product.rb +23 -0
  49. data/app/models/effective/sold_out_validator.rb +7 -0
  50. data/app/models/effective/subscripter.rb +185 -0
  51. data/app/models/effective/subscription.rb +95 -0
  52. data/app/models/effective/tax_rate_calculator.rb +48 -0
  53. data/app/views/admin/customers/_actions.html.haml +2 -0
  54. data/app/views/admin/customers/index.html.haml +6 -0
  55. data/app/views/admin/customers/show.html.haml +6 -0
  56. data/app/views/admin/order_items/index.html.haml +3 -0
  57. data/app/views/admin/orders/_datatable_actions.html.haml +18 -0
  58. data/app/views/admin/orders/_form.html.haml +35 -0
  59. data/app/views/admin/orders/_form_note_internal.html.haml +7 -0
  60. data/app/views/admin/orders/_order_actions.html.haml +9 -0
  61. data/app/views/admin/orders/_order_item_fields.html.haml +14 -0
  62. data/app/views/admin/orders/checkout.html.haml +3 -0
  63. data/app/views/admin/orders/edit.html.haml +6 -0
  64. data/app/views/admin/orders/index.html.haml +6 -0
  65. data/app/views/admin/orders/new.html.haml +4 -0
  66. data/app/views/admin/orders/show.html.haml +4 -0
  67. data/app/views/effective/carts/_cart.html.haml +28 -0
  68. data/app/views/effective/carts/_cart_actions.html.haml +3 -0
  69. data/app/views/effective/carts/show.html.haml +17 -0
  70. data/app/views/effective/customers/_customer.html.haml +72 -0
  71. data/app/views/effective/customers/_form.html.haml +21 -0
  72. data/app/views/effective/customers/edit.html.haml +4 -0
  73. data/app/views/effective/customers/update.js.erb +5 -0
  74. data/app/views/effective/orders/_checkout_actions.html.haml +3 -0
  75. data/app/views/effective/orders/_checkout_step1.html.haml +4 -0
  76. data/app/views/effective/orders/_checkout_step2.html.haml +37 -0
  77. data/app/views/effective/orders/_datatable_actions.html.haml +2 -0
  78. data/app/views/effective/orders/_fields.html.haml +31 -0
  79. data/app/views/effective/orders/_fields_note.html.haml +7 -0
  80. data/app/views/effective/orders/_fields_terms.html.haml +8 -0
  81. data/app/views/effective/orders/_order.html.haml +11 -0
  82. data/app/views/effective/orders/_order_actions.html.haml +18 -0
  83. data/app/views/effective/orders/_order_deferred.html.haml +9 -0
  84. data/app/views/effective/orders/_order_footer.html.haml +1 -0
  85. data/app/views/effective/orders/_order_header.html.haml +23 -0
  86. data/app/views/effective/orders/_order_items.html.haml +72 -0
  87. data/app/views/effective/orders/_order_notes.html.haml +17 -0
  88. data/app/views/effective/orders/_order_payment.html.haml +24 -0
  89. data/app/views/effective/orders/_order_shipping.html.haml +30 -0
  90. data/app/views/effective/orders/_orders_table.html.haml +23 -0
  91. data/app/views/effective/orders/cheque/_form.html.haml +4 -0
  92. data/app/views/effective/orders/declined.html.haml +12 -0
  93. data/app/views/effective/orders/deferred.html.haml +13 -0
  94. data/app/views/effective/orders/deferred/_form.html.haml +16 -0
  95. data/app/views/effective/orders/edit.html.haml +3 -0
  96. data/app/views/effective/orders/free/_form.html.haml +5 -0
  97. data/app/views/effective/orders/index.html.haml +3 -0
  98. data/app/views/effective/orders/mark_as_paid/_form.html.haml +23 -0
  99. data/app/views/effective/orders/moneris/_form.html.haml +47 -0
  100. data/app/views/effective/orders/new.html.haml +3 -0
  101. data/app/views/effective/orders/paypal/_form.html.haml +5 -0
  102. data/app/views/effective/orders/phone/_form.html.haml +4 -0
  103. data/app/views/effective/orders/pretend/_form.html.haml +8 -0
  104. data/app/views/effective/orders/purchased.html.haml +11 -0
  105. data/app/views/effective/orders/refund/_form.html.haml +5 -0
  106. data/app/views/effective/orders/show.html.haml +6 -0
  107. data/app/views/effective/orders/stripe/_element.html.haml +8 -0
  108. data/app/views/effective/orders/stripe/_form.html.haml +31 -0
  109. data/app/views/effective/orders_mailer/order_error.html.haml +11 -0
  110. data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +2 -0
  111. data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +2 -0
  112. data/app/views/effective/orders_mailer/payment_request_to_buyer.html.haml +13 -0
  113. data/app/views/effective/orders_mailer/pending_order_invoice_to_buyer.html.haml +13 -0
  114. data/app/views/effective/orders_mailer/refund_notification_to_admin.html.haml +15 -0
  115. data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
  116. data/app/views/effective/orders_mailer/subscription_created.html.haml +13 -0
  117. data/app/views/effective/orders_mailer/subscription_event_to_admin.html.haml +13 -0
  118. data/app/views/effective/orders_mailer/subscription_payment_failed.html.haml +9 -0
  119. data/app/views/effective/orders_mailer/subscription_payment_succeeded.html.haml +9 -0
  120. data/app/views/effective/orders_mailer/subscription_trial_expired.html.haml +5 -0
  121. data/app/views/effective/orders_mailer/subscription_trialing.html.haml +7 -0
  122. data/app/views/effective/orders_mailer/subscription_updated.html.haml +13 -0
  123. data/app/views/effective/subscripter/_form.html.haml +60 -0
  124. data/app/views/effective/subscripter/_plan.html.haml +23 -0
  125. data/app/views/layouts/effective_orders_mailer_layout.html.haml +25 -0
  126. data/config/effective_orders.rb +279 -0
  127. data/config/routes.rb +70 -0
  128. data/db/migrate/01_create_effective_orders.rb.erb +137 -0
  129. data/lib/effective_orders.rb +243 -0
  130. data/lib/effective_orders/engine.rb +60 -0
  131. data/lib/effective_orders/version.rb +3 -0
  132. data/lib/generators/effective_orders/install_generator.rb +63 -0
  133. data/lib/generators/templates/effective_orders_mailer_preview.rb +120 -0
  134. data/lib/tasks/effective_orders_tasks.rake +69 -0
  135. metadata +276 -0
@@ -0,0 +1,85 @@
1
+ module Effective
2
+ class CartsController < ApplicationController
3
+ layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:carts] : EffectiveOrders.layout)
4
+
5
+ def show
6
+ @cart = current_cart
7
+ @pending_orders = Effective::Order.pending.where(user: current_user) if current_user.present?
8
+
9
+ @page_title ||= 'My Cart'
10
+ EffectiveOrders.authorize!(self, :show, @cart)
11
+ end
12
+
13
+ def destroy
14
+ @cart = current_cart
15
+
16
+ EffectiveOrders.authorize!(self, :destroy, @cart)
17
+
18
+ if @cart.destroy
19
+ flash[:success] = 'Successfully emptied cart.'
20
+ else
21
+ flash[:danger] = 'Unable to destroy cart.'
22
+ end
23
+
24
+ redirect_back_or_to_cart
25
+ end
26
+
27
+ def add_to_cart
28
+ @purchasable = (add_to_cart_params[:purchasable_type].constantize.find(add_to_cart_params[:purchasable_id].to_i) rescue nil)
29
+
30
+ EffectiveOrders.authorize!(self, :update, current_cart)
31
+
32
+ begin
33
+ raise "Please select a valid #{add_to_cart_params[:purchasable_type] || 'item' }." unless @purchasable
34
+
35
+ current_cart.add(@purchasable, quantity: [add_to_cart_params[:quantity].to_i, 1].max)
36
+ flash[:success] = 'Successfully added item to cart.'
37
+ rescue EffectiveOrders::SoldOutException
38
+ flash[:warning] = 'This item is sold out.'
39
+ rescue => e
40
+ flash[:danger] = 'Unable to add item to cart: ' + e.message
41
+ end
42
+
43
+ redirect_back_or_to_cart
44
+ end
45
+
46
+ def remove_from_cart
47
+ @cart_item = current_cart.cart_items.find(remove_from_cart_params[:id])
48
+
49
+ EffectiveOrders.authorize!(self, :update, current_cart)
50
+
51
+ if @cart_item.destroy
52
+ flash[:success] = 'Successfully removed item from cart.'
53
+ else
54
+ flash[:danger] = 'Unable to remove item from cart.'
55
+ end
56
+
57
+ redirect_back_or_to_cart
58
+ end
59
+
60
+ private
61
+
62
+ def current_cart
63
+ view_context.current_cart
64
+ end
65
+
66
+ def add_to_cart_params
67
+ params.permit(:purchasable_type, :purchasable_id, :quantity)
68
+ end
69
+
70
+ def remove_from_cart_params
71
+ params.permit(:id)
72
+ end
73
+
74
+ def redirect_back_or_to_cart
75
+ if respond_to?(:redirect_back)
76
+ redirect_back(fallback_location: effective_orders.cart_path)
77
+ elsif request.referrer.present?
78
+ redirect_to(:back)
79
+ else
80
+ redirect_to(effective_orders.cart_path)
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,62 @@
1
+ module Effective
2
+ module Concerns
3
+ module Purchase
4
+ extend ActiveSupport::Concern
5
+
6
+ protected
7
+
8
+ def order_purchased(payment:, provider:, card: 'none', email: true, skip_buyer_validations: false, purchased_url: nil, declined_url: nil)
9
+ begin
10
+ @order.purchase!(payment: payment, provider: provider, card: card, email: email, skip_buyer_validations: skip_buyer_validations)
11
+
12
+ Effective::Cart.where(user: @order.user).destroy_all
13
+
14
+ if flash[:success].blank?
15
+ if EffectiveOrders.mailer[:send_order_receipt_to_buyer] && email
16
+ flash[:success] = "Payment successful! A receipt has been sent to #{@order.emails_send_to}"
17
+ else
18
+ flash[:success] = "Payment successful! An email receipt has not been sent."
19
+ end
20
+ end
21
+
22
+ purchased_url ||= effective_orders.purchased_order_path(':id')
23
+ redirect_to purchased_url.gsub(':id', @order.to_param.to_s)
24
+ rescue => e
25
+ flash[:danger] = "An error occurred while processing your payment: #{e.message}. Please try again."
26
+
27
+ declined_url ||= effective_orders.declined_order_path(':id')
28
+ redirect_to declined_url.gsub(':id', @order.to_param.to_s)
29
+ end
30
+ end
31
+
32
+ def order_deferred(provider:, email: true, deferred_url: nil)
33
+ @order.defer!(provider: provider, email: email)
34
+
35
+ Effective::Cart.where(user: @order.user).destroy_all
36
+
37
+ if flash[:success].blank?
38
+ if email
39
+ flash[:success] = "Deferred payment created! A request for payment has been sent to #{@order.emails_send_to}"
40
+ else
41
+ flash[:success] = "Deferred payment created!"
42
+ end
43
+ end
44
+
45
+ deferred_url ||= effective_orders.deferred_order_path(':id')
46
+ redirect_to deferred_url.gsub(':id', @order.to_param.to_s)
47
+ end
48
+
49
+ def order_declined(payment:, provider:, card: 'none', declined_url: nil)
50
+ @order.decline!(payment: payment, provider: provider, card: card)
51
+
52
+ if flash[:danger].blank?
53
+ flash[:danger] = 'Payment was unsuccessful. Your credit card was declined by the payment processor. Please try again.'
54
+ end
55
+
56
+ declined_url ||= effective_orders.declined_order_path(':id')
57
+ redirect_to declined_url.gsub(':id', @order.to_param.to_s)
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,20 @@
1
+ module Effective
2
+ class CustomersController < ApplicationController
3
+ layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:customers] : EffectiveOrders.layout)
4
+
5
+ include Effective::CrudController
6
+
7
+ submit :save, 'Save', success: -> { 'Successfully updated card.' }
8
+ page_title 'Customer Settings'
9
+
10
+ def resource
11
+ @customer = Effective::Customer.where(user: current_user).first!
12
+ @subscripter ||= Effective::Subscripter.new(customer: @customer, current_user: current_user)
13
+ end
14
+
15
+ # StrongParameters
16
+ def customer_params
17
+ params.require(:effective_subscripter).permit(:stripe_token)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,162 @@
1
+ module Effective
2
+ class OrdersController < ApplicationController
3
+ include Concerns::Purchase
4
+
5
+ include Providers::Cheque if EffectiveOrders.cheque?
6
+ include Providers::Free if EffectiveOrders.free?
7
+ include Providers::MarkAsPaid if EffectiveOrders.mark_as_paid?
8
+ include Providers::Moneris if EffectiveOrders.moneris?
9
+ include Providers::Paypal if EffectiveOrders.paypal?
10
+ include Providers::Phone if EffectiveOrders.phone?
11
+ include Providers::Pretend if EffectiveOrders.pretend?
12
+ include Providers::Refund if EffectiveOrders.refund?
13
+ include Providers::Stripe if EffectiveOrders.stripe?
14
+
15
+ layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:orders] : EffectiveOrders.layout)
16
+
17
+ before_action :authenticate_user!, except: [:ccbill_postback, :free, :paypal_postback, :moneris_postback, :pretend]
18
+ before_action :set_page_title, except: [:show]
19
+
20
+ # If you want to use the Add to Cart -> Checkout flow
21
+ # Add one or more items however you do.
22
+ # redirect_to effective_orders.new_order_path, which is here.
23
+ # This is the entry point for any Checkout button.
24
+ # It displayes an order based on the cart
25
+ # Always step1
26
+ def new
27
+ @order ||= Effective::Order.new(view_context.current_cart)
28
+
29
+ EffectiveOrders.authorize!(self, :new, @order)
30
+
31
+ unless @order.valid?
32
+ flash[:danger] = "Unable to proceed: #{flash_errors(@order)}. Please try again."
33
+ redirect_to(effective_orders.cart_path)
34
+ return
35
+ end
36
+ end
37
+
38
+ # Confirms an order from the cart.
39
+ def create
40
+ @order ||= Effective::Order.new(view_context.current_cart)
41
+ EffectiveOrders.authorize!(self, :create, @order)
42
+
43
+ @order.assign_attributes(checkout_params)
44
+
45
+ if (@order.confirm! rescue false)
46
+ redirect_to(effective_orders.order_path(@order))
47
+ else
48
+ flash.now[:danger] = "Unable to proceed: #{flash_errors(@order)}. Please try again."
49
+ render :new
50
+ end
51
+ end
52
+
53
+ # If you want to use the order = Effective::Order.new(@thing); order.save! flow
54
+ # Add one or more items to the order.
55
+ # redirect_to effective_orders.order_path(order), which is here
56
+ # This is the entry point for an existing order.
57
+ # Might render step1 or step2
58
+ def show
59
+ @order = Effective::Order.find(params[:id])
60
+ EffectiveOrders.authorize!(self, :show, @order)
61
+
62
+ @page_title ||= ((@order.user == current_user && !@order.purchased?) ? 'Checkout' : @order.to_s)
63
+ end
64
+
65
+ # Always step1
66
+ def edit
67
+ @order ||= Effective::Order.find(params[:id])
68
+ EffectiveOrders.authorize!(self, :edit, @order)
69
+ end
70
+
71
+ # Confirms the order from existing order
72
+ def update
73
+ @order ||= Effective::Order.find(params[:id])
74
+ EffectiveOrders.authorize!(self, :update, @order)
75
+
76
+ @order.assign_attributes(checkout_params)
77
+
78
+ if (@order.confirm! rescue false)
79
+ redirect_to(effective_orders.order_path(@order))
80
+ else
81
+ flash.now[:danger] = "Unable to proceed: #{flash_errors(@order)}. Please try again."
82
+ render :edit
83
+ end
84
+ end
85
+
86
+ # My Orders History
87
+ def index
88
+ @datatable = EffectiveOrdersDatatable.new(user_id: current_user.id)
89
+ EffectiveOrders.authorize!(self, :index, Effective::Order.new(user: current_user))
90
+ end
91
+
92
+ # Thank you for Purchasing this Order. This is where a successfully purchased order ends up
93
+ def purchased # Thank You!
94
+ @order = Effective::Order.purchased.find(params[:id])
95
+ EffectiveOrders.authorize!(self, :show, @order)
96
+ end
97
+
98
+ def deferred
99
+ @order = Effective::Order.deferred.find(params[:id])
100
+ EffectiveOrders.authorize!(self, :show, @order)
101
+ end
102
+
103
+ def declined
104
+ @order = Effective::Order.declined.find(params[:id])
105
+ EffectiveOrders.authorize!(self, :show, @order)
106
+ end
107
+
108
+ def send_buyer_receipt
109
+ @order = Effective::Order.find(params[:id])
110
+ EffectiveOrders.authorize!(self, :show, @order)
111
+
112
+ if @order.send_order_receipt_to_buyer!
113
+ flash[:success] = "A receipt has been sent to #{@order.emails_send_to}"
114
+ else
115
+ flash[:danger] = "Unable to send receipt."
116
+ end
117
+
118
+ if respond_to?(:redirect_back)
119
+ redirect_back(fallback_location: effective_orders.order_path(@order))
120
+ elsif request.referrer.present?
121
+ redirect_to :back
122
+ else
123
+ redirect_to effective_orders.order_path(@order)
124
+ end
125
+ end
126
+
127
+ def bulk_send_buyer_receipt
128
+ @orders = Effective::Order.purchased.where(id: params[:ids])
129
+
130
+ begin
131
+ EffectiveOrders.authorize!(self, :index, Effective::Order.new(user: current_user))
132
+
133
+ @orders.each do |order|
134
+ next unless EffectiveOrders.authorized?(self, :show, order)
135
+ order.send_order_receipt_to_buyer!
136
+ end
137
+
138
+ render json: { status: 200, message: "Successfully sent #{@orders.length} receipt emails"}
139
+ rescue => e
140
+ render json: { status: 500, message: "Bulk send buyer receipt error: #{e.message}" }
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ # StrongParameters
147
+ def checkout_params
148
+ params.require(:effective_order).permit(EffectiveOrders.permitted_params)
149
+ end
150
+
151
+ def set_page_title
152
+ @page_title ||= case params[:action]
153
+ when 'index' ; 'Order History'
154
+ when 'purchased' ; 'Thank You'
155
+ when 'declined' ; 'Payment Declined'
156
+ when 'deferred' ; 'Thank You'
157
+ else 'Checkout'
158
+ end
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,22 @@
1
+ module Effective
2
+ module Providers
3
+ module Cheque
4
+ extend ActiveSupport::Concern
5
+
6
+ def cheque
7
+ @order ||= Order.find(params[:id])
8
+
9
+ EffectiveOrders.authorize!(self, :update, @order)
10
+
11
+ flash[:success] = EffectiveOrders.cheque[:success]
12
+
13
+ order_deferred(provider: 'cheque', deferred_url: cheque_params[:deferred_url])
14
+ end
15
+
16
+ def cheque_params
17
+ params.require(:cheque).permit(:deferred_url)
18
+ end
19
+
20
+ end
21
+ end
22
+ 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
+ payment: 'free order. no payment required.',
19
+ provider: 'free',
20
+ card: 'none',
21
+ purchased_url: free_params[:purchased_url],
22
+ declined_url: free_params[:declined_url],
23
+ email: false
24
+ )
25
+ end
26
+
27
+ def free_params
28
+ params.require(:free).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
+ payment: 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: effective_orders.admin_order_path(@order),
21
+ declined_url: 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
@@ -0,0 +1,60 @@
1
+ require 'net/http'
2
+
3
+ module Effective
4
+ module Providers
5
+ module Moneris
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ skip_before_action :verify_authenticity_token, only: [:moneris_postback]
10
+ end
11
+
12
+ def moneris_postback
13
+ @order ||= Effective::Order.find(params[:response_order_id])
14
+
15
+ (EffectiveOrders.authorize!(self, :update, @order) rescue false)
16
+
17
+ # Delete the Purchased and Declined Redirect URLs
18
+ purchased_url = params.delete(:rvar_purchased_url)
19
+ declined_url = params.delete(:rvar_declined_url)
20
+
21
+ if @order.purchased? # Fallback to a success condition of the Order is already purchased
22
+ return order_purchased(payment: params, provider: 'moneris', card: params[:card], purchased_url: purchased_url)
23
+ end
24
+
25
+ # Invalid Result
26
+ if params[:result].to_s != '1' || params[:transactionKey].blank?
27
+ return order_declined(payment: params, provider: 'moneris', card: params[:card], declined_url: declined_url)
28
+ end
29
+
30
+ # Verify response from moneris
31
+ payment = params.merge(verify_moneris_transaction(params[:transactionKey]))
32
+ valid = (1..49).include?(payment[:response_code].to_i) # Must be > 0 and < 50 to be valid. Sometimes we get the string 'null'
33
+
34
+ if valid == false
35
+ return order_declined(payment: payment, provider: 'moneris', card: params[:card], declined_url: declined_url)
36
+ end
37
+
38
+ order_purchased(payment: payment, provider: 'moneris', card: params[:card], purchased_url: purchased_url)
39
+ end
40
+
41
+ private
42
+
43
+ def verify_moneris_transaction(transactionKey)
44
+ # Send a verification POST request
45
+ uri = URI.parse(EffectiveOrders.moneris[:verify_url])
46
+ params = { ps_store_id: EffectiveOrders.moneris[:ps_store_id], hpp_key: EffectiveOrders.moneris[:hpp_key], transactionKey: transactionKey }
47
+ headers = { 'Referer': effective_orders.moneris_postback_orders_url }
48
+
49
+ http = Net::HTTP.new(uri.host, uri.port)
50
+ http.use_ssl = true
51
+
52
+ body = http.post(uri.path, params.to_query, headers).body
53
+
54
+ # Parse response into a Hash
55
+ body.split('<br>').inject({}) { |h, i| h[i.split(' ').first.to_sym] = i.split(' ').last; h }
56
+ end
57
+
58
+ end
59
+ end
60
+ end