subscription_fu 0.1.0 → 0.2.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.
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
  group :development, :test do
7
7
  gem 'rails'
8
8
  gem 'sqlite3'
9
+ gem 'rake', "0.8.7"
9
10
  gem 'haml'
10
11
  gem 'rspec', '>= 2.5.0'
11
12
  gem 'rspec-rails'
@@ -55,7 +55,7 @@ class SubscriptionFu::Subscription < ActiveRecord::Base
55
55
  # billing time data about the subscription
56
56
 
57
57
  def next_billing_date
58
- paypal_recurring_details[:next_billing_date]
58
+ paypal_recurring_details[:next_billing_date] if paypal?
59
59
  end
60
60
 
61
61
  def estimated_next_billing_date
@@ -64,7 +64,7 @@ class SubscriptionFu::Subscription < ActiveRecord::Base
64
64
  end
65
65
 
66
66
  def last_billing_date
67
- paypal_recurring_details[:last_payment_date]
67
+ paypal_recurring_details[:last_payment_date] if paypal?
68
68
  end
69
69
 
70
70
  def successor_start_date(new_plan_name)
@@ -103,8 +103,14 @@ class SubscriptionFu::Subscription < ActiveRecord::Base
103
103
 
104
104
  private
105
105
 
106
+ def paypal?
107
+ ! paypal_profile_id.blank?
108
+ end
109
+
106
110
  def paypal_recurring_details
107
- @paypal_recurring_details ||= (paypal_profile_id.blank? ? {} : SubscriptionFu::Paypal.paypal.recurring_details(paypal_profile_id))
111
+ @paypal_recurring_details ||= begin
112
+ SubscriptionFu::Paypal.recurring_details(paypal_profile_id)
113
+ end
108
114
  end
109
115
 
110
116
  def convert_paypal_status(paypal_status)
@@ -77,9 +77,15 @@ class SubscriptionFu::Transaction < ActiveRecord::Base
77
77
  private
78
78
 
79
79
  def start_checkout_paypal(return_url, cancel_url)
80
- token = SubscriptionFu::Paypal.paypal.start_checkout(return_url, cancel_url, initiator_email, sub_plan.price_with_tax, sub_plan.currency, sub_human_description)
81
- update_attributes!(:identifier => token)
82
- "#{SubscriptionFu.config.paypal_landing_url}?cmd=_express-checkout&token=#{CGI.escape(token)}"
80
+ # TODO: set initiator_email
81
+ pay_req = Paypal::Payment::Request.new(
82
+ :currency_code => sub_plan.currency,
83
+ :billing_type => :RecurringPayments,
84
+ :billing_agreement_description => sub_human_description)
85
+
86
+ response = SubscriptionFu::Paypal.express_request.setup(pay_req, return_url, cancel_url, :no_shipping => true)
87
+ update_attributes!(:identifier => response.token)
88
+ response.redirect_uri
83
89
  end
84
90
 
85
91
  def start_checkout_nogw(return_url, cancel_url)
@@ -91,9 +97,17 @@ class SubscriptionFu::Transaction < ActiveRecord::Base
91
97
  raise "did you call start_checkout first?" if identifier.blank?
92
98
  raise "already activated" if sub_activated?
93
99
 
94
- paypal_profile_id, paypal_status =
95
- SubscriptionFu::Paypal.paypal.create_recurring(identifier, sub_billing_starts_at, sub_plan.price, sub_plan.price_tax, sub_plan.currency, sub_human_description)
96
- subscription.update_attributes!(:paypal_profile_id => paypal_profile_id, :activated_at => Time.now)
100
+ profile = Paypal::Payment::Recurring.new(
101
+ :start_date => sub_billing_starts_at,
102
+ :description => sub_human_description,
103
+ :billing => {
104
+ :period => :Month,
105
+ :frequency => 1,
106
+ :amount => sub_plan.price,
107
+ :tax => sub_plan.price_tax,
108
+ :currency_code => sub_plan.currency } )
109
+ response = SubscriptionFu::Paypal.express_request.subscribe!(identifier, profile)
110
+ subscription.update_attributes!(:paypal_profile_id => response.recurring.identifier, :activated_at => Time.now)
97
111
  complete_activation
98
112
  end
99
113
 
@@ -114,7 +128,7 @@ class SubscriptionFu::Transaction < ActiveRecord::Base
114
128
  # update the record beforehand, because paypal raises an error if
115
129
  # the profile is already cancelled
116
130
  complete_cancellation(opts)
