paycertify 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1beefa8f5e0710dae9817343ef7507386a6e0c84
4
+ data.tar.gz: a5c8deae72634009b23bd4ace0f3e4849befbb47
5
+ SHA512:
6
+ metadata.gz: f16664472922d267eacf82c898784f720178b89ebc8f7dd7cb006f09c78078b00cbbd94b00d28b058bd0c39763271dce9a078040577a3fb6a787198a69b02702
7
+ data.tar.gz: 9d826c45ac17c4a8288ffabafdeb4136200668cbce8f16c3a14ec86f0b282b848a5ff1319bf97db6cb71c4290c825951866929ebe6852adbfe6effa06ecb9fb1
@@ -0,0 +1,6 @@
1
+ require 'active_support/rails'
2
+ require 'active_support/core_ext'
3
+
4
+ require 'paycertify/three_ds'
5
+
6
+ module PayCertify; end
@@ -0,0 +1,80 @@
1
+ require_relative './three_ds/client'
2
+ require_relative './three_ds/form'
3
+ require_relative './three_ds/payment_authentication'
4
+
5
+ require 'json'
6
+ require 'faraday'
7
+
8
+ module PayCertify
9
+ class ThreeDS
10
+
11
+ class NoCredentialsError < StandardError; end
12
+
13
+ attr_accessor :type, :client, :settings, :authentication
14
+ attr_accessor :card_number, :expiration_month, :expiration_year, :amount, :transaction_id, :message_id, :return_url
15
+
16
+ delegate :api_key, to: :class
17
+ delegate :api_secret, to: :class
18
+
19
+ def initialize(options)
20
+ raise NoCredentialsError, 'No api_key provided.' unless api_key.present?
21
+ raise NoCredentialsError, 'No api_secret provided.' unless api_secret.present?
22
+
23
+ self.type = options[:type].to_sym.in?([:default, :frictionless]) ? options[:type].to_sym : :default
24
+
25
+ self.card_number = options[:card_number]
26
+ self.expiration_month = options[:expiration_month]
27
+ self.expiration_year = options[:expiration_year]
28
+ self.amount = options[:amount]
29
+ self.transaction_id = options[:transaction_id]
30
+ self.message_id = options[:message_id]
31
+ self.return_url = options[:return_url]
32
+
33
+ self.client = PayCertify::ThreeDS::Client.new(api_key: api_key, api_secret: api_secret)
34
+ end
35
+
36
+ def settings
37
+ @settings ||= {
38
+ pan: card_number,
39
+ card_exp_month: expiration_month,
40
+ card_exp_year: expiration_year,
41
+ amount: amount,
42
+ transaction_id: transaction_id,
43
+ message_id: message_id,
44
+ return_url: return_url
45
+ }
46
+ end
47
+
48
+ def payment_authentication
49
+ @payment_authentication ||= PayCertify::ThreeDS::PaymentAuthentication.new(client, settings)
50
+ end
51
+
52
+ def card_enrolled?
53
+ @card_enrolled ||= payment_authentication.card_enrolled?
54
+ end
55
+
56
+ def start!
57
+ self.authentication = payment_authentication.prepare!
58
+ end
59
+
60
+ def render!
61
+ PayCertify::ThreeDS::Form.new(authentication).render_html_for(settings, type)
62
+ end
63
+
64
+ class << self
65
+ cattr_accessor :api_key, :api_secret
66
+
67
+ def configure(&block)
68
+ yield self if block_given?
69
+ end
70
+
71
+ def authenticate!(settings:, callback_params:)
72
+ raise NoCredentialsError, 'No api_key provided.' unless api_key.present?
73
+ raise NoCredentialsError, 'No api_secret provided.' unless api_secret.present?
74
+
75
+ client = PayCertify::ThreeDS::Client.new(api_key: api_key, api_secret: api_secret)
76
+ PayCertify::ThreeDS::PaymentAuthentication.new(client, settings).authenticate!(callback_params)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,60 @@
1
+ require 'faraday'
2
+
3
+ module PayCertify
4
+ class ThreeDS
5
+ class Client
6
+
7
+ BASE_URL = 'https://mpi.3dsintegrator.com'
8
+
9
+ class InvalidRequestError < StandardError; end
10
+
11
+ attr_accessor :api_key, :api_secret
12
+
13
+ def initialize(api_key:, api_secret:)
14
+ self.api_key = api_key
15
+ self.api_secret = api_secret
16
+ end
17
+
18
+ def post(path:, data:)
19
+ sorted_data = JSON.generate(data.sort.to_h)
20
+
21
+ response = connection.post do |request|
22
+ request.url path
23
+ request.headers['Content-Type'] = 'application/json'
24
+ request.headers['x-mpi-api-key'] = api_key
25
+ request.headers['x-mpi-signature'] = signature(path, sorted_data)
26
+ request.body = sorted_data
27
+ end
28
+
29
+ respond_with response
30
+ end
31
+
32
+ private
33
+ def connection
34
+ @connection ||= Faraday.new(url: BASE_URL, ssl: {verify: false}) do |faraday|
35
+ faraday.request :url_encoded
36
+ faraday.response :logger
37
+ faraday.adapter Faraday.default_adapter
38
+ end
39
+ end
40
+
41
+ def signature(path, data)
42
+ Digest::SHA256.hexdigest "#{api_key}#{BASE_URL}#{path}#{data}#{api_secret}"
43
+ end
44
+
45
+ def respond_with(response)
46
+ 3.times{puts}
47
+ puts 'Response -----'
48
+ p response.body
49
+ 10.times{puts}
50
+
51
+ if response.status < 400
52
+ JSON.parse(response.body)
53
+ else
54
+ error = JSON.parse(response.body)['error']
55
+ raise InvalidRequestError, "API responded with #{response.status} and error: #{error}"
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,124 @@
1
+ module PayCertify
2
+ class ThreeDS
3
+ class Form
4
+
5
+ class UnauthenticatedPaymentError < StandardError; end
6
+
7
+ attr_accessor :authentication, :settings
8
+
9
+ def initialize(authentication)
10
+ check_authentication!(authentication)
11
+
12
+ self.authentication = authentication
13
+ end
14
+
15
+ def acs_url
16
+ @acs_url ||= authentication['AcsUrl']
17
+ end
18
+
19
+ def pareq
20
+ @pareq ||= authentication['PaReq']
21
+ end
22
+
23
+ def md
24
+ @md ||= authentication['MD']
25
+ end
26
+
27
+ def term_url
28
+ @term_url ||= authentication['TermUrl']
29
+ end
30
+
31
+ def render_html_for(settings, type)
32
+ self.settings = settings
33
+ send(type)
34
+ rescue NoMethodError
35
+ raise UndefinedTypeError, 'Type is not supported: '+ type
36
+ end
37
+
38
+ def default
39
+ <<-HTML.squish
40
+ #{form}
41
+
42
+ <script>
43
+ window.onload = function() {
44
+ document.form3ds.submit();
45
+ }
46
+ </script>
47
+ HTML
48
+ end
49
+
50
+ def frictionless
51
+ <<-HTML.squish
52
+
53
+ <iframe id="3ds-frame" src="about:blank"></iframe>
54
+
55
+ <form id="callback-form" action="#{term_url}" method="post">
56
+ <input type="hidden" id="pares" name="pares" />
57
+ </form>
58
+
59
+ <script>
60
+ (function(){
61
+ var frame = document.getElementById('3ds-frame');
62
+ var form = document.getElementById('callback-form');
63
+ var submitForm = false;
64
+ var saveBeforeUnload = false;
65
+
66
+ setInterval(function() {
67
+ if (saveBeforeUnload) {
68
+ saveBeforeUnload = false;
69
+ console.log('SAVE!');
70
+ window.onbeforeunload = null;
71
+ document.createElement('form').submit.call(form);
72
+ }
73
+ }, 500);
74
+
75
+
76
+ var exitPoll = function() {
77
+ if (submitForm == false) {
78
+ saveBeforeUnload = true;
79
+ return "Transaction is still processing";
80
+ }
81
+ };
82
+
83
+ window.onbeforeunload = exitPoll;
84
+
85
+ frame.contentDocument.write('#{form}');
86
+ frame.contentDocument.form3ds.submit();
87
+
88
+
89
+ window.onmessage = function(e){
90
+ debugger;
91
+ if (e.data.PaRes != '') {
92
+ j = e.data;
93
+ var pinput = document.getElementById('pares');
94
+ pinput.value = j;
95
+ submitForm = true;
96
+ document.createElement('form').submit.call(form);
97
+ console.log('response received');
98
+ clearInterval(tid);
99
+ }
100
+ };
101
+ })();
102
+ </script>
103
+ HTML
104
+ end
105
+
106
+ private
107
+ def form
108
+ <<-HTML
109
+ <form name="form3ds" action="#{acs_url}" method="post"/>
110
+ <input name="PaReq" type="hidden" value="#{pareq}"/>
111
+ <input name="MD" type="hidden" value="#{md}"/>
112
+ <input name="TermUrl" type="hidden" value="#{term_url}"/>
113
+ </form>
114
+ HTML
115
+ end
116
+
117
+ def check_authentication!(authentication)
118
+ unless authentication.present?
119
+ raise UnauthenticatedPaymentError, 'Please authenticate (run #start!) before rendering html.'
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,51 @@
1
+ module PayCertify
2
+ class ThreeDS
3
+ class PaymentAuthentication
4
+
5
+ ENROLLED_STATUS_PATH = '/index_demo.php/enrolled-status'
6
+ PAREQ_PATH = '/index_demo.php/auth-request'
7
+ PARES_PATH = '/index_demo.php/auth-response'
8
+
9
+ FIELDS = %w(pan card_exp_month card_exp_year amount transaction_id return_url)
10
+
11
+ class FieldNotProvidedError < StandardError; end
12
+
13
+ attr_accessor :client, :params
14
+
15
+ def initialize(client, params)
16
+ self.client = client
17
+ self.params = params
18
+ end
19
+
20
+ def card_enrolled?
21
+ validate!(:pan)
22
+
23
+ response = client.post(path: ENROLLED_STATUS_PATH, data: params.slice(:pan))
24
+
25
+ return response['enrollment_status'] == 'Y'
26
+ end
27
+
28
+ def prepare!
29
+ validate!
30
+ client.post(path: PAREQ_PATH, data: params)
31
+ end
32
+
33
+ def authenticate!(callback_params)
34
+ validate!
35
+ self.params = params.merge(pares: callback_params['PaRes'])
36
+
37
+ client.post(path: PARES_PATH, data: params)
38
+ end
39
+
40
+ private
41
+ def validate!(*settings)
42
+ fields = settings.presence || FIELDS
43
+ fields.each { |field| raise_error_if_field_not_present(params, field.to_sym) }
44
+ end
45
+
46
+ def raise_error_if_field_not_present(settings, field)
47
+ raise FieldNotProvidedError, "no #{field} provided" unless settings[field].present?
48
+ end
49
+ end
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paycertify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - PayCertify Engineering Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
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: faraday
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
+ description: Interact with the Gateway, 3DS, Kount, and FraudPortal
42
+ email: engineering@paycertify.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/paycertify.rb
48
+ - lib/paycertify/three_ds.rb
49
+ - lib/paycertify/three_ds/client.rb
50
+ - lib/paycertify/three_ds/form.rb
51
+ - lib/paycertify/three_ds/payment_authentication.rb
52
+ homepage: http://github.com/paycertify/wrappers/ruby
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.5.1
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: PayCertify wrapper for Ruby language
76
+ test_files: []