paypal-express 0.0.1
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/.document +5 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/lib/cert +3509 -0
- data/lib/paypal.rb +56 -0
- data/lib/paypal/base.rb +19 -0
- data/lib/paypal/exceptions.rb +21 -0
- data/lib/paypal/express.rb +1 -0
- data/lib/paypal/express/request.rb +64 -0
- data/lib/paypal/express/response.rb +19 -0
- data/lib/paypal/nvp/request.rb +59 -0
- data/lib/paypal/nvp/response.rb +145 -0
- data/lib/paypal/payment/recurring.rb +43 -0
- data/lib/paypal/payment/recurring/activation.rb +14 -0
- data/lib/paypal/payment/recurring/billing.rb +37 -0
- data/lib/paypal/payment/recurring/summary.rb +11 -0
- data/lib/paypal/payment/request.rb +24 -0
- data/lib/paypal/payment/response.rb +36 -0
- data/lib/paypal/payment/response/amount.rb +11 -0
- data/lib/paypal/payment/response/info.rb +40 -0
- data/lib/paypal/payment/response/payer.rb +7 -0
- data/lib/paypal/payment/response/ship_to.rb +7 -0
- data/lib/paypal/util.rb +28 -0
- data/lib/restclient_with_ssl_support.rb +16 -0
- data/paypal-express.gemspec +24 -0
- data/spec/fake_response/CreateRecurringPaymentsProfile/failure.txt +1 -0
- data/spec/fake_response/CreateRecurringPaymentsProfile/success.txt +1 -0
- data/spec/fake_response/DoExpressCheckoutPayment/failure.txt +1 -0
- data/spec/fake_response/DoExpressCheckoutPayment/success.txt +1 -0
- data/spec/fake_response/GetExpressCheckoutDetails/failure.txt +1 -0
- data/spec/fake_response/GetExpressCheckoutDetails/success.txt +1 -0
- data/spec/fake_response/GetRecurringPaymentsProfileDetails/failure.txt +1 -0
- data/spec/fake_response/GetRecurringPaymentsProfileDetails/success.txt +1 -0
- data/spec/fake_response/ManageRecurringPaymentsProfileStatus/failure.txt +1 -0
- data/spec/fake_response/ManageRecurringPaymentsProfileStatus/success.txt +1 -0
- data/spec/fake_response/SetExpressCheckout/failure.txt +1 -0
- data/spec/fake_response/SetExpressCheckout/success.txt +1 -0
- data/spec/helpers/fake_response_helper.rb +27 -0
- data/spec/paypal/exception_spec.rb +17 -0
- data/spec/paypal/express/request_spec.rb +223 -0
- data/spec/paypal/express/response_spec.rb +33 -0
- data/spec/paypal/nvp/request_spec.rb +88 -0
- data/spec/paypal/payment/recurring_spec.rb +114 -0
- data/spec/paypal/payment/request_spec.rb +55 -0
- data/spec/paypal/payment/response/amount_spec.rb +36 -0
- data/spec/paypal/payment/response/info_spec.rb +88 -0
- data/spec/paypal/payment/response/payer_spec.rb +26 -0
- data/spec/paypal/payment/response/ship_to_spec.rb +26 -0
- data/spec/paypal/util_spec.rb +32 -0
- data/spec/spec_helper.rb +22 -0
- metadata +267 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Payment
|
3
|
+
class Recurring::Billing < Base
|
4
|
+
attr_optional :period, :frequency, :paid, :currency_code, :total_cycles, :trial_period, :trial_frequency, :trial_total_cycles, :trial_amount, :trial_amount_paid
|
5
|
+
attr_accessor :amount
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
@amount = if attributes[:amount].is_a?(Response::Amount)
|
9
|
+
attributes[:amount]
|
10
|
+
else
|
11
|
+
Response::Amount.new(
|
12
|
+
:total => attributes[:amount],
|
13
|
+
:tax => attributes[:tax_amount],
|
14
|
+
:shipping => attributes[:shipping_amount]
|
15
|
+
)
|
16
|
+
end
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_params
|
21
|
+
{
|
22
|
+
:BILLINGPERIOD => self.period,
|
23
|
+
:BILLINGFREQUENCY => self.frequency,
|
24
|
+
:TOTALBILLINGCYCLES => self.total_cycles,
|
25
|
+
:AMT => Util.formatted_amount(self.amount.total),
|
26
|
+
:TRIALBILLINGPERIOD => self.trial_period,
|
27
|
+
:TRIALBILLINGFREQUENCY => self.trial_frequency,
|
28
|
+
:TRIALTOTALBILLINGCYCLES => self.trial_total_cycles,
|
29
|
+
:TRIALAMT => Util.formatted_amount(self.trial_amount),
|
30
|
+
:CURRENCYCODE => self.currency_code,
|
31
|
+
:SHIPPINGAMT => Util.formatted_amount(self.amount.shipping),
|
32
|
+
:TAXAMT => Util.formatted_amount(self.amount.tax)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Payment
|
3
|
+
class Recurring::Summary < Base
|
4
|
+
attr_optional :next_billing_date, :cycles_completed, :cycles_remaining, :outstanding_balance, :failed_count, :last_payment_date, :last_payment_amount
|
5
|
+
|
6
|
+
def numeric_attribute?(key)
|
7
|
+
super || [:outstanding_balance, :failed_count].include?(key)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Payment
|
3
|
+
class Request < Base
|
4
|
+
attr_optional :amount, :action, :currency_code, :description, :notify_url, :billing_type, :billing_agreement_description
|
5
|
+
|
6
|
+
def to_params(index = 0)
|
7
|
+
{
|
8
|
+
:"PAYMENTREQUEST_#{index}_PAYMENTACTION" => self.action,
|
9
|
+
:"PAYMENTREQUEST_#{index}_AMT" => Util.formatted_amount(self.amount),
|
10
|
+
:"PAYMENTREQUEST_#{index}_CURRENCYCODE" => self.currency_code,
|
11
|
+
:"PAYMENTREQUEST_#{index}_DESC" => self.description,
|
12
|
+
# NOTE:
|
13
|
+
# notify_url works only when DoExpressCheckoutPayment called.
|
14
|
+
# recurring payment doesn't support dynamic notify_url.
|
15
|
+
:"PAYMENTREQUEST_#{index}_NOTIFYURL" => self.notify_url,
|
16
|
+
:"L_BILLINGTYPE#{index}" => self.billing_type,
|
17
|
+
:"L_BILLINGAGREEMENTDESCRIPTION#{index}" => self.billing_agreement_description
|
18
|
+
}.delete_if do |k, v|
|
19
|
+
v.blank?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Payment
|
3
|
+
class Response < Base
|
4
|
+
attr_accessor :amount, :ship_to, :insurance_option_offered, :currency_code, :error_code
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
attrs = attributes.dup
|
8
|
+
@amount = Amount.new(
|
9
|
+
:total => attrs.delete(:AMT),
|
10
|
+
:handing => attrs.delete(:HANDLINGAMT),
|
11
|
+
:insurance => attrs.delete(:INSURANCEAMT),
|
12
|
+
:ship_disc => attrs.delete(:SHIPDISCAMT),
|
13
|
+
:shipping => attrs.delete(:SHIPPINGAMT),
|
14
|
+
:tax => attrs.delete(:TAXAMT)
|
15
|
+
)
|
16
|
+
@ship_to = Payment::Response::ShipTo.new(
|
17
|
+
:name => attrs.delete(:SHIPTONAME),
|
18
|
+
:zip => attrs.delete(:SHIPTOZIP),
|
19
|
+
:street => attrs.delete(:SHIPTOSTREET),
|
20
|
+
:city => attrs.delete(:SHIPTOCITY),
|
21
|
+
:state => attrs.delete(:SHIPTOSTATE),
|
22
|
+
:country_code => attrs.delete(:SHIPTOCOUNTRYCODE),
|
23
|
+
:country_name => attrs.delete(:SHIPTOCOUNTRYNAME)
|
24
|
+
)
|
25
|
+
@insurance_option_offered = attrs.delete(:INSURANCEOPTIONOFFERED) == 'true'
|
26
|
+
@currency_code = attrs.delete(:CURRENCYCODE)
|
27
|
+
@error_code = attrs.delete(:ERRORCODE)
|
28
|
+
|
29
|
+
# warn ignored params
|
30
|
+
attrs.each do |key, value|
|
31
|
+
Paypal.log "Ignored Parameter (#{self.class}): #{key}=#{value}", :warn
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Payment
|
3
|
+
class Response::Info < Base
|
4
|
+
cattr_reader :attribute_mapping
|
5
|
+
@@attribute_mapping = {
|
6
|
+
:ACK => :ack,
|
7
|
+
:CURRENCYCODE => :currency_code,
|
8
|
+
:ERRORCODE => :error_code,
|
9
|
+
:ORDERTIME => :order_time,
|
10
|
+
:PAYMENTSTATUS => :payment_status,
|
11
|
+
:PAYMENTTYPE => :payment_type,
|
12
|
+
:PENDINGREASON => :pending_reason,
|
13
|
+
:PROTECTIONELIGIBILITY => :protection_eligibility,
|
14
|
+
:PROTECTIONELIGIBILITYTYPE => :protection_eligibility_type,
|
15
|
+
:REASONCODE => :reason_code,
|
16
|
+
:TRANSACTIONID => :transaction_id,
|
17
|
+
:TRANSACTIONTYPE => :transaction_type
|
18
|
+
}
|
19
|
+
attr_accessor *@@attribute_mapping.values
|
20
|
+
attr_accessor :amount
|
21
|
+
|
22
|
+
def initialize(attributes = {})
|
23
|
+
attrs = attributes.dup
|
24
|
+
@@attribute_mapping.each do |key, value|
|
25
|
+
self.send "#{value}=", attrs.delete(key)
|
26
|
+
end
|
27
|
+
@amount = Response::Amount.new(
|
28
|
+
:total => attrs.delete(:AMT),
|
29
|
+
:fee => attrs.delete(:FEEAMT),
|
30
|
+
:tax => attrs.delete(:TAXAMT)
|
31
|
+
)
|
32
|
+
|
33
|
+
# warn ignored params
|
34
|
+
attrs.each do |key, value|
|
35
|
+
Paypal.log "Ignored Parameter (#{self.class}): #{key}=#{value}", :warn
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/paypal/util.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Util
|
3
|
+
|
4
|
+
def self.formatted_amount(x)
|
5
|
+
# Thanks @nahi ;)
|
6
|
+
sprintf "%0.2f", BigDecimal.new(x.to_s).truncate(2)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_numeric(x)
|
10
|
+
if x.to_f == x.to_i
|
11
|
+
x.to_i
|
12
|
+
else
|
13
|
+
x.to_f
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def numeric_attribute?(key)
|
18
|
+
!!(key.to_s =~ /(amount|frequency|cycles|paid)/)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
instance_variables.all? do |key|
|
23
|
+
instance_variable_get(key) == other.instance_variable_get(key)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'restclient'
|
2
|
+
|
3
|
+
module RestClient
|
4
|
+
|
5
|
+
def self.ssl_settings
|
6
|
+
{
|
7
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
8
|
+
:ssl_ca_file => File.join(File.dirname(__FILE__), 'cert')
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.post(url, payload, headers={}, &block)
|
13
|
+
Request.execute(ssl_settings.merge(:method => :post, :url => url, :payload => payload, :headers => headers), &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "paypal-express"
|
3
|
+
s.version = File.read(File.join(File.dirname(__FILE__), "VERSION"))
|
4
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
|
5
|
+
s.authors = ["nov matake"]
|
6
|
+
s.description = %q{Rugy Gem for PayPal Express Checkout API}
|
7
|
+
s.summary = %q{PayPal Express Checkout API Client Supporting Both Instant and Recurring Payment}
|
8
|
+
s.email = "nov@matake.jp"
|
9
|
+
s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
|
10
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
11
|
+
s.homepage = "http://github.com/nov/paypal-express"
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.add_dependency "activesupport", ">= 2.3"
|
17
|
+
s.add_dependency "i18n"
|
18
|
+
s.add_dependency "rest-client", ">= 1.4"
|
19
|
+
s.add_dependency "attr_required", ">= 0.0.3"
|
20
|
+
s.add_development_dependency "rake", ">= 0.8"
|
21
|
+
s.add_development_dependency "rcov", ">= 0.9"
|
22
|
+
s.add_development_dependency "rspec", ">= 2"
|
23
|
+
s.add_development_dependency "fakeweb", ">= 1.3.0"
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
TIMESTAMP=2011%2d02%2d08T07%3a18%3a29Z&CORRELATIONID=fde1527b25b4f&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11502&L_SHORTMESSAGE0=Invalid%20Token&L_LONGMESSAGE0=The%20token%20is%20invalid&L_SEVERITYCODE0=Error
|
@@ -0,0 +1 @@
|
|
1
|
+
PROFILEID=I%2dL8N58XFUCET3&PROFILESTATUS=ActiveProfile&TIMESTAMP=2011%2d02%2d08T07%3a17%3a51Z&CORRELATIONID=7d2e125f5ca63&ACK=Success&VERSION=66%2e0&BUILD=1704252
|
@@ -0,0 +1 @@
|
|
1
|
+
TIMESTAMP=2011%2d02%2d08T07%3a15%3a19Z&CORRELATIONID=5dd0308345382&ACK=Failure&VERSION=66%2e0&BUILD=1721431&L_ERRORCODE0=10410&L_SHORTMESSAGE0=Invalid%20token&L_LONGMESSAGE0=Invalid%20token%2e&L_SEVERITYCODE0=Error
|
@@ -0,0 +1 @@
|
|
1
|
+
TOKEN=EC-9E2743126S4330617&SUCCESSPAGEREDIRECTREQUESTED=false&TIMESTAMP=2011-02-08T03:23:55Z&CORRELATIONID=15b93874c358c&ACK=Success&VERSION=66.0&BUILD=1721431&INSURANCEOPTIONSELECTED=false&SHIPPINGOPTIONISDEFAULT=false&PAYMENTINFO_0_TRANSACTIONID=8NC65222871997739&PAYMENTINFO_0_TRANSACTIONTYPE=expresscheckout&PAYMENTINFO_0_PAYMENTTYPE=instant&PAYMENTINFO_0_ORDERTIME=2011-02-08T03:23:54Z&PAYMENTINFO_0_AMT=14.00&PAYMENTINFO_0_FEEAMT=0.85&PAYMENTINFO_0_TAXAMT=0.00&PAYMENTINFO_0_CURRENCYCODE=USD&PAYMENTINFO_0_PAYMENTSTATUS=Completed&PAYMENTINFO_0_PENDINGREASON=None&PAYMENTINFO_0_REASONCODE=None&PAYMENTINFO_0_PROTECTIONELIGIBILITY=Ineligible&PAYMENTINFO_0_PROTECTIONELIGIBILITYTYPE=None&PAYMENTINFO_0_ERRORCODE=0&PAYMENTINFO_0_ACK=Success
|
@@ -0,0 +1 @@
|
|
1
|
+
TOKEN=EC%2d9E2743126S4330617&CHECKOUTSTATUS=PaymentActionCompleted&TIMESTAMP=2011%2d02%2d08T07%3a10%3a26Z&CORRELATIONID=8f5fddf13ed10&ACK=Failure&VERSION=66%2e0&BUILD=1721431&L_ERRORCODE0=10411&L_SHORTMESSAGE0=This%20Express%20Checkout%20session%20has%20expired%2e&L_LONGMESSAGE0=This%20Express%20Checkout%20session%20has%20expired%2e%20%20Token%20value%20is%20no%20longer%20valid%2e&L_SEVERITYCODE0=Error&EMAIL=valid_1296805890_per%40matake%2ejp&PAYERID=PRT3TZ6MCBCNC&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&SHIPTONAME=Test%20User&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United%20States&ADDRESSSTATUS=Confirmed&CURRENCYCODE=USD&AMT=14%2e00&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_CURRENCYCODE=USD&PAYMENTREQUEST_0_AMT=14%2e00&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_TRANSACTIONID=8NC65222871997739&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Test%20User&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20St&PAYMENTREQUEST_0_SHIPTOCITY=San%20Jose&PAYMENTREQUEST_0_SHIPTOSTATE=CA&PAYMENTREQUEST_0_SHIPTOZIP=95131&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=US&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20States&PAYMENTREQUESTINFO_0_TRANSACTIONID=8NC65222871997739&PAYMENTREQUESTINFO_0_ERRORCODE=0
|
@@ -0,0 +1 @@
|
|
1
|
+
TOKEN=EC%2d99G324856K8277846&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2011%2d02%2d08T07%3a14%3a29Z&CORRELATIONID=e4e63a7a94b02&ACK=Success&VERSION=66%2e0&BUILD=1721431&EMAIL=valid_1296805890_per%40matake%2ejp&PAYERID=PRT3TZ6MCBCNC&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&SHIPTONAME=Test%20User&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United%20States&ADDRESSSTATUS=Confirmed&CURRENCYCODE=USD&AMT=14%2e00&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_CURRENCYCODE=USD&PAYMENTREQUEST_0_AMT=14%2e00&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Test%20User&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20St&PAYMENTREQUEST_0_SHIPTOCITY=San%20Jose&PAYMENTREQUEST_0_SHIPTOSTATE=CA&PAYMENTREQUEST_0_SHIPTOZIP=95131&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=US&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20States&PAYMENTREQUESTINFO_0_ERRORCODE=0
|
@@ -0,0 +1 @@
|
|
1
|
+
PROFILEID=I%2dK1VFLRN3VVG0x&TIMESTAMP=2011%2d02%2d08T07%3a19%3a43Z&CORRELATIONID=edc954f1c34c5&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11552&L_SHORTMESSAGE0=Invalid%20profile%20ID&L_LONGMESSAGE0=The%20profile%20ID%20is%20invalid&L_SEVERITYCODE0=Error
|
@@ -0,0 +1 @@
|
|
1
|
+
PROFILEID=I%2dK1VFLRN3VVG0&STATUS=Active&AUTOBILLOUTAMT=NoAutoBill&DESC=iKnow%21%20Subscription&MAXFAILEDPAYMENTS=0&SUBSCRIBERNAME=Test%20User&PROFILESTARTDATE=2011%2d02%2d03T15%3a00%3a00Z&NEXTBILLINGDATE=2011%2d03%2d04T10%3a00%3a00Z&NUMCYCLESCOMPLETED=1&NUMCYCLESREMAINING=18446744073709551615&OUTSTANDINGBALANCE=0&FAILEDPAYMENTCOUNT=0&LASTPAYMENTDATE=2011%2d02%2d04T10%3a50%3a56Z&LASTPAYMENTAMT=1000&TRIALAMTPAID=0®ULARAMTPAID=1000&AGGREGATEAMT=1000&AGGREGATEOPTIONALAMT=0&FINALPAYMENTDUEDATE=1970%2d01%2d01T00%3a00%3a00Z&TIMESTAMP=2011%2d02%2d08T07%3a19%3a25Z&CORRELATIONID=8e18dd6545045&ACK=Success&VERSION=66%2e0&BUILD=1704252&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRY=US&SHIPTOCOUNTRYNAME=United%20States&SHIPADDRESSOWNER=PayPal&SHIPADDRESSSTATUS=Unconfirmed&BILLINGPERIOD=Month&BILLINGFREQUENCY=1&TOTALBILLINGCYCLES=0&CURRENCYCODE=JPY&AMT=1000&SHIPPINGAMT=0&TAXAMT=0®ULARBILLINGPERIOD=Month®ULARBILLINGFREQUENCY=1®ULARTOTALBILLINGCYCLES=0®ULARCURRENCYCODE=JPY®ULARAMT=1000®ULARSHIPPINGAMT=0®ULARTAXAMT=0
|
@@ -0,0 +1 @@
|
|
1
|
+
TIMESTAMP=2011%2d02%2d08T07%3a21%3a08Z&CORRELATIONID=aa160cad77481&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11556&L_SHORTMESSAGE0=Invalid%20profile%20status%20for%20cancel%20action%3b%20profile%20should%20be%20active%20or%20suspended&L_LONGMESSAGE0=Invalid%20profile%20status%20for%20cancel%20action%3b%20profile%20should%20be%20active%20or%20suspended&L_SEVERITYCODE0=Error
|
@@ -0,0 +1 @@
|
|
1
|
+
PROFILEID=I%2dK1VFLRN3VVG0&TIMESTAMP=2011%2d02%2d08T07%3a20%3a44Z&CORRELATIONID=86bde487ccba6&ACK=Success&VERSION=66%2e0&BUILD=1704252
|
@@ -0,0 +1 @@
|
|
1
|
+
TIMESTAMP=2011%2d02%2d02T02%3a16%3a50Z&CORRELATIONID=379d1b7f97afb&ACK=Failure&L_ERRORCODE0=10001&L_SHORTMESSAGE0=Internal%20Error&L_LONGMESSAGE0=Timeout%20processing%20request
|
@@ -0,0 +1 @@
|
|
1
|
+
ACK=Success&BUILD=1721431&CORRELATIONID=5549ea3a78af1&TIMESTAMP=2011-02-02T02%3A02%3A18Z&TOKEN=EC-5YJ90598G69065317&VERSION=66.0
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fakeweb'
|
2
|
+
|
3
|
+
module FakeResponseHelper
|
4
|
+
|
5
|
+
def fake_response(file_path, options = {})
|
6
|
+
Paypal::NVP::Request::ENDPOINT.each do |env, endpoint|
|
7
|
+
FakeWeb.register_uri(
|
8
|
+
:post,
|
9
|
+
endpoint,
|
10
|
+
options.merge(
|
11
|
+
:body => File.read(File.join(File.dirname(__FILE__), '../fake_response', "#{file_path}.txt"))
|
12
|
+
)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def request_to(endpoint, method = :get)
|
18
|
+
raise_error(
|
19
|
+
FakeWeb::NetConnectNotAllowedError,
|
20
|
+
"Real HTTP connections are disabled. Unregistered request: #{method.to_s.upcase} #{endpoint}"
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
FakeWeb.allow_net_connect = false
|
27
|
+
include FakeResponseHelper
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Paypal::HttpError do
|
4
|
+
it 'should have code, message and body' do
|
5
|
+
error = Paypal::HttpError.new(400, 'BadRequest', 'You are bad man!')
|
6
|
+
error.code.should == 400
|
7
|
+
error.message.should == 'BadRequest'
|
8
|
+
error.body.should == 'You are bad man!'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Paypal::APIError do
|
13
|
+
it 'should have raw response' do
|
14
|
+
error = Paypal::APIError.new({:error => 'ERROR!!'})
|
15
|
+
error.response.should == {:error => 'ERROR!!'}
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Paypal::Express::Request do
|
4
|
+
class Paypal::Express::Request
|
5
|
+
attr_accessor :_sent_params_, :_method_
|
6
|
+
def post_with_logging(method, params)
|
7
|
+
self._method_ = method
|
8
|
+
self._sent_params_ = params
|
9
|
+
post_without_logging method, params
|
10
|
+
end
|
11
|
+
alias_method_chain :post, :logging
|
12
|
+
end
|
13
|
+
|
14
|
+
let :attributes do
|
15
|
+
{
|
16
|
+
:username => 'nov',
|
17
|
+
:password => 'password',
|
18
|
+
:signature => 'sig',
|
19
|
+
:return_url => 'http://example.com/success',
|
20
|
+
:cancel_url => 'http://example.com/cancel'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
let :instance do
|
25
|
+
Paypal::Express::Request.new attributes
|
26
|
+
end
|
27
|
+
|
28
|
+
let :instant_payment_request do
|
29
|
+
Paypal::Payment::Request.new(
|
30
|
+
:amount => 1000,
|
31
|
+
:description => 'Instant Payment Request'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
let :recurring_payment_request do
|
36
|
+
Paypal::Payment::Request.new(
|
37
|
+
:billing_type => :RecurringPayments,
|
38
|
+
:billing_agreement_description => 'Recurring Payment Request'
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
let :recurring_profile do
|
43
|
+
Paypal::Payment::Recurring.new(
|
44
|
+
:start_date => Time.utc(2011, 2, 8, 9, 0, 0),
|
45
|
+
:description => 'Recurring Profile',
|
46
|
+
:billing => {
|
47
|
+
:period => :Month,
|
48
|
+
:frequency => 1,
|
49
|
+
:amount => 1000
|
50
|
+
}
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '.new' do
|
55
|
+
context 'when any required parameters are missing' do
|
56
|
+
it 'should raise AttrMissing exception' do
|
57
|
+
attributes.keys.each do |missing_key|
|
58
|
+
insufficient_attributes = attributes.reject do |key, value|
|
59
|
+
key == missing_key
|
60
|
+
end
|
61
|
+
lambda do
|
62
|
+
Paypal::Express::Request.new insufficient_attributes
|
63
|
+
end.should raise_error AttrRequired::AttrMissing
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when all required parameters are given' do
|
69
|
+
it 'should succeed' do
|
70
|
+
lambda do
|
71
|
+
Paypal::Express::Request.new attributes
|
72
|
+
end.should_not raise_error AttrRequired::AttrMissing
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#setup' do
|
78
|
+
it 'should return Paypal::Express::Response' do
|
79
|
+
fake_response 'SetExpressCheckout/success'
|
80
|
+
response = instance.setup recurring_payment_request
|
81
|
+
response.should be_instance_of(Paypal::Express::Response)
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when instance payment request given' do
|
85
|
+
it 'should call SetExpressCheckout' do
|
86
|
+
lambda do
|
87
|
+
instance.setup instant_payment_request
|
88
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
89
|
+
instance._method_.should == :SetExpressCheckout
|
90
|
+
instance._sent_params_.should == {
|
91
|
+
:PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
|
92
|
+
:RETURNURL => 'http://example.com/success',
|
93
|
+
:CANCELURL => 'http://example.com/cancel',
|
94
|
+
:PAYMENTREQUEST_0_AMT => '1000.00'
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when recurring payment request given' do
|
100
|
+
it 'should call SetExpressCheckout' do
|
101
|
+
lambda do
|
102
|
+
instance.setup recurring_payment_request
|
103
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
104
|
+
instance._method_.should == :SetExpressCheckout
|
105
|
+
instance._sent_params_.should == {
|
106
|
+
:L_BILLINGTYPE0 => :RecurringPayments,
|
107
|
+
:L_BILLINGAGREEMENTDESCRIPTION0 => 'Recurring Payment Request',
|
108
|
+
:RETURNURL => 'http://example.com/success',
|
109
|
+
:CANCELURL => 'http://example.com/cancel',
|
110
|
+
:PAYMENTREQUEST_0_AMT => '0.00'
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#details' do
|
117
|
+
it 'should return Paypal::Express::Response' do
|
118
|
+
fake_response 'GetExpressCheckoutDetails/success'
|
119
|
+
response = instance.details 'token'
|
120
|
+
response.should be_instance_of(Paypal::Express::Response)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should call GetExpressCheckoutDetails' do
|
124
|
+
lambda do
|
125
|
+
instance.details 'token'
|
126
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
127
|
+
instance._method_.should == :GetExpressCheckoutDetails
|
128
|
+
instance._sent_params_.should == {
|
129
|
+
:TOKEN => 'token'
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#checkout!' do
|
135
|
+
it 'should return Paypal::Express::Response' do
|
136
|
+
fake_response 'DoExpressCheckoutPayment/success'
|
137
|
+
response = instance.checkout! 'token', 'payer_id', instant_payment_request
|
138
|
+
response.should be_instance_of(Paypal::Express::Response)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should call DoExpressCheckoutPayment' do
|
142
|
+
lambda do
|
143
|
+
instance.checkout! 'token', 'payer_id', instant_payment_request
|
144
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
145
|
+
instance._method_.should == :DoExpressCheckoutPayment
|
146
|
+
instance._sent_params_.should == {
|
147
|
+
:PAYERID => 'payer_id',
|
148
|
+
:TOKEN => 'token',
|
149
|
+
:PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
|
150
|
+
:PAYMENTREQUEST_0_AMT => '1000.00'
|
151
|
+
}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#subscribe!' do
|
156
|
+
it 'should return Paypal::Express::Response' do
|
157
|
+
fake_response 'CreateRecurringPaymentsProfile/success'
|
158
|
+
response = instance.subscribe! 'token', recurring_profile
|
159
|
+
response.should be_instance_of(Paypal::Express::Response)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should call CreateRecurringPaymentsProfile' do
|
163
|
+
lambda do
|
164
|
+
instance.subscribe! 'token', recurring_profile
|
165
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
166
|
+
instance._method_.should == :CreateRecurringPaymentsProfile
|
167
|
+
instance._sent_params_.should == {
|
168
|
+
:DESC => 'Recurring Profile',
|
169
|
+
:TRIALAMT => '0.00',
|
170
|
+
:TOKEN => 'token',
|
171
|
+
:SHIPPINGAMT => '0.00',
|
172
|
+
:AMT => '1000.00',
|
173
|
+
:TRIALTOTALBILLINGCYCLES => 0,
|
174
|
+
:BILLINGFREQUENCY => 1,
|
175
|
+
:MAXFAILEDPAYMENTS => 0,
|
176
|
+
:TRIALBILLINGFREQUENCY => 0,
|
177
|
+
:BILLINGPERIOD => :Month,
|
178
|
+
:TAXAMT => '0.00',
|
179
|
+
:PROFILESTARTDATE => '2011-02-08 09:00:00',
|
180
|
+
:TOTALBILLINGCYCLES => 0
|
181
|
+
}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#subscription' do
|
186
|
+
it 'should return Paypal::Express::Response' do
|
187
|
+
fake_response 'GetRecurringPaymentsProfileDetails/success'
|
188
|
+
response = instance.subscription 'profile_id'
|
189
|
+
response.should be_instance_of(Paypal::Express::Response)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should call GetRecurringPaymentsProfileDetails' do
|
193
|
+
lambda do
|
194
|
+
instance.subscription 'profile_id'
|
195
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
196
|
+
instance._method_.should == :GetRecurringPaymentsProfileDetails
|
197
|
+
instance._sent_params_.should == {
|
198
|
+
:PROFILEID => 'profile_id'
|
199
|
+
}
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe '#renew!' do
|
204
|
+
it 'should return Paypal::Express::Response' do
|
205
|
+
fake_response 'ManageRecurringPaymentsProfileStatus/success'
|
206
|
+
response = instance.renew! 'profile_id', :Cancel
|
207
|
+
response.should be_instance_of(Paypal::Express::Response)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should call ManageRecurringPaymentsProfileStatus' do
|
211
|
+
lambda do
|
212
|
+
instance.renew! 'profile_id', :Cancel
|
213
|
+
end.should request_to 'https://api-3t.paypal.com/nvp', :post
|
214
|
+
instance._method_.should == :ManageRecurringPaymentsProfileStatus
|
215
|
+
instance._sent_params_.should == {
|
216
|
+
:ACTION => :Cancel,
|
217
|
+
:PROFILEID => 'profile_id',
|
218
|
+
:NOTE => ''
|
219
|
+
}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|