ianfleeton-paypal-express 0.8.2

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.
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