nimbleshop_paypalwp 0.0.10 → 0.0.11
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.
- data/app/controllers/nimbleshop_paypalwp/paypalwps_controller.rb +11 -28
- data/app/helpers/nimbleshop_paypalwp/exposed_helper.rb +3 -0
- data/app/models/nimbleshop_paypalwp/paypalwp.rb +4 -0
- data/app/views/nimbleshop_paypalwp/paypalwps/_edit.html.erb +33 -24
- data/lib/nimbleshop_paypalwp/processor.rb +49 -30
- data/test/functional/paypalwps_controller_test.rb +67 -0
- data/test/unit/processor_test.rb +7 -10
- metadata +6 -5
- data/app/views/nimbleshop_paypalwp/paypalwps/_form.html.erb +0 -36
@@ -1,6 +1,6 @@
|
|
1
1
|
module NimbleshopPaypalwp
|
2
2
|
|
3
|
-
#
|
3
|
+
# Following line makes it possible to use this gem without nimbleshop_core
|
4
4
|
klass = defined?(::Admin::PaymentMethodsController) ? ::Admin::PaymentMethodsController : ActionController::Base
|
5
5
|
|
6
6
|
class PaypalwpsController < klass
|
@@ -13,40 +13,23 @@ module NimbleshopPaypalwp
|
|
13
13
|
processor = NimbleshopPaypalwp::Processor.new(raw_post: request.raw_post)
|
14
14
|
order = processor.order
|
15
15
|
|
16
|
-
#
|
17
|
-
unless order.purchased?
|
18
|
-
processor.order.update_attributes(payment_method: NimbleshopPaypalwp::Paypalwp.first)
|
19
|
-
processor.purchase
|
20
|
-
end
|
16
|
+
# order is already in purchased state. Seems like IPN is sending duplicate notification
|
17
|
+
processor.purchase unless order.purchased?
|
21
18
|
|
22
19
|
render nothing: true
|
23
20
|
end
|
24
21
|
|
25
22
|
def update
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
msg = @payment_method.errors.full_messages.first
|
34
|
-
error = %Q[alert("#{msg}")]
|
35
|
-
format.js { render js: error }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
23
|
+
alert_msg = if @payment_method.update_attributes(post_params[:paypalwp])
|
24
|
+
msg = "Record has been updated"
|
25
|
+
%Q[alert("#{msg}")]
|
26
|
+
else
|
27
|
+
msg = @payment_method.errors.full_messages.first
|
28
|
+
%Q[alert("#{msg}")]
|
29
|
+
end
|
39
30
|
|
40
|
-
def destroy
|
41
31
|
respond_to do |format|
|
42
|
-
|
43
|
-
format.js {
|
44
|
-
flash[:notice] = 'Paypal record was successfully deleted'
|
45
|
-
render js: "window.location = '/admin/payment_methods'"
|
46
|
-
}
|
47
|
-
else
|
48
|
-
format.js { render js: 'Paypal record could not be deleted. Please try again later.' }
|
49
|
-
end
|
32
|
+
format.js { render js: alert_msg }
|
50
33
|
end
|
51
34
|
end
|
52
35
|
|
@@ -39,6 +39,8 @@ module NimbleshopPaypalwp
|
|
39
39
|
service.notify_url nimbleshop_paypalwp_notify_url
|
40
40
|
service.return_url nimbleshop_paypalwp_return_url(order)
|
41
41
|
service.cancel_return_url nimbleshop_paypalwp_cancel_url(order)
|
42
|
+
|
43
|
+
Rails.logger.debug "service attributes: #{service.inspect}"
|
42
44
|
end
|
43
45
|
|
44
46
|
def nimbleshop_paypalwp_crud_form
|
@@ -65,6 +67,7 @@ module NimbleshopPaypalwp
|
|
65
67
|
end
|
66
68
|
|
67
69
|
def nimbleshop_paypalwp_protocol
|
70
|
+
# TODO do not hardcode decision based on env
|
68
71
|
NimbleshopPaypalwp::Paypalwp.first.mode == 'production' ? 'https' : 'http'
|
69
72
|
end
|
70
73
|
|
@@ -1,32 +1,41 @@
|
|
1
|
-
|
1
|
+
<% payment_method = NimbleshopPaypalwp::Paypalwp.first %>
|
2
2
|
|
3
|
-
|
4
|
-
<h2>Paypal websites payment standard</h2>
|
5
|
-
<div class="edit_link">
|
6
|
-
<%= link_to 'Edit', '#', class: 'nimbleshop-payment-method-edit', id: 'nimbleshop-paypalwp-payment-method-edit' %>
|
3
|
+
<%= content_tag :div, style: 'display:none', data: { behavior: "payment-method-form-#{payment_method.permalink}" } do %>
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
<div style="width:100px;margin-left:50px;"> <%= nimbleshop_paypalwp_picture_on_admin_payment_methods %> </div>
|
6
|
+
<br />
|
7
|
+
|
8
|
+
<%= form_for payment_method, url: '/nimbleshop_paypalwp/paypalwp',
|
9
|
+
remote: true,
|
10
|
+
html: { method: 'put',
|
11
|
+
id: 'nimbleshop-paypalwp-form',
|
12
|
+
class: 'nimbleshop-payment-method-form form-horizontal'} do |f| %>
|
13
13
|
|
14
|
-
<%= nimbleshop_paypalwp_picture_on_admin_payment_methods %>
|
15
14
|
|
16
|
-
<
|
17
|
-
</div>
|
15
|
+
<fieldset>
|
18
16
|
|
19
|
-
|
20
|
-
|
17
|
+
<div class="control-group">
|
18
|
+
<%= f.label :merchant_email, nil, class: 'control-label' %>
|
19
|
+
<div class="controls">
|
20
|
+
<%= f.text_field :merchant_email, class: 'span6' %>
|
21
|
+
</div>
|
22
|
+
</div>
|
21
23
|
|
22
|
-
<
|
23
|
-
|
24
|
+
<div class="control-group">
|
25
|
+
<div class="controls">
|
26
|
+
<label class='checkbox'>
|
27
|
+
<%= f.check_box :mode, {}, 'test', 'production' %> Enable sandbox mode
|
28
|
+
</label>
|
29
|
+
</div>
|
30
|
+
</div>
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
</fieldset>
|
33
|
+
|
34
|
+
<div class="form-actions">
|
35
|
+
<%= f.submit('Submit', class: 'btn btn-primary') %>
|
36
|
+
|
37
|
+
<%= link_to 'Disable', main_app.disable_admin_payment_method_path(payment_method), class: 'disable-payment-method-link', method: :put %>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
30
40
|
|
31
|
-
|
32
|
-
</script>
|
41
|
+
<% end %>
|
@@ -1,29 +1,23 @@
|
|
1
1
|
module NimbleshopPaypalwp
|
2
2
|
class Processor < Processor::Base
|
3
3
|
|
4
|
-
attr_reader :order, :payment_method
|
4
|
+
attr_reader :order, :payment_method, :notify
|
5
5
|
|
6
6
|
def initialize(options = {})
|
7
|
-
|
8
|
-
|
7
|
+
options.symbolize_keys!
|
8
|
+
options.assert_valid_keys :raw_post
|
9
|
+
raw_post = options.fetch :raw_post
|
10
|
+
|
11
|
+
@notify = ActiveMerchant::Billing::Integrations::Paypal::Notification.new raw_post
|
12
|
+
@order = Order.find_by_number! notify.invoice
|
9
13
|
@payment_method = NimbleshopPaypalwp::Paypalwp.first
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
13
17
|
|
14
|
-
def paypal_ipn(raw_post)
|
15
|
-
# ActiveMerchant::Billing::Integrations::Paypal::Notification is a subclass of
|
16
|
-
# ActiveMerchant::Billing::Integrations::Notification
|
17
|
-
#
|
18
|
-
# And ActiveMerchant::Billing::Integrations::Notification dependds on money gem
|
19
|
-
ActiveMerchant::Billing::Integrations::Paypal::Notification.new(raw_post)
|
20
|
-
end
|
21
|
-
|
22
18
|
def do_capture(options = {})
|
23
|
-
success =
|
24
|
-
|
25
|
-
|
26
|
-
if success
|
19
|
+
if success = ipn_from_paypal?
|
20
|
+
record_transaction 'captured'
|
27
21
|
order.update_attributes(purchased_at: purchased_at, payment_method: payment_method)
|
28
22
|
order.kapture
|
29
23
|
end
|
@@ -32,10 +26,8 @@ module NimbleshopPaypalwp
|
|
32
26
|
end
|
33
27
|
|
34
28
|
def do_authorize(options = {})
|
35
|
-
success =
|
36
|
-
|
37
|
-
|
38
|
-
if success
|
29
|
+
if success = ipn_from_paypal?
|
30
|
+
record_transaction 'authorized'
|
39
31
|
order.update_attributes(purchased_at: purchased_at, payment_method: payment_method)
|
40
32
|
order.authorize
|
41
33
|
end
|
@@ -47,32 +39,59 @@ module NimbleshopPaypalwp
|
|
47
39
|
end
|
48
40
|
|
49
41
|
def do_purchase(options = {})
|
50
|
-
success =
|
51
|
-
|
52
|
-
|
53
|
-
if success
|
54
|
-
order.update_attributes(purchased_at: @paypal_ipn.received_at, payment_method: payment_method)
|
42
|
+
if success = ipn_from_paypal?
|
43
|
+
record_transaction 'purchased'
|
44
|
+
order.update_attributes(purchased_at: notify.received_at, payment_method: payment_method)
|
55
45
|
order.purchase
|
56
46
|
end
|
57
47
|
|
58
48
|
success
|
59
49
|
end
|
60
50
|
|
61
|
-
|
62
51
|
def record_transaction(operation, options = {})
|
63
|
-
order.payment_transactions.create(options.merge(amount:
|
64
|
-
params: { ipn:
|
65
|
-
transaction_gid:
|
52
|
+
order.payment_transactions.create(options.merge(amount: notify.amount.cents,
|
53
|
+
params: { ipn: notify.raw },
|
54
|
+
transaction_gid: notify.transaction_id,
|
66
55
|
operation: operation))
|
56
|
+
end
|
57
|
+
|
58
|
+
def ipn_from_paypal?
|
59
|
+
# this is needed because the intergration mode was being reset in development
|
60
|
+
ActiveMerchant::Billing::Base.integration_mode = payment_method.mode.intern
|
61
|
+
|
62
|
+
result = amount_match? && notify_complete && business_email_match? && notify_acknowledge
|
63
|
+
Rails.logger.debug "ipn_from_paypal? : #{result}"
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def notify_complete
|
68
|
+
result = notify.complete?
|
69
|
+
Rails.logger.debug "notify.complete? : #{result}"
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
def notify_acknowledge
|
74
|
+
result = Rails.env.test? ? true : notify.acknowledge
|
75
|
+
Rails.logger.debug "notify_acknowledge : #{result}"
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
def business_email_match?
|
80
|
+
return true if Rails.env.test?
|
67
81
|
|
82
|
+
result = notify.account == payment_method.merchant_email
|
83
|
+
Rails.logger.debug "business_email_match? : #{result}"
|
84
|
+
result
|
68
85
|
end
|
69
86
|
|
70
87
|
def amount_match?
|
71
|
-
|
88
|
+
result = notify.amount.cents == order.total_amount_in_cents
|
89
|
+
Rails.logger.debug "amount_match? : #{result}"
|
90
|
+
result
|
72
91
|
end
|
73
92
|
|
74
93
|
def purchased_at
|
75
|
-
Time.strptime(
|
94
|
+
Time.strptime(notify.params['payment_date'], "%H:%M:%S %b %d, %Y %z")
|
76
95
|
end
|
77
96
|
end
|
78
97
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaypalwpsControllerTest < ActionController::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
@controller = NimbleshopPaypalwp::PaypalwpsController.new
|
7
|
+
NimbleshopPaypalwp::Paypalwp.create!(name: 'Paypalwp', merchant_email: 'seller_1323037155_biz@bigbinary.com', description: 'this is description')
|
8
|
+
@order = create :order_paid_using_paypalwp
|
9
|
+
end
|
10
|
+
|
11
|
+
test "should accept notification request" do
|
12
|
+
|
13
|
+
hash = { "mc_gross" => "2.99",
|
14
|
+
"invoice"=> @order.number,
|
15
|
+
"item_mpn1"=>"",
|
16
|
+
"protection_eligibility"=>"Ineligible",
|
17
|
+
"item_count_unit1"=>"0",
|
18
|
+
"item_number1"=>"",
|
19
|
+
"tax"=>"0.04",
|
20
|
+
"payer_id"=>"8NMFURHRJBP94",
|
21
|
+
"payment_date"=>"05:50:35 Sep 27, 2012 PDT",
|
22
|
+
"item_tax_rate1"=>"0",
|
23
|
+
"payment_status"=>"Completed",
|
24
|
+
"charset"=>"windows-1252",
|
25
|
+
"mc_shipping"=>"0.00",
|
26
|
+
"item_tax_rate_double1"=>"0.00",
|
27
|
+
"mc_handling"=>"10.00",
|
28
|
+
"first_name"=>"Rashmi",
|
29
|
+
"mc_fee"=>"0.68",
|
30
|
+
"notify_version"=>"3.7",
|
31
|
+
"custom"=>"4",
|
32
|
+
"payer_status"=>"unverified",
|
33
|
+
"business"=>"seller_1323037155_biz@bigbinary.com",
|
34
|
+
"num_cart_items"=>"1",
|
35
|
+
"mc_handling1"=>"0.00",
|
36
|
+
"verify_sign"=>"A52WYOWQ5f6.ZWIwRWkmVwieCw2gAWuLNstA178r02lkMvIe5mnmEib8",
|
37
|
+
"payer_email"=>"hello@bigbinary.com",
|
38
|
+
"mc_shipping1"=>"0.00",
|
39
|
+
"item_style_number1"=>"",
|
40
|
+
"tax1"=>"0.00",
|
41
|
+
"item_plu1"=>"",
|
42
|
+
"txn_id"=>"90U719813N3473230",
|
43
|
+
"payment_type"=>"instant",
|
44
|
+
"last_name"=>"Singh",
|
45
|
+
"item_name1"=>"Hard wood case for iphone",
|
46
|
+
"receiver_email"=>"neeraj@bigbinary.com",
|
47
|
+
"item_isbn1"=>"",
|
48
|
+
"payment_fee"=>"0.68",
|
49
|
+
"quantity1"=>"1",
|
50
|
+
"receiver_id"=>"DS94AKELVSP6U",
|
51
|
+
"txn_type"=>"cart",
|
52
|
+
"item_model_number1"=>"",
|
53
|
+
"mc_gross_1"=>"3.00",
|
54
|
+
"mc_currency"=>"USD",
|
55
|
+
"item_taxable1"=>"N",
|
56
|
+
"residence_country"=>"US",
|
57
|
+
"transaction_subject"=>"4",
|
58
|
+
"payment_gross"=>"13.04",
|
59
|
+
"ipn_track_id"=>"841618d367692"}
|
60
|
+
|
61
|
+
post :notify, { use_route: :nimbleshop_paypalwp }.merge(hash)
|
62
|
+
@order.reload
|
63
|
+
assert @order.purchased?, "payment status is #{@order.payment_status}"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
data/test/unit/processor_test.rb
CHANGED
@@ -14,26 +14,23 @@ module Processor
|
|
14
14
|
@order = create(:order)
|
15
15
|
end
|
16
16
|
|
17
|
-
test "when
|
17
|
+
test "when purchase succeeds" do
|
18
18
|
processor = NimbleshopPaypalwp::Processor.new(raw_post: raw_post(@order.number, @order.total_amount))
|
19
|
-
|
20
|
-
assert_equal true, processor.authorize
|
21
|
-
end
|
19
|
+
assert_equal true, processor.purchase
|
22
20
|
|
23
21
|
@order.reload
|
24
22
|
|
25
23
|
transaction = @order.payment_transactions.last
|
26
|
-
assert_equal '
|
27
|
-
assert_equal true,
|
28
|
-
|
29
|
-
assert_equal "April 01, 2012 at 08:46 pm", @order.purchased_at.to_s(:long)
|
24
|
+
assert_equal 'purchased', transaction.operation
|
25
|
+
assert_equal true, @order.purchased?
|
26
|
+
assert_match /April 01, 2012/, @order.purchased_at.to_s(:long)
|
30
27
|
assert_equal NimbleshopPaypalwp::Paypalwp.first, @order.payment_method
|
31
28
|
assert_equal transaction.amount, @order.total_amount_in_cents
|
32
29
|
end
|
33
30
|
|
34
|
-
test "when
|
31
|
+
test "when purchase fails" do
|
35
32
|
processor = NimbleshopPaypalwp::Processor.new(raw_post: raw_post(@order.number, 10.48))
|
36
|
-
assert_equal false, processor.
|
33
|
+
assert_equal false, processor.purchase
|
37
34
|
assert_nil @order.payment_method
|
38
35
|
end
|
39
36
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nimbleshop_paypalwp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-11-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activemerchant
|
@@ -75,7 +75,6 @@ files:
|
|
75
75
|
- app/views/nimbleshop_paypalwp/payments/_new.html.erb
|
76
76
|
- app/views/nimbleshop_paypalwp/payments/_order_show_extra_info.html.erb
|
77
77
|
- app/views/nimbleshop_paypalwp/paypalwps/_edit.html.erb
|
78
|
-
- app/views/nimbleshop_paypalwp/paypalwps/_form.html.erb
|
79
78
|
- config/routes.rb
|
80
79
|
- lib/nimbleshop_paypalwp/active_merchant/billing/integrations/paypal/helper.rb
|
81
80
|
- lib/nimbleshop_paypalwp/engine.rb
|
@@ -84,6 +83,7 @@ files:
|
|
84
83
|
- lib/tasks/nimbleshop_paypalwp_mock_ipn_callback.rake
|
85
84
|
- lib/tasks/nimbleshop_paypalwp_tasks.rake
|
86
85
|
- README.md
|
86
|
+
- test/functional/paypalwps_controller_test.rb
|
87
87
|
- test/test_helper.rb
|
88
88
|
- test/unit/payment_method_test.rb
|
89
89
|
- test/unit/processor_test.rb
|
@@ -101,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
101
|
version: '0'
|
102
102
|
segments:
|
103
103
|
- 0
|
104
|
-
hash: -
|
104
|
+
hash: -3466410436082107566
|
105
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
106
|
none: false
|
107
107
|
requirements:
|
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
version: '0'
|
111
111
|
segments:
|
112
112
|
- 0
|
113
|
-
hash: -
|
113
|
+
hash: -3466410436082107566
|
114
114
|
requirements: []
|
115
115
|
rubyforge_project:
|
116
116
|
rubygems_version: 1.8.24
|
@@ -118,6 +118,7 @@ signing_key:
|
|
118
118
|
specification_version: 3
|
119
119
|
summary: Paypal WPS extension for nimbleshop
|
120
120
|
test_files:
|
121
|
+
- test/functional/paypalwps_controller_test.rb
|
121
122
|
- test/test_helper.rb
|
122
123
|
- test/unit/payment_method_test.rb
|
123
124
|
- test/unit/processor_test.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
<div class='well nimbleshop-payment-method-form-well' id='nimbleshop-paypalwp-form-well', style='display:none;'>
|
2
|
-
|
3
|
-
<%= form_for NimbleshopPaypalwp::Paypalwp.first, url: '/nimbleshop_paypalwp/paypalwp',
|
4
|
-
remote: true,
|
5
|
-
html: { method: 'put',
|
6
|
-
id: 'nimbleshop-paypalwp-form',
|
7
|
-
class: 'nimbleshop-payment-method-form form-horizontal'} do |f| %>
|
8
|
-
|
9
|
-
|
10
|
-
<fieldset>
|
11
|
-
|
12
|
-
<div class="control-group">
|
13
|
-
<%= f.label :merchant_email, nil, class: 'control-label' %>
|
14
|
-
<div class="controls">
|
15
|
-
<%= f.text_field :merchant_email, class: 'span6' %>
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
|
19
|
-
<div class="control-group">
|
20
|
-
<div class="controls">
|
21
|
-
<label class='checkbox'>
|
22
|
-
<%= f.check_box :mode, {}, 'test', 'production' %> Enable sandbox mode
|
23
|
-
</label>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
|
27
|
-
</fieldset>
|
28
|
-
|
29
|
-
<div class="form-actions">
|
30
|
-
<%= f.submit('Submit', class: 'btn btn-primary') %>
|
31
|
-
|
32
|
-
<%= link_to t(:cancel), nimbleshop_paypalwp.paypalwp_path, class: 'cancel btn' %>
|
33
|
-
</div>
|
34
|
-
<% end %>
|
35
|
-
|
36
|
-
</div>
|