117
- SubscriptionFu::Paypal.paypal.cancel_recurring(sub_paypal_profile_id, sub_cancel_reason)
131
+ SubscriptionFu::Paypal.express_request.renew!(sub_paypal_profile_id, :Cancel, :note => sub_cancel_reason)
118
132
  end
119
133
 
120
134
  def complete_cancellation_nogw(opts)
@@ -1,22 +1,23 @@
1
+ require "paypal"
2
+
1
3
  module SubscriptionFu
2
4
  class Config
3
- attr_accessor :plan_class_name, :paypal_nvp_api_url, :paypal_api_user_id, :paypal_api_pwd, :paypal_api_sig, :paypal_landing_url
5
+ attr_accessor :plan_class_name, :paypal_api_user_id, :paypal_api_pwd, :paypal_api_sig
4
6
  attr_reader :available_plans
5
7
 
6
8
  def initialize
7
9
  @available_plans = {}
8
10
  @plan_class_name = "SubscriptionFu::Plan"
9
11
  paypal_use_production!
12
+ ::Paypal.logger = Rails.logger
10
13
  end
11
14
 
12
15
  def paypal_use_sandbox!
13
- self.paypal_nvp_api_url = "https://api-3t.sandbox.paypal.com/nvp"
14
- self.paypal_landing_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
16
+ ::Paypal.sandbox = true
15
17
  end
16
18
 
17
19
  def paypal_use_production!
18
- self.paypal_nvp_api_url = "https://api-3t.paypal.com/nvp"
19
- self.paypal_landing_url = "https://www.paypal.com/cgi-bin/webscr"
20
+ ::Paypal.sandbox = false
20
21
  end
21
22
 
22
23
  def add_plan(key, price, data = {})
@@ -1,101 +1,19 @@
1
- require "rest-client"
1
+ require "paypal"
2
2
 
3
- class SubscriptionFu::Paypal
3
+ module SubscriptionFu::Paypal
4
+ UTC_TZ = ActiveSupport::TimeZone.new("UTC")
4
5
 
5
- def self.paypal
6
- new(SubscriptionFu.config.paypal_api_user_id,
7
- SubscriptionFu.config.paypal_api_pwd,
8
- SubscriptionFu.config.paypal_api_sig,
9
- SubscriptionFu.config.paypal_nvp_api_url,
10
- Rails.logger)
6
+ def self.express_request
7
+ config = SubscriptionFu.config
8
+ ::Paypal::Express::Request.new(
9
+ :username => config.paypal_api_user_id,
10
+ :password => config.paypal_api_pwd,
11
+ :signature => config.paypal_api_sig)
11
12
  end
12
13
 
13
- class Failure < RuntimeError
14
- attr_reader :request_opts, :response
15
-
16
- def initialize(request_opts, response)
17
- @request_opts = request_opts
18
- @response = response
19
- super "PayPal did not return success: #{@response.inspect}"
20
- end
21
- alias :data :request_opts
22
- end
23
-
24
- def initialize(user, pwd, sig, api_url, logger)
25
- @user = user
26
- @pwd = pwd
27
- @sig = sig
28
- @api_url = api_url
29
- @logger = logger
30
- end
31
-
32
- def start_checkout(return_url, cancel_url, email, maxamt, currency_code, desc)
33
- res = call_paypal('SetExpressCheckout',
34
- 'RETURNURL' => return_url,
35
- 'CANCELURL' => cancel_url,
36
- 'EMAIL' => email,
37
- 'NOSHIPPING' => 1,
38
- 'MAXAMT' => maxamt,
39
- 'PAYMENTREQUEST_0_AMT' => 0,
40
- 'PAYMENTREQUEST_0_CURRENCYCODE' => currency_code,
41
- 'L_BILLINGTYPE0' => 'RecurringPayments',
42
- 'L_BILLINGAGREEMENTDESCRIPTION0' => desc)
43
- res['TOKEN'].first
44
- end
45
-
46
- def create_recurring(token, start_date, amt, taxamt, currency_code, desc)
47
- res = call_paypal('CreateRecurringPaymentsProfile',
48
- 'PROFILESTARTDATE' => start_date.utc.iso8601,
49
- 'BILLINGPERIOD' => 'Month',
50
- 'BILLINGFREQUENCY' => 1,
51
- 'MAXFAILEDPAYMENTS' => 0,
52
- 'AUTOBILLOUTAMT' => 'AddToNextBilling',
53
- 'AMT' => amt,
54
- 'TAXAMT' => taxamt,
55
- 'CURRENCYCODE' => currency_code,
56
- 'DESC' => desc,
57
- 'TOKEN' => token)
58
- [res['PROFILEID'].first, res['PROFILESTATUS'].first || res['STATUS'].first]
59
- end
60
-
61
- def recurring_details(profile_id)
62
- utc = ActiveSupport::TimeZone.new("UTC")
63
- res = call_paypal('GetRecurringPaymentsProfileDetails', 'PROFILEID' => profile_id)
64
- { :id => res['PROFILEID'].first,
65
- :status => res['PROFILESTATUS'].first || res['STATUS'].first,
66
- :next_billing_date => utc.parse(res['NEXTBILLINGDATE'].first.to_s),
67
- :start_date => utc.parse(res['PROFILESTARTDATE'].first.to_s),
68
- :cycles_completed => res['NUMCYCLESCOMPLETED'].first.to_i,
69
- :outstanding_balance => res['OUTSTANDINGBALANCE'].first.to_f,
70
- :last_payment_date => utc.parse(res['LASTPAYMENTDATE'].first.to_s) }
14
+ def self.recurring_details(profile_id)
15
+ res = SubscriptionFu::Paypal.express_request.subscription(profile_id)
16
+ { :next_billing_date => UTC_TZ.parse(res.recurring.summary.next_billing_date.to_s),
17
+ :last_payment_date => UTC_TZ.parse(res.recurring.summary.last_payment_date.to_s), }
71
18
  end
