effective_orders 5.0.5 → 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 +2 -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 +3 -3
- data/app/controllers/effective/orders_controller.rb +1 -0
- data/app/controllers/effective/providers/moneris_checkout.rb +59 -0
- data/app/helpers/effective_moneris_checkout_helper.rb +65 -0
- data/app/helpers/effective_orders_helper.rb +2 -19
- 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 +41 -4
- 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_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 +4 -5
- data/config/effective_orders.rb +19 -0
- data/config/routes.rb +1 -0
- data/lib/effective_orders.rb +23 -2
- data/lib/effective_orders/version.rb +1 -1
- data/lib/generators/templates/effective_orders_mailer_preview.rb +6 -0
- metadata +68 -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()
|
|
@@ -18,7 +18,7 @@ module Effective
|
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
purchased_url
|
|
21
|
+
purchased_url = effective_orders.purchased_order_path(':id') if purchased_url.blank?
|
|
22
22
|
redirect_to purchased_url.gsub(':id', @order.to_param.to_s)
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -35,7 +35,7 @@ module Effective
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
deferred_url
|
|
38
|
+
deferred_url = effective_orders.deferred_order_path(':id') if deferred_url.blank?
|
|
39
39
|
redirect_to deferred_url.gsub(':id', @order.to_param.to_s)
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -46,7 +46,7 @@ module Effective
|
|
|
46
46
|
flash[:danger] = 'Payment was unsuccessful. Your credit card was declined by the payment processor. Please try again.'
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
declined_url
|
|
49
|
+
declined_url = effective_orders.declined_order_path(':id') if declined_url.blank?
|
|
50
50
|
redirect_to declined_url.gsub(':id', @order.to_param.to_s)
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -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
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module EffectiveMonerisCheckoutHelper
|
|
2
|
+
|
|
3
|
+
def moneris_checkout_preload_request(order)
|
|
4
|
+
# Make the Preload Request
|
|
5
|
+
params = {
|
|
6
|
+
# Required
|
|
7
|
+
environment: EffectiveOrders.moneris_checkout.fetch(:environment),
|
|
8
|
+
|
|
9
|
+
api_token: EffectiveOrders.moneris_checkout.fetch(:api_token),
|
|
10
|
+
store_id: EffectiveOrders.moneris_checkout.fetch(:store_id),
|
|
11
|
+
checkout_id: EffectiveOrders.moneris_checkout.fetch(:checkout_id),
|
|
12
|
+
|
|
13
|
+
action: :preload,
|
|
14
|
+
txn_total: price_to_currency(order.total).gsub(',', '').gsub('$', ''),
|
|
15
|
+
|
|
16
|
+
# Optional
|
|
17
|
+
order_no: order.transaction_id, # Has to be unique. This is order number, billing name and Time.now
|
|
18
|
+
cust_id: order.user_id,
|
|
19
|
+
language: 'en',
|
|
20
|
+
|
|
21
|
+
contact_details: {
|
|
22
|
+
first_name: order.billing_first_name,
|
|
23
|
+
last_name: order.billing_last_name,
|
|
24
|
+
email: order.email,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (address = order.billing_address).present?
|
|
29
|
+
params.merge!(
|
|
30
|
+
billing_details: {
|
|
31
|
+
address_1: address.address1,
|
|
32
|
+
address_2: address.address2,
|
|
33
|
+
city: address.city,
|
|
34
|
+
province: address.state_code,
|
|
35
|
+
country: address.country_code,
|
|
36
|
+
postal_code: address.postal_code
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if (address = order.shipping_address).present?
|
|
42
|
+
params.merge!(
|
|
43
|
+
shipping_details: {
|
|
44
|
+
address_1: address.address1,
|
|
45
|
+
address_2: address.address2,
|
|
46
|
+
city: address.city,
|
|
47
|
+
province: address.state_code,
|
|
48
|
+
country: address.country_code,
|
|
49
|
+
postal_code: address.postal_code
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
response = Effective::Http.post(EffectiveOrders.moneris_request_url, params: params)
|
|
55
|
+
preload = response['response'] if response
|
|
56
|
+
|
|
57
|
+
raise("moneris preload error #{response}") unless preload && preload['success'].to_s == 'true'
|
|
58
|
+
|
|
59
|
+
payload = {
|
|
60
|
+
environment: EffectiveOrders.moneris_checkout.fetch(:environment),
|
|
61
|
+
ticket: preload['ticket']
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -42,6 +42,8 @@ module EffectiveOrdersHelper
|
|
|
42
42
|
'Admin: Mark as Paid'
|
|
43
43
|
when :moneris
|
|
44
44
|
'Checkout with Credit Card'
|
|
45
|
+
when :moneris_checkout
|
|
46
|
+
'Pay Now' # Doesn't get displayed anyway
|
|
45
47
|
when :paypal
|
|
46
48
|
'Checkout with PayPal'
|
|
47
49
|
when :phone
|
|
@@ -111,25 +113,6 @@ module EffectiveOrdersHelper
|
|
|
111
113
|
render(partial: 'effective/orders/orders_table', locals: { orders: orders }.merge(opts))
|
|
112
114
|
end
|
|
113
115
|
|
|
114
|
-
def payment_card_label(card)
|
|
115
|
-
card = card.to_s.downcase.gsub(' ', '').strip
|
|
116
|
-
|
|
117
|
-
case card
|
|
118
|
-
when ''
|
|
119
|
-
'None'
|
|
120
|
-
when 'v', 'visa'
|
|
121
|
-
'Visa'
|
|
122
|
-
when 'm', 'mc', 'master', 'mastercard'
|
|
123
|
-
'MasterCard'
|
|
124
|
-
when 'a', 'ax', 'american', 'americanexpress'
|
|
125
|
-
'American Express'
|
|
126
|
-
when 'd', 'discover'
|
|
127
|
-
'Discover'
|
|
128
|
-
else
|
|
129
|
-
card.to_s
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
116
|
def checkout_icon_to(path, options = {})
|
|
134
117
|
icon_to('shopping-cart', path, { title: 'Checkout' }.merge(options))
|
|
135
118
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Effective
|
|
2
2
|
class OrdersMailer < ActionMailer::Base
|
|
3
|
-
default from: -> { EffectiveOrders.mailer[:default_from] }
|
|
3
|
+
default from: -> { EffectiveOrders.mailer[:default_from].presence }
|
|
4
|
+
default cc: -> { EffectiveOrders.mailer[:default_cc].presence }
|
|
5
|
+
default bcc: -> { EffectiveOrders.mailer[:default_bcc].presence }
|
|
4
6
|
layout -> { EffectiveOrders.mailer[:layout].presence || 'effective_orders_mailer_layout' }
|
|
5
7
|
|
|
6
8
|
helper EffectiveOrdersHelper
|
|
@@ -27,7 +29,7 @@ module Effective
|
|
|
27
29
|
|
|
28
30
|
@subject = subject_for(@order, :order_receipt_to_buyer, "Order Receipt: ##{@order.to_param}")
|
|
29
31
|
|
|
30
|
-
mail(to: @order.email, cc: @order.cc, subject: @subject)
|
|
32
|
+
mail({to: @order.email, cc: @order.cc, subject: @subject}.compact)
|
|
31
33
|
end
|
|
32
34
|
end
|
|
33
35
|
|
|
@@ -43,7 +45,7 @@ module Effective
|
|
|
43
45
|
|
|
44
46
|
@subject = subject_for(@order, :payment_request_to_buyer, "Request for Payment: Invoice ##{@order.to_param}")
|
|
45
47
|
|
|
46
|
-
mail(to: @order.email, cc: @order.cc, subject: @subject)
|
|
48
|
+
mail({to: @order.email, cc: @order.cc, subject: @subject}.compact)
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
@@ -58,7 +60,7 @@ module Effective
|
|
|
58
60
|
|
|
59
61
|
@subject = subject_for(@order, :pending_order_invoice_to_buyer, "Pending Order: ##{@order.to_param}")
|
|
60
62
|
|
|
61
|
-
mail(to: @order.email, cc: @order.cc, subject: @subject)
|
|
63
|
+
mail({to: @order.email, cc: @order.cc, subject: @subject}.compact)
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
|
|
@@ -19,6 +19,8 @@ module ActsAsSubscribableBuyer
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
module ClassMethods
|
|
22
|
+
def acts_as_subscribable_buyer?; true; end
|
|
23
|
+
|
|
22
24
|
def after_invoice_payment_succeeded(&block)
|
|
23
25
|
send :define_method, :after_invoice_payment_succeeded do |event| self.instance_exec(event, &block) end
|
|
24
26
|
end
|
|
@@ -46,4 +48,3 @@ module ActsAsSubscribableBuyer
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
end
|
|
49
|
-
|
|
@@ -250,17 +250,54 @@ module Effective
|
|
|
250
250
|
end
|
|
251
251
|
|
|
252
252
|
def to_s
|
|
253
|
+
[label, ' #', to_param].join
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def label
|
|
253
257
|
if refund?
|
|
254
|
-
"Refund
|
|
258
|
+
"Refund"
|
|
255
259
|
elsif purchased?
|
|
256
|
-
"Receipt
|
|
260
|
+
"Receipt"
|
|
257
261
|
elsif pending?
|
|
258
|
-
"Pending Order
|
|
262
|
+
"Pending Order"
|
|
259
263
|
else
|
|
260
|
-
"Order
|
|
264
|
+
"Order"
|
|
261
265
|
end
|
|
262
266
|
end
|
|
263
267
|
|
|
268
|
+
# Visa - 1234
|
|
269
|
+
def payment_method
|
|
270
|
+
return nil unless purchased?
|
|
271
|
+
|
|
272
|
+
# Normalize payment card
|
|
273
|
+
card = case payment_card.to_s.downcase.gsub(' ', '').strip
|
|
274
|
+
when '' then nil
|
|
275
|
+
when 'v', 'visa' then 'Visa'
|
|
276
|
+
when 'm', 'mc', 'master', 'mastercard' then 'MasterCard'
|
|
277
|
+
when 'a', 'ax', 'american', 'americanexpress' then 'American Express'
|
|
278
|
+
when 'd', 'discover' then 'Discover'
|
|
279
|
+
else payment_card.to_s
|
|
280
|
+
end unless payment_provider == 'free'
|
|
281
|
+
|
|
282
|
+
# stripe, moneris, moneris_checkout
|
|
283
|
+
last4 = (payment[:active_card] || payment['f4l4'] || payment['first6last4']).to_s.last(4)
|
|
284
|
+
|
|
285
|
+
[card, '-', last4].compact.join(' ')
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# For moneris and moneris_checkout. Just a unique value.
|
|
289
|
+
def transaction_id
|
|
290
|
+
[to_param, billing_name.to_s.parameterize.presence, Time.zone.now.to_i].compact.join('-')
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def billing_first_name
|
|
294
|
+
billing_name.to_s.split(' ').first
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def billing_last_name
|
|
298
|
+
Array(billing_name.to_s.split(' ')[1..-1]).join(' ')
|
|
299
|
+
end
|
|
300
|
+
|
|
264
301
|
def pending?
|
|
265
302
|
state == EffectiveOrders::PENDING
|
|
266
303
|
end
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
- if EffectiveOrders.moneris?
|
|
21
21
|
= render partial: '/effective/orders/moneris/form', locals: provider_locals
|
|
22
22
|
|
|
23
|
+
- if EffectiveOrders.moneris_checkout?
|
|
24
|
+
= render partial: '/effective/orders/moneris_checkout/form', locals: provider_locals
|
|
25
|
+
|
|
23
26
|
- if EffectiveOrders.paypal?
|
|
24
27
|
= render partial: '/effective/orders/paypal/form', locals: provider_locals
|
|
25
28
|
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
= render partial: 'effective/orders/order_actions', locals: { order: order }
|
|
4
4
|
|
|
5
5
|
= render partial: 'effective/orders/order_header', locals: { order: order }
|
|
6
|
+
= render partial: 'effective/orders/order_payment', locals: { order: order }
|
|
6
7
|
= render partial: 'effective/orders/order_shipping', locals: { order: order }
|
|
7
8
|
= render partial: 'effective/orders/order_deferred', locals: { order: order }
|
|
8
9
|
= render partial: 'effective/orders/order_notes', locals: { order: order }
|
|
9
10
|
= render partial: 'effective/orders/order_items', locals: { order: order }
|
|
10
|
-
= render partial: 'effective/orders/order_payment', locals: { order: order }
|
|
11
11
|
= render partial: 'effective/orders/order_footer', locals: { order: order }
|
|
@@ -1,23 +1,7 @@
|
|
|
1
1
|
.effective-order-header
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
.col-sm-6
|
|
5
|
-
- email_address = EffectiveOrders.mailer[:admin_email] || 'info@acmeindustries.com'
|
|
6
|
-
%p= mail_to u(email_address), email_address
|
|
7
|
-
%p
|
|
8
|
-
1234 Fake Street
|
|
9
|
-
%br
|
|
10
|
-
Edmonton, AB, T5H 4A5
|
|
11
|
-
%br
|
|
12
|
-
%small Customize me by overriding '/app/views/effective/orders/_order_header.html.haml'
|
|
2
|
+
.mb-4.text-center
|
|
3
|
+
= image_tag('effective_orders/logo.png')
|
|
13
4
|
|
|
14
|
-
.
|
|
15
|
-
- if order.purchased?
|
|
16
|
-
%p Receipt: ##{order.to_param}
|
|
17
|
-
- elsif order.persisted?
|
|
18
|
-
%p Order: ##{order.to_param}
|
|
5
|
+
%h2 #{order.label} from Example Inc.
|
|
19
6
|
|
|
20
|
-
|
|
21
|
-
%p Purchased at: #{order.purchased_at.strftime("%F %H:%M")}
|
|
22
|
-
- else
|
|
23
|
-
%p Date: #{Time.zone.now.strftime("%F %H:%M")}
|
|
7
|
+
%p.text-muted= order.to_s
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
- if order.purchased?
|
|
2
|
-
.effective-order-payment
|
|
2
|
+
.effective-order-payment
|
|
3
3
|
%table.table
|
|
4
4
|
%thead
|
|
5
5
|
%tr
|
|
6
|
-
%th
|
|
7
|
-
%th
|
|
6
|
+
%th Amount Paid
|
|
7
|
+
%th Date Paid
|
|
8
|
+
%th Payment Method
|
|
8
9
|
%tbody
|
|
9
10
|
%tr
|
|
10
|
-
%td
|
|
11
|
-
%td= order.
|
|
12
|
-
|
|
13
|
-
- if order.payment_card.present?
|
|
14
|
-
%tr
|
|
15
|
-
%td Card
|
|
16
|
-
%td
|
|
17
|
-
= payment_card_label(order.payment_card)
|
|
18
|
-
- if order.payment.kind_of?(Hash)
|
|
19
|
-
= order.payment[:active_card] || order.payment['f4l4']
|
|
20
|
-
|
|
21
|
-
%tr
|
|
22
|
-
%td Purchased at
|
|
23
|
-
%td= order.purchased_at&.strftime('%F %H:%M')
|
|
24
|
-
|
|
11
|
+
%td= price_to_currency(order.total)
|
|
12
|
+
%td= order.purchased_at.strftime('%b %d, %Y')
|
|
13
|
+
%td= order.payment_method
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
%h1.effective-heading= @page_title
|
|
2
2
|
|
|
3
|
-
%p.effective-orders-page-content
|
|
4
|
-
= link_to 'Home', root_path
|
|
5
|
-
|
|
6
3
|
%p.effective-orders-page-content
|
|
7
4
|
- if current_cart.present?
|
|
8
5
|
Your #{link_to_current_cart(label: 'Cart')} items have been saved. Please try again.
|
|
9
6
|
- else
|
|
10
7
|
Please try again.
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
%p.text-center
|
|
10
|
+
= link_to 'Continue', root_path, class: 'btn btn-primary'
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
%h1.effective-heading= @page_title
|
|
2
2
|
|
|
3
|
-
%p.effective-orders-page-content
|
|
4
|
-
= link_to 'Home', root_path
|
|
5
|
-
|
|
6
3
|
%p.effective-orders-page-content
|
|
7
4
|
You have indicated that this order will be paid by #{@order.payment_provider}.
|
|
8
5
|
Your order will not be considered purchased until we receive your payment.
|
|
@@ -10,4 +7,5 @@
|
|
|
10
7
|
|
|
11
8
|
= render @order
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
%p.text-center
|
|
11
|
+
= link_to 'Continue', root_path, class: 'btn btn-primary'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
= javascript_include_tag(EffectiveOrders.moneris_checkout_script_url)
|
|
2
|
+
|
|
3
|
+
- moneris_checkout = moneris_checkout_preload_request(order)
|
|
4
|
+
|
|
5
|
+
.card
|
|
6
|
+
.card-body.bg-light
|
|
7
|
+
.mb-3.text-center
|
|
8
|
+
%h2 Checkout
|
|
9
|
+
|
|
10
|
+
= effective_form_with(scope: :moneris_checkout, url: effective_orders.moneris_checkout_order_path(order), data: { 'moneris-checkout-form': moneris_checkout.to_json }) do |f|
|
|
11
|
+
= f.hidden_field :purchased_url, value: purchased_url
|
|
12
|
+
= f.hidden_field :declined_url, value: declined_url
|
|
13
|
+
|
|
14
|
+
-# This is set by the moneris_checkout.js javascript
|
|
15
|
+
= f.hidden_field :ticket
|
|
16
|
+
|
|
17
|
+
= render('effective/orders/moneris_checkout/element')
|
|
18
|
+
|
|
19
|
+
.mt-3.text-center
|
|
20
|
+
%em
|
|
21
|
+
This checkout provided by
|
|
22
|
+
= succeed('.') do
|
|
23
|
+
= link_to('Moneris', 'https://www.moneris.com', target: '_blank', class: 'btn-link')
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
%h1.effective-heading= @page_title
|
|
2
2
|
|
|
3
|
-
%p.effective-orders-page-content
|
|
4
|
-
= link_to 'Home', root_path
|
|
5
|
-
|
|
6
3
|
%p.effective-orders-page-content
|
|
7
4
|
You have successfully purchased the following:
|
|
8
5
|
|
|
9
6
|
= render @order
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
%p.text-center
|
|
9
|
+
= link_to 'Continue', root_path, class: 'btn btn-primary'
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
%h1.effective-heading= @page_title
|
|
2
2
|
|
|
3
|
-
- if @order.user == current_user
|
|
3
|
+
- if !@order.purchased? && @order.user == current_user
|
|
4
4
|
= render_checkout(@order)
|
|
5
5
|
- else
|
|
6
|
-
= render
|
|
6
|
+
= render(@order)
|
|
7
7
|
|
|
8
|
-
%
|
|
9
|
-
|
|
10
|
-
= link_to 'Continue', effective_orders.orders_path, class: 'btn btn-primary'
|
|
8
|
+
%p.text-center
|
|
9
|
+
= link_to 'Continue', effective_orders.orders_path, class: 'btn btn-primary'
|
data/config/effective_orders.rb
CHANGED
|
@@ -166,6 +166,25 @@ EffectiveOrders.setup do |config|
|
|
|
166
166
|
# }
|
|
167
167
|
# end
|
|
168
168
|
|
|
169
|
+
# Moneris Checkout
|
|
170
|
+
config.moneris_checkout = false
|
|
171
|
+
|
|
172
|
+
# if Rails.env.production?
|
|
173
|
+
# config.moneris_checkout = {
|
|
174
|
+
# environment: 'prod',
|
|
175
|
+
# store_id: '',
|
|
176
|
+
# api_token: '',
|
|
177
|
+
# checkout_id: '',
|
|
178
|
+
# }
|
|
179
|
+
# else
|
|
180
|
+
# config.moneris_checkout = {
|
|
181
|
+
# environment: 'qa',
|
|
182
|
+
# store_id: 'store1',
|
|
183
|
+
# api_token: 'yesguy1',
|
|
184
|
+
# checkout_id: 'chktJF76Btore1',
|
|
185
|
+
# }
|
|
186
|
+
# end
|
|
187
|
+
|
|
169
188
|
# Paypal
|
|
170
189
|
config.paypal = false
|
|
171
190
|
|
data/config/routes.rb
CHANGED
data/lib/effective_orders.rb
CHANGED
|
@@ -34,7 +34,7 @@ module EffectiveOrders
|
|
|
34
34
|
# Features
|
|
35
35
|
:free_enabled, :mark_as_paid_enabled, :pretend_enabled, :pretend_message,
|
|
36
36
|
# Payment processors. false or Hash
|
|
37
|
-
:cheque, :moneris, :paypal, :phone, :refund, :stripe, :subscriptions, :trial
|
|
37
|
+
:cheque, :moneris, :moneris_checkout, :paypal, :phone, :refund, :stripe, :subscriptions, :trial
|
|
38
38
|
]
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -69,6 +69,10 @@ module EffectiveOrders
|
|
|
69
69
|
moneris.kind_of?(Hash)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
def self.moneris_checkout?
|
|
73
|
+
moneris_checkout.kind_of?(Hash)
|
|
74
|
+
end
|
|
75
|
+
|
|
72
76
|
def self.paypal?
|
|
73
77
|
paypal.kind_of?(Hash)
|
|
74
78
|
end
|
|
@@ -98,7 +102,7 @@ module EffectiveOrders
|
|
|
98
102
|
end
|
|
99
103
|
|
|
100
104
|
def self.single_payment_processor?
|
|
101
|
-
[moneris?, paypal?, stripe?].select { |enabled| enabled }.length == 1
|
|
105
|
+
[moneris?, moneris_checkout?, paypal?, stripe?].select { |enabled| enabled }.length == 1
|
|
102
106
|
end
|
|
103
107
|
|
|
104
108
|
# The Effective::Order.payment_provider value must be in this collection
|
|
@@ -108,6 +112,7 @@ module EffectiveOrders
|
|
|
108
112
|
('credit card' if mark_as_paid?),
|
|
109
113
|
('free' if free?),
|
|
110
114
|
('moneris' if moneris?),
|
|
115
|
+
('moneris_checkout' if moneris_checkout?),
|
|
111
116
|
('paypal' if paypal?),
|
|
112
117
|
('phone' if phone?),
|
|
113
118
|
('pretend' if pretend?),
|
|
@@ -197,6 +202,22 @@ module EffectiveOrders
|
|
|
197
202
|
stripe_plans.map { |plan| [plan[:name], plan[:id]] }
|
|
198
203
|
end
|
|
199
204
|
|
|
205
|
+
def self.moneris_checkout_script_url
|
|
206
|
+
case EffectiveOrders.moneris_checkout.fetch(:environment)
|
|
207
|
+
when 'prod' then 'https://gateway.moneris.com/chkt/js/chkt_v1.00.js'
|
|
208
|
+
when 'qa' then 'https://gatewayt.moneris.com/chkt/js/chkt_v1.00.js'
|
|
209
|
+
else raise('unexpected EffectiveOrders.moneris_checkout :environment key. Please check your config/initializers/effective_orders.rb file')
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def self.moneris_request_url
|
|
214
|
+
case EffectiveOrders.moneris_checkout.fetch(:environment)
|
|
215
|
+
when 'prod' then 'https://gateway.moneris.com/chkt/request/request.php'
|
|
216
|
+
when 'qa' then 'https://gatewayt.moneris.com/chkt/request/request.php'
|
|
217
|
+
else raise('unexpected EffectiveOrders.moneris_checkout :environment key. Please check your config/initializers/effective_orders.rb file')
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
200
221
|
class SoldOutException < Exception; end
|
|
201
222
|
class AlreadyPurchasedException < Exception; end
|
|
202
223
|
end
|
|
@@ -61,6 +61,12 @@ class EffectiveOrdersMailerPreview < ActionMailer::Preview
|
|
|
61
61
|
order = Effective::Order.new(id: 1)
|
|
62
62
|
order.user = preview_user
|
|
63
63
|
preview_order_items.each { |atts| order.order_items.build(atts) }
|
|
64
|
+
|
|
65
|
+
order.state = 'purchased'
|
|
66
|
+
order.payment_card = 'visa'
|
|
67
|
+
order.purchased_at = Time.zone.now
|
|
68
|
+
order.payment = { 'f4l4' => '1234'}
|
|
69
|
+
|
|
64
70
|
order.valid?
|
|
65
71
|
order
|
|
66
72
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: effective_orders
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.0
|
|
4
|
+
version: 5.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Code and Effect
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: sassc
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
@@ -53,7 +53,7 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: effective_addresses
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - ">="
|
|
@@ -72,14 +72,14 @@ dependencies:
|
|
|
72
72
|
requirements:
|
|
73
73
|
- - ">="
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
75
|
+
version: '0'
|
|
76
76
|
type: :runtime
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
80
|
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
82
|
+
version: '0'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: effective_bootstrap
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +108,62 @@ dependencies:
|
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: sqlite3
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: devise
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: haml-rails
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: pry-byebug
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - ">="
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '0'
|
|
160
|
+
type: :development
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - ">="
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '0'
|
|
111
167
|
description: Quickly build an online store with carts, orders, automatic email receipts
|
|
112
168
|
and payment collection via Stripe, StripeConnect, PayPal and Moneris.
|
|
113
169
|
email:
|
|
@@ -119,9 +175,11 @@ files:
|
|
|
119
175
|
- MIT-LICENSE
|
|
120
176
|
- README.md
|
|
121
177
|
- app/assets/config/effective_orders_manifest.js
|
|
178
|
+
- app/assets/images/effective_orders/logo.png
|
|
122
179
|
- app/assets/images/effective_orders/stripe.png
|
|
123
180
|
- app/assets/javascripts/effective_orders.js
|
|
124
181
|
- app/assets/javascripts/effective_orders/customers.js.coffee
|
|
182
|
+
- app/assets/javascripts/effective_orders/providers/moneris_checkout.js.coffee
|
|
125
183
|
- app/assets/javascripts/effective_orders/providers/stripe.js.coffee
|
|
126
184
|
- app/assets/javascripts/effective_orders/subscriptions.js.coffee
|
|
127
185
|
- app/assets/stylesheets/effective_orders.scss
|
|
@@ -138,6 +196,7 @@ files:
|
|
|
138
196
|
- app/controllers/effective/providers/free.rb
|
|
139
197
|
- app/controllers/effective/providers/mark_as_paid.rb
|
|
140
198
|
- app/controllers/effective/providers/moneris.rb
|
|
199
|
+
- app/controllers/effective/providers/moneris_checkout.rb
|
|
141
200
|
- app/controllers/effective/providers/paypal.rb
|
|
142
201
|
- app/controllers/effective/providers/phone.rb
|
|
143
202
|
- app/controllers/effective/providers/pretend.rb
|
|
@@ -149,6 +208,7 @@ files:
|
|
|
149
208
|
- app/datatables/admin/effective_orders_datatable.rb
|
|
150
209
|
- app/datatables/effective_orders_datatable.rb
|
|
151
210
|
- app/helpers/effective_carts_helper.rb
|
|
211
|
+
- app/helpers/effective_moneris_checkout_helper.rb
|
|
152
212
|
- app/helpers/effective_orders_helper.rb
|
|
153
213
|
- app/helpers/effective_paypal_helper.rb
|
|
154
214
|
- app/helpers/effective_stripe_helper.rb
|
|
@@ -214,6 +274,8 @@ files:
|
|
|
214
274
|
- app/views/effective/orders/index.html.haml
|
|
215
275
|
- app/views/effective/orders/mark_as_paid/_form.html.haml
|
|
216
276
|
- app/views/effective/orders/moneris/_form.html.haml
|
|
277
|
+
- app/views/effective/orders/moneris_checkout/_element.html.haml
|
|
278
|
+
- app/views/effective/orders/moneris_checkout/_form.html.haml
|
|
217
279
|
- app/views/effective/orders/new.html.haml
|
|
218
280
|
- app/views/effective/orders/paypal/_form.html.haml
|
|
219
281
|
- app/views/effective/orders/phone/_form.html.haml
|