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 ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*.gem
6
+ .rvmrc
7
+ doc
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'require_all'
6
+ gem 'rest-client'
7
+
8
+ group :test, :development do
9
+ gem 'guard-test'
10
+ gem 'rake'
11
+ platforms :ruby do
12
+ gem 'rb-readline'
13
+ end
14
+ end
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,2 @@
1
+ require 'require_all'
2
+ require_rel 'payson_api'
@@ -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,13 @@
1
+ module PaysonAPI
2
+ module Errors
3
+ class ConfigError < PaysonAPIError
4
+ def initialize(msg)
5
+ @msg = msg
6
+ end
7
+
8
+ def to_s
9
+ @msg
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module PaysonAPI
2
+ module Errors
3
+ class PaysonAPIError < StandardError
4
+ # Base error.
5
+ end
6
+ end
7
+ 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
@@ -0,0 +1,3 @@
1
+ module PaysonAPI
2
+ VERSION = "0.0.3"
3
+ end
@@ -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.2
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: &70181536161320 !ruby/object:Gem::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: *70181536161320
24
+ version_requirements: *70104901674140
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rest-client
27
- requirement: &70181536160680 !ruby/object:Gem::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: *70181536160680
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: