paypal-masspay 1.1.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.
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Envato
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,85 @@
1
+ # Paypal::Masspay
2
+
3
+ Paypal::Masspay is a Ruby library that uses PayPals MassPay API to send Mass Payments.
4
+
5
+ The MassPay API provides a SOAP and NVP (Name-Value Pair) interface, however this library uses the NVP interface exclusively.
6
+
7
+ You can read more about PayPals MassPay API at the following link: [PayPal MassPay API Documentationn](https://developer.paypal.com/docs/classic/mass-pay/integration-guide/MassPayUsingAPI/)
8
+
9
+ A introduction about PayPals NVP interface in general can be found here: [PayPal NVP API Overview](https://developer.paypal.com/docs/classic/api/NVPAPIOverview/)
10
+
11
+ ## Usage
12
+
13
+ In a nutshell the Paypal::Masspay library lets you send multiple payments at once using the following schema:
14
+
15
+ ``` ruby
16
+ Paypal::Masspay::Configuration.configure do |config|
17
+ config.environment = :production
18
+ config.username = 'your_paypal_username'
19
+ config.password = 'your_paypal_password'
20
+ config.signature = 'your_paypal_signature'
21
+ end
22
+
23
+ masspay = Paypal::Masspay.new(:currency => 'USD') do |bucket|
24
+ bucket.add_recipient(Paypal::Masspay::Recipient.new(:recipient_email => 'chunky@example.com', :amount => 10.00, :unique_id => 1234, :note => 'hello'))
25
+ bucket.add_recipient(Paypal::Masspay::Recipient.new(:recipient_email => 'bacon@example.com', :amount => 2.95, :unique_id => 222))
26
+ end
27
+
28
+ masspay.deliver
29
+ ```
30
+
31
+ It also supports being used like this:
32
+ ``` ruby
33
+ Paypal::Masspay::Configuration.configure do |config|
34
+ config.environment = :production
35
+ config.username = 'your_paypal_username'
36
+ config.password = 'your_paypal_password'
37
+ config.signature = 'your_paypal_signature'
38
+ end
39
+
40
+ recipients = [
41
+ Paypal::Masspay::Recipient.new(
42
+ :recipient_email => 'chunky@example.com',
43
+ :amount => 10.00,
44
+ :unique_id => 1234,
45
+ :note => 'hello'),
46
+ Paypal::Masspay::Recipient.new(
47
+ :recipient_email => 'bacon@example.com',
48
+ :amount => 2.95,
49
+ :unique_id => 222)
50
+ ]
51
+
52
+ masspay = Paypal::Masspay.new(:currency => 'USD', :recipients => recipients)
53
+
54
+ masspay.deliver
55
+ ```
56
+
57
+ This sends a post request to the PayPal NVP API endpoint containing the following data:
58
+
59
+ ```
60
+ USER=your_paypal_username&
61
+ PWD=your_paypal_password&
62
+ SIGNATURE=your_paypal_signature&
63
+ VERSION=2.3&
64
+ METHOD=MassPay&
65
+ RECEIVERTYPE=EmailAddress&
66
+ L_EMAIL0=chunky@example.com&
67
+ L_AMT0=10.00&
68
+ L_UNIQUEID0=1234&
69
+ L_NOTE0=hello&
70
+ L_EMAIL1=bacon@example.com&
71
+ L_AMT1=2.95&
72
+ L_UNIQUEID1=222&
73
+ CURRENCYCODE=USD
74
+ ```
75
+
76
+ You are also able to check whether or not the request was successfully sent to paypal, and can check any returned error/warnings using the following code:
77
+
78
+ ``` ruby
79
+ masspay.successful? # ===> true/false
80
+
81
+ masspay.errors # ===> [ <Paypal::Masspay::Error>, <Paypal::Masspay::Error>, ... ]
82
+ masspay.errors[0].methods # ===> [ :code, :short_message, :long_message, :severity ]
83
+ masspay.errors[0].code # ===> 10000
84
+ masspay.errors[0].short_message # ===> "insufficient funds"
85
+ ```
@@ -0,0 +1,19 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ begin
7
+ require 'cane'
8
+ require 'cane/rake_task'
9
+
10
+ desc "Run cane to check quality metrics"
11
+ Cane::RakeTask.new(:quality) do |cane|
12
+ cane.no_style = true
13
+ cane.no_doc = true
14
+ end
15
+ rescue LoadError
16
+ warn "cane not available, quality task not provided."
17
+ end
18
+
19
+ task :default => [ :quality, :spec ]
@@ -0,0 +1,131 @@
1
+ require 'paypal/masspay/version'
2
+ require 'paypal/masspay/response_parser'
3
+ require 'paypal/masspay/recipient'
4
+ require 'paypal/masspay/length_validator'
5
+ require 'paypal/masspay/configuration'
6
+
7
+ require 'faraday'
8
+ require 'ostruct'
9
+
10
+ module Paypal
11
+ class Masspay
12
+ SANDBOX_API_URL = 'https://api-3t.sandbox.paypal.com'
13
+ PRODUCTION_API_URL = 'https://api-3t.paypal.com'
14
+ API_PATH = '/nvp'
15
+ API_VERSION = '2.3'
16
+ IDENTIFIER = 'EmailAddress'
17
+ METHOD = 'MassPay'
18
+ MAX_PER_REQUEST = 250
19
+
20
+ DEFAULT_CURRENCY = 'USD'
21
+ DEFAULT_SUBJECT = 'Paypal Masspay'
22
+
23
+ CURRENCY_MAX_LENGTH = 3
24
+ SUBJECT_MAX_LENGTH = 255
25
+
26
+ attr_reader :errors
27
+
28
+ def initialize(options = {}, &block)
29
+ build_options(options)
30
+
31
+ @success = true
32
+ @delivered = false
33
+ @errors = []
34
+
35
+ yield(self) if block_given?
36
+ end
37
+
38
+ def add_recipient(recipient)
39
+ @recipients << recipient
40
+ end
41
+
42
+ def deliver
43
+ validate
44
+
45
+ connection = create_connection
46
+
47
+ @recipients.each_slice(MAX_PER_REQUEST) do |recipients_slice|
48
+ response = connection.post(API_PATH, request_data(recipients_slice))
49
+ check_response(response)
50
+ end
51
+
52
+ @delivered = true
53
+ end
54
+
55
+ def successful?
56
+ @success
57
+ end
58
+
59
+ def delivered?
60
+ @delivered
61
+ end
62
+
63
+ private
64
+
65
+ def validate
66
+ Paypal::Masspay::LengthValidator.validate(@currency, CURRENCY_MAX_LENGTH, :currency)
67
+ Paypal::Masspay::LengthValidator.validate(@subject, SUBJECT_MAX_LENGTH, :subject)
68
+ end
69
+
70
+ def create_connection
71
+ Faraday.new(:url => api_url) do |con|
72
+ con.use(Faraday::Request::UrlEncoded)
73
+ con.use(Faraday::Adapter::NetHttp)
74
+ end
75
+ end
76
+
77
+ def api_url
78
+ if Paypal::Masspay::Configuration.environment == :production
79
+ PRODUCTION_API_URL
80
+ else
81
+ SANDBOX_API_URL
82
+ end
83
+ end
84
+
85
+ def check_response(response)
86
+ response = Paypal::Masspay::ResponseParser.new(response.body)
87
+ if response.successful?
88
+ @success = true && @success
89
+ else
90
+ @success = false
91
+ @errors.concat(response.errors)
92
+ end
93
+ end
94
+
95
+ def request_data(recipients)
96
+ (default_options.merge(credentials).merge(build_payments(recipients))).delete_if { |k, v| v.nil? }
97
+ end
98
+
99
+ def build_options(options)
100
+ @recipients = options[:recipients] || []
101
+ @currency = options[:currency] || DEFAULT_CURRENCY
102
+ @subject = options[:subject] || DEFAULT_SUBJECT
103
+ end
104
+
105
+ def build_payments(recipients)
106
+ Hash.new({}).tap do |output|
107
+ recipients.each_with_index do |payment, index|
108
+ output.merge!(payment.get_params(index))
109
+ end
110
+ end
111
+ end
112
+
113
+ def credentials
114
+ {
115
+ 'USER' => Paypal::Masspay::Configuration.username,
116
+ 'PWD' => Paypal::Masspay::Configuration.password,
117
+ 'SIGNATURE' => Paypal::Masspay::Configuration.signature
118
+ }
119
+ end
120
+
121
+ def default_options
122
+ {
123
+ 'VERSION' => API_VERSION,
124
+ 'METHOD' => METHOD,
125
+ 'RECEIVERTYPE' => IDENTIFIER,
126
+ 'CURRENCYCODE' => @currency,
127
+ 'EMAILSUBJECT' => @subject
128
+ }
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,13 @@
1
+ module Paypal
2
+ class Masspay::Configuration
3
+ class << self
4
+ attr_accessor :environment, :username, :password, :signature
5
+
6
+ def configure
7
+ @configuration ||= Paypal::Masspay::Configuration.tap do |config|
8
+ yield config
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Paypal
2
+ class Masspay::Error
3
+ attr_reader :code, :short_message, :long_message, :severity
4
+
5
+ def initialize(params = {})
6
+ @code = params[:code]
7
+ @short_message = params[:short_message]
8
+ @long_message = params[:long_message]
9
+ @severity = params[:severity]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Paypal
2
+ class Masspay::LengthValidator
3
+ class FieldLengthTooLarge < StandardError; end
4
+
5
+ def self.validate(string, length, field_name)
6
+ string.tap do |output|
7
+ raise FieldLengthTooLarge.new("#{output} is longer than the paypal max char limit of #{length} for field #{field_name}") if !output.nil? && output.length > length
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ module Paypal
2
+ class Masspay::Recipient
3
+ RECIPIENT_EMAIL_MAX_LENGTH = 127
4
+ RECIPIENT_NOTE_MAX_LENGTH = 4000
5
+ RECIPIENT_UNIQUE_ID_MAX_LENGTH = 30
6
+
7
+ def initialize(args = {})
8
+ @recipient_email = Paypal::Masspay::LengthValidator.validate(args[:recipient_email], RECIPIENT_EMAIL_MAX_LENGTH, :recipient_email)
9
+ @note = Paypal::Masspay::LengthValidator.validate(args[:note], RECIPIENT_NOTE_MAX_LENGTH, :note)
10
+ @unique_id = Paypal::Masspay::LengthValidator.validate(args[:unique_id], RECIPIENT_UNIQUE_ID_MAX_LENGTH, :unique_id)
11
+ @amount = args[:amount]
12
+ end
13
+
14
+ def get_params(index)
15
+ {
16
+ "L_EMAIL#{index}" => @recipient_email,
17
+ "L_AMT#{index}" => @amount,
18
+ "L_NOTE#{index}" => @note,
19
+ "L_UNIQUEID#{index}" => @unique_id
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,62 @@
1
+ require 'cgi'
2
+ require 'paypal/masspay/error'
3
+
4
+ module Paypal
5
+ class Masspay::ResponseParser
6
+ SUCCESS_ACK = 'Success'
7
+ SUCCESS_WITH_WARN_ACK = 'SuccessWithWarning'
8
+ SUCCESSFUL_ACKS = [ SUCCESS_ACK, SUCCESS_WITH_WARN_ACK ]
9
+
10
+ def initialize(response_body)
11
+ @response_body = response_body
12
+ @errors = []
13
+ end
14
+
15
+ def successful?
16
+ SUCCESSFUL_ACKS.include?(ack)
17
+ end
18
+
19
+ def errors
20
+ @errors.tap do |errors|
21
+ parsed_response.select { |k, v| k.match(/^L_ERRORCODE\d+$/) }.keys.count.times do |i|
22
+ errors << Paypal::Masspay::Error.new(
23
+ :code => error_code_for(i),
24
+ :short_message => short_message_for(i),
25
+ :long_message => long_message_for(i),
26
+ :severity => severity_for(i))
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def parsed_response
34
+ if @parsed_response.nil?
35
+ @parsed_response = CGI::parse(@response_body)
36
+ @parsed_response.each { |key, value| @parsed_response[key] = value.first }
37
+ end
38
+
39
+ @parsed_response
40
+ end
41
+
42
+ def ack
43
+ parsed_response["ACK"]
44
+ end
45
+
46
+ def error_code_for(index)
47
+ parsed_response["L_ERRORCODE#{index}"].to_i
48
+ end
49
+
50
+ def short_message_for(index)
51
+ parsed_response["L_SHORTMESSAGE#{index}"]
52
+ end
53
+
54
+ def long_message_for(index)
55
+ parsed_response["L_LONGMESSAGE#{index}"]
56
+ end
57
+
58
+ def severity_for(index)
59
+ parsed_response["L_SEVERITYCODE#{index}"]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ module Paypal
2
+ class Masspay
3
+ VERSION = '1.1.0'
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'paypal/masspay/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'paypal-masspay'
8
+ gem.version = Paypal::Masspay::VERSION
9
+ gem.authors = ['Martin Jagusch', 'Shervin Aflatooni']
10
+ gem.email = ['shervinaflatooni@gmail.com']
11
+ gem.description = 'Performing multiple payments to PayPal using the MassPay API'
12
+ gem.summary = "paypal-masspay-#{Paypal::Masspay::VERSION}"
13
+ gem.homepage = 'https://github.com/envato/paypal-masspay'
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files -z`.split("\x0")
17
+ gem.test_files = gem.files.grep(%r{^spec/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_dependency 'faraday', '~> 0.9', '>= 0.9.0'
21
+
22
+ gem.add_development_dependency 'rake', '~> 10.3'
23
+ gem.add_development_dependency 'rspec', '~> 3.0.0.beta1'
24
+ gem.add_development_dependency 'cane', '~> 2.6'
25
+ gem.add_development_dependency 'webmock', '~> 1.17'
26
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'performing a masspay' do
4
+ let(:success_body) { 'ACK=Success' }
5
+ let(:fail_body) { 'ACK=Failure&L_ERRORCODE0=10000&L_SHORTMESSAGE0=short_error_message&L_LONGMESSAGE0=long_error_message&L_SEVERITYCODE0=Error&L_ERRORCODE1=20000&L_SHORTMESSAGE1=short_error_message2&L_LONGMESSAGE1=long_error_message2&L_SEVERITYCODE1=Error' }
6
+ let(:response_body) { success_body }
7
+
8
+ let(:recipient_one) { Paypal::Masspay::Recipient.new(:recipient_email => 'chunky@example.com', :amount => 10.00) }
9
+ let(:recipient_two) { Paypal::Masspay::Recipient.new(:recipient_email => 'bacon@example.com', :amount => 2.95) }
10
+
11
+ before do
12
+ stub_request(:post, "https://api-3t.sandbox.paypal.com/nvp").with(
13
+ :body => {
14
+ "USER" => "your_paypal_username",
15
+ "PWD" => "your_paypal_password",
16
+ "SIGNATURE" => "your_paypal_signature",
17
+ "CURRENCYCODE" => "USD",
18
+ "EMAILSUBJECT" => "Paypal Masspay",
19
+ "L_AMT0" => "10.0",
20
+ "L_AMT1" => "2.95",
21
+ "L_EMAIL0" => "chunky@example.com",
22
+ "L_EMAIL1" => "bacon@example.com",
23
+ "METHOD" => "MassPay",
24
+ "RECEIVERTYPE" => "EmailAddress",
25
+ "VERSION" => "2.3"
26
+ }).to_return(:body => response_body)
27
+
28
+ Paypal::Masspay::Configuration.configure do |config|
29
+ config.environment = :sandbox
30
+ config.username = 'your_paypal_username'
31
+ config.password = 'your_paypal_password'
32
+ config.signature = 'your_paypal_signature'
33
+ end
34
+ end
35
+
36
+ context 'adding recipients one at a time' do
37
+ before do
38
+ @masspay = Paypal::Masspay.new(:currency => 'USD', :subject => 'Paypal Masspay') do |bucket|
39
+ bucket.add_recipient(recipient_one)
40
+ bucket.add_recipient(recipient_two)
41
+ end
42
+ end
43
+
44
+ context 'when the response was successful' do
45
+ let(:response_body) { success_body }
46
+
47
+ it 'sends the correct request to the paypal api and is successful' do
48
+ expect(@masspay).to_not be_delivered
49
+ @masspay.deliver
50
+ expect(@masspay).to be_successful
51
+ expect(@masspay).to be_delivered
52
+ end
53
+ end
54
+
55
+ context 'when the response was not successful' do
56
+ let(:response_body) { fail_body }
57
+
58
+ it 'sends the correct request to the paypal api and is successful' do
59
+ @masspay.deliver
60
+ expect(@masspay).to_not be_successful
61
+ end
62
+
63
+ it 'has 2 errors' do
64
+ @masspay.deliver
65
+ expect(@masspay.errors.count).to eq(2)
66
+ end
67
+
68
+ it 'has the correct error codes' do
69
+ @masspay.deliver
70
+ expect(@masspay.errors[0].code).to eq(10000)
71
+ expect(@masspay.errors[1].code).to eq(20000)
72
+ end
73
+ end
74
+ end
75
+
76
+ context 'adding recipients in a hash' do
77
+ let(:recipients) { [recipient_one, recipient_two] }
78
+
79
+ before do
80
+ @masspay = Paypal::Masspay.new(:currency => 'USD', :subject => 'Paypal Masspay', :recipients => recipients)
81
+ end
82
+
83
+ context 'when the response was successful' do
84
+ let(:response_body) { success_body }
85
+
86
+ it 'sends the correct request to the paypal api and is successful' do
87
+ @masspay.deliver
88
+ expect(@masspay).to be_successful
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paypal::Masspay::Error do
4
+ let(:code) { double }
5
+ let(:short_message) { double }
6
+ let(:long_message) { double }
7
+ let(:severity) { double }
8
+ let(:arguments) { { :code => code, :short_message => short_message, :long_message => long_message, :severity => severity } }
9
+ subject(:error) { Paypal::Masspay::Error.new(arguments) }
10
+
11
+ describe '#code' do
12
+ it 'returns the error code' do
13
+ expect(error.code).to eq(code)
14
+ end
15
+ end
16
+
17
+ describe '#short_message' do
18
+ it 'returns the error short_message' do
19
+ expect(error.short_message).to eq(short_message)
20
+ end
21
+ end
22
+
23
+ describe '#long_message' do
24
+ it 'returns the error long_message' do
25
+ expect(error.long_message).to eq(long_message)
26
+ end
27
+ end
28
+
29
+ describe '#severity' do
30
+ it 'returns the error severity' do
31
+ expect(error.severity).to eq(severity)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paypal::Masspay::LengthValidator do
4
+ describe '.validate' do
5
+ context 'the string is valid' do
6
+ it 'returns the string' do
7
+ expect(Paypal::Masspay::LengthValidator.validate("hello", 5, :test)).to eq("hello")
8
+ end
9
+ end
10
+
11
+ context 'the string is not valid' do
12
+ it 'raises a field too large exception' do
13
+ expect { Paypal::Masspay::LengthValidator.validate("hello", 4, :test) }.to raise_error(Paypal::Masspay::LengthValidator::FieldLengthTooLarge)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paypal::Masspay::Recipient do
4
+ let(:recipient_email) { double }
5
+ let(:amount) { double }
6
+ let(:note) { double }
7
+ let(:unique_id) { double }
8
+ let(:arguments) { { :recipient_email => recipient_email, :amount => amount, :note => note, :unique_id => unique_id } }
9
+ subject(:recipient) { Paypal::Masspay::Recipient.new(arguments) }
10
+
11
+ before do
12
+ allow(Paypal::Masspay::LengthValidator).to receive(:validate).with(recipient_email, 127, :recipient_email).and_return(recipient_email)
13
+ allow(Paypal::Masspay::LengthValidator).to receive(:validate).with(note, 4000, :note).and_return(note)
14
+ allow(Paypal::Masspay::LengthValidator).to receive(:validate).with(unique_id, 30, :unique_id).and_return(unique_id)
15
+ end
16
+
17
+ describe '#get_params' do
18
+ it 'returns the arguments in the correct format' do
19
+ expect(recipient.get_params(5)).to eq({
20
+ "L_EMAIL5" => recipient_email,
21
+ "L_AMT5" => amount,
22
+ "L_NOTE5" => note,
23
+ "L_UNIQUEID5" => unique_id
24
+ })
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paypal::Masspay::ResponseParser do
4
+ let(:success_body) { 'ACK=Success' }
5
+ let(:fail_body) { 'ACK=Failure&L_ERRORCODE0=10000&L_SHORTMESSAGE0=short_error_message&L_LONGMESSAGE0=long_error_message&L_SEVERITYCODE0=Error&L_ERRORCODE1=20000&L_SHORTMESSAGE1=short_error_message2&L_LONGMESSAGE1=long_error_message2&L_SEVERITYCODE1=Error' }
6
+ let(:response_body) { success_body }
7
+ subject(:response_parser) { Paypal::Masspay::ResponseParser.new(response_body) }
8
+
9
+ describe '#successful?' do
10
+ context 'the response was successful' do
11
+ let(:response_body) { success_body }
12
+
13
+ it 'returns true' do
14
+ expect(response_parser).to be_successful
15
+ end
16
+ end
17
+
18
+ context 'the response was not successful' do
19
+ let(:response_body) { fail_body }
20
+
21
+ it 'returns false' do
22
+ expect(response_parser).to_not be_successful
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#errors' do
28
+ context 'the response was successful' do
29
+ let(:response_body) { success_body }
30
+
31
+ it 'has no errors' do
32
+ expect(response_parser.errors.count).to eq(0)
33
+ end
34
+ end
35
+
36
+ context 'the response was not successful' do
37
+ let(:response_body) { fail_body }
38
+
39
+ it 'has errors' do
40
+ expect(response_parser.errors.count).to eq(2)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paypal::Masspay do
4
+ let(:recipient_one) { double }
5
+ let(:recipient_two) { double }
6
+ let(:response) { double(:successful? => successful, :errors => errors) }
7
+ let(:errors) { [] }
8
+
9
+ let(:successful) { true }
10
+ let(:success_body) { 'ACK=Success' }
11
+ let(:fail_body) { 'ACK=Failure&L_ERRORCODE0=10000&L_SHORTMESSAGE0=short_error_message&L_LONGMESSAGE0=long_error_message&L_SEVERITYCODE0=Error&L_ERRORCODE1=20000&L_SHORTMESSAGE1=short_error_message2&L_LONGMESSAGE1=long_error_message2&L_SEVERITYCODE1=Error' }
12
+ let(:response_body) { success_body }
13
+
14
+ before do
15
+ allow(Paypal::Masspay::Configuration).to receive(:environment).and_return(:sandbox)
16
+ allow(Paypal::Masspay::Configuration).to receive(:username).and_return("user1")
17
+ allow(Paypal::Masspay::Configuration).to receive(:password).and_return("password1")
18
+ allow(Paypal::Masspay::Configuration).to receive(:signature).and_return("sig1")
19
+
20
+ allow(recipient_one).to receive(:get_params).with(0).and_return({"L_EMAIL0" => 'chunky@example.com', "L_AMT0" => 10.0})
21
+ allow(recipient_two).to receive(:get_params).with(1).and_return({"L_EMAIL1" => 'bacon@example.com', "L_AMT1" => 2.95})
22
+ allow(Paypal::Masspay::ResponseParser).to receive(:new).with(response_body).and_return(response)
23
+
24
+ allow(Paypal::Masspay::LengthValidator).to receive(:validate).with('USD', 3, :currency).and_return('USD')
25
+ allow(Paypal::Masspay::LengthValidator).to receive(:validate).with('Paypal Masspay', 255, :subject).and_return('Paypal Masspay')
26
+
27
+ stub_request(:post, "https://api-3t.sandbox.paypal.com/nvp").with(
28
+ :body => {
29
+ "USER" => "user1",
30
+ "PWD" => "password1",
31
+ "SIGNATURE" => "sig1",
32
+ "CURRENCYCODE" => "USD",
33
+ "EMAILSUBJECT" => "Paypal Masspay",
34
+ "L_AMT0" => "10.0",
35
+ "L_AMT1" => "2.95",
36
+ "L_EMAIL0" => "chunky@example.com",
37
+ "L_EMAIL1" => "bacon@example.com",
38
+ "METHOD" => "MassPay",
39
+ "RECEIVERTYPE" => "EmailAddress",
40
+ "VERSION" => "2.3"
41
+ }).to_return(:body => response_body)
42
+ end
43
+
44
+ context 'adding recipients one at a time' do
45
+ before do
46
+
47
+ @masspay = Paypal::Masspay.new(:currency => 'USD', :subject => 'Paypal Masspay') do |bucket|
48
+ bucket.add_recipient(recipient_one)
49
+ bucket.add_recipient(recipient_two)
50
+ end
51
+ end
52
+
53
+ context 'when the response was successful' do
54
+ let(:response_body) { success_body }
55
+ let(:successful) { true }
56
+ let(:errors) { [] }
57
+
58
+ it 'sends the correct request to the paypal api and is successful' do
59
+ expect(@masspay).to_not be_delivered
60
+ @masspay.deliver
61
+ expect(@masspay).to be_successful
62
+ expect(@masspay).to be_delivered
63
+ end
64
+ end
65
+
66
+ context 'when the response was not successful' do
67
+ let(:response_body) { fail_body }
68
+ let(:successful) { false }
69
+ let(:errors) { [ double, double ] }
70
+
71
+ it 'sends the correct request to the paypal api and is successful' do
72
+ @masspay.deliver
73
+ expect(@masspay).to_not be_successful
74
+ end
75
+
76
+ it 'has 2 errors' do
77
+ @masspay.deliver
78
+ expect(@masspay.errors.count).to eq(2)
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'adding recipients in a hash' do
84
+ let(:recipients) { [recipient_one, recipient_two] }
85
+
86
+ before do
87
+ @masspay = Paypal::Masspay.new(:currency => 'USD', :subject => 'Paypal Masspay', :recipients => recipients)
88
+ end
89
+
90
+ context 'when the response was successful' do
91
+ let(:response_body) { success_body }
92
+ let(:successful) { true }
93
+ let(:errors) { [] }
94
+
95
+ it 'sends the correct request to the paypal api and is successful' do
96
+ @masspay.deliver
97
+ expect(@masspay).to be_successful
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,6 @@
1
+ lib = File.expand_path('../../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'paypal/masspay'
5
+ require 'rspec'
6
+ require 'webmock/rspec'
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paypal-masspay
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Martin Jagusch
9
+ - Shervin Aflatooni
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-09-09 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: faraday
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '0.9'
23
+ - - ! '>='
24
+ - !ruby/object:Gem::Version
25
+ version: 0.9.0
26
+ type: :runtime
27
+ prerelease: false
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 0.9.0
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ requirement: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '10.3'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: '10.3'
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ requirement: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: 3.0.0.beta1
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0.beta1
69
+ - !ruby/object:Gem::Dependency
70
+ name: cane
71
+ requirement: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '2.6'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ~>
83
+ - !ruby/object:Gem::Version
84
+ version: '2.6'
85
+ - !ruby/object:Gem::Dependency
86
+ name: webmock
87
+ requirement: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ~>
91
+ - !ruby/object:Gem::Version
92
+ version: '1.17'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ version: '1.17'
101
+ description: Performing multiple payments to PayPal using the MassPay API
102
+ email:
103
+ - shervinaflatooni@gmail.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - .gitignore
109
+ - .rspec
110
+ - Gemfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - lib/paypal/masspay.rb
115
+ - lib/paypal/masspay/configuration.rb
116
+ - lib/paypal/masspay/error.rb
117
+ - lib/paypal/masspay/length_validator.rb
118
+ - lib/paypal/masspay/recipient.rb
119
+ - lib/paypal/masspay/response_parser.rb
120
+ - lib/paypal/masspay/version.rb
121
+ - paypal-masspay.gemspec
122
+ - spec/lib/integration/masspay_spec.rb
123
+ - spec/lib/paypal/masspay/error_spec.rb
124
+ - spec/lib/paypal/masspay/length_validator_spec.rb
125
+ - spec/lib/paypal/masspay/recipient_spec.rb
126
+ - spec/lib/paypal/masspay/response_parser_spec.rb
127
+ - spec/lib/paypal/masspay_spec.rb
128
+ - spec/spec_helper.rb
129
+ homepage: https://github.com/envato/paypal-masspay
130
+ licenses:
131
+ - MIT
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 1.8.21
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: paypal-masspay-1.1.0
154
+ test_files:
155
+ - spec/lib/integration/masspay_spec.rb
156
+ - spec/lib/paypal/masspay/error_spec.rb
157
+ - spec/lib/paypal/masspay/length_validator_spec.rb
158
+ - spec/lib/paypal/masspay/recipient_spec.rb
159
+ - spec/lib/paypal/masspay/response_parser_spec.rb
160
+ - spec/lib/paypal/masspay_spec.rb
161
+ - spec/spec_helper.rb