payson_api 0.0.2 → 0.0.3
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/.gitignore +7 -0
- data/Gemfile +14 -0
- data/README.rdoc +84 -0
- data/lib/payson_api.rb +2 -0
- data/lib/payson_api/client.rb +18 -0
- data/lib/payson_api/config.rb +39 -0
- data/lib/payson_api/errors/config_error.rb +13 -0
- data/lib/payson_api/errors/payson_api_error.rb +7 -0
- data/lib/payson_api/errors/remote_error.rb +55 -0
- data/lib/payson_api/order_item.rb +46 -0
- data/lib/payson_api/pay_data.rb +35 -0
- data/lib/payson_api/receiver.rb +35 -0
- data/lib/payson_api/response.rb +35 -0
- data/lib/payson_api/sender.rb +19 -0
- data/lib/payson_api/version.rb +3 -0
- data/payson_api.gemspec +26 -0
- metadata +22 -17
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
= Payson API
|
2
|
+
|
3
|
+
A simple utility to handle requests against the Payson payment gateway.
|
4
|
+
|
5
|
+
|
6
|
+
== Supported versions
|
7
|
+
|
8
|
+
* Ruby 1.9.3
|
9
|
+
|
10
|
+
|
11
|
+
== Install
|
12
|
+
|
13
|
+
Put this line in your Gemfile:
|
14
|
+
gem 'payson_api'
|
15
|
+
|
16
|
+
Then bundle:
|
17
|
+
% bundle
|
18
|
+
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
=== General configuration options
|
23
|
+
|
24
|
+
You can configure the following default values by overriding these values using the <tt>PaysonAPI.configure</tt> method.
|
25
|
+
|
26
|
+
PaysonAPI.configure do |config|
|
27
|
+
config.api_user = 'XXXX'
|
28
|
+
config.api_key = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
29
|
+
end
|
30
|
+
|
31
|
+
=== Initiating a payment
|
32
|
+
|
33
|
+
return_url = 'http://localhost/payson/success'
|
34
|
+
cancel_url = 'http://localhost/payson/cancel'
|
35
|
+
ipn_url = 'http://localhost/payson/ipn'
|
36
|
+
memo = 'Sample order description'
|
37
|
+
|
38
|
+
receivers = []
|
39
|
+
receivers << PaysonAPI::Receiver.new(
|
40
|
+
email = 'me@mydomain.com',
|
41
|
+
amount = 100
|
42
|
+
)
|
43
|
+
|
44
|
+
sender = PaysonAPI::Sender.new(
|
45
|
+
email = 'mycustomer@mydomain.com,
|
46
|
+
first_name = 'My',
|
47
|
+
last_name = 'Customer'
|
48
|
+
)
|
49
|
+
|
50
|
+
order_items = []
|
51
|
+
order_items << PaysonAPI::OrderItem.new(
|
52
|
+
description = 'Order item description',
|
53
|
+
unit_price = 100,
|
54
|
+
quantity = 1,
|
55
|
+
tax = 0,
|
56
|
+
sku = 'MY-ITEM-1'
|
57
|
+
)
|
58
|
+
|
59
|
+
pay_data = PaysonAPI::PayData.new(
|
60
|
+
return_url,
|
61
|
+
cancel_url,
|
62
|
+
ipn_url,
|
63
|
+
memo,
|
64
|
+
sender,
|
65
|
+
receivers
|
66
|
+
)
|
67
|
+
pay_data.order_items = order_items
|
68
|
+
|
69
|
+
response = PaysonAPI::Client.pay(pay_data)
|
70
|
+
|
71
|
+
if response.success?
|
72
|
+
# Redirect to response.forward_url
|
73
|
+
else
|
74
|
+
puts response.errors
|
75
|
+
end
|
76
|
+
|
77
|
+
== Questions, Feedback
|
78
|
+
|
79
|
+
Feel free to message me on Github (stoffus).
|
80
|
+
|
81
|
+
|
82
|
+
== Copyright
|
83
|
+
|
84
|
+
Copyright (c) 2012 Christopher Svensson.
|
data/lib/payson_api.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module PaysonAPI
|
4
|
+
class Client
|
5
|
+
def self.pay(pay_data)
|
6
|
+
action = '/%s/%s/' % [PAYSON_API_VERSION, PAYSON_API_PAY_ACTION]
|
7
|
+
headers = {
|
8
|
+
"PAYSON-SECURITY-USERID" => PaysonAPI.config.api_user,
|
9
|
+
"PAYSON-SECURITY-PASSWORD" => PaysonAPI.config.api_key
|
10
|
+
}
|
11
|
+
response = RestClient.post(PAYSON_API_ENDPOINT + action,
|
12
|
+
pay_data.to_hash,
|
13
|
+
headers
|
14
|
+
)
|
15
|
+
Response.new(response)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PaysonAPI
|
2
|
+
|
3
|
+
# Some hard constants
|
4
|
+
|
5
|
+
PAYSON_WWW_HOST = "https://www.payson.se"
|
6
|
+
PAYSON_WWW_PAY_FORWARD_URL = "/paysecure/?token=%s"
|
7
|
+
|
8
|
+
PAYSON_API_ENDPOINT = "https://api.payson.se"
|
9
|
+
PAYSON_API_VERSION = "1.0"
|
10
|
+
PAYSON_API_PAY_ACTION = "Pay"
|
11
|
+
PAYSON_API_PAYMENT_DETAILS_ACTION = "PaymentDetails"
|
12
|
+
PAYSON_API_PAYMENT_UPDATE_ACTION = "PaymentUpdate"
|
13
|
+
PAYSON_API_PAYMENT_VALIDATE_ACTION = "Validate"
|
14
|
+
|
15
|
+
LOCALES = %w[SV FI EN]
|
16
|
+
CURRENCIES = %w[SEK EUR]
|
17
|
+
|
18
|
+
# Configures global settings for Payson
|
19
|
+
# PaysonAPI.configure do |config|
|
20
|
+
# config.api_user = 12345
|
21
|
+
# end
|
22
|
+
def self.configure(&block)
|
23
|
+
yield @config ||= PaysonAPI::Configuration.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.config
|
27
|
+
@config
|
28
|
+
end
|
29
|
+
|
30
|
+
class Configuration
|
31
|
+
attr_accessor :api_user, :api_key
|
32
|
+
end
|
33
|
+
|
34
|
+
configure do |config|
|
35
|
+
config.api_user = 'XXXX'
|
36
|
+
config.api_key = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
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
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PaysonAPI
|
2
|
+
class OrderItem
|
3
|
+
FORMAT_STRING = "orderItemList.orderItem(%d).%s"
|
4
|
+
attr_accessor :description, :quantity, :unit_price, :sku, :tax
|
5
|
+
|
6
|
+
def initialize(description, unit_price, quantity, tax, sku)
|
7
|
+
@description = description
|
8
|
+
@unit_price = unit_price
|
9
|
+
@quantity = quantity
|
10
|
+
@tax = tax
|
11
|
+
@sku = sku
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.to_hash(order_items)
|
15
|
+
{}.tap do |hash|
|
16
|
+
order_items.each_with_index do |item, index|
|
17
|
+
raise "Invalid order item" unless item.instance_of?(self)
|
18
|
+
hash.merge!({
|
19
|
+
FORMAT_STRING % [index, 'description'] => item.description,
|
20
|
+
FORMAT_STRING % [index, 'unitPrice'] => item.unit_price,
|
21
|
+
FORMAT_STRING % [index, 'quantity'] => item.quantity,
|
22
|
+
FORMAT_STRING % [index, 'taxPercentage'] => item.tax,
|
23
|
+
FORMAT_STRING % [index, 'sku'] => item.sku
|
24
|
+
})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse_order_items(data)
|
30
|
+
i = 0
|
31
|
+
[].tap do |order_items|
|
32
|
+
while data[FORMAT_STRING % [i, 'description']]
|
33
|
+
description = data[FORMAT_STRING % [i, 'description']]
|
34
|
+
unit_price = data[FORMAT_STRING % [i, 'unitPrice']]
|
35
|
+
quantity = data[FORMAT_STRING % [i, 'quantity']]
|
36
|
+
tax = data[FORMAT_STRING % [i, 'taxPercentage']]
|
37
|
+
sku = data[FORMAT_STRING % [i, 'sku']]
|
38
|
+
|
39
|
+
order_items << OrderItem.new(description, unit_price, quantity, tax, sku)
|
40
|
+
i += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PaysonAPI
|
2
|
+
class PayData
|
3
|
+
attr_accessor :return_url, :cancel_url, :ipn_url, :memo, :sender, :receivers,
|
4
|
+
:locale, :currency, :tracking_id, :invoice_fee, :order_items
|
5
|
+
|
6
|
+
def initialize(return_url, cancel_url, ipn_url, memo, sender, receivers)
|
7
|
+
@return_url = return_url
|
8
|
+
@cancel_url = cancel_url
|
9
|
+
@ipn_url = ipn_url
|
10
|
+
@memo = memo
|
11
|
+
@sender = sender
|
12
|
+
@receivers = receivers
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
{}.tap do |hash|
|
17
|
+
hash['returnUrl'] = @return_url
|
18
|
+
hash['cancelUrl'] = @cancel_url
|
19
|
+
hash['ipnNotificationUrl'] = @ipn_url unless @ipn_url.empty?
|
20
|
+
hash['memo'] = @memo
|
21
|
+
hash['localeCode'] = LOCALES[@locale] if @locale
|
22
|
+
hash['currencyCode'] = CURRENCIES[@currency] if @currency
|
23
|
+
hash.merge!(Receiver.to_hash(@receivers))
|
24
|
+
hash.merge!(@sender.to_hash)
|
25
|
+
hash.merge!(OrderItem.to_hash(@order_items)) if @order_items
|
26
|
+
hash['invoiceFee'] = @invoice_fee if @invoice_fee
|
27
|
+
hash['trackingId'] = @tracking_id if @tracking_id
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
to_hash.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PaysonAPI
|
2
|
+
class Receiver
|
3
|
+
FORMAT_STRING = "receiverList.receiver(%d).%s"
|
4
|
+
attr_accessor :email, :amount
|
5
|
+
|
6
|
+
def initialize(email, amount)
|
7
|
+
@email = email
|
8
|
+
@amount = amount
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_hash(receivers)
|
12
|
+
{}.tap do |hash|
|
13
|
+
receivers.each_with_index do |receiver, index|
|
14
|
+
raise "Invalid receiver" unless receiver.instance_of?(self)
|
15
|
+
hash.merge!({
|
16
|
+
FORMAT_STRING % [index, 'email'] => receiver.email,
|
17
|
+
FORMAT_STRING % [index, 'amount'] => receiver.amount
|
18
|
+
})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.parse_receivers(data)
|
24
|
+
i = 0
|
25
|
+
[].tap do |receivers|
|
26
|
+
while data[FORMAT_STRING % [i, 'email']]
|
27
|
+
email = data[FORMAT_STRING % [i, 'email']]
|
28
|
+
amount = data[FORMAT_STRING % [i, 'amount']]
|
29
|
+
receivers << Receiver.new(email, amount)
|
30
|
+
i += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PaysonAPI
|
2
|
+
class Sender
|
3
|
+
attr_accessor :email, :first_name, :last_name
|
4
|
+
|
5
|
+
def initialize(email, first_name, last_name)
|
6
|
+
@email = email
|
7
|
+
@first_name = first_name
|
8
|
+
@last_name = last_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_hash
|
12
|
+
{}.tap do |hash|
|
13
|
+
hash['senderEmail'] = @email
|
14
|
+
hash['senderFirstName'] = @first_name
|
15
|
+
hash['senderLastName'] = @last_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/payson_api.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "payson_api/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "payson_api"
|
8
|
+
s.version = PaysonAPI::VERSION
|
9
|
+
s.authors = ["Christopher Svensson"]
|
10
|
+
s.email = ["stoffus@stoffus.com"]
|
11
|
+
s.homepage = "https://github.com/stoffus/payson_api"
|
12
|
+
s.summary = %q{Client for Payson API}
|
13
|
+
s.description = %q{Client that enables access to the Payson payment gateway API.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency 'require_all'
|
21
|
+
s.add_dependency 'rest-client'
|
22
|
+
|
23
|
+
# specify any dependencies here; for example:
|
24
|
+
# s.add_development_dependency "rspec"
|
25
|
+
# s.add_runtime_dependency "rest-client"
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: payson_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-07-24 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: require_all
|
16
|
-
requirement: &
|
16
|
+
requirement: &70104901674140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70104901674140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rest-client
|
27
|
-
requirement: &
|
27
|
+
requirement: &70104901657500 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,25 +32,30 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: activesupport
|
38
|
-
requirement: &70181536159840 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ! '>='
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 3.0.0
|
44
|
-
type: :runtime
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *70181536159840
|
35
|
+
version_requirements: *70104901657500
|
47
36
|
description: Client that enables access to the Payson payment gateway API.
|
48
37
|
email:
|
49
38
|
- stoffus@stoffus.com
|
50
39
|
executables: []
|
51
40
|
extensions: []
|
52
41
|
extra_rdoc_files: []
|
53
|
-
files:
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- README.rdoc
|
46
|
+
- lib/payson_api.rb
|
47
|
+
- lib/payson_api/client.rb
|
48
|
+
- lib/payson_api/config.rb
|
49
|
+
- lib/payson_api/errors/config_error.rb
|
50
|
+
- lib/payson_api/errors/payson_api_error.rb
|
51
|
+
- lib/payson_api/errors/remote_error.rb
|
52
|
+
- lib/payson_api/order_item.rb
|
53
|
+
- lib/payson_api/pay_data.rb
|
54
|
+
- lib/payson_api/receiver.rb
|
55
|
+
- lib/payson_api/response.rb
|
56
|
+
- lib/payson_api/sender.rb
|
57
|
+
- lib/payson_api/version.rb
|
58
|
+
- payson_api.gemspec
|
54
59
|
homepage: https://github.com/stoffus/payson_api
|
55
60
|
licenses: []
|
56
61
|
post_install_message:
|