payson_api 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|