payson_api 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Guardfile CHANGED
@@ -5,5 +5,5 @@ guard 'test' do
5
5
  watch(%r{^test/unit/.+_test\.rb$}) { "test" }
6
6
  watch(%r{^test/fixtures/(.+)\.yml$}) { "test" }
7
7
  watch(%r{^test/integration/.+_test\.rb$}) { "test" }
8
- watch('test/.+.rb') { "test" }
8
+ watch('test/.+\.rb') { "test" }
9
9
  end
data/README.rdoc CHANGED
@@ -38,7 +38,10 @@ You can configure the following default values by overriding these values using
38
38
  receivers = []
39
39
  receivers << PaysonAPI::Receiver.new(
40
40
  email = 'me@mydomain.com',
41
- amount = 100
41
+ amount = 100,
42
+ first_name = 'Me',
43
+ last_name = 'Just me',
44
+ primary = true
42
45
  )
43
46
 
44
47
  sender = PaysonAPI::Sender.new(
@@ -116,8 +119,8 @@ This example assumes the use of the Rails web framework.
116
119
  ipn_response = PaysonAPI::Response::IPN.new(request_body)
117
120
 
118
121
  # Do business stuff, e.g. update the corresponding order:
119
- # order = Order.find_by_payson_token(ipn.token)
120
- # order.payson_status = ipn.status
122
+ # order = Order.find_by_payson_token(ipn_response.token)
123
+ # order.payson_status = ipn_response.status
121
124
  # order.save!
122
125
 
123
126
  # Create a new IPN request object containing the raw response from above
@@ -134,10 +137,7 @@ This example assumes the use of the Rails web framework.
134
137
 
135
138
  == Todo
136
139
 
137
- Implement the following requests:
138
-
139
- * Validate - Validate an IPN (Instant Payment Notification).
140
-
140
+ Nothing at the moment. Will focus on writing more thourough test cases and look over the code all in all.
141
141
 
142
142
 
143
143
  == Build Status {<img src="https://secure.travis-ci.org/stoffus/payson_api.png"/>}[http://travis-ci.org/stoffus/payson_api]
@@ -11,8 +11,20 @@ module PaysonAPI
11
11
  PAYSON_API_PAYMENT_UPDATE_ACTION = "PaymentUpdate"
12
12
  PAYSON_API_PAYMENT_VALIDATE_ACTION = "Validate"
13
13
 
14
- LOCALES = %w[SV FI EN]
14
+ LOCALES = %w[SV EN FI]
15
15
  CURRENCIES = %w[SEK EUR]
16
+ FEES_PAYERS = %w[EACHRECEIVER SENDER PRIMARYRECEIVER SECONDARYONLY]
17
+ FUNDING_CONSTRAINTS = %w[CREDITCARD BANK INVOICE]
18
+ GUARANTEE_OFFERINGS = %w[OPTIONAL REQUIRED NO]
19
+ PAYMENT_STATUSES = %w[CREATED PENDING PROCESSING COMPLETED CREDITED
20
+ INCOMPLETE ERROR EXPIRED REVERSALERROR ABORTED]
21
+ PAYMENT_TYPES = %w[TRANSFER GUARANTEE INVOICE]
22
+ GUARANTEE_STATUSES = %w[WAITINGFORSEND WAITINGFORACCEPTANCE WAITINGFORRETURN
23
+ WAITINGFORRETURNACCEPTANCE RETURNNOTACCEPTED NOTRECEIVED RETURNNOTRECEIVED
24
+ MONEYRETURNEDTOSENDER RETURNACCEPTED
25
+ ]
26
+ INVOICE_STATUSES = %w[PENDING ORDERCREATED CANCELED SHIPPED DONE CREDITED]
27
+ PAYMENT_ACTIONS = %w[CANCELORDER SHIPORDER CREDITORDER REFUND]
16
28
 
17
29
  def configure(&block)
18
30
  yield @config ||= Configuration.new
@@ -13,7 +13,7 @@ class Envelope
13
13
 
14
14
  def self.parse(data)
15
15
  ack = data[FORMAT_STRING % 'ack']
16
- timestamp = DateTime.parse(CGI.unescape(data[FORMAT_STRING % 'timestamp']))
16
+ timestamp = DateTime.parse(CGI.unescape(data[FORMAT_STRING % 'timestamp'].to_s))
17
17
  correlation_id = data[FORMAT_STRING % 'correlationId']
18
18
  self.new(ack, timestamp, correlation_id)
19
19
  end
@@ -4,6 +4,9 @@ class Funding
4
4
  attr_accessor :constraint
5
5
 
6
6
  def initialize(constraint)
7
+ if !FUNDING_CONSTRAINTS.include?(constraint)
8
+ raise "Unknown funding constraint: #{constraint}"
9
+ end
7
10
  @constraint = constraint
8
11
  end
9
12
 
@@ -11,7 +14,7 @@ class Funding
11
14
  {}.tap do |hash|
12
15
  fundings.each_with_index do |funding, index|
13
16
  hash.merge!({
14
- FORMAT_STRING % [index, 'email'] => funding.constraint
17
+ FORMAT_STRING % [index, 'constraint'] => funding.constraint
15
18
  })
16
19
  end
17
20
  end
@@ -31,7 +31,7 @@ class OrderItem
31
31
  [].tap do |order_items|
32
32
  i = 0
33
33
  while data[FORMAT_STRING % [i, 'description']]
34
- description = CGI.unescape(data[FORMAT_STRING % [i, 'description']])
34
+ description = CGI.unescape(data[FORMAT_STRING % [i, 'description']].to_s)
35
35
  unit_price = data[FORMAT_STRING % [i, 'unitPrice']]
36
36
  quantity = data[FORMAT_STRING % [i, 'quantity']]
37
37
  tax = data[FORMAT_STRING % [i, 'taxPercentage']]
@@ -3,11 +3,14 @@ require 'cgi'
3
3
  module PaysonAPI
4
4
  class Receiver
5
5
  FORMAT_STRING = "receiverList.receiver(%d).%s"
6
- attr_accessor :email, :amount
6
+ attr_accessor :email, :amount, :first_name, :last_name, :primary
7
7
 
8
- def initialize(email, amount)
8
+ def initialize(email, amount, first_name, last_name, primary = true)
9
9
  @email = email
10
10
  @amount = amount
11
+ @first_name = first_name
12
+ @last_name = last_name
13
+ @primary = primary
11
14
  end
12
15
 
13
16
  def self.to_hash(receivers)
@@ -16,7 +19,10 @@ class Receiver
16
19
  raise "Invalid receiver" unless receiver.instance_of?(self)
17
20
  hash.merge!({
18
21
  FORMAT_STRING % [index, 'email'] => receiver.email,
19
- FORMAT_STRING % [index, 'amount'] => receiver.amount
22
+ FORMAT_STRING % [index, 'amount'] => receiver.amount,
23
+ FORMAT_STRING % [index, 'firstName'] => receiver.first_name,
24
+ FORMAT_STRING % [index, 'lastName'] => receiver.last_name,
25
+ FORMAT_STRING % [index, 'primary'] => receiver.primary
20
26
  })
21
27
  end
22
28
  end
@@ -26,9 +32,12 @@ class Receiver
26
32
  [].tap do |receivers|
27
33
  i = 0
28
34
  while data[FORMAT_STRING % [i, 'email']]
29
- email = CGI.unescape(data[FORMAT_STRING % [i, 'email']])
35
+ email = CGI.unescape(data[FORMAT_STRING % [i, 'email']].to_s)
30
36
  amount = data[FORMAT_STRING % [i, 'amount']]
31
- receivers << self.new(email, amount)
37
+ first_name = CGI.unescape(data[FORMAT_STRING % [i, 'firstName']].to_s)
38
+ last_name = CGI.unescape(data[FORMAT_STRING % [i, 'lastName']].to_s)
39
+ primary = data[FORMAT_STRING % [i, 'primary']]
40
+ receivers << self.new(email, amount, first_name, last_name, primary)
32
41
  i += 1
33
42
  end
34
43
  end
@@ -2,7 +2,8 @@ module PaysonAPI
2
2
  module Request
3
3
  class Payment
4
4
  attr_accessor :return_url, :cancel_url, :ipn_url, :memo, :sender, :receivers,
5
- :locale, :currency, :tracking_id, :invoice_fee, :order_items
5
+ :locale, :currency, :tracking_id, :invoice_fee, :order_items, :fundings,
6
+ :fees_payer, :guarantee_offered
6
7
 
7
8
  def initialize(return_url, cancel_url, ipn_url, memo, sender, receivers)
8
9
  @return_url = return_url
@@ -15,21 +16,51 @@ class Payment
15
16
 
16
17
  def to_hash
17
18
  {}.tap do |hash|
19
+ # Append mandatory params
18
20
  hash['returnUrl'] = @return_url
19
21
  hash['cancelUrl'] = @cancel_url
20
- if @ipn_url && !@ipn_url.empty?
21
- hash['ipnNotificationUrl'] = @ipn_url
22
- end
23
22
  hash['memo'] = @memo
24
- hash['localeCode'] = LOCALES[@locale] if @locale
25
- hash['currencyCode'] = CURRENCIES[@currency] if @currency
26
- hash.merge!(Receiver.to_hash(@receivers))
27
23
  hash.merge!(@sender.to_hash)
24
+ hash.merge!(Receiver.to_hash(@receivers))
25
+
26
+ # Append optional params
27
+ append_locale(hash, @locale) if @locale
28
+ append_currency(hash, @currency) if @currency
29
+ append_fees_payer(hash, @fees_payer) if @fees_payer
30
+ append_guarantee(hash, @guarantee_offered) if @guarantee_offered
28
31
  hash.merge!(OrderItem.to_hash(@order_items)) if @order_items
32
+ hash.merge!(Funding.to_hash(@fundings)) if @fundings
33
+ hash['ipnNotificationUrl'] = @ipn_url if @ipn_url
29
34
  hash['invoiceFee'] = @invoice_fee if @invoice_fee
30
35
  hash['trackingId'] = @tracking_id if @tracking_id
31
36
  end
32
37
  end
38
+
39
+ private
40
+
41
+ def append_locale(hash, locale)
42
+ raise "Unknown locale: #{locale}" if !LOCALES.include?(locale)
43
+ hash['localeCode'] = locale
44
+ end
45
+
46
+ def append_currency(hash, currency)
47
+ raise "Unknown currency: #{currency}" if !CURRENCIES.include?(currency)
48
+ hash['currencyCode'] = currency
49
+ end
50
+
51
+ def append_guarantee(hash, guarantee_offered)
52
+ if !GUARANTEE_OFFERINGS.include?(guarantee_offered)
53
+ raise "Unknown guarantee offering: #{guarantee_offered}"
54
+ end
55
+ hash['guaranteeOffered'] = guarantee_offered
56
+ end
57
+
58
+ def append_fees_payer(hash, fees_payer)
59
+ if !FEES_PAYERS.include?(fees_payer)
60
+ raise "Unknown fees payer: #{fees_payer}"
61
+ end
62
+ hash['feesPayer'] = fees_payer if fees_payer
63
+ end
33
64
  end
34
65
  end
35
66
  end
@@ -5,6 +5,9 @@ class PaymentUpdate
5
5
 
6
6
  def initialize(token, action)
7
7
  @token = token
8
+ if !PAYMENT_ACTIONS.include?(action)
9
+ raise "Unknown payment update action: #{action}"
10
+ end
8
11
  @action = action
9
12
  end
10
13
 
@@ -27,7 +27,9 @@ class PaymentDetails
27
27
  @guarantee_deadline_at = Time.at(data['guaranteeDeadlineTimestamp'])
28
28
  when 'INVOICE'
29
29
  @invoice_status = data['invoiceStatus']
30
- @shipping_address = ShippingAddress.parse(data)
30
+ if %w[ORDERCREATED SHIPPED DONE CREDITED].include?(@invoice_status)
31
+ @shipping_address = ShippingAddress.parse(data)
32
+ end
31
33
  end
32
34
  end
33
35
 
@@ -21,8 +21,8 @@ class Sender
21
21
 
22
22
  def self.parse(data)
23
23
  email = data[FORMAT_STRING % 'email']
24
- first_name = CGI.unescape(data[FORMAT_STRING % 'FirstName'])
25
- last_name = CGI.unescape(data[FORMAT_STRING % 'LastName'])
24
+ first_name = CGI.unescape(data[FORMAT_STRING % 'FirstName'].to_s)
25
+ last_name = CGI.unescape(data[FORMAT_STRING % 'LastName'].to_s)
26
26
  self.new(email, first_name, last_name)
27
27
  end
28
28
  end
@@ -25,11 +25,11 @@ class ShippingAddress
25
25
 
26
26
  def self.parse(data)
27
27
  return unless data[FORMAT_STRING % 'name']
28
- name = CGI.unescape(data[FORMAT_STRING % 'name'])
29
- street_address = CGI.unescape(data[FORMAT_STRING % 'streetAddress'])
30
- postal_code = CGI.unescape(data[FORMAT_STRING % 'postalCode'])
31
- city = CGI.unescape(data[FORMAT_STRING % 'city'])
32
- country = CGI.unescape(data[FORMAT_STRING % 'country'])
28
+ name = CGI.unescape(data[FORMAT_STRING % 'name'].to_s)
29
+ street_address = CGI.unescape(data[FORMAT_STRING % 'streetAddress'].to_s)
30
+ postal_code = CGI.unescape(data[FORMAT_STRING % 'postalCode'].to_s)
31
+ city = CGI.unescape(data[FORMAT_STRING % 'city'].to_s)
32
+ country = CGI.unescape(data[FORMAT_STRING % 'country'].to_s)
33
33
  self.new(name, street_address, postal_code, city, country)
34
34
  end
35
35
  end
@@ -1,3 +1,3 @@
1
1
  module PaysonAPI
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,18 +1,24 @@
1
1
  :return_url: http://localhost/return
2
2
  :cancel_url: http://localhost/cancel
3
- :ipn_url:
3
+ :ipn_url: http://localhost/ipn
4
4
  :memo: Test
5
5
  :receivers:
6
6
  -
7
7
  :email: mytest@domain.com
8
8
  :amount: 123
9
+ :first_name: Test
10
+ :last_name: Person 1
11
+ :primary: true
9
12
  -
10
13
  :email: mytest2@domain2.com
11
14
  :amount: 234
15
+ :first_name: Test
16
+ :last_name: Person 2
17
+ :primary: false
12
18
  :sender:
13
19
  :email: test_person@anotherdomain.com
14
20
  :first_name: Test
15
- :last_name: Person
21
+ :last_name: Receiver
16
22
  :order_items:
17
23
  -
18
24
  :description: 'My order item description'
@@ -26,3 +32,11 @@
26
32
  :quantity: 2
27
33
  :tax: 10
28
34
  :sku: 'MY-ITEM-2'
35
+ :fundings:
36
+ -
37
+ :constraint: CREDITCARD
38
+ -
39
+ :constraint: BANK
40
+ :fees_payer: EACHRECEIVER
41
+ :guarantee_offered: NO
42
+ :locale: SV
@@ -19,9 +19,6 @@ class PaymentDetailsTest < Test::Unit::TestCase
19
19
 
20
20
  payment_details = PaysonAPI::Request::PaymentDetails.new(token)
21
21
  response = PaysonAPI::Client.get_payment_details(payment_details)
22
-
23
-
24
-
25
- p response
22
+ #p response
26
23
  end
27
24
  end
@@ -14,15 +14,22 @@ class PaymentTest < Test::Unit::TestCase
14
14
  assert_equal PAYMENT_DATA[:cancel_url], @payment_hash['cancelUrl']
15
15
  assert_equal PAYMENT_DATA[:ipn_url], @payment_hash['ipnNotificationUrl']
16
16
  assert_equal PAYMENT_DATA[:memo], @payment_hash['memo']
17
+ assert_equal PAYMENT_DATA[:locale], @payment_hash['localeCode']
17
18
 
18
19
  # Ensure expected format of receiver list
19
20
  receiver_format = PaysonAPI::Receiver::FORMAT_STRING
20
21
  @receivers.each_with_index do |receiver, index|
21
22
  email = @payment_hash[receiver_format % [index, 'email']]
22
23
  amount = @payment_hash[receiver_format % [index, 'amount']]
24
+ first_name = @payment_hash[receiver_format % [index, 'firstName']]
25
+ last_name = @payment_hash[receiver_format % [index, 'lastName']]
26
+ primary = @payment_hash[receiver_format % [index, 'primary']]
23
27
 
24
28
  assert_equal receiver.email, email
25
29
  assert_equal receiver.amount, amount
30
+ assert_equal receiver.first_name, first_name
31
+ assert_equal receiver.last_name, last_name
32
+ assert_equal receiver.primary, primary
26
33
  end
27
34
 
28
35
  # Do same test for order items
@@ -40,6 +47,13 @@ class PaymentTest < Test::Unit::TestCase
40
47
  assert_equal order_item.tax, tax
41
48
  assert_equal order_item.sku, sku
42
49
  end
50
+
51
+ # Ensure expected format of fundings list
52
+ funding_format = PaysonAPI::Funding::FORMAT_STRING
53
+ @fundings.each_with_index do |funding, index|
54
+ constraint = @payment_hash[funding_format % [index, 'constraint']]
55
+ assert_equal funding.constraint, constraint
56
+ end
43
57
  end
44
58
 
45
59
  def test_payment_initiation_request
data/test/test_helper.rb CHANGED
@@ -22,7 +22,10 @@ module TestHelper
22
22
  PAYMENT_DATA[:receivers].each do |receiver|
23
23
  @receivers << PaysonAPI::Receiver.new(
24
24
  receiver[:email],
25
- receiver[:amount]
25
+ receiver[:amount],
26
+ receiver[:first_name],
27
+ receiver[:last_name],
28
+ receiver[:primary]
26
29
  )
27
30
  end
28
31
 
@@ -46,7 +49,19 @@ module TestHelper
46
49
  )
47
50
  end
48
51
 
52
+ @fundings = []
53
+ PAYMENT_DATA[:fundings].each do |funding|
54
+ @fundings << PaysonAPI::Funding.new(
55
+ funding[:constraint]
56
+ )
57
+ end
58
+
49
59
  @payment.order_items = @order_items if include_order_items
60
+ @payment.fundings = @fundings
61
+ @payment.fees_payer = PAYMENT_DATA[:fees_payer]
62
+ @payment.locale = PAYMENT_DATA[:locale]
63
+ @payment.guarantee_offered = PAYMENT_DATA[:guarantee_offered]
64
+
50
65
  @payment_hash = @payment.to_hash
51
66
  end
52
67
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Christopher Svensson