killbill-securenet 0.1.0

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.
data/NEWS ADDED
@@ -0,0 +1,2 @@
1
+ 0.1.0
2
+ Initial release for Kill Bill 0.16.x
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ killbill-securenet-plugin
2
+ =========================
3
+
4
+ Plugin to use [SecureNet](http://www.securenet.com/) as a gateway.
5
+
6
+ Release builds are available on [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.kill-bill.billing.plugin.ruby%22%20AND%20a%3A%22securenet-plugin%22) with coordinates `org.kill-bill.billing.plugin.ruby:securenet-plugin`.
7
+
8
+ Kill Bill compatibility
9
+ -----------------------
10
+
11
+ | Plugin version | Kill Bill version |
12
+ | -------------: | ----------------: |
13
+ | 0.1.y | 0.16.z |
14
+
15
+ Requirements
16
+ ------------
17
+
18
+ The plugin needs a database. The latest version of the schema can be found [here](https://github.com/killbill/killbill-securenet-plugin/blob/master/db/ddl.sql).
19
+
20
+ Configuration
21
+ -------------
22
+
23
+ ```
24
+ curl -v \
25
+ -X POST \
26
+ -u admin:password \
27
+ -H 'X-Killbill-ApiKey: bob' \
28
+ -H 'X-Killbill-ApiSecret: lazar' \
29
+ -H 'X-Killbill-CreatedBy: admin' \
30
+ -H 'Content-Type: text/plain' \
31
+ -d ':securenet:
32
+ :login: "your-login"
33
+ :password: "your-password"' \
34
+ http://127.0.0.1:8080/1.0/kb/tenants/uploadPluginConfig/killbill-securenet
35
+ ```
36
+
37
+ To go to production, create a `securenet.yml` configuration file under `/var/tmp/bundles/plugins/ruby/killbill-securenet/x.y.z/` containing the following:
38
+
39
+ ```
40
+ :securenet:
41
+ :test: false
42
+ ```
43
+
44
+ Usage
45
+ -----
46
+
47
+ Note: integration with PayOS.js hasn't been done yet.
48
+
49
+ To store a credit card:
50
+
51
+ ```
52
+ curl -v \
53
+ -X POST \
54
+ -u admin:password \
55
+ -H 'X-Killbill-ApiKey: bob' \
56
+ -H 'X-Killbill-ApiSecret: lazar' \
57
+ -H 'X-Killbill-CreatedBy: admin' \
58
+ -H 'Content-Type: application/json' \
59
+ -d '{
60
+ "pluginName": "killbill-securenet",
61
+ "pluginInfo": {
62
+ "properties": [
63
+ {
64
+ "key": "ccFirstName",
65
+ "value": "John"
66
+ },
67
+ {
68
+ "key": "ccLastName",
69
+ "value": "Doe"
70
+ },
71
+ {
72
+ "key": "ccExpirationMonth",
73
+ "value": 12
74
+ },
75
+ {
76
+ "key": "ccExpirationYear",
77
+ "value": 2017
78
+ },
79
+ {
80
+ "key": "ccNumber",
81
+ "value": "4111111111111111"
82
+ }
83
+ ]
84
+ }
85
+ }' \
86
+ "http://127.0.0.1:8080/1.0/kb/accounts/2a55045a-ce1d-4344-942d-b825536328f9/paymentMethods?isDefault=true&pluginProperty=skip_gw=true"
87
+ ```
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env rake
2
+
3
+ # Install tasks to build and release the plugin
4
+ require 'bundler/setup'
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ # Install test tasks
8
+ require 'rspec/core/rake_task'
9
+ namespace :test do
10
+ desc 'Run RSpec tests'
11
+ RSpec::Core::RakeTask.new do |task|
12
+ task.name = 'spec'
13
+ task.pattern = './spec/*/*_spec.rb'
14
+ end
15
+
16
+ namespace :remote do
17
+ desc 'Run RSpec remote tests'
18
+ RSpec::Core::RakeTask.new do |task|
19
+ task.name = 'spec'
20
+ task.pattern = './spec/*/remote/*_spec.rb'
21
+ end
22
+ end
23
+ end
24
+
25
+ # Install tasks to package the plugin for Killbill
26
+ require 'killbill/rake_task'
27
+ Killbill::PluginHelper.install_tasks
28
+
29
+ # Run tests by default
30
+ task :default => 'test:spec'
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/config.ru ADDED
@@ -0,0 +1,4 @@
1
+ require 'securenet'
2
+ require 'securenet/application'
3
+
4
+ run Sinatra::Application
data/db/ddl.sql ADDED
@@ -0,0 +1,75 @@
1
+ CREATE TABLE `securenet_payment_methods` (
2
+ `id` int(11) NOT NULL AUTO_INCREMENT,
3
+ `kb_payment_method_id` varchar(255) DEFAULT NULL,
4
+ `token` varchar(255) DEFAULT NULL,
5
+ `cc_first_name` varchar(255) DEFAULT NULL,
6
+ `cc_last_name` varchar(255) DEFAULT NULL,
7
+ `cc_type` varchar(255) DEFAULT NULL,
8
+ `cc_exp_month` varchar(255) DEFAULT NULL,
9
+ `cc_exp_year` varchar(255) DEFAULT NULL,
10
+ `cc_number` varchar(255) DEFAULT NULL,
11
+ `cc_last_4` varchar(255) DEFAULT NULL,
12
+ `cc_start_month` varchar(255) DEFAULT NULL,
13
+ `cc_start_year` varchar(255) DEFAULT NULL,
14
+ `cc_issue_number` varchar(255) DEFAULT NULL,
15
+ `cc_verification_value` varchar(255) DEFAULT NULL,
16
+ `cc_track_data` varchar(255) DEFAULT NULL,
17
+ `address1` varchar(255) DEFAULT NULL,
18
+ `address2` varchar(255) DEFAULT NULL,
19
+ `city` varchar(255) DEFAULT NULL,
20
+ `state` varchar(255) DEFAULT NULL,
21
+ `zip` varchar(255) DEFAULT NULL,
22
+ `country` varchar(255) DEFAULT NULL,
23
+ `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
24
+ `created_at` datetime NOT NULL,
25
+ `updated_at` datetime NOT NULL,
26
+ `kb_account_id` varchar(255) DEFAULT NULL,
27
+ `kb_tenant_id` varchar(255) DEFAULT NULL,
28
+ PRIMARY KEY (`id`),
29
+ KEY `index_securenet_payment_methods_on_kb_account_id` (`kb_account_id`),
30
+ KEY `index_securenet_payment_methods_on_kb_payment_method_id` (`kb_payment_method_id`)
31
+ ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
32
+
33
+ CREATE TABLE `securenet_transactions` (
34
+ `id` int(11) NOT NULL AUTO_INCREMENT,
35
+ `securenet_response_id` int(11) NOT NULL,
36
+ `api_call` varchar(255) NOT NULL,
37
+ `kb_payment_id` varchar(255) NOT NULL,
38
+ `kb_payment_transaction_id` varchar(255) NOT NULL,
39
+ `transaction_type` varchar(255) NOT NULL,
40
+ `payment_processor_account_id` varchar(255) DEFAULT NULL,
41
+ `txn_id` varchar(255) DEFAULT NULL,
42
+ `amount_in_cents` int(11) DEFAULT NULL,
43
+ `currency` varchar(255) DEFAULT NULL,
44
+ `created_at` datetime NOT NULL,
45
+ `updated_at` datetime NOT NULL,
46
+ `kb_account_id` varchar(255) NOT NULL,
47
+ `kb_tenant_id` varchar(255) NOT NULL,
48
+ PRIMARY KEY (`id`),
49
+ KEY `index_securenet_transactions_on_kb_payment_id` (`kb_payment_id`)
50
+ ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
51
+
52
+ CREATE TABLE `securenet_responses` (
53
+ `id` int(11) NOT NULL AUTO_INCREMENT,
54
+ `api_call` varchar(255) NOT NULL,
55
+ `kb_payment_id` varchar(255) DEFAULT NULL,
56
+ `kb_payment_transaction_id` varchar(255) DEFAULT NULL,
57
+ `transaction_type` varchar(255) DEFAULT NULL,
58
+ `payment_processor_account_id` varchar(255) DEFAULT NULL,
59
+ `message` varchar(255) DEFAULT NULL,
60
+ `authorization` varchar(255) DEFAULT NULL,
61
+ `fraud_review` tinyint(1) DEFAULT NULL,
62
+ `test` tinyint(1) DEFAULT NULL,
63
+ `avs_result_code` varchar(255) DEFAULT NULL,
64
+ `avs_result_message` varchar(255) DEFAULT NULL,
65
+ `avs_result_street_match` varchar(255) DEFAULT NULL,
66
+ `avs_result_postal_match` varchar(255) DEFAULT NULL,
67
+ `cvv_result_code` varchar(255) DEFAULT NULL,
68
+ `cvv_result_message` varchar(255) DEFAULT NULL,
69
+ `success` tinyint(1) DEFAULT NULL,
70
+ `created_at` datetime NOT NULL,
71
+ `updated_at` datetime NOT NULL,
72
+ `kb_account_id` varchar(255) DEFAULT NULL,
73
+ `kb_tenant_id` varchar(255) DEFAULT NULL,
74
+ PRIMARY KEY (`id`)
75
+ ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
data/db/schema.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Schema.define(:version => 20140410153635) do
4
+ create_table "securenet_payment_methods", :force => true do |t|
5
+ t.string "kb_payment_method_id" # NULL before Kill Bill knows about it
6
+ t.string "token" # securenet id
7
+ t.string "cc_first_name"
8
+ t.string "cc_last_name"
9
+ t.string "cc_type"
10
+ t.string "cc_exp_month"
11
+ t.string "cc_exp_year"
12
+ t.string "cc_number"
13
+ t.string "cc_last_4"
14
+ t.string "cc_start_month"
15
+ t.string "cc_start_year"
16
+ t.string "cc_issue_number"
17
+ t.string "cc_verification_value"
18
+ t.string "cc_track_data"
19
+ t.string "address1"
20
+ t.string "address2"
21
+ t.string "city"
22
+ t.string "state"
23
+ t.string "zip"
24
+ t.string "country"
25
+ t.boolean "is_deleted", :null => false, :default => false
26
+ t.datetime "created_at", :null => false
27
+ t.datetime "updated_at", :null => false
28
+ t.string "kb_account_id"
29
+ t.string "kb_tenant_id"
30
+ end
31
+
32
+ add_index(:securenet_payment_methods, :kb_account_id)
33
+ add_index(:securenet_payment_methods, :kb_payment_method_id)
34
+
35
+ create_table "securenet_transactions", :force => true do |t|
36
+ t.integer "securenet_response_id", :null => false
37
+ t.string "api_call", :null => false
38
+ t.string "kb_payment_id", :null => false
39
+ t.string "kb_payment_transaction_id", :null => false
40
+ t.string "transaction_type", :null => false
41
+ t.string "payment_processor_account_id"
42
+ t.string "txn_id" # securenet transaction id
43
+ # Both null for void
44
+ t.integer "amount_in_cents"
45
+ t.string "currency"
46
+ t.datetime "created_at", :null => false
47
+ t.datetime "updated_at", :null => false
48
+ t.string "kb_account_id", :null => false
49
+ t.string "kb_tenant_id", :null => false
50
+ end
51
+
52
+ add_index(:securenet_transactions, :kb_payment_id)
53
+
54
+ create_table "securenet_responses", :force => true do |t|
55
+ t.string "api_call", :null => false
56
+ t.string "kb_payment_id"
57
+ t.string "kb_payment_transaction_id"
58
+ t.string "transaction_type"
59
+ t.string "payment_processor_account_id"
60
+ t.string "message"
61
+ t.string "authorization"
62
+ t.boolean "fraud_review"
63
+ t.boolean "test"
64
+ t.string "avs_result_code"
65
+ t.string "avs_result_message"
66
+ t.string "avs_result_street_match"
67
+ t.string "avs_result_postal_match"
68
+ t.string "cvv_result_code"
69
+ t.string "cvv_result_message"
70
+ t.boolean "success"
71
+ t.datetime "created_at", :null => false
72
+ t.datetime "updated_at", :null => false
73
+ t.string "kb_account_id"
74
+ t.string "kb_tenant_id"
75
+ end
76
+ end
@@ -0,0 +1,52 @@
1
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'killbill-securenet'
5
+ s.version = version
6
+ s.summary = 'Plugin to use SecureNet as a gateway.'
7
+ s.description = 'Kill Bill payment plugin for SecureNet.'
8
+
9
+ s.required_ruby_version = '>= 1.9.3'
10
+
11
+ s.license = 'Apache License (2.0)'
12
+
13
+ s.author = 'Kill Bill core team'
14
+ s.email = 'killbilling-users@googlegroups.com'
15
+ s.homepage = 'http://killbill.io'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.bindir = 'bin'
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+
23
+ s.rdoc_options << '--exclude' << '.'
24
+
25
+ s.add_dependency 'killbill', '~> 7.0'
26
+
27
+ s.add_dependency 'sinatra', '~> 1.3.4'
28
+ s.add_dependency 'thread_safe', '~> 0.3.4'
29
+ s.add_dependency 'activerecord', '~> 4.1.0'
30
+ if defined?(JRUBY_VERSION)
31
+ s.add_dependency 'activerecord-bogacs', '~> 0.3'
32
+ s.add_dependency 'activerecord-jdbc-adapter', '~> 1.3'
33
+ # Required to avoid errors like java.lang.NoClassDefFoundError: org/bouncycastle/asn1/DERBoolean
34
+ s.add_dependency 'jruby-openssl', '~> 0.9.6'
35
+ end
36
+ s.add_dependency 'actionpack', '~> 4.1.0'
37
+ s.add_dependency 'actionview', '~> 4.1.0'
38
+ s.add_dependency 'activemerchant', '~> 1.48.0'
39
+ s.add_dependency 'offsite_payments', '~> 2.1.0'
40
+ s.add_dependency 'monetize', '~> 1.1.0'
41
+ s.add_dependency 'money', '~> 6.5.1'
42
+
43
+ s.add_development_dependency 'jbundler', '~> 0.9.2'
44
+ s.add_development_dependency 'rake', '>= 10.0.0'
45
+ s.add_development_dependency 'rspec', '~> 2.12.0'
46
+ if defined?(JRUBY_VERSION)
47
+ s.add_development_dependency 'jdbc-sqlite3', '~> 3.7'
48
+ s.add_development_dependency 'jdbc-mariadb', '~> 1.1'
49
+ else
50
+ s.add_development_dependency 'sqlite3', '~> 1.3.7'
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ mainClass=Killbill::Securenet::PaymentPlugin
2
+ require=securenet
3
+ pluginType=PAYMENT
data/lib/securenet.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'openssl'
2
+ require 'action_controller'
3
+ require 'active_record'
4
+ require 'action_view'
5
+ require 'active_merchant'
6
+ require 'active_support'
7
+ require 'bigdecimal'
8
+ require 'money'
9
+ require 'monetize'
10
+ require 'offsite_payments'
11
+ require 'pathname'
12
+ require 'sinatra'
13
+ require 'singleton'
14
+ require 'yaml'
15
+
16
+ require 'killbill'
17
+ require 'killbill/helpers/active_merchant'
18
+
19
+ require 'securenet/api'
20
+ require 'securenet/private_api'
21
+
22
+ require 'securenet/models/payment_method'
23
+ require 'securenet/models/response'
24
+ require 'securenet/models/transaction'
@@ -0,0 +1,185 @@
1
+ module Killbill #:nodoc:
2
+ module Securenet #:nodoc:
3
+ class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
4
+
5
+ def initialize
6
+ gateway_builder = Proc.new do |config|
7
+ ::ActiveMerchant::Billing::SecureNetGateway.new :login => config[:login], :password => config[:password]
8
+ end
9
+
10
+ super(gateway_builder,
11
+ :securenet,
12
+ ::Killbill::Securenet::SecurenetPaymentMethod,
13
+ ::Killbill::Securenet::SecurenetTransaction,
14
+ ::Killbill::Securenet::SecurenetResponse)
15
+ end
16
+
17
+ def on_event(event)
18
+ # Require to deal with per tenant configuration invalidation
19
+ super(event)
20
+ #
21
+ # Custom event logic could be added below...
22
+ #
23
+ end
24
+
25
+ def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
26
+ # Pass extra parameters for the gateway here
27
+ options = {}
28
+
29
+ default_options(options, kb_payment_transaction_id)
30
+
31
+ properties = merge_properties(properties, options)
32
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
33
+ end
34
+
35
+ def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
36
+ # Pass extra parameters for the gateway here
37
+ options = {}
38
+
39
+ default_options(options, kb_payment_transaction_id)
40
+
41
+ properties = merge_properties(properties, options)
42
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
43
+ end
44
+
45
+ def purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
46
+ # Pass extra parameters for the gateway here
47
+ options = {}
48
+
49
+ default_options(options, kb_payment_transaction_id)
50
+
51
+ properties = merge_properties(properties, options)
52
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
53
+ end
54
+
55
+ def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
56
+ # Pass extra parameters for the gateway here
57
+ options = {}
58
+
59
+ default_options(options, kb_payment_transaction_id)
60
+
61
+ properties = merge_properties(properties, options)
62
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
63
+ end
64
+
65
+ def credit_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
66
+ # Pass extra parameters for the gateway here
67
+ options = {}
68
+
69
+ default_options(options, kb_payment_transaction_id)
70
+
71
+ properties = merge_properties(properties, options)
72
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
73
+ end
74
+
75
+ def refund_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
76
+ # Pass extra parameters for the gateway here
77
+ options = {}
78
+
79
+ default_options(options, kb_payment_transaction_id)
80
+
81
+ properties = merge_properties(properties, options)
82
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
83
+ end
84
+
85
+ def get_payment_info(kb_account_id, kb_payment_id, properties, context)
86
+ # Pass extra parameters for the gateway here
87
+ options = {}
88
+
89
+ properties = merge_properties(properties, options)
90
+ super(kb_account_id, kb_payment_id, properties, context)
91
+ end
92
+
93
+ def search_payments(search_key, offset, limit, properties, context)
94
+ # Pass extra parameters for the gateway here
95
+ options = {}
96
+
97
+ properties = merge_properties(properties, options)
98
+ super(search_key, offset, limit, properties, context)
99
+ end
100
+
101
+ def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
102
+ # Pass extra parameters for the gateway here
103
+ options = {}
104
+
105
+ properties = merge_properties(properties, options)
106
+ super(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
107
+ end
108
+
109
+ def delete_payment_method(kb_account_id, kb_payment_method_id, properties, context)
110
+ # Pass extra parameters for the gateway here
111
+ options = {}
112
+
113
+ properties = merge_properties(properties, options)
114
+ super(kb_account_id, kb_payment_method_id, properties, context)
115
+ end
116
+
117
+ def get_payment_method_detail(kb_account_id, kb_payment_method_id, properties, context)
118
+ # Pass extra parameters for the gateway here
119
+ options = {}
120
+
121
+ properties = merge_properties(properties, options)
122
+ super(kb_account_id, kb_payment_method_id, properties, context)
123
+ end
124
+
125
+ def set_default_payment_method(kb_account_id, kb_payment_method_id, properties, context)
126
+ # TODO
127
+ end
128
+
129
+ def get_payment_methods(kb_account_id, refresh_from_gateway, properties, context)
130
+ # Pass extra parameters for the gateway here
131
+ options = {}
132
+
133
+ properties = merge_properties(properties, options)
134
+ super(kb_account_id, refresh_from_gateway, properties, context)
135
+ end
136
+
137
+ def search_payment_methods(search_key, offset, limit, properties, context)
138
+ # Pass extra parameters for the gateway here
139
+ options = {}
140
+
141
+ properties = merge_properties(properties, options)
142
+ super(search_key, offset, limit, properties, context)
143
+ end
144
+
145
+ def reset_payment_methods(kb_account_id, payment_methods, properties, context)
146
+ super
147
+ end
148
+
149
+ def build_form_descriptor(kb_account_id, descriptor_fields, properties, context)
150
+ # Pass extra parameters for the gateway here
151
+ options = {}
152
+ properties = merge_properties(properties, options)
153
+
154
+ # Add your custom static hidden tags here
155
+ options = {
156
+ #:token => config[:securenet][:token]
157
+ }
158
+ descriptor_fields = merge_properties(descriptor_fields, options)
159
+
160
+ super(kb_account_id, descriptor_fields, properties, context)
161
+ end
162
+
163
+ def process_notification(notification, properties, context)
164
+ # Pass extra parameters for the gateway here
165
+ options = {}
166
+ properties = merge_properties(properties, options)
167
+
168
+ super(notification, properties, context) do |gw_notification, service|
169
+ # Retrieve the payment
170
+ # gw_notification.kb_payment_id =
171
+ #
172
+ # Set the response body
173
+ # gw_notification.entity =
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def default_options(options, kb_payment_transaction_id)
180
+ # SecureNet limits it to 25 characters
181
+ options[:order_id] ||= Killbill::Plugin::ActiveMerchant::Utils.compact_uuid(kb_payment_transaction_id)
182
+ end
183
+ end
184
+ end
185
+ end