openpayu 0.0.2

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.
Files changed (102) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +45 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +10 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +193 -0
  11. data/Rakefile +1 -0
  12. data/doc/EmptyResponseError.html +123 -0
  13. data/doc/HttpStatusException.html +123 -0
  14. data/doc/NotImplementedException.html +123 -0
  15. data/doc/OpenPayU.html +436 -0
  16. data/doc/OpenPayU/Configuration.html +1530 -0
  17. data/doc/OpenPayU/Connection.html +381 -0
  18. data/doc/OpenPayU/Document.html +705 -0
  19. data/doc/OpenPayU/Documents.html +117 -0
  20. data/doc/OpenPayU/Documents/Request.html +503 -0
  21. data/doc/OpenPayU/Documents/Response.html +783 -0
  22. data/doc/OpenPayU/Models.html +117 -0
  23. data/doc/OpenPayU/Models/Address.html +861 -0
  24. data/doc/OpenPayU/Models/Buyer.html +587 -0
  25. data/doc/OpenPayU/Models/Buyer/Delivery.html +312 -0
  26. data/doc/OpenPayU/Models/Card.html +507 -0
  27. data/doc/OpenPayU/Models/Fee.html +367 -0
  28. data/doc/OpenPayU/Models/Model.html +1208 -0
  29. data/doc/OpenPayU/Models/NotifyResponse.html +297 -0
  30. data/doc/OpenPayU/Models/Order.html +1155 -0
  31. data/doc/OpenPayU/Models/PayMethod.html +507 -0
  32. data/doc/OpenPayU/Models/Product.html +787 -0
  33. data/doc/OpenPayU/Models/Refund.html +1020 -0
  34. data/doc/OpenPayU/Models/ShippingMethod.html +367 -0
  35. data/doc/OpenPayU/Models/StatusUpdate.html +647 -0
  36. data/doc/OpenPayU/Models/Token.html +507 -0
  37. data/doc/OpenPayU/Order.html +924 -0
  38. data/doc/OpenPayU/Refund.html +269 -0
  39. data/doc/OpenPayU/Token.html +288 -0
  40. data/doc/OpenPayU/XmlBuilder.html +277 -0
  41. data/doc/WrongConfigurationError.html +123 -0
  42. data/doc/WrongNotifyRequest.html +123 -0
  43. data/doc/WrongOrderParameters.html +267 -0
  44. data/doc/WrongSignatureException.html +123 -0
  45. data/doc/_index.html +446 -0
  46. data/doc/class_list.html +54 -0
  47. data/doc/css/common.css +1 -0
  48. data/doc/css/full_list.css +57 -0
  49. data/doc/css/style.css +338 -0
  50. data/doc/file.README.html +281 -0
  51. data/doc/file_list.html +56 -0
  52. data/doc/frames.html +26 -0
  53. data/doc/index.html +281 -0
  54. data/doc/js/app.js +214 -0
  55. data/doc/js/full_list.js +178 -0
  56. data/doc/js/jquery.js +4 -0
  57. data/doc/method_list.html +1007 -0
  58. data/doc/top-level-namespace.html +114 -0
  59. data/lib/openpayu.rb +66 -0
  60. data/lib/openpayu/configuration.rb +62 -0
  61. data/lib/openpayu/connection.rb +65 -0
  62. data/lib/openpayu/document.rb +105 -0
  63. data/lib/openpayu/documents/request.rb +34 -0
  64. data/lib/openpayu/documents/response.rb +48 -0
  65. data/lib/openpayu/exceptions.rb +19 -0
  66. data/lib/openpayu/models/address.rb +12 -0
  67. data/lib/openpayu/models/buyer.rb +11 -0
  68. data/lib/openpayu/models/buyer/delivery.rb +7 -0
  69. data/lib/openpayu/models/buyer/invoice.rb +8 -0
  70. data/lib/openpayu/models/card.rb +10 -0
  71. data/lib/openpayu/models/fee.rb +9 -0
  72. data/lib/openpayu/models/model.rb +151 -0
  73. data/lib/openpayu/models/notify_response.rb +9 -0
  74. data/lib/openpayu/models/order.rb +28 -0
  75. data/lib/openpayu/models/pay_method.rb +10 -0
  76. data/lib/openpayu/models/product.rb +10 -0
  77. data/lib/openpayu/models/refund.rb +41 -0
  78. data/lib/openpayu/models/shipping_method.rb +9 -0
  79. data/lib/openpayu/models/status_update.rb +14 -0
  80. data/lib/openpayu/models/token.rb +10 -0
  81. data/lib/openpayu/order.rb +119 -0
  82. data/lib/openpayu/refund.rb +26 -0
  83. data/lib/openpayu/token.rb +27 -0
  84. data/lib/openpayu/version.rb +4 -0
  85. data/lib/openpayu/xml_builder.rb +23 -0
  86. data/lib/openpayu_ruby.rb +2 -0
  87. data/openpayu_ruby.gemspec +40 -0
  88. data/spec/cassettes/cancel_order.yml +50 -0
  89. data/spec/cassettes/create_order.yml +51 -0
  90. data/spec/cassettes/refund_order.yml +100 -0
  91. data/spec/cassettes/retrieve_order.yml +51 -0
  92. data/spec/cassettes/update_order.yml +50 -0
  93. data/spec/integration/order_spec.rb +103 -0
  94. data/spec/openpayu.yml +11 -0
  95. data/spec/spec_helper.rb +27 -0
  96. data/spec/test_objects/order.rb +97 -0
  97. data/spec/unit/configuration_spec.rb +71 -0
  98. data/spec/unit/document_spec.rb +18 -0
  99. data/spec/unit/models/order_spec.rb +82 -0
  100. data/spec/unit/models/refund_spec.rb +24 -0
  101. data/spec/unit/openpayu_spec.rb +27 -0
  102. metadata +327 -0
