ianfleeton-paypal-express 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +11 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +20 -0
  8. data/README.rdoc +43 -0
  9. data/Rakefile +19 -0
  10. data/VERSION +1 -0
  11. data/ianfleeton-paypal-express.gemspec +24 -0
  12. data/lib/paypal.rb +86 -0
  13. data/lib/paypal/base.rb +19 -0
  14. data/lib/paypal/exception.rb +4 -0
  15. data/lib/paypal/exception/api_error.rb +94 -0
  16. data/lib/paypal/exception/http_error.rb +12 -0
  17. data/lib/paypal/express.rb +1 -0
  18. data/lib/paypal/express/request.rb +186 -0
  19. data/lib/paypal/express/response.rb +35 -0
  20. data/lib/paypal/ipn.rb +23 -0
  21. data/lib/paypal/nvp/request.rb +66 -0
  22. data/lib/paypal/nvp/response.rb +237 -0
  23. data/lib/paypal/payment/common/amount.rb +13 -0
  24. data/lib/paypal/payment/recurring.rb +43 -0
  25. data/lib/paypal/payment/recurring/activation.rb +14 -0
  26. data/lib/paypal/payment/recurring/billing.rb +39 -0
  27. data/lib/paypal/payment/recurring/summary.rb +11 -0
  28. data/lib/paypal/payment/request.rb +67 -0
  29. data/lib/paypal/payment/request/item.rb +26 -0
  30. data/lib/paypal/payment/response.rb +75 -0
  31. data/lib/paypal/payment/response/address.rb +7 -0
  32. data/lib/paypal/payment/response/info.rb +45 -0
  33. data/lib/paypal/payment/response/item.rb +41 -0
  34. data/lib/paypal/payment/response/payee_info.rb +7 -0
  35. data/lib/paypal/payment/response/payer.rb +7 -0
  36. data/lib/paypal/payment/response/reference.rb +23 -0
  37. data/lib/paypal/payment/response/refund.rb +17 -0
  38. data/lib/paypal/payment/response/refund_info.rb +7 -0
  39. data/lib/paypal/util.rb +27 -0
  40. data/spec/fake_response/BillAgreementUpdate/fetch.txt +1 -0
  41. data/spec/fake_response/BillAgreementUpdate/revoke.txt +1 -0
  42. data/spec/fake_response/CreateBillingAgreement/success.txt +1 -0
  43. data/spec/fake_response/CreateRecurringPaymentsProfile/failure.txt +1 -0
  44. data/spec/fake_response/CreateRecurringPaymentsProfile/success.txt +1 -0
  45. data/spec/fake_response/DoCapture/failure.txt +1 -0
  46. data/spec/fake_response/DoCapture/success.txt +1 -0
  47. data/spec/fake_response/DoExpressCheckoutPayment/failure.txt +1 -0
  48. data/spec/fake_response/DoExpressCheckoutPayment/success.txt +1 -0
  49. data/spec/fake_response/DoExpressCheckoutPayment/success_with_billing_agreement.txt +1 -0
  50. data/spec/fake_response/DoExpressCheckoutPayment/success_with_many_items.txt +1 -0
  51. data/spec/fake_response/DoReferenceTransaction/failure.txt +1 -0
  52. data/spec/fake_response/DoReferenceTransaction/success.txt +1 -0
  53. data/spec/fake_response/DoVoid/success.txt +1 -0
  54. data/spec/fake_response/GetExpressCheckoutDetails/failure.txt +1 -0
  55. data/spec/fake_response/GetExpressCheckoutDetails/success.txt +1 -0
  56. data/spec/fake_response/GetExpressCheckoutDetails/with_billing_accepted_status.txt +1 -0
  57. data/spec/fake_response/GetRecurringPaymentsProfileDetails/failure.txt +1 -0
  58. data/spec/fake_response/GetRecurringPaymentsProfileDetails/success.txt +1 -0
  59. data/spec/fake_response/GetTransactionDetails/failure.txt +1 -0
  60. data/spec/fake_response/GetTransactionDetails/success.txt +1 -0
  61. data/spec/fake_response/IPN/invalid.txt +1 -0
  62. data/spec/fake_response/IPN/valid.txt +1 -0
  63. data/spec/fake_response/ManageRecurringPaymentsProfileStatus/failure.txt +1 -0
  64. data/spec/fake_response/ManageRecurringPaymentsProfileStatus/success.txt +1 -0
  65. data/spec/fake_response/RefundTransaction/full.txt +1 -0
  66. data/spec/fake_response/SetExpressCheckout/failure.txt +1 -0
  67. data/spec/fake_response/SetExpressCheckout/success.txt +1 -0
  68. data/spec/helpers/fake_response_helper.rb +29 -0
  69. data/spec/paypal/exception/api_error_spec.rb +105 -0
  70. data/spec/paypal/exception/http_error_spec.rb +20 -0
  71. data/spec/paypal/express/request_spec.rb +578 -0
  72. data/spec/paypal/express/response_spec.rb +89 -0
  73. data/spec/paypal/ipn_spec.rb +19 -0
  74. data/spec/paypal/nvp/request_spec.rb +113 -0
  75. data/spec/paypal/nvp/response_spec.rb +175 -0
  76. data/spec/paypal/payment/common/amount_spec.rb +36 -0
  77. data/spec/paypal/payment/recurring/activation_spec.rb +19 -0
  78. data/spec/paypal/payment/recurring_spec.rb +170 -0
  79. data/spec/paypal/payment/request/item_spec.rb +27 -0
  80. data/spec/paypal/payment/request_spec.rb +136 -0
  81. data/spec/paypal/payment/response/address_spec.rb +26 -0
  82. data/spec/paypal/payment/response/info_spec.rb +93 -0
  83. data/spec/paypal/payment/response/item_spec.rb +78 -0
  84. data/spec/paypal/payment/response/payee_info_spec.rb +24 -0
  85. data/spec/paypal/payment/response/payer_spec.rb +26 -0
  86. data/spec/paypal/payment/response/reference_info_spec.rb +36 -0
  87. data/spec/paypal/payment/response/refund_info_spec.rb +18 -0
  88. data/spec/paypal/payment/response/refund_spec.rb +28 -0
  89. data/spec/paypal/payment/response_spec.rb +29 -0
  90. data/spec/paypal/util_spec.rb +32 -0
  91. data/spec/spec_helper.rb +25 -0
  92. metadata +319 -0
