complete_payment_systems 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5a30b99b8dc3c9b281274253a749868aff351cce
4
+ data.tar.gz: f365572a3c26dbc912dc1b16743853e3cc78e7b0
5
+ SHA512:
6
+ metadata.gz: afd6276737dda4f26fb571b4040997f5b17c1a50989572849af97a043c67e25614fd5366d79f44aa55e2b2093261d9c5b8b236fc1c679428b8f71f154571218e
7
+ data.tar.gz: 670de0ec274fcba92b69a817638907c2639e4dd40bcdd399e18140b09c7ab8be8de434c627decb380004eb2e8ebc8ff73eaf1345eb150e28d992edc10638efe9
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in complete_payment_systems.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Epigene
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # CompletePaymentSystems
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'complete_payment_systems'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install complete_payment_systems
18
+
19
+ ## Usage
20
+
21
+ The complete module name is CompletePaymentSystems, but the aliased shorthand CPS is recommended.
22
+
23
+ ### Configure Defaults
24
+ in */config/initializers/cps.rb*
25
+
26
+ ```ruby
27
+ CPS.configure do |config|
28
+ # Your CPS account user
29
+ config.default_user = "pasta_test_3d"
30
+
31
+ # server-to-server POST response processing route
32
+ config.default_callback_url = "http://www.app.com/cps/process"
33
+
34
+ # Url to "Thank-you"-"Retry" differ route
35
+ config.default_redirect_url = "http://www.app.com/cps/return"
36
+ config.default_product_name = "Product"
37
+ config.default_product_url = "www.test.com"
38
+ config.default_country = "US"
39
+
40
+ # Used in client data, like street and zip, if you choose not to ask for these
41
+ config.placeholder_value = "PLACEHOLDER"
42
+
43
+ config.cps_url = "https://3ds.cps.lv/GatorServo/request" # This will probably never change
44
+ config.cps_method = "sendForAuth" # This will also probably remain the same
45
+ config.cert_pass = 'pasS%123' # your cert chain password
46
+
47
+ # Your .pem format cert chain location
48
+ config.rsa_cert_path = "#{CPS.root}/lib/complete_payment_systems/certs/Pasta_test_3d.pem"
49
+ end
50
+ ```
51
+
52
+ ### Build a payment request
53
+ Instantiate a CPS::Request object, passit a hash with parameters:
54
+ ```ruby
55
+ hash = {
56
+ order: (Time.now.to_i), # Pass the unique purchase ID here
57
+ value: 100 , # Pass the purchase value in cents here (1$ purcase value = 100)
58
+ currency: "EUR", # Pass the purchase currency 3-letter code here ($ = "USD")
59
+ holder_name: "John", # Ask buyer for this in a form
60
+ holder_surname: "Doe", # Ask buyer for this in a form
61
+ card_number: "4314229999999913", # Ask buyer for this in a form
62
+ card_exp: "01/18", # Ask buyer for this in a form
63
+ card_cvv: "123", # Ask buyer for this in a form
64
+ holder_ip: "123.124.125.226", # Get this from request.remote_ip
65
+ holder_street: "NOT USED", # (Optional) Ask buyer for this in a form
66
+ holder_zip: "NOT USED", # (Optional) Ask buyer for this in a form
67
+ holder_city: "NOT USED", # (Optional) Ask buyer for this in a form
68
+ holder_country: "US", # (Optional) Ask buyer for this in a form
69
+ holder_email: "test@domain.com", # (Optional) Ask buyer for this in a form
70
+ user: "Some User" # Best defined in config and not passed
71
+ callback_url: "http://www.app.lv", # Best defined in config and not passed
72
+ redirect_url: "http://www.app.lv", # Best defined in config and not passed
73
+ product_name: "Product", # Best defined in config and not passed
74
+ product_url: "www.test.com" # Best defined in config and not passed
75
+ }
76
+ CPS::Request.new(hash)
77
+ ```
78
+ # Process response
79
+ Instantiate a CPS::Response object with an xml parameter (get the xml from server response .body)
80
+ ```ruby
81
+ @response = CPS.Response.new(request_response.body)
82
+ ```
83
+ API exposes reader methods #xml, #response_hash, #code, #message
84
+ as well as convenience methods #ok? and #signature_ok?
85
+
86
+ ```ruby
87
+ r = CPS::Response.new(valid_xml_response)
88
+ r.response_hash
89
+ => {"referenceId"=>"9095359",
90
+ "orderId"=>"1422019383",
91
+ "value"=>"100",
92
+ "currency"=>"USD",
93
+ "resultCode"=>"000",
94
+ "resultMessage"=>"Captured",
95
+ "resultText"=>"Captured",
96
+ "digiSignature"=>
97
+ "HlcnASe5fZyM7uVz4xwqp ... XGx5SVqSA=="}
98
+ r.code
99
+ => "000"
100
+ r.message
101
+ => "Captured"
102
+ r.signature_ok?
103
+ => true
104
+ r.ok?
105
+ => true
106
+ ```
107
+
108
+ ## Contributing
109
+
110
+ 1. Fork it ( https://github.com/[my-github-username]/complete_payment_systems/fork )
111
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
112
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
113
+ 4. Push to the branch (`git push origin my-new-feature`)
114
+ 5. Create a new Pull Request
115
+
116
+ ## Dev Notes
117
+
118
+ calbackUrl atbilde atnāks pirmā, jo te mēs sūtam atbildi pa tiešo no mūsu servera uz jūso noradītu URL
119
+
120
+ #### Direct-3D request example
121
+ hash = {
122
+ order: (Time.now.to_i), # Pass the unique purchase ID here
123
+ value: 166, # Pass the purchase value in cents here (1$ purcase value = 100)
124
+ currency: (params["currency"]), # Pass the purchase currency 3-letter code here ($ = "USD")
125
+ holder_name: "John", # Ask buyer for this in a form
126
+ holder_surname: "Doe", # Ask buyer for this in a form
127
+ card_number: "4314229999999913", # Ask buyer for this in a form
128
+ card_exp: "01/18", # Ask buyer for this in a form
129
+ card_cvv: "123", # Ask buyer for this in a form
130
+ holder_ip: "123.124.125.226", # Get this from request.remote_ip
131
+ holder_street: "NOT USED", # (Optional) Ask buyer for this in a form
132
+ holder_zip: "NOT USED", # (Optional) Ask buyer for this in a form
133
+ holder_city: "NOT USED", # (Optional) Ask buyer for this in a form
134
+ holder_country: "US", # (Optional) Ask buyer for this in a form
135
+ holder_email: "test@domain.com", # (Optional) Ask buyer for this in a form
136
+ user: "Some User" # Best defined in config and not passed
137
+ callback_url: "http://www.app.lv", # Best defined in config and not passed
138
+ redirect_url: "http://www.app.lv", # Best defined in config and not passed
139
+ product_name: "Product", # Best defined in config and not passed
140
+ product_url: "www.test.com" # Best defined in config and not passed
141
+ }
142
+ @request = CPS::Request.new(hash)
143
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'complete_payment_systems/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "complete_payment_systems"
8
+ spec.version = CompletePaymentSystems::VERSION
9
+ spec.date = Date.today.to_s
10
+ spec.authors = ["Epigene"]
11
+ spec.email = ["augusts.bautra@gmail.com"]
12
+ spec.summary = %q{A client for CPS (Complete Payment Systems) card payment service}
13
+ spec.description = %q{Coming soon...}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency 'unirest'
23
+ spec.add_dependency 'activesupport'
24
+ spec.add_dependency 'nokogiri', '~> 1.6.6'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.6"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency 'rspec', "~> 3.1.0"
29
+ end
data/cps.xml ADDED
@@ -0,0 +1,43 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <cpsxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:schemaLocation="http://www.cps.lv/xml/ns/cpsxml https://3ds.cps.lv/GatorServo/Gator_SendForAuth.xsd"
4
+ xmlns="http://www.cps.lv/xml/ns/cpsxml">
5
+ <header xmlns="">
6
+ <responsetype>direct</responsetype>
7
+ <user>pasta_test_3d</user>
8
+ <type>sendForAuth</type>
9
+ <transType>DB</transType>
10
+ <digiSignature>NP+o4wK17G3tqcTF5K2vfBjXQ4RpCLEYPoK9I99/9GPQO95fD0Xp+DueUV4c
11
+ AtgNQmQg4C2BTw0vh1fme8PQanaGF50WJOTdgXdU5ygRxkjja4EyA9cDe1cq
12
+ Ex7iqtSazv2FZXu/6RfVgwcoy4SRuNuQrsDqo6/7isJ/BpgppTI=
13
+ </digiSignature>
14
+ <callbackUrl>www.google.lv</callbackUrl>
15
+ <redirectUrl>http://www.google.lv</redirectUrl>
16
+ </header>
17
+ <request xmlns="">
18
+ <orderNumber>1422028510</orderNumber>
19
+ <cardholder>
20
+ <firstName>Test</firstName>
21
+ <lastName>User</lastName>
22
+ <street>NOT USED</street>
23
+ <zip>NOT USED</zip>
24
+ <city>NOT USED</city>
25
+ <country>LV</country>
26
+ <email>hi@creo.mobi</email>
27
+ <ip>123.124.125.226</ip>
28
+ </cardholder>
29
+ <card>
30
+ <cardNumber>4314229999999913</cardNumber>
31
+ <expires>01/18</expires>
32
+ <cvv>123</cvv>
33
+ </card>
34
+ <amount>
35
+ <value>100</value>
36
+ <currency>USD</currency>
37
+ </amount>
38
+ <product>
39
+ <productName>Product</productName>
40
+ <productUrl>www.test.com</productUrl>
41
+ </product>
42
+ </request>
43
+ </cpsxml>
@@ -0,0 +1,129 @@
1
+ require "complete_payment_systems/version"
2
+ require "complete_payment_systems/request_processing"
3
+ require "complete_payment_systems/response_processing"
4
+ #require 'rubygems'
5
+ require 'openssl'
6
+ require 'digest/sha1'
7
+ require 'base64'
8
+ require 'unirest'
9
+ require 'active_support/all'
10
+ require 'nokogiri'
11
+
12
+ module CompletePaymentSystems
13
+
14
+ CPS = CompletePaymentSystems
15
+ ROOT = File.expand_path("../..", __FILE__)
16
+
17
+ def self.root
18
+ ROOT
19
+ end
20
+
21
+ class << self
22
+ attr_accessor :config
23
+ end
24
+
25
+ def self.configure
26
+ self.config ||= Config.new
27
+ yield(config)
28
+ end
29
+
30
+ class Config
31
+ attr_accessor :default_user, :default_callback_url, :default_redirect_url, :default_product_name, :default_product_url, :default_country, :placeholder_value,
32
+ :cps_url, :cps_method, :cert_pass, :rsa_cert_path, :success_regex
33
+
34
+ def initialize
35
+ @default_user = "pasta_test_3d"
36
+ @default_callback_url = "http://www.google.com"
37
+ @default_redirect_url = "http://www.google.lv"
38
+ @default_product_name = "Product"
39
+ @default_product_url = "www.test.com"
40
+ @default_country = "US"
41
+ @placeholder_value = "PLACEHOLDER"
42
+
43
+ @cps_url = "https://3ds.cps.lv/GatorServo/request"
44
+ @cps_method = "sendForAuth"
45
+ @cert_pass = 'pasS%123'
46
+ @rsa_cert_path = "#{CPS.root}/lib/complete_payment_systems/certs/Pasta_test_3d.pem"
47
+ @success_regex = /Captured/
48
+ end
49
+
50
+ end
51
+
52
+ CPS.configure {}
53
+
54
+ # TO-DO Delete this after production checks
55
+ def self.make_xml
56
+ values = {
57
+ user: "pasta_test_3d", # "test_pasta_sign" for direct, "pasta_test_3d" for direct with 3D
58
+ callback_url: "http://www.google.lv",
59
+ redirect_url: "http://www.google.lv",
60
+ order: (Time.now.to_i),
61
+ holder_name: "Test",
62
+ holder_surname: "User",
63
+ holder_street: "NOT USED",
64
+ holder_zip: "NOT USED",
65
+ holder_city: "NOT USED",
66
+ holder_country: "LV",
67
+ holder_email: "hi@creo.mobi",
68
+ holder_ip: "123.124.125.226",
69
+ card_number: "4314229999999913", # 4012001037167778 for direct, For 3D-Secure number is 4314229999999913
70
+ card_exp: "01/18", # 06/18 for direct, 3D-sec is "01/18"
71
+ card_cvv: "123", # 999 for direct, 3D-sec is "123"
72
+ product_name: "Product",
73
+ product_url: "www.test.com"
74
+ }
75
+
76
+ values[:signature] = CPS.sign(user: values[:user], card_number: values[:card_number])
77
+
78
+ values[:signature_line] = '<digiSignature>' + values[:signature] + '</digiSignature>'
79
+
80
+ xml_path = "#{CPS.root}/cps.xml"
81
+ a = File.open(xml_path,'w') do |file|
82
+ file.write(%Q|<?xml version="1.0" encoding="UTF-8" ?>\n|)
83
+ file.write(%Q|<cpsxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n|)
84
+ file.write(%Q| xsi:schemaLocation="http://www.cps.lv/xml/ns/cpsxml https://3ds.cps.lv/GatorServo/Gator_SendForAuth.xsd"\n|)
85
+ file.write(%Q| xmlns="http://www.cps.lv/xml/ns/cpsxml">\n|)
86
+ file.write(%Q| <header xmlns="">\n|)
87
+ file.write(%Q| <responsetype>direct</responsetype>\n|)
88
+ file.write(%Q| <user>#{values[:user]}</user>\n|)
89
+ file.write(%Q| <type>sendForAuth</type>\n|)
90
+ file.write(%Q| <transType>DB</transType>\n|)
91
+ file.write(%Q| | + values[:signature_line] + "\n")
92
+ file.write(%Q| <callbackUrl>#{values[:callback_url]}</callbackUrl>\n|)
93
+ file.write(%Q| <redirectUrl>#{values[:redirect_url]}</redirectUrl>\n|)
94
+ file.write(%Q| </header>\n|)
95
+ file.write(%Q| <request xmlns="">\n|)
96
+ file.write(%Q| <orderNumber>#{values[:order]}</orderNumber>\n|)
97
+ file.write(%Q| <cardholder>\n|)
98
+ file.write(%Q| <firstName>#{values[:holder_name]}</firstName>\n|)
99
+ file.write(%Q| <lastName>#{values[:holder_surname]}</lastName>\n|)
100
+ file.write(%Q| <street>#{values[:holder_street]}</street>\n|)
101
+ file.write(%Q| <zip>#{values[:holder_zip]}</zip>\n|)
102
+ file.write(%Q| <city>#{values[:holder_city]}</city>\n|)
103
+ file.write(%Q| <country>#{values[:holder_country]}</country>\n|)
104
+ file.write(%Q| <email>#{values[:holder_email]}</email>\n|)
105
+ file.write(%Q| <ip>#{values[:holder_ip]}</ip>\n|)
106
+ file.write(%Q| </cardholder>\n|)
107
+ file.write(%Q| <card>\n|)
108
+ file.write(%Q| <cardNumber>#{values[:card_number]}</cardNumber>\n|)
109
+ file.write(%Q| <expires>#{values[:card_exp]}</expires>\n|)
110
+ file.write(%Q| <cvv>#{values[:card_cvv]}</cvv>\n|)
111
+ file.write(%Q| </card>\n|)
112
+ file.write(%Q| <amount>\n|)
113
+ file.write(%Q| <value>100</value>\n|)
114
+ file.write(%Q| <currency>USD</currency>\n|)
115
+ file.write(%Q| </amount>\n|)
116
+ file.write(%Q| <product>\n|)
117
+ file.write(%Q| <productName>#{values[:product_name]}</productName>\n|)
118
+ file.write(%Q| <productUrl>#{values[:product_url]}</productUrl>\n|)
119
+ file.write(%Q| </product>\n|)
120
+ file.write(%Q| </request>\n|)
121
+ file.write(%Q|</cpsxml>|)
122
+ end
123
+
124
+ return File.read(xml_path)
125
+ end
126
+
127
+ end
128
+
129
+ CPS = CompletePaymentSystems
@@ -0,0 +1,64 @@
1
+ Bag Attributes
2
+ localKeyID: 26 83 8E 91 1D 9E AD 51 06 F0 F3 FF 51 32 B8 F3 59 34 65 C7
3
+ friendlyName: pasta_test_3d
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIICXQIBAAKBgQCbb+tyvaH9XEVqgf5yuCF79cFoRvAU9dJXq25KlMq7xAL4H0Hh
7
+ SR5tEdkQPPLOA5Xg4A68X9EjbRwkBhIpcfcxWnx7nCsZKGpKVByIicWgF8H71Psb
8
+ o9nRzehJhAw/kJMMa2KbWk9TQ8iwMwRQgBHl51eN6Y14/yNOGWRghPhhHwIDAQAB
9
+ AoGAJv3UWlwnnp7e6vDhG3YFMEtd0QK6hweDVGq0qBDbKm7pL8TnidQFxeaMRP6F
10
+ ChjsKBUMnUSL+g8M2ByNwcfM8jhCM3GDNn6wjatqq3bRC3miSFVzyRA1VO9wAAWS
11
+ gL54iwySrjWIHjZ12SS6dqSodP8fTxoIR5fFGvUuflQtSIECQQDSAdgceXG/MSmm
12
+ WC+9+JzBNMC4jjRQLYgAFDlKl4/jADo/S5qgcWmgur037PDmcy8wVcxZGUoz2IR+
13
+ lIEVLfFpAkEAvXqUvcC6MS35AJqB4eei4D24z3+8yOwdYZ8A0KZLAcQBDpnjEval
14
+ BMgxmf3oZW/4/rHOn6lZxX0SsbYIAZxlRwJAKEn8SPIvlUt8PxJ6DksM37AcLQvz
15
+ E1K43bMDjsDm9NjNU+lQP+miJxjMRldpm/yLGA3Nx2YnqyyltpcM8KBAyQJBAIes
16
+ kXr52JjEcWrUN7JZmY/1wjKaJcS9BSDUqNG+cTD3d0ZMPINkpq6w5ot8ev6/WcyN
17
+ 5wT+T3CQ6WTkkgENSpsCQQDEjzZVysbMwi/bbMU7awvy38YgmudFnowma57660vn
18
+ Y/zYHlg6TIKbvuUzKbDXtR1v6V/Oo8Fwz6WImu25RYMw
19
+ -----END RSA PRIVATE KEY-----
20
+ Bag Attributes
21
+ localKeyID: 26 83 8E 91 1D 9E AD 51 06 F0 F3 FF 51 32 B8 F3 59 34 65 C7
22
+ friendlyName: pasta_test_3d
23
+ subject=/CN=pasta_test_3d
24
+ issuer=/CN=AdminCA1/O=EJBCA Sample/C=SE
25
+ -----BEGIN CERTIFICATE-----
26
+ MIICbjCCAVagAwIBAgIIY2pN0FJ3p1EwDQYJKoZIhvcNAQEFBQAwNzERMA8GA1UE
27
+ AwwIQWRtaW5DQTExFTATBgNVBAoMDEVKQkNBIFNhbXBsZTELMAkGA1UEBhMCU0Uw
28
+ HhcNMTQwNTI4MTM1ODE0WhcNMTgwNTI3MTM1ODE0WjAYMRYwFAYDVQQDDA1wYXN0
29
+ YV90ZXN0XzNkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbb+tyvaH9XEVq
30
+ gf5yuCF79cFoRvAU9dJXq25KlMq7xAL4H0HhSR5tEdkQPPLOA5Xg4A68X9EjbRwk
31
+ BhIpcfcxWnx7nCsZKGpKVByIicWgF8H71Psbo9nRzehJhAw/kJMMa2KbWk9TQ8iw
32
+ MwRQgBHl51eN6Y14/yNOGWRghPhhHwIDAQABoyEwHzAdBgNVHQ4EFgQUJoOOkR2e
33
+ rVEG8PP/UTK481k0ZccwDQYJKoZIhvcNAQEFBQADggEBABLiKL9np1amPZTFdPNf
34
+ IU0b8d/oA7I/5jI04ze1en5GB4YkZbAeCxR9P/ox/+o32hJCYOw9Tiho7RabguA6
35
+ FC/weiJ6vt8lrdpJ+Vjcoq4pCzNOR6JFDRTNWqnJ6t+/rOQ5twXSisI86dXL3F1j
36
+ zHfaZgRMQ1sErab1G+Z3Bz0Px42M6+7unEBJuJVmsy1EuL40qSP68SXvl4uNsTua
37
+ 8MNmYneG7gvV6GxnQ/U1z6M5Z0HGwpY9lYD9f4M01UyrlDoqzxDmUwLsZX4KmSvT
38
+ SabDHwvcoxfGdV5TiKJBqpvMa9YgHBGV+F3Hei/4a14VLx4amzf2wuSbHRZ/sAYJ
39
+ cU4=
40
+ -----END CERTIFICATE-----
41
+ Bag Attributes
42
+ friendlyName: AdminCA1
43
+ subject=/CN=AdminCA1/O=EJBCA Sample/C=SE
44
+ issuer=/CN=AdminCA1/O=EJBCA Sample/C=SE
45
+ -----BEGIN CERTIFICATE-----
46
+ MIIDUzCCAjugAwIBAgIIBtGA8vEQJpgwDQYJKoZIhvcNAQEFBQAwNzERMA8GA1UE
47
+ AwwIQWRtaW5DQTExFTATBgNVBAoMDEVKQkNBIFNhbXBsZTELMAkGA1UEBhMCU0Uw
48
+ HhcNMTEwOTI5MTQwMTM3WhcNMjEwOTI2MTQwMTM3WjA3MREwDwYDVQQDDAhBZG1p
49
+ bkNBMTEVMBMGA1UECgwMRUpCQ0EgU2FtcGxlMQswCQYDVQQGEwJTRTCCASIwDQYJ
50
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+4uvaJ102AJZ4qXzhm2AnevjiAyZiv
51
+ /LOKb4W0bZ8ilUBd3wwj3ZsB7eGO33Nm2dVA9pyFs155JyJ68fqq01rzdwLD2Qh6
52
+ 3cFOTaX82xVxqGIR/l4uIEE5RvVhLIvufAomgMmWR6aPUry+aS5cTcqJHpc+QJi4
53
+ habRuMBhUh7gJ/rq0KncNiGAjM4LIAwf98hw9TYpVQkPCxaQlTLV5sxLDwbfdPC2
54
+ AHuu7QeA1LyycOGe37xGGbY3r5qiwW++jaDHuE7ZI6Lo+6xazO+rgVHbCczH5+H0
55
+ sig28UJ68MgZ+5QeUuiy8Gt/umffNABqdbCSWlh1QHxkJPWYu3qtOWMCAwEAAaNj
56
+ MGEwHQYDVR0OBBYEFEHzgvBlyUFi8+aVh/QbfFqpkENwMA8GA1UdEwEB/wQFMAMB
57
+ Af8wHwYDVR0jBBgwFoAUQfOC8GXJQWLz5pWH9Bt8WqmQQ3AwDgYDVR0PAQH/BAQD
58
+ AgGGMA0GCSqGSIb3DQEBBQUAA4IBAQA+JMYbNAgcBSmBsrEeFyCovy1gJtDe6kUP
59
+ a0E4GBpwb0yaF+9sndsfvvH1Y8kutySsThYA8cdDMAhaZ6TGcm1YhPHhI/pkuCJP
60
+ NBWpvWjaQsJ7WlYmsyZvrxig1T2369iHA5glYaC1ohxzDYlu6I1FPUK9cw+d5YtW
61
+ FiETlPQ4jTOSyIXnPVD7ymIS/PcWL76Yglrtx/OvSlAbhoqVEgXFzPADjis4hEvR
62
+ Xa1z4EC6VsVUjEadxK1eWSnRoENoarBr+zSW588cq6hq7vpXAcdNNkfrMzTcC+ew
63
+ 52cy0dLAIai1hP25ingiBOmQ3SdsbjkitfSCdqqYon1+YUkiiZ3g
64
+ -----END CERTIFICATE-----
@@ -0,0 +1,64 @@
1
+ Bag Attributes
2
+ localKeyID: 78 E3 3E D9 03 A9 EF 05 E9 E8 AF 7A 3D F9 BF 42 0B 06 81 16
3
+ friendlyName: test_pasta_sign
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIICXAIBAAKBgQCqZS0lN3kCYEGO0+MsA9czB4EU/XsmFgxJkHnAM4DejFgdh7I6
7
+ jmOVGsUIv9U/tkQqDw6D+M/w4B+O6Oc98wR4mT5t1ahEuG/Ph+K2PUdd2x/rRH4A
8
+ QgTDj0g+6suAETIEVx6BgTbMmuikZjbAm0mfchNkJxAdj543OUB+gzmrEwIDAQAB
9
+ AoGATlUU2/cUejMl8DMYTDO3yo24mZ2t72RTYb45OlJy+9wo5epr1N+AiBs2WT9X
10
+ GWMBExS455KKhYGDAH+xTplZhBZRANepxMdFu5UlVe4Dzu9sbBQ13XuR6LmgSta2
11
+ BwK+TKoBwgIWHjAniIX5NpuOs8Ty/SdNRZshOT1BGAa0SIECQQDoSUuqvHUd3kUK
12
+ HOiWTekpoF5jWZ5KMXnXrgZr70qqlwyHCtJkFfPwHqn7NrHA1G2JgywpQQKCdthv
13
+ +2mDu1vXAkEAu8piIMU6/34TTcX7KwnLz9ry+ZjhWBXeWiA7kB5v7BD7AU4thIUK
14
+ pQfDYMn6SKu3ypihRI1Un8oRtrFBhkEjJQJBANRU47EPkjMaUZu77zQtxdwCNyWz
15
+ 7wi9DzaDYmVZmLQ1XQM4djd9Bb5SGWmEhpnQ1MwltsGDJoshnhlHBR2gr4MCQGNH
16
+ 5AkfPMnGhb4gZWGjlDUXtE1xHfHL3foYAGV5MgLEF2/hPP9Ktw34xLpvDftNjaV2
17
+ fAwaDBtOYX8Mx2+LEGECQHHAjsa6wSINc/RbVc7zhmUe7f1hAJg7Lna8x9BzfFuD
18
+ 1pxRm3dJ2uBikGmmt3kBZ3t1jDEUIsWPPf9OXNF+nPQ=
19
+ -----END RSA PRIVATE KEY-----
20
+ Bag Attributes
21
+ localKeyID: 78 E3 3E D9 03 A9 EF 05 E9 E8 AF 7A 3D F9 BF 42 0B 06 81 16
22
+ friendlyName: test_pasta_sign
23
+ subject=/CN=test_pasta_sign
24
+ issuer=/CN=AdminCA1/O=EJBCA Sample/C=SE
25
+ -----BEGIN CERTIFICATE-----
26
+ MIICcDCCAVigAwIBAgIIDWKDcl6OwJQwDQYJKoZIhvcNAQEFBQAwNzERMA8GA1UE
27
+ AwwIQWRtaW5DQTExFTATBgNVBAoMDEVKQkNBIFNhbXBsZTELMAkGA1UEBhMCU0Uw
28
+ HhcNMTMxMTAxMDg1NjI3WhcNMTcxMDMxMDg1NjI3WjAaMRgwFgYDVQQDDA90ZXN0
29
+ X3Bhc3RhX3NpZ24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKplLSU3eQJg
30
+ QY7T4ywD1zMHgRT9eyYWDEmQecAzgN6MWB2HsjqOY5UaxQi/1T+2RCoPDoP4z/Dg
31
+ H47o5z3zBHiZPm3VqES4b8+H4rY9R13bH+tEfgBCBMOPSD7qy4ARMgRXHoGBNsya
32
+ 6KRmNsCbSZ9yE2QnEB2Pnjc5QH6DOasTAgMBAAGjITAfMB0GA1UdDgQWBBR44z7Z
33
+ A6nvBenor3o9+b9CCwaBFjANBgkqhkiG9w0BAQUFAAOCAQEAai+u5hY8g8h726VE
34
+ w46WcKs6A8KV+esGD6T5uyvyuwEkC0LPV5Ch+NvAuGAt+vAVaiwK/KHMMS1HZzf5
35
+ WWHWdyAGiP/+LsHsZoKamvMt6wuDVst74YnGG4o8UICi6gyClBnwwVpWaxTXLdSE
36
+ Bpu2bT4vSPAb9Rp2DAz7dawAm6+GJGHdxpNppJa84jFS+8MyKFhXU7L96qFVoE7V
37
+ ZKOy06hrTLsU02eH2/EljCtNMXIucpDQTqhJYZgo5GCK6IsvpUKAFblPDKuLKS5m
38
+ TdG+dY5wm4RfWclmliQ46s0umMAWVWddJWDp/tkByhVoy9gN4Jkkh3QHDmmGi2O+
39
+ JZI8zA==
40
+ -----END CERTIFICATE-----
41
+ Bag Attributes
42
+ friendlyName: AdminCA1
43
+ subject=/CN=AdminCA1/O=EJBCA Sample/C=SE
44
+ issuer=/CN=AdminCA1/O=EJBCA Sample/C=SE
45
+ -----BEGIN CERTIFICATE-----
46
+ MIIDUzCCAjugAwIBAgIIBtGA8vEQJpgwDQYJKoZIhvcNAQEFBQAwNzERMA8GA1UE
47
+ AwwIQWRtaW5DQTExFTATBgNVBAoMDEVKQkNBIFNhbXBsZTELMAkGA1UEBhMCU0Uw
48
+ HhcNMTEwOTI5MTQwMTM3WhcNMjEwOTI2MTQwMTM3WjA3MREwDwYDVQQDDAhBZG1p
49
+ bkNBMTEVMBMGA1UECgwMRUpCQ0EgU2FtcGxlMQswCQYDVQQGEwJTRTCCASIwDQYJ
50
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+4uvaJ102AJZ4qXzhm2AnevjiAyZiv
51
+ /LOKb4W0bZ8ilUBd3wwj3ZsB7eGO33Nm2dVA9pyFs155JyJ68fqq01rzdwLD2Qh6
52
+ 3cFOTaX82xVxqGIR/l4uIEE5RvVhLIvufAomgMmWR6aPUry+aS5cTcqJHpc+QJi4
53
+ habRuMBhUh7gJ/rq0KncNiGAjM4LIAwf98hw9TYpVQkPCxaQlTLV5sxLDwbfdPC2
54
+ AHuu7QeA1LyycOGe37xGGbY3r5qiwW++jaDHuE7ZI6Lo+6xazO+rgVHbCczH5+H0
55
+ sig28UJ68MgZ+5QeUuiy8Gt/umffNABqdbCSWlh1QHxkJPWYu3qtOWMCAwEAAaNj
56
+ MGEwHQYDVR0OBBYEFEHzgvBlyUFi8+aVh/QbfFqpkENwMA8GA1UdEwEB/wQFMAMB
57
+ Af8wHwYDVR0jBBgwFoAUQfOC8GXJQWLz5pWH9Bt8WqmQQ3AwDgYDVR0PAQH/BAQD
58
+ AgGGMA0GCSqGSIb3DQEBBQUAA4IBAQA+JMYbNAgcBSmBsrEeFyCovy1gJtDe6kUP
59
+ a0E4GBpwb0yaF+9sndsfvvH1Y8kutySsThYA8cdDMAhaZ6TGcm1YhPHhI/pkuCJP
60
+ NBWpvWjaQsJ7WlYmsyZvrxig1T2369iHA5glYaC1ohxzDYlu6I1FPUK9cw+d5YtW
61
+ FiETlPQ4jTOSyIXnPVD7ymIS/PcWL76Yglrtx/OvSlAbhoqVEgXFzPADjis4hEvR
62
+ Xa1z4EC6VsVUjEadxK1eWSnRoENoarBr+zSW588cq6hq7vpXAcdNNkfrMzTcC+ew
63
+ 52cy0dLAIai1hP25ingiBOmQ3SdsbjkitfSCdqqYon1+YUkiiZ3g
64
+ -----END CERTIFICATE-----
@@ -0,0 +1,57 @@
1
+ Bag Attributes
2
+ friendlyName: test_sign
3
+ localKeyID: DE 64 9B C6 66 F2 11 9E E3 DB 46 60 FD 61 7A F8 E5 59 ED B6
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIICXQIBAAKBgQCFykc5k38LoNOVVC7W/7NePhOc8qBMI5HPow5GtMZ4SSCcAjo2
7
+ V8wMrT9HYFE7EK3/w5DNKJDI4OvFOnZHCo3EkuU1tBtWyJBJTKtpXgx/HBFqKPZZ
8
+ b7z5Kh+qD93jQ1Oi8Pe9e7rq/d2gddM6/5RMXG/OowlBEqR56G1mKJ1u3QIDAQAB
9
+ AoGAIIa97CyEvZH6/pn5zUFbHTVgVU7TU89t+pn8tYnrmoDE0cjk2CNeM1LHSJYN
10
+ CZwTgVPNV2NeV8f+6fM9oCXbsywOxB3bjCGIpR5UFad9G7Q/wVIgb4ijxw0201we
11
+ 0CxtIFkYxV5wCt3fgpcnP5F8siKNEYGNEpPN182FW62/igECQQDgV5FT0JmAEUxd
12
+ ozksQOpt+2CeO44p2TYwcRB4NiiihQre+KvtDlDktlZdDGkqZGSEdBsbbNMbm/tw
13
+ isbGWv+BAkEAmKt+B5Ll0dOi1C4n0HKIZh0Ec1LT/w9jpfUYDxB/wPgJAO5VxpDR
14
+ FPQwIzDaJM/1OUiM2IhcBRG5E24VWR0dXQJBAMnEOAJHtCaIaEQ3Dq6MW8s6sHTf
15
+ X0aoAqKirYtQOk+glFxhDk+P9pUcoKPjC5qC3Bx8R/zsbRmBuixHw+qV4QECQE4o
16
+ ZWHdO1ibPx3e7zUQnXGhY1jiy3MlXr9kZUe5C54vnPRkD3eTReazSD2L0fHMoN8N
17
+ nEVyMaHKu/QNhFJVzGUCQQCNN2YJ1BkCtbDnNetxf3vmIbyfoZUpLEWH3mbt0aG1
18
+ bdVZ/NGS6lHGtgUPnrhDFehCgmL01kCEqqa80hZ7WTrf
19
+ -----END RSA PRIVATE KEY-----
20
+ Bag Attributes
21
+ friendlyName: test_sign
22
+ localKeyID: DE 64 9B C6 66 F2 11 9E E3 DB 46 60 FD 61 7A F8 E5 59 ED B6
23
+ subject=/CN=test_sign
24
+ issuer=/CN=Complete Payment Systems Certificates/O=EJBCA Production/C=SE
25
+ -----BEGIN CERTIFICATE-----
26
+ MIICCjCCAXOgAwIBAgIIb5GAi+59gAIwDQYJKoZIhvcNAQEFBQAwWDEuMCwGA1UE
27
+ AwwlQ29tcGxldGUgUGF5bWVudCBTeXN0ZW1zIENlcnRpZmljYXRlczEZMBcGA1UE
28
+ CgwQRUpCQ0EgUHJvZHVjdGlvbjELMAkGA1UEBhMCU0UwHhcNMTExMDExMDgzMTI4
29
+ WhcNMTUxMDEwMDgzMTI4WjAUMRIwEAYDVQQDDAl0ZXN0X3NpZ24wgZ8wDQYJKoZI
30
+ hvcNAQEBBQADgY0AMIGJAoGBAIXKRzmTfwug05VULtb/s14+E5zyoEwjkc+jDka0
31
+ xnhJIJwCOjZXzAytP0dgUTsQrf/DkM0okMjg68U6dkcKjcSS5TW0G1bIkElMq2le
32
+ DH8cEWoo9llvvPkqH6oP3eNDU6Lw9717uur93aB10zr/lExcb86jCUESpHnobWYo
33
+ nW7dAgMBAAGjITAfMB0GA1UdDgQWBBTeZJvGZvIRnuPbRmD9YXr45VnttjANBgkq
34
+ hkiG9w0BAQUFAAOBgQA9M8v8vjChuIdT7vWye5nQcwX5vJ3PkyJlnlKXM8bmCq5J
35
+ 9LinqdWRXYcGQBPEJ+DBIIDSKUhTSh5O6Emi8upRKIhGLiI+R3pSnxxveq7iYKlM
36
+ Xx0Kv1UKU6m5HjphAc2dhQckW0Fmdbla/Ma4wSIMnRTJBouU40xxT6YflCicXA==
37
+ -----END CERTIFICATE-----
38
+ Bag Attributes
39
+ friendlyName: Complete Payment Systems Certificates
40
+ subject=/CN=Complete Payment Systems Certificates/O=EJBCA Production/C=SE
41
+ issuer=/CN=Complete Payment Systems Certificates/O=EJBCA Production/C=SE
42
+ -----BEGIN CERTIFICATE-----
43
+ MIICkDCCAfmgAwIBAgIIQ/jnhZUMyZowDQYJKoZIhvcNAQEFBQAwWDEuMCwGA1UE
44
+ AwwlQ29tcGxldGUgUGF5bWVudCBTeXN0ZW1zIENlcnRpZmljYXRlczEZMBcGA1UE
45
+ CgwQRUpCQ0EgUHJvZHVjdGlvbjELMAkGA1UEBhMCU0UwHhcNMTEwOTI5MTQzMjU5
46
+ WhcNMzEwOTI0MTQzMjU5WjBYMS4wLAYDVQQDDCVDb21wbGV0ZSBQYXltZW50IFN5
47
+ c3RlbXMgQ2VydGlmaWNhdGVzMRkwFwYDVQQKDBBFSkJDQSBQcm9kdWN0aW9uMQsw
48
+ CQYDVQQGEwJTRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxOJdeplgc+7/
49
+ eHpeZcY7SSwFbZOSOy6ytboP1sIq/ktRyI4fl9l49TfiREyBuDx62TRQenW0oWuG
50
+ I9CwI5YsciALG5jOPRXpXLjjdUzphpq77BT5zm4Br2fDl06gyGhs1P8AFUJEjXtx
51
+ fX4r84C9nawUQhhUNJr0sz+DBTNbqv0CAwEAAaNjMGEwHQYDVR0OBBYEFIiRA63u
52
+ UxDtZMpEFP7om6Z9+QPGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUiJED
53
+ re5TEO1kykQU/uibpn35A8YwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUA
54
+ A4GBAJvCQa1j2xa0uFrOh+GxIBlKcieFnGProMJUMZSufd7KkrEzwcjpYiJp0Kuv
55
+ GCXdsW6YH1yDyT2V4ZhygwT05A3PwvPgwrqOt8gJ1pNtmw0EhakCfc8bZ6YqSiBo
56
+ qe3r+o0aiDEVwKVxuI3rA7oUiqyp9hobwu9rXGYSjREK6M1N
57
+ -----END CERTIFICATE-----
@@ -0,0 +1,103 @@
1
+ module CompletePaymentSystems
2
+ class Request
3
+
4
+ attr_reader :params, :xml
5
+
6
+ def initialize(params)
7
+ @params = params #|| File.read("#{CPS.root}/response.xml")
8
+ @xml = build_request_xml
9
+ end
10
+
11
+ def send!
12
+ response = Unirest.post CPS.config.cps_url,
13
+ #headers:{ "Accept" => "application/json" },
14
+ parameters:{ type: CPS.config.cps_method, xml: xml }
15
+
16
+ puts response.code # Status code
17
+ puts response.headers # Response headers
18
+ puts response.body # Parsed body
19
+
20
+ return "OK" if response.body.to_s.match(CPS.config.success_regex).present?
21
+ return "ERROR"
22
+ end
23
+
24
+ private
25
+ def self.sign(type: CPS.config.cps_method, user: CPS.config.default_user, order_id: , value: , currency: , card_number: , product: CPS.config.default_product_name)
26
+ sign_string = [type, user, order_id, value, currency, card_number, product].join()
27
+ rsa = OpenSSL::PKey::RSA.new(File.read(CPS.config.rsa_cert_path), CPS.config.cert_pass )
28
+ signed_hash = rsa.sign(OpenSSL::Digest::SHA1.new, sign_string)
29
+ Base64.encode64(signed_hash)
30
+ end
31
+
32
+ def build_request_xml
33
+ params = @params
34
+ values = {
35
+ user: (params["user"] || CPS.config.default_user), # "test_pasta_sign" for direct, "pasta_test_3d" for direct with 3D
36
+ callback_url: (params["callback_url"] || CPS.config.default_callback_url),
37
+ redirect_url: (params["redirect_url"] || CPS.config.default_redirect_url),
38
+ order: (params["order"] || Time.now.to_i), # TO-DO remove fallback
39
+ value: (params["value"]),
40
+ currency: (params["currency"]),
41
+ holder_name: params["holder_name"],
42
+ holder_surname: params["holder_surname"],
43
+ holder_street: (params["holder_street"] || CPS.config.placeholder_value),
44
+ holder_zip: (params["holder_zip"] || CPS.config.placeholder_value),
45
+ holder_city: (params["holder_city"] || CPS.config.placeholder_value),
46
+ holder_country: (params["holder_country"] || CPS.config.default_country),
47
+ holder_email: (params["holder_email"] || CPS.config.placeholder_value),
48
+ holder_ip: ( params["holder_ip"] ),
49
+ card_number: params["card_number"], # 4012001037167778 for direct, For 3D-Secure number is 4314229999999913
50
+ card_exp: params["card_exp"], # 06/18 for direct, 3D-sec is "01/18"
51
+ card_cvv: params["card_cvv"], # 999 for direct, 3D-sec is "123"
52
+ product_name: (params["product_name"] || CPS.config.default_product_name),
53
+ product_url: (params["product_url"] || CPS.config.default_product_url)
54
+ }
55
+
56
+ values[:signature] = CPS.sign(order_id: values[:order], value: values[:value], currency: values[:currency], card_number: values[:card_number]).gsub(/\n/, '')
57
+
58
+ values[:signature_line] = '<digiSignature>' + values[:signature] + '</digiSignature>'
59
+
60
+ xml_string = ""
61
+ xml_string = %Q|<?xml version="1.0" encoding="UTF-8" ?>\n| +
62
+ %Q|<cpsxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n| +
63
+ %Q| xsi:schemaLocation="http://www.cps.lv/xml/ns/cpsxml https://3ds.cps.lv/GatorServo/Gator_SendForAuth.xsd"\n| +
64
+ %Q| xmlns="http://www.cps.lv/xml/ns/cpsxml">\n| +
65
+ %Q| <header xmlns="">\n| +
66
+ %Q| <responsetype>direct</responsetype>\n| +
67
+ %Q| <user>#{values[:user]}</user>\n| +
68
+ %Q| <type>sendForAuth</type>\n| +
69
+ %Q| <transType>DB</transType>\n| +
70
+ %Q| | + values[:signature_line] + "\n" +
71
+ %Q| <callbackUrl>#{values[:callback_url]}</callbackUrl>\n| +
72
+ %Q| <redirectUrl>#{values[:redirect_url]}</redirectUrl>\n| +
73
+ %Q| </header>\n| +
74
+ %Q| <request xmlns="">\n| +
75
+ %Q| <orderNumber>#{values[:order]}</orderNumber>\n| +
76
+ %Q| <cardholder>\n| +
77
+ %Q| <firstName>#{values[:holder_name]}</firstName>\n| +
78
+ %Q| <lastName>#{values[:holder_surname]}</lastName>\n| +
79
+ %Q| <street>#{values[:holder_street]}</street>\n| +
80
+ %Q| <zip>#{values[:holder_zip]}</zip>\n| +
81
+ %Q| <city>#{values[:holder_city]}</city>\n| +
82
+ %Q| <country>#{values[:holder_country]}</country>\n| +
83
+ %Q| <email>#{values[:holder_email]}</email>\n| +
84
+ %Q| <ip>#{values[:holder_ip]}</ip>\n| +
85
+ %Q| </cardholder>\n| +
86
+ %Q| <card>\n| +
87
+ %Q| <cardNumber>#{values[:card_number]}</cardNumber>\n| +
88
+ %Q| <expires>#{values[:card_exp]}</expires>\n| +
89
+ %Q| <cvv>#{values[:card_cvv]}</cvv>\n| +
90
+ %Q| </card>\n| +
91
+ %Q| <amount>\n| +
92
+ %Q| <value>#{values[:value]}</value>\n| +
93
+ %Q| <currency>#{values[:currency]}</currency>\n| +
94
+ %Q| </amount>\n| +
95
+ %Q| <product>\n| +
96
+ %Q| <productName>#{values[:product_name]}</productName>\n| +
97
+ %Q| <productUrl>#{values[:product_url]}</productUrl>\n| +
98
+ %Q| </product>\n| +
99
+ %Q| </request>\n| +
100
+ %Q|</cpsxml>|
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,57 @@
1
+ module CompletePaymentSystems
2
+ class Response
3
+
4
+ attr_reader :xml, :response_hash, :code, :message
5
+
6
+ def initialize(xml)
7
+ @xml = xml #|| File.read("#{CPS.root}/response.xml")
8
+ @response_hash = parse_response(@xml)
9
+ @code = @response_hash["resultCode"]
10
+ @message = @response_hash["resultMessage"]
11
+ end
12
+
13
+ def ok?
14
+ return signature_ok? && message.match(CPS.config.success_regex).present? && code == "000"
15
+ end
16
+
17
+ def signature_ok?
18
+ digi_signature = response_hash["digiSignature"]
19
+ hash_string = build_hashable_string
20
+ decoded_resp = Base64.decode64(digi_signature)
21
+ public_key = OpenSSL::X509::Certificate.new(
22
+ File.read "#{CPS.root}/lib/complete_payment_systems/certs/cps.cer").
23
+ public_key
24
+ return public_key.verify(OpenSSL::Digest::SHA1.new, decoded_resp, hash_string)
25
+ end
26
+
27
+ private
28
+
29
+ def parse_response xml
30
+ @response = Nokogiri::XML(xml) do |config|
31
+ config.strict.nonet
32
+ end
33
+
34
+ return {
35
+ "referenceId" => @response.xpath("//referenceId").text,
36
+ "orderId" => @response.xpath("//orderId").text,
37
+ "value" => @response.xpath("//value").text,
38
+ "currency" => @response.xpath("//currency").text,
39
+ "resultCode" => @response.xpath("//resultCode").text,
40
+ "resultMessage" => @response.xpath("//resultMessage").text, # Important
41
+ "resultText" => @response.xpath("//resultText").text, # Informative only
42
+ "digiSignature" => @response.xpath("//digiSignature").text
43
+ }
44
+ end
45
+
46
+ def build_hashable_string
47
+ rh = @response_hash
48
+ return "#{rh["referenceId"]}#{rh["orderId"]}#{rh["value"]}#{rh["currency"]}#{rh["resultCode"]}#{rh["resultMessage"]}#{rh["resultText"]}"
49
+ end
50
+
51
+ end
52
+
53
+ # def self.read_test_xml
54
+ # return File.read("#{CPS.root}/response.xml")
55
+ # end
56
+
57
+ end
@@ -0,0 +1,3 @@
1
+ module CompletePaymentSystems
2
+ VERSION = "0.0.1"
3
+ end
data/response.xml ADDED
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <cpsxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:schemaLocation="http://www.cps.lv/xml/ns/cpsxml /GatorServo/Gator_Response.xsd"
4
+ xmlns="http://www.cps.lv/xml/ns/cpsxml">
5
+ <transData xmlns="">
6
+ <referenceId>9095359</referenceId>
7
+ <orderId>1422019383</orderId>
8
+ <amount>
9
+ <value>100</value>
10
+ <currency>USD</currency>
11
+ </amount>
12
+ </transData>
13
+ <result xmlns="">
14
+ <resultCode>000</resultCode>
15
+ <resultMessage>Captured</resultMessage>
16
+ <resultText>Captured</resultText>
17
+ <digiSignature>HlcnASe5fZyM7uVz4xwqpe9MF6+pHWXt0Fg9t5tbgmgsjLIzVZMvErzJYsZymiHEnyCbYdbAUcman8JfOP1/LnAvPAhpxz09wNsXBYJcK7YjR+Ktu2faraRfgVG0t8QTjUumk5ayTMIA/IYHvIy+2bDJgmqVQEIctl8mFdn/RyrOFFhSB2aNQwXFP1DA9Ul4c+UyDq1d5AqwGyuevKR3qFodco2DT8eO6PMpRZstecAib2Bjk5tkIY2iNRYTj7TFwtM2ASMXnbYWz82E389/AHTCBpKl4d7o6ewysPjvz4LI1pykvCJRrL10y7HGYKgoo/+JnCp9s9J4iFGx5SVqSA==</digiSignature>
18
+ </result>
19
+ </cpsxml>
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require "complete_payment_systems"
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
@@ -0,0 +1,8 @@
1
+ # rspec spec/tests/request_spec.rb
2
+
3
+ describe "Test request" do
4
+ it "should be successful" do
5
+ expect(CPS.unirest).to eq "OK"
6
+ end
7
+
8
+ end
data/test.html ADDED
@@ -0,0 +1,55 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <form method="POST" action="https://3ds.cps.lv/GatorServo/request">
6
+ <input name="type" value="sendForAuth">
7
+ <textarea name="xml">
8
+ <?xml version="1.0" encoding="UTF-8" ?>
9
+ <cpsxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10
+ xsi:schemaLocation="http://www.cps.lv/xml/ns/cpsxml https://3ds.cps.lv/GatorServo/Gator_SendForAuth.xsd"
11
+ xmlns="http://www.cps.lv/xml/ns/cpsxml">
12
+ <header xmlns="">
13
+ <responsetype>direct</responsetype>
14
+ <user>pasta_test_3d</user>
15
+ <type>sendForAuth</type>
16
+ <transType>DB</transType>
17
+ <digiSignature>NP+o4wK17G3tqcTF5K2vfBjXQ4RpCLEYPoK9I99/9GPQO95fD0Xp+DueUV4c
18
+ AtgNQmQg4C2BTw0vh1fme8PQanaGF50WJOTdgXdU5ygRxkjja4EyA9cDe1cq
19
+ Ex7iqtSazv2FZXu/6RfVgwcoy4SRuNuQrsDqo6/7isJ/BpgppTI=
20
+ </digiSignature>
21
+ <callbackUrl>www.google.com</callbackUrl>
22
+ <redirectUrl>http://www.google.lv</redirectUrl>
23
+ </header>
24
+ <request xmlns="">
25
+ <orderNumber>1422028510</orderNumber>
26
+ <cardholder>
27
+ <firstName>Test</firstName>
28
+ <lastName>User</lastName>
29
+ <street>NOT USED</street>
30
+ <zip>NOT USED</zip>
31
+ <city>NOT USED</city>
32
+ <country>LV</country>
33
+ <email>hi@creo.mobi</email>
34
+ <ip>123.124.125.226</ip>
35
+ </cardholder>
36
+ <card>
37
+ <cardNumber>4314229999999913</cardNumber>
38
+ <expires>01/18</expires>
39
+ <cvv>123</cvv>
40
+ </card>
41
+ <amount>
42
+ <value>100</value>
43
+ <currency>USD</currency>
44
+ </amount>
45
+ <product>
46
+ <productName>Product</productName>
47
+ <productUrl>www.test.com</productUrl>
48
+ </product>
49
+ </request>
50
+ </cpsxml>
51
+ </textarea>
52
+ <input type="submit" value="Send">
53
+ </form>
54
+ </body>
55
+ </html>
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: complete_payment_systems
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Epigene
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: unirest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.6.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.1.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.1.0
97
+ description: Coming soon...
98
+ email:
99
+ - augusts.bautra@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - complete_payment_systems.gemspec
111
+ - cps.xml
112
+ - lib/complete_payment_systems.rb
113
+ - lib/complete_payment_systems/certs/Pasta_test_3d.p12
114
+ - lib/complete_payment_systems/certs/Pasta_test_3d.pem
115
+ - lib/complete_payment_systems/certs/Test_pasta_sign.p12
116
+ - lib/complete_payment_systems/certs/Test_pasta_sign.pem
117
+ - lib/complete_payment_systems/certs/Test_sign.p12
118
+ - lib/complete_payment_systems/certs/Test_sign.pem
119
+ - lib/complete_payment_systems/certs/cps.cer
120
+ - lib/complete_payment_systems/request_processing.rb
121
+ - lib/complete_payment_systems/response_processing.rb
122
+ - lib/complete_payment_systems/version.rb
123
+ - response.xml
124
+ - spec/spec_helper.rb
125
+ - spec/tests/request_spec.rb
126
+ - test.html
127
+ homepage: ''
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.4.3
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: A client for CPS (Complete Payment Systems) card payment service
151
+ test_files:
152
+ - spec/spec_helper.rb
153
+ - spec/tests/request_spec.rb