@@ -0,0 +1,114 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.8.7.2
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+
36
+
37
+ <span class="title">Top Level Namespace</span>
38
+
39
+
40
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
+ </div>
42
+
43
+ <div id="search">
44
+
45
+ <a class="full_list_link" id="class_list_link"
46
+ href="class_list.html">
47
+ Class List
48
+ </a>
49
+
50
+ <a class="full_list_link" id="method_list_link"
51
+ href="method_list.html">
52
+ Method List
53
+ </a>
54
+
55
+ <a class="full_list_link" id="file_list_link"
56
+ href="file_list.html">
57
+ File List
58
+ </a>
59
+
60
+ </div>
61
+ <div class="clear"></div>
62
+ </div>
63
+
64
+ <iframe id="search_frame"></iframe>
65
+
66
+ <div id="content"><h1>Top Level Namespace
67
+
68
+
69
+
70
+ </h1>
71
+
72
+ <dl class="box">
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </dl>
82
+ <div class="clear"></div>
83
+
84
+ <h2>Defined Under Namespace</h2>
85
+ <p class="children">
86
+
87
+
88
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="OpenPayU.html" title="OpenPayU (module)">OpenPayU</a></span>
89
+
90
+
91
+
92
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="EmptyResponseError.html" title="EmptyResponseError (class)">EmptyResponseError</a></span>, <span class='object_link'><a href="HttpStatusException.html" title="HttpStatusException (class)">HttpStatusException</a></span>, <span class='object_link'><a href="NotImplementedException.html" title="NotImplementedException (class)">NotImplementedException</a></span>, <span class='object_link'><a href="WrongConfigurationError.html" title="WrongConfigurationError (class)">WrongConfigurationError</a></span>, <span class='object_link'><a href="WrongNotifyRequest.html" title="WrongNotifyRequest (class)">WrongNotifyRequest</a></span>, <span class='object_link'><a href="WrongOrderParameters.html" title="WrongOrderParameters (class)">WrongOrderParameters</a></span>, <span class='object_link'><a href="WrongSignatureException.html" title="WrongSignatureException (class)">WrongSignatureException</a></span>
93
+
94
+
95
+ </p>
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+ </div>
106
+
107
+ <div id="footer">
108
+ Generated on Tue Dec 17 15:20:58 2013 by
109
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
110
+ 0.8.7.2 (ruby-1.9.3).
111
+ </div>
112
+
113
+ </body>
114
+ </html>
data/lib/openpayu.rb ADDED
@@ -0,0 +1,66 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require_relative 'openpayu/xml_builder'
3
+ require_relative 'openpayu/version'
4
+ require_relative 'openpayu/configuration'
5
+ require_relative 'openpayu/connection'
6
+ require_relative 'openpayu/exceptions'
7
+ require_relative 'openpayu/order'
8
+ require_relative 'openpayu/refund'
9
+ require_relative 'openpayu/token'
10
+ require_relative 'openpayu/document'
11
+ require_relative 'openpayu/models/model'
12
+ require_relative 'openpayu/models/order'
13
+ require_relative 'openpayu/documents/request'
14
+ require_relative 'openpayu/documents/response'
15
+ require_relative 'openpayu/models/address'
16
+ require_relative 'openpayu/models/buyer'
17
+ require_relative 'openpayu/models/buyer/delivery'
18
+ require_relative 'openpayu/models/buyer/invoice'
19
+ require_relative 'openpayu/models/card'
20
+ require_relative 'openpayu/models/fee'
21
+ require_relative 'openpayu/models/token'
22
+ require_relative 'openpayu/models/pay_method'
23
+ require_relative 'openpayu/models/product'
24
+ require_relative 'openpayu/models/shipping_method'
25
+ require_relative 'openpayu/models/refund'
26
+ require_relative 'openpayu/models/status_update'
27
+ require_relative 'openpayu/models/notify_response'
28
+
29
+ module OpenPayU
30
+
31
+ # Generate a signature for signing form sent directly to PayU
32
+ #
33
+ # @param [Hash] form_fields Hash with all form fields with values
34
+ # @param [String] signature_key defaults to Configuration.signature_key
35
+ # @param [String] algorithm defaults to OpenPayU::Configuration.algorithm
36
+ # @param [String] merchant_pos_id defaults to Configuration.merchant_pos_id
37
+ # @return [String] Signature that should be inserted to field
38
+ # with name "OpenPayu-Signature"
39
+ def self.sign_form(form_fields, key = nil, algorithm = nil, pos_id = nil)
40
+ sorted_values = form_fields.sort.map { |array| array[1] }.join
41
+ Document.new.generate_signature_structure(
42
+ sorted_values,
43
+ algorithm || Configuration.algorithm,
44
+ pos_id || Configuration.merchant_pos_id,
45
+ key || Configuration.signature_key
46
+ )
47
+ end
48
+
49
+ # Generate a form body for hosted order
50
+ #
51
+ # @param [Hash] order Hash
52
+ # @return [String] A full form containign an order
53
+ def self.hosted_order_form(order)
54
+ @order = Models::Order.new(order)
55
+ render_hash = @order.to_flatten_hash
56
+ html_form = "<form method='post' " +
57
+ "action='#{Configuration.get_base_url}order'>\n"
58
+ render_hash.each do |key, value|
59
+ html_form << "<input type='hidden' name='#{key}' value='#{value}' />\n"
60
+ end
61
+
62
+ html_form << "<input type='hidden' name='OpenPayu-Signature'
63
+ value='#{sign_form(render_hash)}' />
64
+ <button type='submit' formtarget='_blank' />\n</form>"
65
+ end
66
+ end
@@ -0,0 +1,62 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'singleton'
3
+
4
+ module OpenPayU
5
+
6
+ class Configuration
7
+
8
+ include Singleton
9
+
10
+ class << self
11
+ attr_accessor :env, :merchant_pos_id, :pos_auth_key, :client_id,
12
+ :client_secret, :signature_key, :service_domain, :country, :data_format,
13
+ :algorithm, :protocol, :order_url, :notify_url, :continue_url
14
+
15
+ def configure(file_path = nil)
16
+ set_defaults
17
+ if block_given?
18
+ yield self
19
+ else
20
+ file = File.open(file_path) if file_path && File.exists?(file_path)
21
+ env = defined?(Rails) ? Rails.env : ENV['RACK_ENV']
22
+ config = YAML.load(file)[env]
23
+ if config.present?
24
+ config.each_pair do |key, value|
25
+ send("#{key}=", value)
26
+ end
27
+ end
28
+ end
29
+ valid?
30
+ end
31
+
32
+ def set_defaults
33
+ @service_domain = 'payu.com'
34
+ @env = 'sandbox'
35
+ @country = 'pl'
36
+ @algorithm = 'MD5'
37
+ end
38
+
39
+ def required_parameters
40
+ [:merchant_pos_id, :signature_key]
41
+ end
42
+
43
+ def valid?
44
+ required_parameters.each do |parameter|
45
+ if send(parameter).nil? || send(parameter).blank?
46
+ raise WrongConfigurationError, "Parameter #{parameter} is invalid."
47
+ end
48
+ end
49
+ true
50
+ end
51
+
52
+ def get_base_url
53
+ "#{@protocol}://#{@env}.#{@service_domain}/api/v2/"
54
+ end
55
+
56
+ def use_ssl?
57
+ @protocol == 'https'
58
+ end
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,65 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'uri'
5
+
6
+ module OpenPayU
7
+
8
+ class Connection
9
+
10
+ def self.post(url, data, headers)
11
+ uri = URI.parse(url)
12
+ http = Net::HTTP.new(uri.host, uri.port)
13
+ http.use_ssl = true if OpenPayU::Configuration.use_ssl?
14
+ request = Net::HTTP::Post.new(uri.path)
15
+ request.body = data
16
+ request['Content-Type'] =
17
+ "application/#{OpenPayU::Configuration.data_format}"
18
+ request['OpenPayu-Signature'] = headers['OpenPayu-Signature']
19
+ response = http.request(request)
20
+ { response: response, request: request }
21
+ end
22
+
23
+ def self.put(url, data, headers)
24
+ uri = URI.parse(url)
25
+ http = Net::HTTP.new(uri.host, uri.port)
26
+ http.use_ssl = true if OpenPayU::Configuration.use_ssl?
27
+ request = Net::HTTP::Put.new(uri.path)
28
+ request.body = data
29
+ request['Content-Type'] =
30
+ "application/#{OpenPayU::Configuration.data_format}"
31
+ request['OpenPayu-Signature'] = headers['OpenPayu-Signature']
32
+ response = http.request(request)
33
+ { response: response, request: request }
34
+ end
35
+
36
+ def self.get(url, data, headers)
37
+ common_connection(url, data, headers, 'GET')
38
+ end
39
+
40
+ def self.delete(url, data, headers)
41
+ common_connection(url, data, headers, 'DELETE')
42
+ end
43
+
44
+ private
45
+
46
+ def self.common_connection(url, data, headers, method)
47
+ uri = URI.parse(url)
48
+ http = Net::HTTP.new(uri.host, uri.port)
49
+ http.use_ssl = true if OpenPayU::Configuration.use_ssl?
50
+ request =
51
+ if method == 'DELETE'
52
+ Net::HTTP::Delete.new(uri.request_uri, headers)
53
+ else
54
+ Net::HTTP::Get.new(uri.request_uri, headers)
55
+ end
56
+ request['Content-Type'] =
57
+ "application/#{OpenPayU::Configuration.data_format}"
58
+ request['OpenPayu-Signature'] = headers['OpenPayu-Signature']
59
+ response = http.request(request)
60
+ { response: response, request: request }
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,105 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'digest'
3
+
4
+ module OpenPayU
5
+
6
+ class Document
7
+
8
+ def generate_signature_structure(data, algorithm, pos_id = '', key = '')
9
+ if key.empty?
10
+ raise WrongConfigurationError,
11
+ 'Merchant Signature Key (signature_key)
12
+ should not be null or empty.'
13
+ end
14
+ raise WrongConfigurationError,
15
+ 'Merchant Pos Id (merchant_pos_id) should
16
+ not be null or empty.' if pos_id.blank?
17
+ signature = generate_signature(data, algorithm, key)
18
+ "sender=#{pos_id};signature=#{signature};algorithm=#{algorithm}"
19
+ end
20
+
21
+ def generate_signature(data, algorithm, signature_key)
22
+ data = data + signature_key.to_s
23
+ if algorithm == 'MD5'
24
+ signature = Digest::MD5.hexdigest(data)
25
+ elsif %w(SHA SHA1 SHA-1).include? algorithm
26
+ signature = Digest::SHA1.hexdigest data
27
+ elsif %w(SHA-256 SHA256 SHA_256).include? algorithm
28
+ signature = Digest::SHA256.hexdigest data
29
+ else
30
+ signature = ''
31
+ end
32
+ signature
33
+ end
34
+
35
+ def verify_response
36
+ unless @response
37
+ raise EmptyResponseError,
38
+ "Got empty response from request: #{@request.try(:body)}"
39
+ end
40
+ if (@message_name == 'OrderNotifyRequest' ||
41
+ %w(200 201 422 302).include?(response.code)) &&
42
+ verify_signature(@body)
43
+ true
44
+ else
45
+ raise HttpStatusException,
46
+ "Invalid HTTP response code (#{@response.code}).
47
+ Response body: #{@body}."
48
+ end
49
+ end
50
+
51
+ def verify_signature(message)
52
+ signature = parse_signature
53
+ generated_signature = generate_signature(
54
+ message,
55
+ signature['algorithm'],
56
+ OpenPayU::Configuration.signature_key
57
+ )
58
+ if generated_signature == signature['signature']
59
+ true
60
+ else
61
+ raise WrongSignatureException,
62
+ "Invalid signature: Got message signed with:
63
+ #{signature["signature"]}. Generated signature:
64
+ #{generated_signature}"
65
+ end
66
+
67
+ end
68
+
69
+ def parse_signature
70
+ parameters = {}
71
+ get_signature.split(';').each do |parameter|
72
+ k, v = parameter.split('=')
73
+ parameters[k] = v
74
+ end
75
+ parameters
76
+ end
77
+
78
+ def get_signature
79
+ @response['X-OpenPayU-Signature'] ||
80
+ @response['x-openpayu-signature'] ||
81
+ @response['openpayu-signature'] ||
82
+ @response.headers['x-openpayu-signature'] ||
83
+ @response.headers['openpayu-signature']
84
+ end
85
+
86
+ def underscore_keys(hash)
87
+ deep_transform_keys(hash) { |key| key.underscore }
88
+ end
89
+
90
+ def deep_transform_keys(hash, &block)
91
+ result = {}
92
+ hash.each do |key, value|
93
+ result[yield(key)] =
94
+ if value.is_a?(Hash)
95
+ deep_transform_keys(value, &block)
96
+ else
97
+ value
98
+ end
99
+ end
100
+ result
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module OpenPayU
3
+ module Documents
4
+ class Request < Document
5
+ attr_accessor :headers, :body
6
+
7
+ def initialize(data)
8
+ @body = data
9
+ set_headers
10
+ end
11
+
12
+ def set_headers
13
+ @headers = {
14
+ 'OpenPayu-Signature' => generate_signature_structure(
15
+ @body,
16
+ OpenPayU::Configuration.algorithm,
17
+ OpenPayU::Configuration.merchant_pos_id,
18
+ OpenPayU::Configuration.signature_key
19
+ ),
20
+ 'openpayu-signature' => generate_signature_structure(
21
+ @body,
22
+ OpenPayU::Configuration.algorithm,
23
+ OpenPayU::Configuration.merchant_pos_id,
24
+ OpenPayU::Configuration.signature_key
25
+ )
26
+ }
27
+ end
28
+
29
+ def [](header_name)
30
+ @headers[header_name]
31
+ end
32
+ end
33
+ end
34
+ end