@@ -0,0 +1 @@
1
+ ADDRESSOWNER=PayPal&ADDRESSSTATUS=None&TIMESTAMP=2012%2d02%2d23T21%3a07%3a22Z&CORRELATIONID=4e18d75a23953&ACK=Failure&VERSION=78%2e0&BUILD=2571254&L_ERRORCODE0=10004&L_SHORTMESSAGE0=Transaction%20refused%20because%20of%20an%20invalid%20argument%2e%20See%20additional%20error%20messages%20for%20details%2e&L_LONGMESSAGE0=The%20transaction%20id%20is%20not%20valid&L_SEVERITYCODE0=Error&PENDINGREASON=None&REASONCODE=None
@@ -0,0 +1 @@
1
+ RECEIVEREMAIL=test%40email%2ecom&RECEIVERID=ABCDEFG12345&EMAIL=test%40email%2ecom&PAYERID=12345ABCDEFG&PAYERSTATUS=verified&COUNTRYCODE=US&SHIPTONAME=Billy%20Bob&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United%20States&SHIPTOZIP=95131&ADDRESSOWNER=PayPal&ADDRESSSTATUS=Confirmed&SALESTAX=0%2e00&SUBJECT=Test%20Subject&TIMESTAMP=2012%2d02%2d23T20%3a51%3a29Z&CORRELATIONID=4fc0a06cbaec7&ACK=Success&VERSION=78%2e0&BUILD=2571254&FIRSTNAME=Billy&LASTNAME=Bob&TRANSACTIONID=123456789ABCD&TRANSACTIONTYPE=cart&PAYMENTTYPE=instant&ORDERTIME=2012%2d02%2d13T23%3a09%3a46Z&AMT=740%2e43&FEEAMT=21%2e77&TAXAMT=0%2e00&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&CURRENCYCODE=USD&PAYMENTSTATUS=Completed&PENDINGREASON=None&REASONCODE=None&PROTECTIONELIGIBILITY=Eligible&PROTECTIONELIGIBILITYTYPE=ItemNotReceivedEligible%2cUnauthorizedPaymentEligible&L_NAME0=Item%201&L_NAME1=Item%202&L_QTY0=1&L_QTY1=1&L_SHIPPINGAMT0=0%2e00&L_SHIPPINGAMT1=0%2e00&L_HANDLINGAMT0=0%2e00&L_HANDLINGAMT1=0%2e00&L_CURRENCYCODE0=USD&L_CURRENCYCODE1=USD&L_AMT0=687%2e93&L_AMT1=52%2e50
@@ -0,0 +1 @@
1
+ INVALID
@@ -0,0 +1 @@
1
+ VERIFIED
@@ -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
+ REFUNDTRANSACTIONID=6D456341FS516215S&FEEREFUNDAMT=0%2e50&GROSSREFUNDAMT=10%2e00&NETREFUNDAMT=9%2e50&CURRENCYCODE=USD&TOTALREFUNDEDAMOUNT=10%2e00&TIMESTAMP=2011%2d05%2d21T14%3a13%3a32Z&CORRELATIONID=862bfc523cca2&ACK=Success&VERSION=204%2e0&BUILD=1882144&REFUNDSTATUS=Instant
@@ -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,29 @@
1
+ require 'webmock/rspec'
2
+
3
+ module FakeResponseHelper
4
+
5
+ def fake_response(file_path, api = :NVP)
6
+ endpoint = case api
7
+ when :NVP
8
+ Paypal::NVP::Request.endpoint
9
+ when :IPN
10
+ Paypal::IPN.endpoint
11
+ else
12
+ raise "Non-supported API: #{api}"
13
+ end
14
+ stub_request(:post, endpoint)
15
+ .to_return(
16
+ body: File.read(File.join(File.dirname(__FILE__), '../fake_response', "#{file_path}.txt"))
17
+ )
18
+ end
19
+
20
+ def request_to(endpoint, method = :get)
21
+ raise_error(
22
+ WebMock::NetConnectNotAllowedError,
23
+ /Real HTTP connections are disabled. Unregistered request: #{method.to_s.upcase} #{endpoint}/
24
+ )
25
+ end
26
+
27
+ end
28
+
29
+ include FakeResponseHelper
@@ -0,0 +1,105 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Paypal::Exception::APIError do
4
+ let(:error) { Paypal::Exception::APIError.new(params) }
5
+
6
+ context 'when Hash is given' do
7
+ let :params do
8
+ {
9
+ :VERSION=>"66.0",
10
+ :TIMESTAMP=>"2011-03-03T06:33:51Z",
11
+ :CORRELATIONID=>"758ebdc546b9c",
12
+ :BUILD=>"1741654",
13
+ :ACK=>"Failure",
14
+ :L_SEVERITYCODE0=>"Error",
15
+ :L_ERRORCODE0=>"10411",
16
+ :L_LONGMESSAGE0=>"This Express Checkout session has expired. Token value is no longer valid.",
17
+ :L_SHORTMESSAGE0=>"This Express Checkout session has expired.",
18
+ :L_SEVERITYCODE1=>"Error",
19
+ :L_ERRORCODE1=>"2468",
20
+ :L_LONGMESSAGE1=>"Sample of a long message for the second item.",
21
+ :L_SHORTMESSAGE1=>"Second short message.",
22
+ }
23
+ end
24
+
25
+ describe "#message" do
26
+ it "aggregates short messages" do
27
+ expect(error.message).to eq(
28
+ "PayPal API Error: 'This Express Checkout session has expired.', 'Second short message.'"
29
+ )
30
+ end
31
+ end
32
+
33
+ describe '#subject' do
34
+ subject { error.response }
35
+
36
+ describe '#raw' do
37
+ subject { super().raw }
38
+ it { is_expected.to eq(params) }
39
+ end
40
+ Paypal::Exception::APIError::Response.attribute_mapping.each do |key, attribute|
41
+ describe attribute do
42
+ subject { super().send(attribute) }
43
+ it { is_expected.to eq(params[key]) }
44
+ end
45
+ end
46
+
47
+ describe '#details' do
48
+ subject { error.response.details.first }
49
+ Paypal::Exception::APIError::Response::Detail.attribute_mapping.each do |key, attribute|
50
+ describe attribute do
51
+ subject { super().send(attribute) }
52
+ it { is_expected.to eq(params[:"L_#{key}0"]) }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ context 'when unknown params given' do
60
+ let :params do
61
+ {
62
+ :UNKNOWN => 'Unknown',
63
+ :L_UNKNOWN0 => 'Unknown Detail'
64
+ }
65
+ end
66
+
67
+ it 'should warn' do
68
+ expect(Paypal.logger).to receive(:warn).with(
69
+ "Ignored Parameter (Paypal::Exception::APIError::Response): UNKNOWN=Unknown"
70
+ )
71
+ expect(Paypal.logger).to receive(:warn).with(
72
+ "Ignored Parameter (Paypal::Exception::APIError::Response::Detail): UNKNOWN=Unknown Detail"
73
+ )
74
+ error
75
+ end
76
+ describe '#response' do
77
+ subject { error.response }
78
+
79
+ describe '#raw' do
80
+ subject { super().raw }
81
+ it { is_expected.to eq(params) }
82
+ end
83
+ end
84
+
85
+ describe '#message' do
86
+ subject { super().message }
87
+ it { is_expected.to eq("PayPal API Error") }
88
+ end
89
+ end
90
+
91
+ context 'otherwise' do
92
+ subject { error }
93
+ let(:params) { 'Failure' }
94
+
95
+ describe '#response' do
96
+ subject { super().response }
97
+ it { is_expected.to eq(params) }
98
+ end
99
+
100
+ describe '#message' do
101
+ subject { super().message }
102
+ it { is_expected.to eq("PayPal API Error") }
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Paypal::Exception::HttpError do
4
+ subject { Paypal::Exception::HttpError.new(400, 'BadRequest', 'You are bad man!') }
5
+
6
+ describe '#code' do
7
+ subject { super().code }
8
+ it { is_expected.to eq(400) }
9
+ end
10
+
11
+ describe '#message' do
12
+ subject { super().message }
13
+ it { is_expected.to eq('BadRequest') }
14
+ end
15
+
16
+ describe '#body' do
17
+ subject { super().body }
18
+ it { is_expected.to eq('You are bad man!') }
19
+ end
20
+ end
@@ -0,0 +1,578 @@
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(:return_url) { 'http://example.com/success' }
15
+ let(:cancel_url) { 'http://example.com/cancel' }
16
+ let(:nvp_endpoint) { Paypal::NVP::Request::ENDPOINT[:production] }
17
+ let :attributes do
18
+ {
19
+ :username => 'nov',
20
+ :password => 'password',
21
+ :signature => 'sig'
22
+ }
23
+ end
24
+
25
+ let :instance do
26
+ Paypal::Express::Request.new attributes
27
+ end
28
+
29
+ let :instant_payment_request do
30
+ Paypal::Payment::Request.new(
31
+ :amount => 1000,
32
+ :description => 'Instant Payment Request'
33
+ )
34
+ end
35
+
36
+ let :many_items do
37
+ items = Array.new
38
+ (1..20).each do |index|
39
+ items << Paypal::Payment::Request::Item.new(
40
+ :name => "Item#{index.to_s}",
41
+ :description => "A new Item #{index.to_s}",
42
+ :amount => 50.00,
43
+ :quantity => 1
44
+ )
45
+ end
46
+ end
47
+
48
+ let :instant_payment_request_with_many_items do
49
+ Paypal::Payment::Request.new(
50
+ :amount => 1000,
51
+ :description => 'Instant Payment Request',
52
+ :items => many_items
53
+ )
54
+ end
55
+
56
+ let :recurring_payment_request do
57
+ Paypal::Payment::Request.new(
58
+ :billing_type => :RecurringPayments,
59
+ :billing_agreement_description => 'Recurring Payment Request'
60
+ )
61
+ end
62
+
63
+ let :recurring_profile do
64
+ Paypal::Payment::Recurring.new(
65
+ :start_date => Time.utc(2011, 2, 8, 9, 0, 0),
66
+ :description => 'Recurring Profile',
67
+ :billing => {
68
+ :period => :Month,
69
+ :frequency => 1,
70
+ :amount => 1000
71
+ }
72
+ )
73
+ end
74
+
75
+ let :reference_transaction_request do
76
+ Paypal::Payment::Request.new(
77
+ :billing_type => :MerchantInitiatedBilling,
78
+ :billing_agreement_description => 'Billing Agreement Request'
79
+ )
80
+ end
81
+
82
+ describe '.new' do
83
+ context 'when any required parameters are missing' do
84
+ it 'should raise AttrRequired::AttrMissing' do
85
+ attributes.keys.each do |missing_key|
86
+ insufficient_attributes = attributes.reject do |key, value|
87
+ key == missing_key
88
+ end
89
+ expect do
90
+ Paypal::Express::Request.new insufficient_attributes
91
+ end.to raise_error AttrRequired::AttrMissing
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'when all required parameters are given' do
97
+ it 'should succeed' do
98
+ expect do
99
+ Paypal::Express::Request.new attributes
100
+ end.not_to raise_error
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#setup' do
106
+ it 'should return Paypal::Express::Response' do
107
+ fake_response 'SetExpressCheckout/success'
108
+ response = instance.setup recurring_payment_request, return_url, cancel_url
109
+ expect(response).to be_instance_of Paypal::Express::Response
110
+ end
111
+
112
+ it 'should support no_shipping option' do
113
+ expect do
114
+ instance.setup instant_payment_request, return_url, cancel_url, :no_shipping => true
115
+ end.to request_to nvp_endpoint, :post
116
+ expect(instance._method_).to eq(:SetExpressCheckout)
117
+ expect(instance._sent_params_).to eq({
118
+ :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
119
+ :RETURNURL => return_url,
120
+ :CANCELURL => cancel_url,
121
+ :PAYMENTREQUEST_0_AMT => '1000.00',
122
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
123
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00",
124
+ :REQCONFIRMSHIPPING => 0,
125
+ :NOSHIPPING => 1
126
+ })
127
+ end
128
+
129
+ it 'should support allow_note=false option' do
130
+ expect do
131
+ instance.setup instant_payment_request, return_url, cancel_url, :allow_note => false
132
+ end.to request_to nvp_endpoint, :post
133
+ expect(instance._method_).to eq(:SetExpressCheckout)
134
+ expect(instance._sent_params_).to eq({
135
+ :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
136
+ :RETURNURL => return_url,
137
+ :CANCELURL => cancel_url,
138
+ :PAYMENTREQUEST_0_AMT => '1000.00',
139
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
140
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00",
141
+ :ALLOWNOTE => 0
142
+ })
143
+ end
144
+
145
+ {
146
+ :solution_type => :SOLUTIONTYPE,
147
+ :landing_page => :LANDINGPAGE,
148
+ :email => :EMAIL,
149
+ :brand => :BRANDNAME,
150
+ :locale => :LOCALECODE,
151
+ :logo => :LOGOIMG,
152
+ :cart_border_color => :CARTBORDERCOLOR,
153
+ :payflow_color => :PAYFLOWCOLOR
154
+ }.each do |option_key, param_key|
155
+ it "should support #{option_key} option" do
156
+ expect do
157
+ instance.setup instant_payment_request, return_url, cancel_url, option_key => 'some value'
158
+ end.to request_to nvp_endpoint, :post
159
+ expect(instance._method_).to eq(:SetExpressCheckout)
160
+ expect(instance._sent_params_).to include param_key
161
+ expect(instance._sent_params_[param_key]).to eq('some value')
162
+ end
163
+ end
164
+
165
+ context 'when instance payment request given' do
166
+ it 'should call SetExpressCheckout' do
167
+ expect do
168
+ instance.setup instant_payment_request, return_url, cancel_url
169
+ end.to request_to nvp_endpoint, :post
170
+ expect(instance._method_).to eq(:SetExpressCheckout)
171
+ expect(instance._sent_params_).to eq({
172
+ :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
173
+ :RETURNURL => return_url,
174
+ :CANCELURL => cancel_url,
175
+ :PAYMENTREQUEST_0_AMT => '1000.00',
176
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
177
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00"
178
+ })
179
+ end
180
+ end
181
+
182
+ context 'when recurring payment request given' do
183
+ it 'should call SetExpressCheckout' do
184
+ expect do
185
+ instance.setup recurring_payment_request, return_url, cancel_url
186
+ end.to request_to nvp_endpoint, :post
187
+ expect(instance._method_).to eq(:SetExpressCheckout)
188
+ expect(instance._sent_params_).to eq({
189
+ :L_BILLINGTYPE0 => :RecurringPayments,
190
+ :L_BILLINGAGREEMENTDESCRIPTION0 => 'Recurring Payment Request',
191
+ :RETURNURL => return_url,
192
+ :CANCELURL => cancel_url,
193
+ :PAYMENTREQUEST_0_AMT => '0.00',
194
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
195
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00"
196
+ })
197
+ end
198
+ end
199
+
200
+ context 'when reference transaction request given' do
201
+ it 'should call SetExpressCheckout' do
202
+ expect do
203
+ instance.setup reference_transaction_request, return_url, cancel_url
204
+ end.to request_to nvp_endpoint, :post
205
+ expect(instance._method_).to eq(:SetExpressCheckout)
206
+ expect(instance._sent_params_).to eq({
207
+ :L_BILLINGTYPE0 => :MerchantInitiatedBilling,
208
+ :L_BILLINGAGREEMENTDESCRIPTION0 => 'Billing Agreement Request',
209
+ :RETURNURL => return_url,
210
+ :CANCELURL => cancel_url,
211
+ :PAYMENTREQUEST_0_AMT => '0.00',
212
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
213
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00"
214
+ })
215
+ end
216
+ end
217
+ end
218
+
219
+ describe '#details' do
220
+ it 'should return Paypal::Express::Response' do
221
+ fake_response 'GetExpressCheckoutDetails/success'
222
+ response = instance.details 'token'
223
+ expect(response).to be_instance_of Paypal::Express::Response
224
+ end
225
+
226
+ it 'should call GetExpressCheckoutDetails' do
227
+ expect do
228
+ instance.details 'token'
229
+ end.to request_to nvp_endpoint, :post
230
+ expect(instance._method_).to eq(:GetExpressCheckoutDetails)
231
+ expect(instance._sent_params_).to eq({ TOKEN: 'token' })
232
+ end
233
+ end
234
+
235
+ describe '#transaction_details' do
236
+ it 'should return Paypal::Express::Response' do
237
+ fake_response 'GetTransactionDetails/success'
238
+ response = instance.transaction_details 'transaction_id'
239
+ expect(response).to be_instance_of Paypal::Express::Response
240
+ end
241
+
242
+ it 'should call GetTransactionDetails' do
243
+ expect do
244
+ instance.transaction_details 'transaction_id'
245
+ end.to request_to nvp_endpoint, :post
246
+ expect(instance._method_).to eq(:GetTransactionDetails)
247
+ expect(instance._sent_params_).to eq({
248
+ :TRANSACTIONID=> 'transaction_id'
249
+ })
250
+ end
251
+
252
+ it 'should fail with bad transaction id' do
253
+ expect do
254
+ fake_response 'GetTransactionDetails/failure'
255
+ response = instance.transaction_details 'bad_transaction_id'
256
+ end.to raise_error(Paypal::Exception::APIError)
257
+ end
258
+
259
+ it 'should handle all attributes' do
260
+ expect(Paypal.logger).not_to receive(:warn)
261
+ fake_response 'GetTransactionDetails/success'
262
+ response = instance.transaction_details 'transaction_id'
263
+ end
264
+ end
265
+
266
+ describe "#capture!" do
267
+ it 'should return Paypal::Express::Response' do
268
+ fake_response 'DoCapture/success'
269
+ response = instance.capture! 'authorization_id', 181.98, :BRL
270
+ expect(response).to be_instance_of Paypal::Express::Response
271
+ end
272
+
273
+ it 'should call DoExpressCheckoutPayment' do
274
+ expect do
275
+ instance.capture! 'authorization_id', 181.98, :BRL
276
+ end.to request_to nvp_endpoint, :post
277
+
278
+ expect(instance._method_).to eq(:DoCapture)
279
+ expect(instance._sent_params_).to eq({
280
+ :AUTHORIZATIONID => 'authorization_id',
281
+ :COMPLETETYPE => 'Complete',
282
+ :AMT => 181.98,
283
+ :CURRENCYCODE => :BRL
284
+ })
285
+ end
286
+
287
+ it 'should call DoExpressCheckoutPayment with NotComplete capture parameter' do
288
+ expect do
289
+ instance.capture! 'authorization_id', 181.98, :BRL, 'NotComplete'
290
+ end.to request_to nvp_endpoint, :post
291
+
292
+ expect(instance._method_).to eq(:DoCapture)
293
+ expect(instance._sent_params_).to eq({
294
+ :AUTHORIZATIONID => 'authorization_id',
295
+ :COMPLETETYPE => 'NotComplete',
296
+ :AMT => 181.98,
297
+ :CURRENCYCODE => :BRL
298
+ })
299
+ end
300
+ end
301
+
302
+ describe "#void!" do
303
+ it 'should return Paypal::Express::Response' do
304
+ fake_response 'DoVoid/success'
305
+ response = instance.void! 'authorization_id', note: "note"
306
+ expect(response).to be_instance_of Paypal::Express::Response
307
+ end
308
+
309
+ it 'should call DoVoid' do
310
+ expect do
311
+ instance.void! 'authorization_id', note: "note"
312
+ end.to request_to nvp_endpoint, :post
313
+
314
+ expect(instance._method_).to eq(:DoVoid)
315
+ expect(instance._sent_params_).to eq({
316
+ :AUTHORIZATIONID => 'authorization_id',
317
+ :NOTE => "note"
318
+ })
319
+ end
320
+ end
321
+
322
+ describe '#checkout!' do
323
+ it 'should return Paypal::Express::Response' do
324
+ fake_response 'DoExpressCheckoutPayment/success'
325
+ response = instance.checkout! 'token', 'payer_id', instant_payment_request
326
+ expect(response).to be_instance_of Paypal::Express::Response
327
+ end
328
+
329
+ it 'should call DoExpressCheckoutPayment' do
330
+ expect do
331
+ instance.checkout! 'token', 'payer_id', instant_payment_request
332
+ end.to request_to nvp_endpoint, :post
333
+ expect(instance._method_).to eq(:DoExpressCheckoutPayment)
334
+ expect(instance._sent_params_).to eq({
335
+ :PAYERID => 'payer_id',
336
+ :TOKEN => 'token',
337
+ :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',
338
+ :PAYMENTREQUEST_0_AMT => '1000.00',
339
+ :PAYMENTREQUEST_0_TAXAMT => "0.00",
340
+ :PAYMENTREQUEST_0_SHIPPINGAMT => "0.00"
341
+ })
342
+ end
343
+
344
+ context "with many items" do
345
+ before do
346
+ fake_response 'DoExpressCheckoutPayment/success_with_many_items'
347
+ end
348
+
349
+ it 'should handle all attributes' do
350
+ expect(Paypal.logger).not_to receive(:warn)
351
+ response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items
352
+ end
353
+
354
+ it 'should return Paypal::Express::Response' do
355
+ response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items
356
+ expect(response).to be_instance_of Paypal::Express::Response
357
+ end
358
+
359
+ it 'should return twenty items' do
360
+ response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items
361
+ expect(instance._method_).to eq(:DoExpressCheckoutPayment)
362
+ expect(response.items.count).to eq(20)
363
+ end
364
+ end
365
+ end
366
+
367
+ describe '#subscribe!' do
368
+ it 'should return Paypal::Express::Response' do
369
+ fake_response 'CreateRecurringPaymentsProfile/success'
370
+ response = instance.subscribe! 'token', recurring_profile
371
+ expect(response).to be_instance_of Paypal::Express::Response
372
+ end
373
+
374
+ it 'should call CreateRecurringPaymentsProfile' do
375
+ expect do
376
+ instance.subscribe! 'token', recurring_profile
377
+ end.to request_to nvp_endpoint, :post
378
+ expect(instance._method_).to eq(:CreateRecurringPaymentsProfile)
379
+ expect(instance._sent_params_).to eq({
380
+ :DESC => 'Recurring Profile',
381
+ :TOKEN => 'token',
382
+ :SHIPPINGAMT => '0.00',
383
+ :AMT => '1000.00',
384
+ :BILLINGFREQUENCY => 1,
385
+ :MAXFAILEDPAYMENTS => 0,
386
+ :BILLINGPERIOD => :Month,
387
+ :TAXAMT => '0.00',
388
+ :PROFILESTARTDATE => '2011-02-08 09:00:00',
389
+ :TOTALBILLINGCYCLES => 0
390
+ })
391
+ end
392
+ end
393
+
394
+ describe '#subscription' do
395
+ it 'should return Paypal::Express::Response' do
396
+ fake_response 'GetRecurringPaymentsProfileDetails/success'
397
+ response = instance.subscription 'profile_id'
398
+ expect(response).to be_instance_of(Paypal::Express::Response)
399
+ end
400
+
401
+ it 'should call GetRecurringPaymentsProfileDetails' do
402
+ expect do
403
+ instance.subscription 'profile_id'
404
+ end.to request_to nvp_endpoint, :post
405
+ expect(instance._method_).to eq(:GetRecurringPaymentsProfileDetails)
406
+ expect(instance._sent_params_).to eq({ PROFILEID: 'profile_id' })
407
+ end
408
+ end
409
+
410
+ describe '#renew!' do
411
+ it 'should return Paypal::Express::Response' do
412
+ fake_response 'ManageRecurringPaymentsProfileStatus/success'
413
+ response = instance.renew! 'profile_id', :Cancel
414
+ expect(response).to be_instance_of Paypal::Express::Response
415
+ end
416
+
417
+ it 'should call ManageRecurringPaymentsProfileStatus' do
418
+ expect do
419
+ instance.renew! 'profile_id', :Cancel
420
+ end.to request_to nvp_endpoint, :post
421
+ expect(instance._method_).to eq(:ManageRecurringPaymentsProfileStatus)
422
+ expect(instance._sent_params_).to eq({
423
+ :ACTION => :Cancel,
424
+ :PROFILEID => 'profile_id'
425
+ })
426
+ end
427
+ end
428
+
429
+ describe '#cancel!' do
430
+ it 'should return Paypal::Express::Response' do
431
+ fake_response 'ManageRecurringPaymentsProfileStatus/success'
432
+ response = instance.cancel! 'profile_id'
433
+ expect(response).to be_instance_of(Paypal::Express::Response)
434
+ end
435
+
436
+ it 'should call ManageRecurringPaymentsProfileStatus' do
437
+ expect do
438
+ instance.cancel! 'profile_id'
439
+ end.to request_to nvp_endpoint, :post
440
+ expect(instance._method_).to eq(:ManageRecurringPaymentsProfileStatus)
441
+ expect(instance._sent_params_).to eq({
442
+ :ACTION => :Cancel,
443
+ :PROFILEID => 'profile_id'
444
+ })
445
+ end
446
+ end
447
+
448
+ describe '#suspend!' do
449
+ it 'should return Paypal::Express::Response' do
450
+ fake_response 'ManageRecurringPaymentsProfileStatus/success'
451
+ response = instance.cancel! 'profile_id'
452
+ expect(response).to be_instance_of Paypal::Express::Response
453
+ end
454
+
455
+ it 'should call ManageRecurringPaymentsProfileStatus' do
456
+ expect do
457
+ instance.suspend! 'profile_id'
458
+ end.to request_to nvp_endpoint, :post
459
+ expect(instance._method_).to eq(:ManageRecurringPaymentsProfileStatus)
460
+ expect(instance._sent_params_).to eq({
461
+ :ACTION => :Suspend,
462
+ :PROFILEID => 'profile_id'
463
+ })
464
+ end
465
+ end
466
+
467
+ describe '#reactivate!' do
468
+ it 'should return Paypal::Express::Response' do
469
+ fake_response 'ManageRecurringPaymentsProfileStatus/success'
470
+ response = instance.cancel! 'profile_id'
471
+ expect(response).to be_instance_of Paypal::Express::Response
472
+ end
473
+
474
+ it 'should call ManageRecurringPaymentsProfileStatus' do
475
+ expect do
476
+ instance.reactivate! 'profile_id'
477
+ end.to request_to nvp_endpoint, :post
478
+ expect(instance._method_).to eq(:ManageRecurringPaymentsProfileStatus)
479
+ expect(instance._sent_params_).to eq({
480
+ :ACTION => :Reactivate,
481
+ :PROFILEID => 'profile_id'
482
+ })
483
+ end
484
+ end
485
+
486
+ describe '#agree!' do
487
+ it 'should return Paypal::Express::Response' do
488
+ fake_response 'CreateBillingAgreement/success'
489
+ response = instance.agree! 'token'
490
+ expect(response).to be_instance_of Paypal::Express::Response
491
+ end
492
+
493
+ it 'should call CreateBillingAgreement' do
494
+ expect do
495
+ instance.agree! 'token'
496
+ end.to request_to nvp_endpoint, :post
497
+ expect(instance._method_).to eq(:CreateBillingAgreement)
498
+ expect(instance._sent_params_).to eq({ TOKEN: 'token' })
499
+ end
500
+ end
501
+
502
+ describe '#agreement' do
503
+ it 'should return Paypal::Express::Response' do
504
+ fake_response 'BillAgreementUpdate/fetch'
505
+ response = instance.agreement 'reference_id'
506
+ expect(response).to be_instance_of Paypal::Express::Response
507
+ end
508
+
509
+ it 'should call BillAgreementUpdate' do
510
+ expect do
511
+ instance.agreement 'reference_id'
512
+ end.to request_to nvp_endpoint, :post
513
+ expect(instance._method_).to eq(:BillAgreementUpdate)
514
+ expect(instance._sent_params_).to eq({
515
+ :REFERENCEID => 'reference_id'
516
+ })
517
+ end
518
+ end
519
+
520
+ describe '#charge!' do
521
+ it 'should return Paypal::Express::Response' do
522
+ fake_response 'DoReferenceTransaction/success'
523
+ response = instance.charge! 'billing_agreement_id', 1000
524
+ expect(response).to be_instance_of Paypal::Express::Response
525
+ end
526
+
527
+ it 'should call DoReferenceTransaction' do
528
+ expect do
529
+ instance.charge! 'billing_agreement_id', 1000, :currency_code => :JPY
530
+ end.to request_to nvp_endpoint, :post
531
+ expect(instance._method_).to eq(:DoReferenceTransaction)
532
+ expect(instance._sent_params_).to eq({
533
+ :REFERENCEID => 'billing_agreement_id',
534
+ :AMT => '1000.00',
535
+ :PAYMENTACTION => :Sale,
536
+ :CURRENCYCODE => :JPY
537
+ })
538
+ end
539
+ end
540
+
541
+ describe '#revoke!' do
542
+ it 'should return Paypal::Express::Response' do
543
+ fake_response 'BillAgreementUpdate/revoke'
544
+ response = instance.revoke! 'reference_id'
545
+ expect(response).to be_instance_of Paypal::Express::Response
546
+ end
547
+
548
+ it 'should call BillAgreementUpdate' do
549
+ expect do
550
+ instance.revoke! 'reference_id'
551
+ end.to request_to nvp_endpoint, :post
552
+ expect(instance._method_).to eq(:BillAgreementUpdate)
553
+ expect(instance._sent_params_).to eq({
554
+ :REFERENCEID => 'reference_id',
555
+ :BillingAgreementStatus => :Canceled
556
+ })
557
+ end
558
+ end
559
+
560
+ describe '#refund!' do
561
+ it 'should return Paypal::Express::Response' do
562
+ fake_response 'RefundTransaction/full'
563
+ response = instance.refund! 'transaction_id'
564
+ expect(response).to be_instance_of Paypal::Express::Response
565
+ end
566
+
567
+ it 'should call RefundTransaction' do
568
+ expect do
569
+ instance.refund! 'transaction_id'
570
+ end.to request_to nvp_endpoint, :post
571
+ expect(instance._method_).to eq(:RefundTransaction)
572
+ expect(instance._sent_params_).to eq({
573
+ :TRANSACTIONID => 'transaction_id',
574
+ :REFUNDTYPE => :Full
575
+ })
576
+ end
577
+ end
578
+ end