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 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: