openpayu 0.0.2

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