effective_orders 5.0.1 → 5.1.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.
- checksums.yaml +4 -4
- data/README.md +67 -1
- data/app/assets/config/effective_orders_manifest.js +3 -0
- data/app/assets/images/effective_orders/logo.png +0 -0
- data/app/assets/javascripts/effective_orders.js +1 -1
- data/app/assets/javascripts/effective_orders/providers/moneris_checkout.js.coffee +71 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +4 -0
- data/app/controllers/effective/concerns/purchase.rb +14 -21
- data/app/controllers/effective/orders_controller.rb +2 -2
- data/app/controllers/effective/providers/free.rb +0 -1
- data/app/controllers/effective/providers/mark_as_paid.rb +1 -2
- data/app/controllers/effective/providers/moneris_checkout.rb +59 -0
- data/app/controllers/effective/providers/pretend.rb +1 -2
- data/app/controllers/effective/providers/refund.rb +1 -2
- data/app/controllers/effective/providers/stripe.rb +1 -2
- data/app/datatables/admin/effective_orders_datatable.rb +5 -8
- data/app/datatables/effective_orders_datatable.rb +3 -7
- data/app/helpers/effective_moneris_checkout_helper.rb +65 -0
- data/app/helpers/effective_orders_helper.rb +3 -26
- data/app/mailers/effective/orders_mailer.rb +6 -4
- data/app/models/concerns/acts_as_purchasable.rb +2 -0
- data/app/models/concerns/acts_as_subscribable.rb +1 -0
- data/app/models/concerns/acts_as_subscribable_buyer.rb +2 -1
- data/app/models/effective/order.rb +56 -35
- data/app/models/effective/order_item.rb +10 -0
- data/app/models/effective/product.rb +2 -0
- data/app/views/effective/orders/_checkout_step2.html.haml +3 -0
- data/app/views/effective/orders/_order.html.haml +1 -1
- data/app/views/effective/orders/_order_actions.html.haml +1 -1
- data/app/views/effective/orders/_order_footer.html.haml +3 -1
- data/app/views/effective/orders/_order_header.html.haml +4 -20
- data/app/views/effective/orders/_order_payment.html.haml +7 -18
- data/app/views/effective/orders/declined.html.haml +2 -4
- data/app/views/effective/orders/deferred.html.haml +2 -4
- data/app/views/effective/orders/moneris_checkout/_element.html.haml +4 -0
- data/app/views/effective/orders/moneris_checkout/_form.html.haml +23 -0
- data/app/views/effective/orders/purchased.html.haml +2 -4
- data/app/views/effective/orders/show.html.haml +5 -2
- data/config/effective_orders.rb +19 -0
- data/config/routes.rb +1 -0
- data/lib/effective_orders.rb +23 -2
- data/lib/effective_orders/engine.rb +2 -2
- data/lib/effective_orders/version.rb +1 -1
- data/lib/generators/templates/effective_orders_mailer_preview.rb +6 -0
- metadata +69 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31540d5d07a5c2afc891284cd037d88d25ea6aba9db57073a53b5dd60c952a11
|
4
|
+
data.tar.gz: 502ad51ce45452ff307292de9d2f16c934a7e1a0aca7c62376272b1f3ede07b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7541296d5ee6f6d52dc2edf94938f28734bf8da046612c46b0de23ee51fcd70c2eb80a32dd53534d16ffd3a9de72a923de9fffa709c4b96651ccf49fe7779b9b
|
7
|
+
data.tar.gz: 7be888605850e6dda6b952bf6ba9cceb575577b3d18ded8c118c8028890715bf41c8d8ded387de1bd5378c38207329af61709d071f2a80eec528ce6c7e701164
|
data/README.md
CHANGED
@@ -594,8 +594,74 @@ You will need an external IP address to work with these sandboxes.
|
|
594
594
|
|
595
595
|
We suggest the free application `https://ngrok.com/` for this ability.
|
596
596
|
|
597
|
+
## Paying with Moneris Checkout
|
597
598
|
|
598
|
-
|
599
|
+
Use the following instructions to set up a Moneris Checkout store.
|
600
|
+
|
601
|
+
This is the javascript / pay in place form implementation.
|
602
|
+
|
603
|
+
We do not use or implement tokenization of credentials with Moneris Checkout.
|
604
|
+
|
605
|
+
We are also going to use ngrok to give us a public facing URL
|
606
|
+
|
607
|
+
### Create Test / Development Store
|
608
|
+
|
609
|
+
Visit https://esqa.moneris.com/mpg/ and login with: demouser / store1 / password
|
610
|
+
|
611
|
+
- Select Admin -> Moneris Checkout Config from the menu
|
612
|
+
- Click Create Profile
|
613
|
+
|
614
|
+
Checkout Type: I have my custom order form and want to use Moneris simply for payment processing
|
615
|
+
|
616
|
+
Multi-Currency: None
|
617
|
+
|
618
|
+
Payment:
|
619
|
+
|
620
|
+
- Google Pay: No
|
621
|
+
- Card Logos: Yes
|
622
|
+
- Payment Security: CVV
|
623
|
+
- Transaction Type: Purchase
|
624
|
+
- Transaction Limits: None
|
625
|
+
|
626
|
+
Branding & Design
|
627
|
+
|
628
|
+
- Logo Url: None
|
629
|
+
- Colors: Default
|
630
|
+
|
631
|
+
Customizations
|
632
|
+
|
633
|
+
- Enable Fullscreen: No false (important)
|
634
|
+
- Card Borders/Shadows: Yes
|
635
|
+
|
636
|
+
Order Confirmation
|
637
|
+
|
638
|
+
- Order Confirmation Processing: Use Moneris
|
639
|
+
- Confirmation Page Content: Check all
|
640
|
+
|
641
|
+
Email Communications
|
642
|
+
|
643
|
+
- None
|
644
|
+
- Customer Emails: None
|
645
|
+
|
646
|
+
|
647
|
+
Now copy the Checkout id, something like `chktJF76Btore1` into the config/initializers/effective_orders.rb file.
|
648
|
+
|
649
|
+
For the store_id and api_token values, you can use
|
650
|
+
|
651
|
+
```
|
652
|
+
config.moneris_checkout = {
|
653
|
+
environment: 'qa',
|
654
|
+
store_id: 'store1',
|
655
|
+
api_token: 'yesguy1',
|
656
|
+
checkout_id: '', # You need to generate this one
|
657
|
+
}
|
658
|
+
```
|
659
|
+
|
660
|
+
[Testing a Solution](https://developer.moneris.com/en/More/Testing/Testing%20a%20Solution)
|
661
|
+
|
662
|
+
|
663
|
+
|
664
|
+
## Paying via Moneris (hosted pay page - old)
|
599
665
|
|
600
666
|
Use the following instructions to set up a Moneris TEST store.
|
601
667
|
|
Binary file
|
@@ -0,0 +1,71 @@
|
|
1
|
+
this.MonerisCheckoutForm ||= class MonerisCheckoutForm
|
2
|
+
constructor: ->
|
3
|
+
@form = null
|
4
|
+
@data = null
|
5
|
+
@moneris = null
|
6
|
+
|
7
|
+
initialize: ->
|
8
|
+
@form = $('form[data-moneris-checkout-form]:not(.initialized)').first()
|
9
|
+
return false unless @form.length > 0
|
10
|
+
|
11
|
+
@data = @form.data('moneris-checkout-form')
|
12
|
+
@moneris = new monerisCheckout()
|
13
|
+
|
14
|
+
@mount()
|
15
|
+
@form.addClass('initialized')
|
16
|
+
|
17
|
+
mount: ->
|
18
|
+
@moneris.setCheckoutDiv('monerisCheckout')
|
19
|
+
|
20
|
+
@moneris.setCallback('page_loaded', @pageLoaded)
|
21
|
+
@moneris.setCallback('cancel_transaction', @cancelTransaction)
|
22
|
+
@moneris.setCallback('error_event', @errorEvent)
|
23
|
+
@moneris.setCallback('payment_receipt', @paymentReceipt)
|
24
|
+
@moneris.setCallback('payment_complete', @paymentComplete)
|
25
|
+
|
26
|
+
@moneris.setMode(@data.environment)
|
27
|
+
@moneris.startCheckout(@data.ticket)
|
28
|
+
|
29
|
+
success: (payload) ->
|
30
|
+
@moneris.closeCheckout()
|
31
|
+
|
32
|
+
payment = JSON.parse(payload)
|
33
|
+
@form.find('#moneris-checkout-success').html("Transaction complete! Please wait a moment...")
|
34
|
+
@form.find("input[name$='[ticket]']").first().val(payment['ticket'])
|
35
|
+
@form.submit()
|
36
|
+
|
37
|
+
error: (text) ->
|
38
|
+
@moneris.closeCheckout()
|
39
|
+
|
40
|
+
text = "<p>" + text + "<p>Please <a href='#', onclick='window.location.reload();' class='alert-link'>reload the page</a> and try again.</p>"
|
41
|
+
@form.find('#moneris-checkout-error').addClass('alert').html(text)
|
42
|
+
EffectiveForm.invalidate(@form)
|
43
|
+
|
44
|
+
# Moneris iframe has loaded
|
45
|
+
pageLoaded: (payload) =>
|
46
|
+
preload = JSON.parse(payload)
|
47
|
+
|
48
|
+
switch preload['response_code']
|
49
|
+
when '001'
|
50
|
+
true # Success. Nothing to do.
|
51
|
+
when '902'
|
52
|
+
@error('3-D secure failed on response')
|
53
|
+
when '2001'
|
54
|
+
@error('Invalid ticket/ticket re-use')
|
55
|
+
else
|
56
|
+
@error('Unknown payment gateway preload status')
|
57
|
+
|
58
|
+
# Cancel Button
|
59
|
+
cancelTransaction: (payload) => false
|
60
|
+
|
61
|
+
# Any kind of error
|
62
|
+
errorEvent: (payload) =>
|
63
|
+
error = JSON.parse(payload)
|
64
|
+
@error("A payment gateway error #{error['response_code']} has occurred. Your card has not been charged.")
|
65
|
+
|
66
|
+
# Payment is all done
|
67
|
+
paymentReceipt: (payload) => @success(payload)
|
68
|
+
paymentComplete: (payload) => @success(payload)
|
69
|
+
|
70
|
+
$ -> (new MonerisCheckoutForm()).initialize()
|
71
|
+
$(document).on 'turbolinks:load', -> (new MonerisCheckoutForm()).initialize()
|
@@ -5,28 +5,21 @@ module Effective
|
|
5
5
|
|
6
6
|
protected
|
7
7
|
|
8
|
-
def order_purchased(payment:, provider:, card: 'none', email: true, skip_buyer_validations: false, purchased_url: nil
|
9
|
-
|
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
|
8
|
+
def order_purchased(payment:, provider:, card: 'none', email: true, skip_buyer_validations: false, purchased_url: nil)
|
9
|
+
@order.purchase!(payment: payment, provider: provider, card: card, email: email, skip_buyer_validations: skip_buyer_validations)
|
21
10
|
|
22
|
-
|
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."
|
11
|
+
Effective::Cart.where(user: @order.user).destroy_all
|
26
12
|
|
27
|
-
|
28
|
-
|
13
|
+
if flash[:success].blank?
|
14
|
+
if email && EffectiveOrders.mailer[:send_order_receipt_to_buyer]
|
15
|
+
flash[:success] = "Payment successful! A receipt has been sent to #{@order.emails_send_to}"
|
16
|
+
else
|
17
|
+
flash[:success] = "Payment successful! An email receipt has not been sent."
|
18
|
+
end
|
29
19
|
end
|
20
|
+
|
21
|
+
purchased_url = effective_orders.purchased_order_path(':id') if purchased_url.blank?
|
22
|
+
redirect_to purchased_url.gsub(':id', @order.to_param.to_s)
|
30
23
|
end
|
31
24
|
|
32
25
|
def order_deferred(provider:, email: true, deferred_url: nil)
|
@@ -42,7 +35,7 @@ module Effective
|
|
42
35
|
end
|
43
36
|
end
|
44
37
|
|
45
|
-
deferred_url
|
38
|
+
deferred_url = effective_orders.deferred_order_path(':id') if deferred_url.blank?
|
46
39
|
redirect_to deferred_url.gsub(':id', @order.to_param.to_s)
|
47
40
|
end
|
48
41
|
|
@@ -53,7 +46,7 @@ module Effective
|
|
53
46
|
flash[:danger] = 'Payment was unsuccessful. Your credit card was declined by the payment processor. Please try again.'
|
54
47
|
end
|
55
48
|
|
56
|
-
declined_url
|
49
|
+
declined_url = effective_orders.declined_order_path(':id') if declined_url.blank?
|
57
50
|
redirect_to declined_url.gsub(':id', @order.to_param.to_s)
|
58
51
|
end
|
59
52
|
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module Effective
|
2
2
|
class OrdersController < ApplicationController
|
3
|
+
include Effective::CrudController
|
3
4
|
include Concerns::Purchase
|
4
5
|
|
5
6
|
include Providers::Cheque
|
6
7
|
include Providers::Free
|
7
8
|
include Providers::MarkAsPaid
|
8
9
|
include Providers::Moneris
|
10
|
+
include Providers::MonerisCheckout
|
9
11
|
include Providers::Paypal
|
10
12
|
include Providers::Phone
|
11
13
|
include Providers::Pretend
|
12
14
|
include Providers::Refund
|
13
15
|
include Providers::Stripe
|
14
16
|
|
15
|
-
include Effective::CrudController
|
16
|
-
|
17
17
|
if (config = EffectiveOrders.layout)
|
18
18
|
layout(config.kind_of?(Hash) ? (config[:orders] || config[:application]) : config)
|
19
19
|
end
|
@@ -19,8 +19,7 @@ module Effective
|
|
19
19
|
card: mark_as_paid_params[:payment_card],
|
20
20
|
email: @order.send_mark_as_paid_email_to_buyer?,
|
21
21
|
skip_buyer_validations: true,
|
22
|
-
purchased_url: effective_orders.admin_order_path(@order)
|
23
|
-
declined_url: effective_orders.admin_order_path(@order)
|
22
|
+
purchased_url: effective_orders.admin_order_path(@order)
|
24
23
|
)
|
25
24
|
end
|
26
25
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Effective
|
2
|
+
module Providers
|
3
|
+
module MonerisCheckout
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def moneris_checkout
|
7
|
+
raise('moneris_checkout provider is not available') unless EffectiveOrders.moneris_checkout?
|
8
|
+
|
9
|
+
@order = Order.find(params[:id])
|
10
|
+
(EffectiveResources.authorize!(self, :update, @order) rescue false)
|
11
|
+
|
12
|
+
payment = moneris_checkout_receipt_request(moneris_checkout_params[:ticket])
|
13
|
+
purchased = (1..49).include?(payment['response_code'].to_i) # Must be > 0 and < 50 to be valid. Sometimes we get the string 'null'
|
14
|
+
|
15
|
+
if purchased == false
|
16
|
+
return order_declined(
|
17
|
+
payment: payment,
|
18
|
+
provider: 'moneris_checkout',
|
19
|
+
declined_url: moneris_checkout_params[:declined_url]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
order_purchased(
|
24
|
+
payment: payment,
|
25
|
+
provider: 'moneris_checkout',
|
26
|
+
card: payment['card_type'],
|
27
|
+
purchased_url: moneris_checkout_params[:purchased_url]
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def moneris_checkout_params
|
34
|
+
params.require(:moneris_checkout).permit(:ticket, :purchased_url, :declined_url)
|
35
|
+
end
|
36
|
+
|
37
|
+
def moneris_checkout_receipt_request(ticket)
|
38
|
+
params = {
|
39
|
+
environment: EffectiveOrders.moneris_checkout.fetch(:environment),
|
40
|
+
|
41
|
+
api_token: EffectiveOrders.moneris_checkout.fetch(:api_token),
|
42
|
+
store_id: EffectiveOrders.moneris_checkout.fetch(:store_id),
|
43
|
+
checkout_id: EffectiveOrders.moneris_checkout.fetch(:checkout_id),
|
44
|
+
|
45
|
+
action: :receipt,
|
46
|
+
ticket: ticket
|
47
|
+
}
|
48
|
+
|
49
|
+
response = Effective::Http.post(EffectiveOrders.moneris_request_url, params: params)
|
50
|
+
response = response['response'] if response
|
51
|
+
|
52
|
+
raise("moneris receipt error #{response}") unless response && response['success'].to_s == 'true'
|
53
|
+
|
54
|
+
response.dig('receipt', 'cc') || response.dig('receipt', 'gift') || response
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -21,8 +21,7 @@ module Effective
|
|
21
21
|
order_purchased(
|
22
22
|
payment: 'refund. no payment required.',
|
23
23
|
provider: 'refund',
|
24
|
-
purchased_url: refund_params[:purchased_url]
|
25
|
-
declined_url: refund_params[:declined_url]
|
24
|
+
purchased_url: refund_params[:purchased_url]
|
26
25
|
)
|
27
26
|
end
|
28
27
|
|
@@ -14,12 +14,12 @@ class Admin::EffectiveOrdersDatatable < Effective::Datatable
|
|
14
14
|
end
|
15
15
|
|
16
16
|
filters do
|
17
|
-
|
18
|
-
scope :
|
17
|
+
unless attributes[:skip_filters]
|
18
|
+
scope :all
|
19
|
+
scope :purchased
|
19
20
|
scope :deferred
|
20
21
|
scope :refunds
|
21
22
|
scope :not_purchased
|
22
|
-
scope :all
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -84,13 +84,14 @@ class Admin::EffectiveOrdersDatatable < Effective::Datatable
|
|
84
84
|
end
|
85
85
|
|
86
86
|
collection do
|
87
|
-
scope = Effective::Order.all.
|
87
|
+
scope = Effective::Order.all.deep
|
88
88
|
|
89
89
|
if EffectiveOrders.orders_collection_scope.respond_to?(:call)
|
90
90
|
scope = EffectiveOrders.orders_collection_scope.call(scope)
|
91
91
|
end
|
92
92
|
|
93
93
|
if attributes[:user_id].present?
|
94
|
+
user = current_user.class.find(attributes[:user_id])
|
94
95
|
scope = scope.where(user: user)
|
95
96
|
end
|
96
97
|
|
@@ -101,8 +102,4 @@ class Admin::EffectiveOrdersDatatable < Effective::Datatable
|
|
101
102
|
scope
|
102
103
|
end
|
103
104
|
|
104
|
-
def user
|
105
|
-
@user ||= current_user.class.find(attributes[:user_id])
|
106
|
-
end
|
107
|
-
|
108
105
|
end
|
@@ -6,8 +6,6 @@ class EffectiveOrdersDatatable < Effective::Datatable
|
|
6
6
|
scope :purchased, default: true
|
7
7
|
scope :deferred
|
8
8
|
scope :refunds
|
9
|
-
scope :not_purchased
|
10
|
-
scope :all
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
@@ -61,7 +59,9 @@ class EffectiveOrdersDatatable < Effective::Datatable
|
|
61
59
|
end
|
62
60
|
|
63
61
|
collection do
|
64
|
-
|
62
|
+
user = current_user.class.find(attributes[:user_id])
|
63
|
+
|
64
|
+
scope = Effective::Order.all.deep.where(user: user)
|
65
65
|
|
66
66
|
if EffectiveOrders.orders_collection_scope.respond_to?(:call)
|
67
67
|
scope = EffectiveOrders.orders_collection_scope.call(scope)
|
@@ -78,8 +78,4 @@ class EffectiveOrdersDatatable < Effective::Datatable
|
|
78
78
|
scope
|
79
79
|
end
|
80
80
|
|
81
|
-
def user
|
82
|
-
@user ||= current_user.class.find(attributes[:user_id])
|
83
|
-
end
|
84
|
-
|
85
81
|
end
|