72
-
73
- def cancel_recurring(profile_id, reason)
74
- call_paypal('ManageRecurringPaymentsProfileStatus',
75
- 'PROFILEID' => profile_id,
76
- 'ACTION' => 'Cancel',
77
- 'NOTE' => I18n.t(reason, :scope => [:subscription_fu, :subscription, :cancel_notes]))
78
- end
79
-
80
- private
81
-
82
- def call_paypal(method, opts)
83
- full_opts = paypal_api_opts(method, opts)
84
- CGI.parse(RestClient.post(@api_url, full_opts)).tap do |result|
85
- if result['ACK'].first != 'Success'
86
- @logger.warn("PayPal did not return success for call to #{method}")
87
- @logger.info(" called with: #{full_opts.inspect}")
88
- @logger.info(" result: #{result.inspect}")
89
- raise Failure.new(full_opts, result)
90
- else
91
- @logger.info("PayPal returned success for call to #{method}")
92
- @logger.info(" result: #{result.inspect}")
93
- end
94
- end
95
- end
96
-
97
- def paypal_api_opts(method, opts)
98
- opts.merge('USER' => @user, 'PWD' => @pwd, 'SIGNATURE' => @sig, 'VERSION' => '65.0', 'METHOD' => method)
99
- end
100
-
101
19
  end
@@ -1,3 +1,3 @@
1
1
  module SubscriptionFu
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -74,7 +74,7 @@ module PaypalTestHelper
74
74
  end
75
75
 
76
76
  def paypal_profile_res(profile, status, opts = {})
77
- paypal_res(opts.merge("PROFILEID"=>profile,"STATUS"=>status))
77
+ paypal_res(opts.merge("PROFILEID"=>profile,"STATUS"=>status,"REGULARAMT"=>"0"))
78
78
  end
79
79
 
80
80
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.rubyforge_project = "subscriptionfu"
17
17
 
18
18
  s.add_dependency 'rails', '>= 3.0.3'
19
- s.add_dependency 'rest-client', '>= 1.6.1'
19
+ s.add_dependency 'paypal-express', '~> 0.3.0'
20
20
 
21
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
22
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: subscription_fu
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul McMahon
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-05-20 00:00:00 +09:00
14
+ date: 2011-05-29 00:00:00 +09:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -26,14 +26,14 @@ dependencies:
26
26
  type: :runtime
27
27
  version_requirements: *id001
28
28
  - !ruby/object:Gem::Dependency
29
- name: rest-client
29
+ name: paypal-express
30
30
  prerelease: false
31
31
  requirement: &id002 !ruby/object:Gem::Requirement
32
32
  none: false
33
33
  requirements:
34
- - - ">="
34
+ - - ~>
35
35
  - !ruby/object:Gem::Version
36
- version: 1.6.1
36
+ version: 0.3.0
37
37
  type: :runtime
38
38
  version_requirements: *id002
39
39
  description: SubscriptionFu helps with building services which have paid subscriptions. It includes the models to store subscription status, and provides integration with PayPal for paid subscriptions.
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  requirements: []
127
127
 
128
128
  rubyforge_project: subscriptionfu
129
- rubygems_version: 1.6.2
129
+ rubygems_version: 1.5.2
130
130
  signing_key:
131
131
  specification_version: 3
132
132
  summary: Rails support for handling free/paid subscriptions