payson_api 0.0.6 → 0.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.
data/README.rdoc CHANGED
@@ -42,7 +42,7 @@ You can configure the following default values by overriding these values using
42
42
  )
43
43
 
44
44
  sender = PaysonAPI::Sender.new(
45
- email = 'mycustomer@mydomain.com,
45
+ email = 'mycustomer@mydomain.com',
46
46
  first_name = 'My',
47
47
  last_name = 'Customer'
48
48
  )
@@ -56,7 +56,7 @@ You can configure the following default values by overriding these values using
56
56
  sku = 'MY-ITEM-1'
57
57
  )
58
58
 
59
- pay_data = PaysonAPI::PayData.new(
59
+ payment = PaysonAPI::Request::Payment.new(
60
60
  return_url,
61
61
  cancel_url,
62
62
  ipn_url,
@@ -64,9 +64,9 @@ You can configure the following default values by overriding these values using
64
64
  sender,
65
65
  receivers
66
66
  )
67
- pay_data.order_items = order_items
67
+ payment.order_items = order_items
68
68
 
69
- response = PaysonAPI::Client.pay(pay_data)
69
+ response = PaysonAPI::Client.initiate_payment(payment)
70
70
 
71
71
  if response.success?
72
72
  # Redirect to response.forward_url
@@ -75,12 +75,67 @@ You can configure the following default values by overriding these values using
75
75
  end
76
76
 
77
77
 
78
+ === Requesting payment details
79
+
80
+ token = 'token-received-from-payment-request'
81
+
82
+ payment_details = PaysonAPI::Request::PaymentDetails.new(token)
83
+
84
+ response = PaysonAPI::Client.get_payment_details(payment_details)
85
+
86
+ if response.success?
87
+ # Do stuff with response object
88
+ else
89
+ puts response.errors
90
+ end
91
+
92
+
93
+ === Updating a payment
94
+
95
+ token = 'token-received-from-payment-request'
96
+ action = 'CANCELORDER'
97
+
98
+ payment_update = PaysonAPI::Request::PaymentUpdate.new(token, action)
99
+
100
+ response = PaysonAPI::Client.update_payment(payment_update)
101
+
102
+ if response.success?
103
+ # Do stuff with response object
104
+ else
105
+ puts response.errors
106
+ end
107
+
108
+
109
+ === Validating an IPN response
110
+
111
+ This example assumes the use of the Rails web framework.
112
+
113
+ class Payson < ApplicationController
114
+ def ipn_responder
115
+ request_body = request.body.read
116
+ ipn_response = PaysonAPI::Response::IPN.new(request_body)
117
+
118
+ # Do business stuff, e.g. update the corresponding order:
119
+ # order = Order.find_by_payson_token(ipn.token)
120
+ # order.payson_status = ipn.status
121
+ # order.save!
122
+
123
+ # Create a new IPN request object containing the raw response from above
124
+ ipn_request = PaysonAPI::Request::IPN.new(ipn_response.raw)
125
+
126
+ validate = PaysonAPI::Client.validate_ipn(ipn_request)
127
+
128
+ unless validate.verified?
129
+ raise "Something went terribly wrong."
130
+ end
131
+ end
132
+ end
133
+
134
+
78
135
  == Todo
79
136
 
80
137
  Implement the following requests:
81
138
 
82
- * PaymentDetails - Get details on a payment.
83
- * PaymentUpdate - Update a payment.
84
139
  * Validate - Validate an IPN (Instant Payment Notification).
85
140
 
86
141
 
@@ -1,37 +1,82 @@
1
1
  require 'net/https'
2
2
 
3
3
  module PaysonAPI
4
- class Client
5
- def self.pay(pay_data)
6
- action = '/%s/%s/' % [PAYSON_API_VERSION, PAYSON_API_PAY_ACTION]
7
- response = post(PAYSON_API_ENDPOINT + action, pay_data.to_hash)
8
- Response.new(response.body)
9
- end
4
+ class Client
5
+ def self.initiate_payment(payment_data)
6
+ response = payson_request(
7
+ PAYSON_API_PAY_ACTION,
8
+ payment_data.to_hash
9
+ )
10
+ response_hash = params_to_hash(response.body)
11
+ PaysonAPI::Response::Payment.new(response_hash)
12
+ end
13
+
14
+ def self.get_payment_details(payment_details_data)
15
+ response = payson_request(
16
+ PAYSON_API_PAYMENT_DETAILS_ACTION,
17
+ payment_details_data.to_hash
18
+ )
19
+ response_hash = params_to_hash(response.body)
20
+ PaysonAPI::Response::PaymentDetails.new(response_hash)
21
+ end
22
+
23
+ def self.update_payment(payment_update_data)
24
+ response = payson_request(
25
+ PAYSON_API_PAYMENT_DETAILS_ACTION,
26
+ payment_update_data.to_hash
27
+ )
28
+ response_hash = params_to_hash(response.body)
29
+ PaysonAPI::Response::PaymentUpdate.new(response_hash)
30
+ end
31
+
32
+ def self.validate_ipn(ipn_data)
33
+ response = payson_request(
34
+ PAYSON_API_PAYMENT_VALIDATE_ACTION,
35
+ ipn_data.to_s
36
+ )
37
+ PaysonAPI::Response::Validate.new(response.body)
38
+ end
10
39
 
11
- private
12
-
13
- def self.post(url, data)
14
- headers = {
15
- 'PAYSON-SECURITY-USERID' => PaysonAPI.config.api_user_id,
16
- 'PAYSON-SECURITY-PASSWORD' => PaysonAPI.config.api_password,
17
- 'Content-Type' => 'application/x-www-form-urlencoded'
18
- }
19
- uri = URI.parse(url)
20
- http = Net::HTTP.new(uri.host, uri.port)
21
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
22
- http.use_ssl = uri.scheme == 'https'
23
- req = Net::HTTP::Post.new(uri.path)
24
- req.body = hash_to_params(data)
25
- headers.each do |name, value|
26
- req[name] = value
40
+ def self.hash_to_params(hash)
41
+ out = ""
42
+ hash.each { |k, v| out << "#{k}=#{v}&" }
43
+ out.chop
44
+ end
45
+
46
+ def self.params_to_hash(params)
47
+ {}.tap do |hash|
48
+ parts = params.split(/&/)
49
+ parts.each do |part|
50
+ key, val = part.split(/=/)
51
+ hash[key] = val
27
52
  end
28
- http.request(req)
29
53
  end
54
+ end
55
+
56
+ private
30
57
 
31
- def self.hash_to_params(hash)
32
- out = ""
33
- hash.each { |k, v| out << "#{k}=#{v}&" }
34
- out.chop
58
+ def self.payson_request(action, data)
59
+ action = '/%s/%s/' % [PAYSON_API_VERSION, action]
60
+ url = PAYSON_API_ENDPOINT + action
61
+ headers = {
62
+ 'PAYSON-SECURITY-USERID' => PaysonAPI.config.api_user_id,
63
+ 'PAYSON-SECURITY-PASSWORD' => PaysonAPI.config.api_password,
64
+ 'Content-Type' => 'application/x-www-form-urlencoded'
65
+ }
66
+ post(url, data, headers)
67
+ end
68
+
69
+ def self.post(url, data, headers)
70
+ uri = URI.parse(url)
71
+ http = Net::HTTP.new(uri.host, uri.port)
72
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
73
+ http.use_ssl = uri.scheme == 'https'
74
+ req = Net::HTTP::Post.new(uri.path)
75
+ req.body = data.is_a?(Hash) ? hash_to_params(data) : data
76
+ headers.each do |name, value|
77
+ req[name] = value
35
78
  end
79
+ http.request(req)
36
80
  end
37
81
  end
82
+ end
@@ -14,10 +14,6 @@ module PaysonAPI
14
14
  LOCALES = %w[SV FI EN]
15
15
  CURRENCIES = %w[SEK EUR]
16
16
 
17
- # Configures global settings for Payson
18
- # PaysonAPI.configure do |config|
19
- # config.api_user = 12345
20
- # end
21
17
  def configure(&block)
22
18
  yield @config ||= Configuration.new
23
19
  end
@@ -34,5 +30,4 @@ module PaysonAPI
34
30
  config.api_user_id = 'XXXX'
35
31
  config.api_password = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
36
32
  end
37
-
38
33
  end
@@ -0,0 +1,21 @@
1
+ require 'cgi'
2
+
3
+ module PaysonAPI
4
+ class Envelope
5
+ attr_accessor :ack, :timestamp, :correlation_id
6
+ FORMAT_STRING = "responseEnvelope.%s"
7
+
8
+ def initialize(ack, timestamp, correlation_id)
9
+ @ack = ack
10
+ @timestamp = timestamp
11
+ @correlation_id = correlation_id
12
+ end
13
+
14
+ def self.parse(data)
15
+ ack = data[FORMAT_STRING % 'ack']
16
+ timestamp = DateTime.parse(CGI.unescape(data[FORMAT_STRING % 'timestamp']))
17
+ correlation_id = data[FORMAT_STRING % 'correlationId']
18
+ self.new(ack, timestamp, correlation_id)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module PaysonAPI
2
+ class Funding
3
+ FORMAT_STRING = "fundingList.fundingConstraint(%d).%s"
4
+ attr_accessor :constraint
5
+
6
+ def initialize(constraint)
7
+ @constraint = constraint
8
+ end
9
+
10
+ def self.to_hash(fundings)
11
+ {}.tap do |hash|
12
+ fundings.each_with_index do |funding, index|
13
+ hash.merge!({
14
+ FORMAT_STRING % [index, 'email'] => funding.constraint
15
+ })
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.parse(data)
21
+ [].tap do |fundings|
22
+ i = 0
23
+ while data[FORMAT_STRING % [i, 'constraint']]
24
+ constraint = data[FORMAT_STRING % [i, 'constraint']]
25
+ fundings << self.new(constraint)
26
+ i += 1
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,7 +1,9 @@
1
+ require 'cgi'
2
+
1
3
  module PaysonAPI
2
4
  class OrderItem
3
- FORMAT_STRING = "orderItemList.orderItem(%d).%s"
4
5
  attr_accessor :description, :quantity, :unit_price, :sku, :tax
6
+ FORMAT_STRING = "orderItemList.orderItem(%d).%s"
5
7
 
6
8
  def initialize(description, unit_price, quantity, tax, sku)
7
9
  @description = description
@@ -14,7 +16,6 @@ class OrderItem
14
16
  def self.to_hash(order_items)
15
17
  {}.tap do |hash|
16
18
  order_items.each_with_index do |item, index|
17
- raise "Invalid order item" unless item.instance_of?(self)
18
19
  hash.merge!({
19
20
  FORMAT_STRING % [index, 'description'] => item.description,
20
21
  FORMAT_STRING % [index, 'unitPrice'] => item.unit_price,
@@ -26,21 +27,26 @@ class OrderItem
26
27
  end
27
28
  end
28
29
 
29
- def self.parse_order_items(data)
30
- i = 0
30
+ def self.parse(data)
31
31
  [].tap do |order_items|
32
+ i = 0
32
33
  while data[FORMAT_STRING % [i, 'description']]
33
- description = data[FORMAT_STRING % [i, 'description']]
34
+ description = CGI.unescape(data[FORMAT_STRING % [i, 'description']])
34
35
  unit_price = data[FORMAT_STRING % [i, 'unitPrice']]
35
36
  quantity = data[FORMAT_STRING % [i, 'quantity']]
36
37
  tax = data[FORMAT_STRING % [i, 'taxPercentage']]
37
38
  sku = data[FORMAT_STRING % [i, 'sku']]
38
39
 
39
- order_items << OrderItem.new(description, unit_price, quantity, tax, sku)
40
+ order_items << OrderItem.new(
41
+ description,
42
+ unit_price,
43
+ quantity,
44
+ tax,
45
+ sku
46
+ )
40
47
  i += 1
41
48
  end
42
49
  end
43
50
  end
44
-
45
51
  end
46
52
  end
@@ -1,3 +1,5 @@
1
+ require 'cgi'
2
+
1
3
  module PaysonAPI
2
4
  class Receiver
3
5
  FORMAT_STRING = "receiverList.receiver(%d).%s"
@@ -20,13 +22,13 @@ class Receiver
20
22
  end
21
23
  end
22
24
 
23
- def self.parse_receivers(data)
24
- i = 0
25
+ def self.parse(data)
25
26
  [].tap do |receivers|
27
+ i = 0
26
28
  while data[FORMAT_STRING % [i, 'email']]
27
- email = data[FORMAT_STRING % [i, 'email']]
29
+ email = CGI.unescape(data[FORMAT_STRING % [i, 'email']])
28
30
  amount = data[FORMAT_STRING % [i, 'amount']]
29
- receivers << Receiver.new(email, amount)
31
+ receivers << self.new(email, amount)
30
32
  i += 1
31
33
  end
32
34
  end
@@ -0,0 +1,31 @@
1
+ require 'cgi'
2
+
3
+ module PaysonAPI
4
+ class RemoteError
5
+ attr_accessor :id, :message, :parameter
6
+ FORMAT_STRING = "errorList.error(%d).%s"
7
+
8
+ def initialize(id, message, parameter)
9
+ @id = id
10
+ @message = message
11
+ @parameter = parameter
12
+ end
13
+
14
+ def self.parse(data)
15
+ [].tap do |errors|
16
+ i = 0
17
+ while data[FORMAT_STRING % [i, 'errorId']]
18
+ id = data[FORMAT_STRING % [i, 'errorId']]
19
+ message = CGI.unescape(data[FORMAT_STRING % [i, 'message']])
20
+ parameter = CGI.unescape(data[FORMAT_STRING % [i, 'parameter']])
21
+ errors << self.new(id, message, parameter)
22
+ i += 1
23
+ end
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ "ID: #{@id}, Message: #{@message}, Parameter: #{@parameter}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ module PaysonAPI
2
+ module Request
3
+ class IPN
4
+ attr_accessor :data
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ end
9
+
10
+ def to_s
11
+ @data
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,6 @@
1
1
  module PaysonAPI
2
- class PayData
2
+ module Request
3
+ class Payment
3
4
  attr_accessor :return_url, :cancel_url, :ipn_url, :memo, :sender, :receivers,
4
5
  :locale, :currency, :tracking_id, :invoice_fee, :order_items
5
6
 
@@ -29,9 +30,6 @@ class PayData
29
30
  hash['trackingId'] = @tracking_id if @tracking_id
30
31
  end
31
32
  end
32
-
33
- def to_s
34
- to_hash.to_s
35
- end
33
+ end
36
34
  end
37
35
  end
@@ -0,0 +1,15 @@
1
+ module PaysonAPI
2
+ module Request
3
+ class PaymentDetails
4
+ attr_accessor :token
5
+
6
+ def initialize(token)
7
+ @token = token
8
+ end
9
+
10
+ def to_hash
11
+ { 'token' => @token }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module PaysonAPI
2
+ module Request
3
+ class PaymentUpdate
4
+ attr_accessor :token, :action
5
+
6
+ def initialize(token, action)
7
+ @token = token
8
+ @action = action
9
+ end
10
+
11
+ def to_hash
12
+ {}.tap do |hash|
13
+ hash['token'] = @token
14
+ hash['action'] = @action
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module PaysonAPI
2
+ module Response
3
+ class IPN
4
+ attr_accessor :purchase_id, :sender_email, :status,
5
+ :payment_type, :guarantee_status, :guarantee_deadline_at,
6
+ :invoice_status, :custom, :tracking_id, :receivers, :currency,
7
+ :order_items, :fundings, :token, :shipping_address, :raw, :hash
8
+
9
+ def initialize(raw_data)
10
+ @raw = raw_data
11
+ data_hash = PaysonAPI::Client.params_to_hash(raw_data)
12
+ @purchase_id = data_hash['purchaseId']
13
+ @payment_type = data_hash['type']
14
+ @comment = data_hash['custom']
15
+ @tracking_id = data_hash['trackingId']
16
+ @currency = data_hash['currencyCode']
17
+ @sender_email = data_hash['senderEmail']
18
+ @status = data_hash['status']
19
+ @token = data_hash['token']
20
+ @fundings = Funding.parse(data_hash)
21
+ @receivers = Receiver.parse(data_hash)
22
+ @order_items = OrderItem.parse(data_hash)
23
+ @hash = data_hash['HASH']
24
+
25
+ case @payment_type
26
+ when 'GUARANTEE'
27
+ @guarantee_status = data_hash['guaranteeStatus']
28
+ @guarantee_deadline_at = Time.at(data_hash['guaranteeDeadlineTimestamp'])
29
+ when 'INVOICE'
30
+ @invoice_status = data_hash['invoiceStatus']
31
+ @shipping_address = ShippingAddress.parse(data_hash)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ module PaysonAPI
2
+ module Response
3
+ class Payment
4
+ attr_accessor :envelope, :token, :errors
5
+
6
+ def initialize(data)
7
+ @envelope = Envelope.parse(data)
8
+ @token = data['TOKEN']
9
+ @errors = RemoteError.parse(data)
10
+ end
11
+
12
+ def success?
13
+ @envelope.ack == 'SUCCESS'
14
+ end
15
+
16
+ def forward_url
17
+ PAYSON_WWW_HOST + PAYSON_WWW_PAY_FORWARD_URL % @token
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ module PaysonAPI
2
+ module Response
3
+ class PaymentDetails
4
+ attr_accessor :envelope, :purchase_id, :sender_email, :status,
5
+ :payment_type, :guarantee_status, :guarantee_deadline_at,
6
+ :invoice_status, :custom, :tracking_id, :receivers, :currency,
7
+ :order_items, :errors, :fundings, :token, :shipping_address
8
+
9
+ def initialize(data)
10
+ @envelope = Envelope.parse(data)
11
+ @purchase_id = data['purchaseId']
12
+ @payment_type = data['type']
13
+ @comment = data['custom']
14
+ @tracking_id = data['trackingId']
15
+ @currency = data['currencyCode']
16
+ @sender_email = data['senderEmail']
17
+ @status = data['status']
18
+ @token = data['token']
19
+ @fundings = Funding.parse(data)
20
+ @receivers = Receiver.parse(data)
21
+ @order_items = OrderItem.parse(data)
22
+ @errors = RemoteError.parse(data)
23
+
24
+ case @payment_type
25
+ when 'GUARANTEE'
26
+ @guarantee_status = data['guaranteeStatus']
27
+ @guarantee_deadline_at = Time.at(data['guaranteeDeadlineTimestamp'])
28
+ when 'INVOICE'
29
+ @invoice_status = data['invoiceStatus']
30
+ @shipping_address = ShippingAddress.parse(data)
31
+ end
32
+ end
33
+
34
+ def success?
35
+ @envelope.ack == 'SUCCESS'
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module PaysonAPI
2
+ module Response
3
+ class PaymentUpdate
4
+ attr_accessor :envelope, :errors
5
+
6
+ def initialize(data)
7
+ @envelope = Envelope.parse(data)
8
+ @errors = RemoteError.parse(data)
9
+ end
10
+
11
+ def success?
12
+ @envelope.ack == 'SUCCESS'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module PaysonAPI
2
+ module Response
3
+ class Validate
4
+ attr_accessor :data
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ end
9
+
10
+ def verified?
11
+ @data == 'VERIFIED'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,8 @@
1
+ require 'cgi'
2
+
1
3
  module PaysonAPI
2
4
  class Sender
5
+ FORMAT_STRING = "sender%s"
3
6
  attr_accessor :email, :first_name, :last_name
4
7
 
5
8
  def initialize(email, first_name, last_name)
@@ -10,10 +13,17 @@ class Sender
10
13
 
11
14
  def to_hash
12
15
  {}.tap do |hash|
13
- hash['senderEmail'] = @email
14
- hash['senderFirstName'] = @first_name
15
- hash['senderLastName'] = @last_name
16
+ hash[FORMAT_STRING % 'Email'] = @email
17
+ hash[FORMAT_STRING % 'FirstName'] = @first_name
18
+ hash[FORMAT_STRING % 'LastName'] = @last_name
16
19
  end
17
20
  end
21
+
22
+ def self.parse(data)
23
+ email = data[FORMAT_STRING % 'email']
24
+ first_name = CGI.unescape(data[FORMAT_STRING % 'FirstName'])
25
+ last_name = CGI.unescape(data[FORMAT_STRING % 'LastName'])
26
+ self.new(email, first_name, last_name)
27
+ end
18
28
  end
19
29
  end
@@ -0,0 +1,36 @@
1
+ require 'cgi'
2
+
3
+ module PaysonAPI
4
+ class ShippingAddress
5
+ FORMAT_STRING = "shippingAddress.%s"
6
+ attr_accessor :name, :street_address, :postal_code, :city, :country
7
+
8
+ def initialize(name, street_address, postal_code, city, country)
9
+ @name = name
10
+ @street_address = street_address
11
+ @postal_code = postal_code
12
+ @city = city
13
+ @country = country
14
+ end
15
+
16
+ def to_hash
17
+ {}.tap do |hash|
18
+ hash[FORMAT_STRING % 'name'] = @name
19
+ hash[FORMAT_STRING % 'streetAddress'] = @street_address
20
+ hash[FORMAT_STRING % 'postalCode'] = @postal_code
21
+ hash[FORMAT_STRING % 'city'] = @city
22
+ hash[FORMAT_STRING % 'country'] = @country
23
+ end
24
+ end
25
+
26
+ def self.parse(data)
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'])
33
+ self.new(name, street_address, postal_code, city, country)
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module PaysonAPI
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/payson_api.rb CHANGED
@@ -1,10 +1,26 @@
1
- require 'payson_api/config'
2
- require 'payson_api/client'
3
- require 'payson_api/errors/payson_api_error'
4
- require 'payson_api/errors/remote_error'
5
- require 'payson_api/order_item'
6
- require 'payson_api/pay_data'
7
- require 'payson_api/receiver'
8
- require 'payson_api/response'
9
- require 'payson_api/sender'
10
- require 'payson_api/version'
1
+ required_files = [
2
+ 'config',
3
+ 'error_codes',
4
+ 'client',
5
+ 'envelope',
6
+ 'funding',
7
+ 'order_item',
8
+ 'receiver',
9
+ 'remote_error',
10
+ 'request/ipn',
11
+ 'request/payment_details',
12
+ 'request/payment_update',
13
+ 'request/payment',
14
+ 'response/ipn',
15
+ 'response/payment_details',
16
+ 'response/payment_update',
17
+ 'response/payment',
18
+ 'response/validate',
19
+ 'sender',
20
+ 'shipping_address',
21
+ 'version'
22
+ ]
23
+
24
+ required_files.each do |file|
25
+ require "payson_api/#{file}"
26
+ end
@@ -1,2 +1,5 @@
1
- :api_user_id: XXXX
2
- :api_password: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
1
+ #:api_user_id: XXXX
2
+ #:api_password: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
3
+
4
+ :api_user_id: 13671
5
+ :api_password: 305390e8-f866-41e5-a543-dc8747f545f8
File without changes
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test/unit'
4
+ require 'test_helper'
5
+ require 'payson_api'
6
+
7
+ class PaymentDetailsTest < Test::Unit::TestCase
8
+ include TestHelper
9
+
10
+ def test_generated_hash_from_payment_details
11
+ #token = acquire_token
12
+ #token = 'b28c31bb-1499-4988-9fc6-fa915c287e90'
13
+ token = '4d7328b0-9883-44e3-a19d-b25cef65a3b8'
14
+
15
+ if !token
16
+ puts "Token was not received, please look into your test config"
17
+ return
18
+ end
19
+
20
+ payment_details = PaysonAPI::Request::PaymentDetails.new(token)
21
+ response = PaysonAPI::Client.get_payment_details(payment_details)
22
+
23
+
24
+
25
+ p response
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test/unit'
4
+ require 'test_helper'
5
+ require 'payson_api'
6
+
7
+ class PaymentTest < Test::Unit::TestCase
8
+ include TestHelper
9
+
10
+ def test_generated_hash_from_payment_data
11
+ setup_payment_hash(include_order_items = true)
12
+
13
+ assert_equal PAYMENT_DATA[:return_url], @payment_hash['returnUrl']
14
+ assert_equal PAYMENT_DATA[:cancel_url], @payment_hash['cancelUrl']
15
+ assert_equal PAYMENT_DATA[:ipn_url], @payment_hash['ipnNotificationUrl']
16
+ assert_equal PAYMENT_DATA[:memo], @payment_hash['memo']
17
+
18
+ # Ensure expected format of receiver list
19
+ receiver_format = PaysonAPI::Receiver::FORMAT_STRING
20
+ @receivers.each_with_index do |receiver, index|
21
+ email = @payment_hash[receiver_format % [index, 'email']]
22
+ amount = @payment_hash[receiver_format % [index, 'amount']]
23
+
24
+ assert_equal receiver.email, email
25
+ assert_equal receiver.amount, amount
26
+ end
27
+
28
+ # Do same test for order items
29
+ order_item_format = PaysonAPI::OrderItem::FORMAT_STRING
30
+ @order_items.each_with_index do |order_item, index|
31
+ description = @payment_hash[order_item_format % [index, 'description']]
32
+ unit_price = @payment_hash[order_item_format % [index, 'unitPrice']]
33
+ quantity = @payment_hash[order_item_format % [index, 'quantity']]
34
+ tax = @payment_hash[order_item_format % [index, 'taxPercentage']]
35
+ sku = @payment_hash[order_item_format % [index, 'sku']]
36
+
37
+ assert_equal order_item.description, description
38
+ assert_equal order_item.unit_price, unit_price
39
+ assert_equal order_item.quantity, quantity
40
+ assert_equal order_item.tax, tax
41
+ assert_equal order_item.sku, sku
42
+ end
43
+ end
44
+
45
+ def test_payment_initiation_request
46
+ token = acquire_token
47
+
48
+ if !token
49
+ puts "Token was not received, please look into your test config"
50
+ return
51
+ end
52
+ end
53
+ end
data/test/test_helper.rb CHANGED
@@ -2,6 +2,7 @@ require 'yaml'
2
2
 
3
3
  module TestHelper
4
4
  CONFIG = YAML.load_file('test/fixtures/config.yml')
5
+ PAYMENT_DATA = YAML.load_file('test/fixtures/payment_data.yml')
5
6
 
6
7
  def setup
7
8
  PaysonAPI.configure do |config|
@@ -10,6 +11,56 @@ module TestHelper
10
11
  end
11
12
  end
12
13
 
14
+ def setup_payment_hash(include_order_items = false)
15
+ @sender = PaysonAPI::Sender.new(
16
+ PAYMENT_DATA[:sender][:email],
17
+ PAYMENT_DATA[:sender][:first_name],
18
+ PAYMENT_DATA[:sender][:last_name]
19
+ )
20
+
21
+ @receivers = []
22
+ PAYMENT_DATA[:receivers].each do |receiver|
23
+ @receivers << PaysonAPI::Receiver.new(
24
+ receiver[:email],
25
+ receiver[:amount]
26
+ )
27
+ end
28
+
29
+ @payment = PaysonAPI::Request::Payment.new(
30
+ PAYMENT_DATA[:return_url],
31
+ PAYMENT_DATA[:cancel_url],
32
+ PAYMENT_DATA[:ipn_url],
33
+ PAYMENT_DATA[:memo],
34
+ @sender,
35
+ @receivers
36
+ )
37
+
38
+ @order_items = []
39
+ PAYMENT_DATA[:order_items].each do |order_item|
40
+ @order_items << PaysonAPI::OrderItem.new(
41
+ order_item[:description],
42
+ order_item[:unit_price],
43
+ order_item[:quantity],
44
+ order_item[:tax],
45
+ order_item[:sku]
46
+ )
47
+ end
48
+
49
+ @payment.order_items = @order_items if include_order_items
50
+ @payment_hash = @payment.to_hash
51
+ end
52
+
53
+ # Note that for this method to succeed you must configure the tests
54
+ # with your personal details:
55
+ # * The api_user_id/api_password must be valid (in config.yml)
56
+ # * The receiver email must be valid for the supplied credentials
57
+ # (in payment_data.yml)
58
+ def acquire_token
59
+ setup_payment_hash
60
+ response = PaysonAPI::Client.initiate_payment(@payment_hash)
61
+ response.token
62
+ end
63
+
13
64
  def teardown
14
65
  end
15
66
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 6
9
- version: 0.0.6
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Christopher Svensson
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-07-25 00:00:00 +02:00
17
+ date: 2012-07-27 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -61,20 +61,29 @@ files:
61
61
  - lib/payson_api.rb
62
62
  - lib/payson_api/client.rb
63
63
  - lib/payson_api/config.rb
64
- - lib/payson_api/errors/payson_api_error.rb
65
- - lib/payson_api/errors/remote_error.rb
64
+ - lib/payson_api/envelope.rb
65
+ - lib/payson_api/funding.rb
66
66
  - lib/payson_api/order_item.rb
67
- - lib/payson_api/pay_data.rb
68
67
  - lib/payson_api/receiver.rb
69
- - lib/payson_api/response.rb
68
+ - lib/payson_api/remote_error.rb
69
+ - lib/payson_api/request/ipn.rb
70
+ - lib/payson_api/request/payment.rb
71
+ - lib/payson_api/request/payment_details.rb
72
+ - lib/payson_api/request/payment_update.rb
73
+ - lib/payson_api/response/ipn.rb
74
+ - lib/payson_api/response/payment.rb
75
+ - lib/payson_api/response/payment_details.rb
76
+ - lib/payson_api/response/payment_update.rb
77
+ - lib/payson_api/response/validate.rb
70
78
  - lib/payson_api/sender.rb
79
+ - lib/payson_api/shipping_address.rb
71
80
  - lib/payson_api/version.rb
72
81
  - payson_api.gemspec
73
82
  - test/fixtures/config.yml
74
- - test/fixtures/order.yml
83
+ - test/fixtures/payment_data.yml
75
84
  - test/integration/config_test.rb
76
- - test/integration/pay_data_test.rb
77
- - test/integration/request_test.rb
85
+ - test/integration/payment_details_test.rb
86
+ - test/integration/payment_test.rb
78
87
  - test/test_helper.rb
79
88
  has_rdoc: true
80
89
  homepage: https://github.com/stoffus/payson_api
@@ -108,8 +117,8 @@ specification_version: 3
108
117
  summary: Client for Payson API
109
118
  test_files:
110
119
  - test/fixtures/config.yml
111
- - test/fixtures/order.yml
120
+ - test/fixtures/payment_data.yml
112
121
  - test/integration/config_test.rb
113
- - test/integration/pay_data_test.rb
114
- - test/integration/request_test.rb
122
+ - test/integration/payment_details_test.rb
123
+ - test/integration/payment_test.rb
115
124
  - test/test_helper.rb
@@ -1,7 +0,0 @@
1
- module PaysonAPI
2
- module Errors
3
- class PaysonAPIError < StandardError
4
- # Base error.
5
- end
6
- end
7
- end
@@ -1,55 +0,0 @@
1
- module PaysonAPI
2
- module Errors
3
- class RemoteError < PaysonAPIError
4
- ERROR_CODES = {
5
- '500000' => "System error.",
6
- '520002' => "Internal error.",
7
- '520003' => "Authentication failed; Credentials were not valid.",
8
- '520004' => "The merchant account is restricted.",
9
- '520005' => "The merchant account is locked.",
10
- '520006' => "The requested API endpoint is unknown.",
11
- '529038' => "Error while executing payment.",
12
- '539041' => "An email account is not receive enabled.",
13
- '539043' => "An email account is not send enabled.",
14
- '559044' => "A receiver's preferences denied the payment.",
15
- '560027' => "Unrecognized fees payer type.",
16
- '579007' => "Payment request number of receivers exceeds the maximum.",
17
- '579008' => "Number of primary receivers exceeds 1.",
18
- '579017' => "Primary receiver amount for chained payment must not be less than sum of other receiver amounts.",
19
- '579033' => "Sender and each receiver must all have different accounts.",
20
- '579040' => "Two receivers belong to the same Payson user account.",
21
- '579042' => "The tracking ID already exists and cannot be duplicated.",
22
- '579045' => "This request would exceed the receiving limit for an account.",
23
- '579047' => "This request would exceed the purse limit for an account.",
24
- '579048' => "This request would exceed the sending limit for an account.",
25
- '579049' => "The payment request you are looking for was not found in our system.",
26
- '580001' => "Invalid request - the request did not pass our basic validation.",
27
- '580021' => "Invalid parameter - too long.",
28
- '580022' => "Your request was invalid. Check the parameter of the error to see which is invalid.",
29
- '580023' => "A receiver was given more than once in the request.",
30
- '580027' => "Unsupported currency code.",
31
- '580028' => "A URL supplied with the request is malformed.",
32
- '580029' => "A required parameter was not provided. Check the error parameter list.",
33
- '589018' => "Invalid pay key.",
34
- '589052' => "The transaction ID was not found in our system.",
35
- '589053' => "All payment methods have been disabled for this combination of funding constraint, merchant and receiver.",
36
- '590001' => "The total amount specified for receivers does not match the total amount specified by the order items.",
37
- '590005' => "Not all related order item parameters where specified. All or none of unitPrice, quantity, taxPercentage and sku must be set.",
38
- '590006' => "Invoice requires one reciever.",
39
- '590007' => "Invoice requires fee on reciever.",
40
- '590008' => "Invoice requires that order items are specified.",
41
- '590009' => "Invoice payments are not available to this merchant.",
42
- '590010' => "The requested action is not possible in the current state of the payment.",
43
- '590011' => "The amount on the invoice is below the minimum limit.",
44
- '590012' => "Invoice does not support the selected currency.",
45
- '590013' => "The invoice fee out of the valid range (0-30 SEK).",
46
- '590014' => "The invoice fee can only be specified for invoices.",
47
- '590015' => "The receiver is not allowed to receive invoices.",
48
- '590016' => "The sender and reciever is the same user.",
49
- '590017' => "Invoice is frozen and cannot be updated.",
50
- '590018' => "The requested action is not possible for the current type of payment.",
51
- '590021' => "The funding constraint INVOICE cannot be combined with other funding constraints."
52
- }
53
- end
54
- end
55
- end
@@ -1,35 +0,0 @@
1
- module PaysonAPI
2
- class Response
3
- attr_accessor :envelope, :token, :errors
4
-
5
- def initialize(response)
6
- @errors = {}
7
- @envelope = {}
8
- @token = nil
9
- parse_response(response)
10
- end
11
-
12
- def parse_response(response)
13
- response.split(/&/).each do |item|
14
- if item =~ /TOKEN/
15
- @token = item.split(/=/)[1]
16
- elsif item =~ /errorId/
17
- code = item.split(/=/)[1]
18
- @errors[code] = Errors::RemoteError::ERROR_CODES[code]
19
- elsif item =~ /responseEnvelope/
20
- name, value = item.split(/=/)
21
- name = name.split(/\./)[1]
22
- @envelope[name] = value
23
- end
24
- end
25
- end
26
-
27
- def success?
28
- @envelope['ack'] == 'SUCCESS'
29
- end
30
-
31
- def forward_url
32
- url = PAYSON_WWW_HOST + PAYSON_WWW_PAY_FORWARD_URL % @token
33
- end
34
- end
35
- end
@@ -1,80 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'test/unit'
4
- require 'test_helper'
5
- require 'payson_api'
6
-
7
- class PayDataTest < Test::Unit::TestCase
8
- include TestHelper
9
- ORDER = YAML.load_file('test/fixtures/order.yml')
10
-
11
- def test_generated_hash_from_pay_data
12
- sender = PaysonAPI::Sender.new(
13
- ORDER[:sender][:email],
14
- ORDER[:sender][:first_name],
15
- ORDER[:sender][:last_name]
16
- )
17
-
18
- receivers = []
19
- ORDER[:receivers].each do |receiver|
20
- receivers << PaysonAPI::Receiver.new(
21
- receiver[:email],
22
- receiver[:amount]
23
- )
24
- end
25
-
26
- pay_data = PaysonAPI::PayData.new(
27
- ORDER[:return_url],
28
- ORDER[:cancel_url],
29
- ORDER[:ipn_url],
30
- ORDER[:memo],
31
- sender,
32
- receivers
33
- )
34
-
35
- order_items = []
36
- ORDER[:order_items].each do |order_item|
37
- order_items << PaysonAPI::OrderItem.new(
38
- order_item[:description],
39
- order_item[:unit_price],
40
- order_item[:quantity],
41
- order_item[:tax],
42
- order_item[:sku]
43
- )
44
- end
45
-
46
- pay_data.order_items = order_items
47
- pay_data_hash = pay_data.to_hash
48
-
49
- assert_equal ORDER[:return_url], pay_data_hash['returnUrl']
50
- assert_equal ORDER[:cancel_url], pay_data_hash['cancelUrl']
51
- assert_equal ORDER[:ipn_url], pay_data_hash['ipnNotificationUrl']
52
- assert_equal ORDER[:memo], pay_data_hash['memo']
53
-
54
- # Ensure expected format of receiver list
55
- receiver_format = PaysonAPI::Receiver::FORMAT_STRING
56
- receivers.each_with_index do |receiver, index|
57
- email = pay_data_hash[receiver_format % [index, 'email']]
58
- amount = pay_data_hash[receiver_format % [index, 'amount']]
59
-
60
- assert_equal receiver.email, email
61
- assert_equal receiver.amount, amount
62
- end
63
-
64
- # Do same test for order items
65
- order_item_format = PaysonAPI::OrderItem::FORMAT_STRING
66
- order_items.each_with_index do |order_item, index|
67
- description = pay_data_hash[order_item_format % [index, 'description']]
68
- unit_price = pay_data_hash[order_item_format % [index, 'unitPrice']]
69
- quantity = pay_data_hash[order_item_format % [index, 'quantity']]
70
- tax = pay_data_hash[order_item_format % [index, 'taxPercentage']]
71
- sku = pay_data_hash[order_item_format % [index, 'sku']]
72
-
73
- assert_equal order_item.description, description
74
- assert_equal order_item.unit_price, unit_price
75
- assert_equal order_item.quantity, quantity
76
- assert_equal order_item.tax, tax
77
- assert_equal order_item.sku, sku
78
- end
79
- end
80
- end
@@ -1,40 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'test/unit'
4
- require 'test_helper'
5
- require 'payson_api'
6
-
7
- class PayDataTest < Test::Unit::TestCase
8
- include TestHelper
9
- ORDER = YAML.load_file('test/fixtures/order.yml')
10
-
11
- def test_request_and_fail_gracefully
12
- sender = PaysonAPI::Sender.new(
13
- ORDER[:sender][:email],
14
- ORDER[:sender][:first_name],
15
- ORDER[:sender][:last_name]
16
- )
17
-
18
- receivers = []
19
- ORDER[:receivers].each do |receiver|
20
- receivers << PaysonAPI::Receiver.new(
21
- receiver[:email],
22
- receiver[:amount]
23
- )
24
- end
25
-
26
- pay_data = PaysonAPI::PayData.new(
27
- ORDER[:return_url],
28
- ORDER[:cancel_url],
29
- ORDER[:ipn_url],
30
- ORDER[:memo],
31
- sender,
32
- receivers
33
- )
34
-
35
- response = PaysonAPI::Client.pay(pay_data)
36
-
37
- # This should fail due to bad credentials
38
- assert_equal 'FAILURE', response.envelope['ack']
39
- end
40
- end