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.
@@ -1,6 +1,6 @@
1
1
  module NimbleshopPaypalwp
2
2
 
3
- # this line makes it possible to use this gem without nimbleshop_core
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
- # Since IPN can send notification multiple times check if the order has already been set to purchased status
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
- respond_to do |format|
27
- if @payment_method.update_attributes(post_params[:paypalwp])
28
- format.js {
29
- flash[:notice] = 'Paypal record was successfully updated'
30
- render js: "window.location = '/admin/payment_methods'"
31
- }
32
- else
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
- if @payment_method.destroy
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
 
@@ -9,6 +9,10 @@ module NimbleshopPaypalwp
9
9
 
10
10
  before_validation :strip_attributes
11
11
 
12
+ def test_mode?
13
+ self.mode == 'test'
14
+ end
15
+
12
16
  private
13
17
 
14
18
  def set_mode
@@ -1,32 +1,41 @@
1
- <div class='payment-method-engine-well'>
1
+ <% payment_method = NimbleshopPaypalwp::Paypalwp.first %>
2
2
 
3
- <div>
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
- <%= link_to nimbleshop_paypalwp.paypalwp_path, class: 'nimbleshop-payment-method-delete',
9
- confirm: 'Do you really want to delete Paypal payment method', method: :delete, remote: true do %>
10
- <i class='icon-remove icon-white'></i>
11
- <% end %>
12
- </div>
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
- <div class='clear'></div>
17
- </div>
15
+ <fieldset>
18
16
 
19
- <%= render partial: '/nimbleshop_paypalwp/paypalwps/form' %>
20
- </div>
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
- <script>
23
- $(function(){
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
- $('#nimbleshop-paypalwp-payment-method-edit').toggle(function(){
26
- $('#nimbleshop-paypalwp-form-well').show();
27
- }, function(){
28
- $('#nimbleshop-paypalwp-form-well').hide();
29
- });
32
+ </fieldset>
33
+
34
+ <div class="form-actions">
35
+ <%= f.submit('Submit', class: 'btn btn-primary') %>
36
+ &nbsp;
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
- @paypal_ipn = paypal_ipn(options[:raw_post])
8
- @order = Order.find_by_number!(@paypal_ipn.invoice)
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 = amount_match?
24
- record_transaction('captured', success: success)
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 = amount_match?
36
- record_transaction('authorized', success: success)
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 = amount_match?
51
- record_transaction('purchased', success: success)
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: @paypal_ipn.amount.cents,
64
- params: { ipn: @paypal_ipn.raw },
65
- transaction_gid: @paypal_ipn.transaction_id,
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
- @paypal_ipn.amount.cents == order.total_amount_in_cents
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(@paypal_ipn.params['payment_date'], "%H:%M:%S %b %d, %Y %z")
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
+
@@ -14,26 +14,23 @@ module Processor
14
14
  @order = create(:order)
15
15
  end
16
16
 
17
- test "when authorization succeeds" do
17
+ test "when purchase succeeds" do
18
18
  processor = NimbleshopPaypalwp::Processor.new(raw_post: raw_post(@order.number, @order.total_amount))
19
- playcasette('paypal/authorize-success') do
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 'authorized', transaction.operation
27
- assert_equal true, transaction.success
28
- assert_equal true, @order.authorized?
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 authorization fails" do
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.authorize
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.10
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-08-23 00:00:00.000000000 Z
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: -4510410604428150121
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: -4510410604428150121
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
- &nbsp;
32
- <%= link_to t(:cancel), nimbleshop_paypalwp.paypalwp_path, class: 'cancel btn' %>
33
- </div>
34
- <% end %>
35
-
36
- </div>