killbill-stripe 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.
- checksums.yaml +7 -0
- data/.gitignore +39 -0
- data/.travis.yml +19 -0
- data/Gemfile +3 -0
- data/Jarfile +6 -0
- data/NEWS +2 -0
- data/README.md +21 -0
- data/Rakefile +30 -0
- data/VERSION +1 -0
- data/config.ru +4 -0
- data/db/ddl.sql +99 -0
- data/db/schema.rb +99 -0
- data/killbill-stripe.gemspec +42 -0
- data/killbill.properties +3 -0
- data/lib/stripe/api.rb +248 -0
- data/lib/stripe/config/application.rb +76 -0
- data/lib/stripe/config/configuration.rb +38 -0
- data/lib/stripe/config/properties.rb +23 -0
- data/lib/stripe/models/stripe_payment_method.rb +182 -0
- data/lib/stripe/models/stripe_response.rb +242 -0
- data/lib/stripe/models/stripe_transaction.rb +44 -0
- data/lib/stripe/private_api.rb +52 -0
- data/lib/stripe/stripe/gateway.rb +24 -0
- data/lib/stripe/stripe_utils.rb +27 -0
- data/lib/stripe/views/stripejs.erb +88 -0
- data/lib/stripe.rb +30 -0
- data/pom.xml +44 -0
- data/release.sh +41 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/stripe/base_plugin_spec.rb +85 -0
- data/spec/stripe/remote/integration_spec.rb +208 -0
- data/spec/stripe/stripe_payment_method_spec.rb +97 -0
- data/spec/stripe/stripe_response_spec.rb +84 -0
- metadata +222 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 70736e813db9a21f0144ef12503a5e257978d083
|
4
|
+
data.tar.gz: f620f84e2a4da96f51fbb70a0b1c5c2b39a42303
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5991a3693fdfb78f398bcde89f8113fed5ad72fe6d58d17ea8bd887a4cc570fafab74d1d43014ef1b16af26732c967a6d3fb9a5992c70d0c9bc206210f49173a
|
7
|
+
data.tar.gz: 8ed1cc06a9801512930f089a1d9e90143c224272c411cea8ff043c93cd90cc89e79d715a498eabf4eac63af6de3a9bae3a16ee904f88ca24e4f3713ed23e0958
|
data/.gitignore
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
*.swp
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
coverage
|
7
|
+
InstalledFiles
|
8
|
+
lib/bundler/man
|
9
|
+
pkg
|
10
|
+
rdoc
|
11
|
+
spec/reports
|
12
|
+
test/tmp
|
13
|
+
test/version_tmp
|
14
|
+
tmp
|
15
|
+
|
16
|
+
# YARD artifacts
|
17
|
+
.yardoc
|
18
|
+
_yardoc
|
19
|
+
doc/
|
20
|
+
|
21
|
+
.jbundler
|
22
|
+
Jarfile.lock
|
23
|
+
Gemfile.lock
|
24
|
+
|
25
|
+
.DS_Store
|
26
|
+
|
27
|
+
# Build directory
|
28
|
+
killbill-stripe/
|
29
|
+
|
30
|
+
# Config file
|
31
|
+
stripe.yml
|
32
|
+
|
33
|
+
# Testing database
|
34
|
+
test.db
|
35
|
+
|
36
|
+
target
|
37
|
+
pom.xml.asc
|
38
|
+
|
39
|
+
.idea/
|
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
notifications:
|
4
|
+
email:
|
5
|
+
- kill-bill-commits@googlegroups.com
|
6
|
+
|
7
|
+
rvm:
|
8
|
+
- jruby-19mode
|
9
|
+
- jruby-20mode
|
10
|
+
- jruby-head
|
11
|
+
|
12
|
+
jdk:
|
13
|
+
- openjdk6
|
14
|
+
- openjdk7
|
15
|
+
- oraclejdk7
|
16
|
+
|
17
|
+
matrix:
|
18
|
+
allow_failures:
|
19
|
+
- rvm: jruby-head
|
data/Gemfile
ADDED
data/Jarfile
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
jar 'org.kill-bill.billing:killbill-api', '0.8.2'
|
2
|
+
jar 'org.kill-bill.billing.plugin:killbill-plugin-api-notification', '0.6.4'
|
3
|
+
jar 'org.kill-bill.billing.plugin:killbill-plugin-api-payment', '0.6.4'
|
4
|
+
jar 'org.kill-bill.billing.plugin:killbill-plugin-api-currency', '0.6.4'
|
5
|
+
jar 'org.kill-bill.billing:killbill-util:tests', '0.9.1'
|
6
|
+
jar 'javax.servlet:javax.servlet-api', '3.0.1'
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
killbill-stripe-plugin
|
2
|
+
======================
|
3
|
+
|
4
|
+
Killbill payment plugin for Stripe.
|
5
|
+
|
6
|
+
Getting started
|
7
|
+
---------------
|
8
|
+
|
9
|
+
1. Make sure you can build the project by running the smoke tests: `mvn clean test`
|
10
|
+
2. Go to [stripe.com](http://stripe.com/) and create an account. This account will be used as a sandbox environment for testing.
|
11
|
+
3. In your Stripe account, click on **Your Account** (top right), then click on **Account Settings** and then on the **API Keys** tab. Write down your Test Secret Key.
|
12
|
+
4. Verify the setup by running the killbill-stripe-plugin integration tests (make sure to update your API Key): `mvn clean test -Pintegration -Dkillbill.payment.stripe.apiKey=1234567689abcdef`
|
13
|
+
5. Go to your Stripe account, you should see some data (e.g. account created).
|
14
|
+
6. Congrats! You're all set!
|
15
|
+
|
16
|
+
Build
|
17
|
+
-----
|
18
|
+
|
19
|
+
To build the project, use maven:
|
20
|
+
|
21
|
+
mvn clean install
|
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
data/db/ddl.sql
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
CREATE TABLE `stripe_payment_methods` (
|
2
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
3
|
+
`kb_account_id` varchar(255) NOT NULL,
|
4
|
+
`kb_payment_method_id` varchar(255) DEFAULT NULL,
|
5
|
+
`stripe_customer_id` varchar(255) DEFAULT NULL,
|
6
|
+
`stripe_card_id_or_token` varchar(255) NOT NULL,
|
7
|
+
`cc_first_name` varchar(255) DEFAULT NULL,
|
8
|
+
`cc_last_name` varchar(255) DEFAULT NULL,
|
9
|
+
`cc_type` varchar(255) DEFAULT NULL,
|
10
|
+
`cc_exp_month` int(11) DEFAULT NULL,
|
11
|
+
`cc_exp_year` int(11) DEFAULT NULL,
|
12
|
+
`cc_last_4` int(11) DEFAULT NULL,
|
13
|
+
`address1` varchar(255) DEFAULT NULL,
|
14
|
+
`address2` varchar(255) DEFAULT NULL,
|
15
|
+
`city` varchar(255) DEFAULT NULL,
|
16
|
+
`state` varchar(255) DEFAULT NULL,
|
17
|
+
`zip` varchar(255) DEFAULT NULL,
|
18
|
+
`country` varchar(255) DEFAULT NULL,
|
19
|
+
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
|
20
|
+
`created_at` datetime NOT NULL,
|
21
|
+
`updated_at` datetime NOT NULL,
|
22
|
+
PRIMARY KEY (`id`),
|
23
|
+
KEY `index_stripe_payment_methods_on_kb_account_id` (`kb_account_id`),
|
24
|
+
KEY `index_stripe_payment_methods_on_kb_payment_method_id` (`kb_payment_method_id`)
|
25
|
+
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
26
|
+
|
27
|
+
CREATE TABLE `stripe_transactions` (
|
28
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
29
|
+
`stripe_response_id` int(11) NOT NULL,
|
30
|
+
`api_call` varchar(255) NOT NULL,
|
31
|
+
`kb_payment_id` varchar(255) NOT NULL,
|
32
|
+
`stripe_txn_id` varchar(255) NOT NULL,
|
33
|
+
`amount_in_cents` int(11) NOT NULL,
|
34
|
+
`currency` char(3) NOT NULL,
|
35
|
+
`created_at` datetime NOT NULL,
|
36
|
+
`updated_at` datetime NOT NULL,
|
37
|
+
PRIMARY KEY (`id`),
|
38
|
+
KEY `index_stripe_transactions_on_kb_payment_id` (`kb_payment_id`)
|
39
|
+
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
40
|
+
|
41
|
+
CREATE TABLE `stripe_responses` (
|
42
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
43
|
+
`api_call` varchar(255) NOT NULL,
|
44
|
+
`kb_payment_id` varchar(255) DEFAULT NULL,
|
45
|
+
`message` varchar(255) DEFAULT NULL,
|
46
|
+
`authorization` varchar(255) DEFAULT NULL,
|
47
|
+
`fraud_review` tinyint(1) DEFAULT NULL,
|
48
|
+
`test` tinyint(1) DEFAULT NULL,
|
49
|
+
`params_id` varchar(255) DEFAULT NULL,
|
50
|
+
`params_object` varchar(255) DEFAULT NULL,
|
51
|
+
`params_created` varchar(255) DEFAULT NULL,
|
52
|
+
`params_livemode` varchar(255) DEFAULT NULL,
|
53
|
+
`params_paid` varchar(255) DEFAULT NULL,
|
54
|
+
`params_amount` varchar(255) DEFAULT NULL,
|
55
|
+
`params_currency` varchar(255) DEFAULT NULL,
|
56
|
+
`params_refunded` varchar(255) DEFAULT NULL,
|
57
|
+
`params_card_id` varchar(255) DEFAULT NULL,
|
58
|
+
`params_card_object` varchar(255) DEFAULT NULL,
|
59
|
+
`params_card_last4` varchar(255) DEFAULT NULL,
|
60
|
+
`params_card_type` varchar(255) DEFAULT NULL,
|
61
|
+
`params_card_exp_month` varchar(255) DEFAULT NULL,
|
62
|
+
`params_card_exp_year` varchar(255) DEFAULT NULL,
|
63
|
+
`params_card_fingerprint` varchar(255) DEFAULT NULL,
|
64
|
+
`params_card_customer` varchar(255) DEFAULT NULL,
|
65
|
+
`params_card_country` varchar(255) DEFAULT NULL,
|
66
|
+
`params_card_name` varchar(255) DEFAULT NULL,
|
67
|
+
`params_card_address_line1` varchar(255) DEFAULT NULL,
|
68
|
+
`params_card_address_line2` varchar(255) DEFAULT NULL,
|
69
|
+
`params_card_address_city` varchar(255) DEFAULT NULL,
|
70
|
+
`params_card_address_state` varchar(255) DEFAULT NULL,
|
71
|
+
`params_card_address_zip` varchar(255) DEFAULT NULL,
|
72
|
+
`params_card_address_country` varchar(255) DEFAULT NULL,
|
73
|
+
`params_card_cvc_check` varchar(255) DEFAULT NULL,
|
74
|
+
`params_card_address_line1_check` varchar(255) DEFAULT NULL,
|
75
|
+
`params_card_address_zip_check` varchar(255) DEFAULT NULL,
|
76
|
+
`params_captured` varchar(255) DEFAULT NULL,
|
77
|
+
`params_refunds` varchar(255) DEFAULT NULL,
|
78
|
+
`params_balance_transaction` varchar(255) DEFAULT NULL,
|
79
|
+
`params_failure_message` varchar(255) DEFAULT NULL,
|
80
|
+
`params_failure_code` varchar(255) DEFAULT NULL,
|
81
|
+
`params_amount_refunded` varchar(255) DEFAULT NULL,
|
82
|
+
`params_customer` varchar(255) DEFAULT NULL,
|
83
|
+
`params_invoice` varchar(255) DEFAULT NULL,
|
84
|
+
`params_description` varchar(255) DEFAULT NULL,
|
85
|
+
`params_dispute` varchar(255) DEFAULT NULL,
|
86
|
+
`params_metadata` varchar(255) DEFAULT NULL,
|
87
|
+
`params_error_type` varchar(255) DEFAULT NULL,
|
88
|
+
`params_error_message` varchar(255) DEFAULT NULL,
|
89
|
+
`avs_result_code` varchar(255) DEFAULT NULL,
|
90
|
+
`avs_result_message` varchar(255) DEFAULT NULL,
|
91
|
+
`avs_result_street_match` varchar(255) DEFAULT NULL,
|
92
|
+
`avs_result_postal_match` varchar(255) DEFAULT NULL,
|
93
|
+
`cvv_result_code` varchar(255) DEFAULT NULL,
|
94
|
+
`cvv_result_message` varchar(255) DEFAULT NULL,
|
95
|
+
`success` tinyint(1) DEFAULT NULL,
|
96
|
+
`created_at` datetime NOT NULL,
|
97
|
+
`updated_at` datetime NOT NULL,
|
98
|
+
PRIMARY KEY (`id`)
|
99
|
+
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
data/db/schema.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define(:version => 20130311153635) do
|
4
|
+
create_table "stripe_payment_methods", :force => true do |t|
|
5
|
+
t.string "kb_account_id", :null => false
|
6
|
+
t.string "kb_payment_method_id" # NULL before Killbill knows about it
|
7
|
+
t.string "stripe_customer_id"
|
8
|
+
t.string "stripe_card_id_or_token",:null => false
|
9
|
+
t.string "cc_first_name"
|
10
|
+
t.string "cc_last_name"
|
11
|
+
t.string "cc_type"
|
12
|
+
t.integer "cc_exp_month"
|
13
|
+
t.integer "cc_exp_year"
|
14
|
+
t.integer "cc_last_4"
|
15
|
+
t.string "address1"
|
16
|
+
t.string "address2"
|
17
|
+
t.string "city"
|
18
|
+
t.string "state"
|
19
|
+
t.string "zip"
|
20
|
+
t.string "country"
|
21
|
+
t.boolean "is_deleted", :null => false, :default => false
|
22
|
+
t.datetime "created_at", :null => false
|
23
|
+
t.datetime "updated_at", :null => false
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index(:stripe_payment_methods, :kb_account_id)
|
27
|
+
add_index(:stripe_payment_methods, :kb_payment_method_id)
|
28
|
+
|
29
|
+
create_table "stripe_transactions", :force => true do |t|
|
30
|
+
t.integer "stripe_response_id", :null => false
|
31
|
+
t.string "api_call", :null => false
|
32
|
+
t.string "kb_payment_id", :null => false
|
33
|
+
t.string "stripe_txn_id", :null => false
|
34
|
+
t.integer "amount_in_cents", :null => false
|
35
|
+
t.string "currency", :null => false
|
36
|
+
t.datetime "created_at", :null => false
|
37
|
+
t.datetime "updated_at", :null => false
|
38
|
+
end
|
39
|
+
|
40
|
+
add_index(:stripe_transactions, :kb_payment_id)
|
41
|
+
|
42
|
+
create_table "stripe_responses", :force => true do |t|
|
43
|
+
t.string "api_call", :null => false
|
44
|
+
t.string "kb_payment_id"
|
45
|
+
t.string "message"
|
46
|
+
t.string "authorization"
|
47
|
+
t.boolean "fraud_review"
|
48
|
+
t.boolean "test"
|
49
|
+
t.string "params_id"
|
50
|
+
t.string "params_object"
|
51
|
+
t.string "params_created"
|
52
|
+
t.string "params_livemode"
|
53
|
+
t.string "params_paid"
|
54
|
+
t.string "params_amount"
|
55
|
+
t.string "params_currency"
|
56
|
+
t.string "params_refunded"
|
57
|
+
t.string "params_card_id"
|
58
|
+
t.string "params_card_object"
|
59
|
+
t.string "params_card_last4"
|
60
|
+
t.string "params_card_type"
|
61
|
+
t.string "params_card_exp_month"
|
62
|
+
t.string "params_card_exp_year"
|
63
|
+
t.string "params_card_fingerprint"
|
64
|
+
t.string "params_card_customer"
|
65
|
+
t.string "params_card_country"
|
66
|
+
t.string "params_card_name"
|
67
|
+
t.string "params_card_address_line1"
|
68
|
+
t.string "params_card_address_line2"
|
69
|
+
t.string "params_card_address_city"
|
70
|
+
t.string "params_card_address_state"
|
71
|
+
t.string "params_card_address_zip"
|
72
|
+
t.string "params_card_address_country"
|
73
|
+
t.string "params_card_cvc_check"
|
74
|
+
t.string "params_card_address_line1_check"
|
75
|
+
t.string "params_card_address_zip_check"
|
76
|
+
t.string "params_captured"
|
77
|
+
t.string "params_refunds"
|
78
|
+
t.string "params_balance_transaction"
|
79
|
+
t.string "params_failure_message"
|
80
|
+
t.string "params_failure_code"
|
81
|
+
t.string "params_amount_refunded"
|
82
|
+
t.string "params_customer"
|
83
|
+
t.string "params_invoice"
|
84
|
+
t.string "params_description"
|
85
|
+
t.string "params_dispute"
|
86
|
+
t.string "params_metadata"
|
87
|
+
t.string "params_error_type"
|
88
|
+
t.string "params_error_message"
|
89
|
+
t.string "avs_result_code"
|
90
|
+
t.string "avs_result_message"
|
91
|
+
t.string "avs_result_street_match"
|
92
|
+
t.string "avs_result_postal_match"
|
93
|
+
t.string "cvv_result_code"
|
94
|
+
t.string "cvv_result_message"
|
95
|
+
t.boolean "success"
|
96
|
+
t.datetime "created_at", :null => false
|
97
|
+
t.datetime "updated_at", :null => false
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
version = File.read(File.expand_path('../VERSION', __FILE__)).strip
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'killbill-stripe'
|
5
|
+
s.version = version
|
6
|
+
s.summary = 'Plugin to use Stripe as a gateway.'
|
7
|
+
s.description = 'Kill Bill payment plugin for Stripe.'
|
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://kill-bill.org'
|
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', '~> 3.0.0'
|
26
|
+
s.add_dependency 'activemerchant', '~> 1.42.3'
|
27
|
+
s.add_dependency 'activerecord', '~> 3.2.1'
|
28
|
+
s.add_dependency 'money', '~> 6.0.0'
|
29
|
+
s.add_dependency 'sinatra', '~> 1.3.4'
|
30
|
+
if defined?(JRUBY_VERSION)
|
31
|
+
s.add_dependency 'activerecord-jdbcmysql-adapter', '~> 1.2.9'
|
32
|
+
end
|
33
|
+
|
34
|
+
s.add_development_dependency 'jbundler', '~> 0.4.1'
|
35
|
+
s.add_development_dependency 'rake', '>= 10.0.0'
|
36
|
+
s.add_development_dependency 'rspec', '~> 2.12.0'
|
37
|
+
if defined?(JRUBY_VERSION)
|
38
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.2.6'
|
39
|
+
else
|
40
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
41
|
+
end
|
42
|
+
end
|
data/killbill.properties
ADDED
data/lib/stripe/api.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
module Killbill::Stripe
|
2
|
+
class PaymentPlugin < Killbill::Plugin::Payment
|
3
|
+
def start_plugin
|
4
|
+
Killbill::Stripe.initialize! @logger, @conf_dir, @kb_apis
|
5
|
+
|
6
|
+
super
|
7
|
+
|
8
|
+
@logger.info 'Killbill::Stripe::PaymentPlugin started'
|
9
|
+
end
|
10
|
+
|
11
|
+
# return DB connections to the Pool if required
|
12
|
+
def after_request
|
13
|
+
ActiveRecord::Base.connection.close
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, call_context = nil, options = {})
|
17
|
+
# Use Money to compute the amount in cents, as it depends on the currency (1 cent of BTC is 1 Satoshi, not 0.01 BTC)
|
18
|
+
amount_in_cents = Money.new_with_amount(amount, currency).cents.to_i
|
19
|
+
|
20
|
+
# If the payment was already made, just return the status
|
21
|
+
stripe_transaction = StripeTransaction.from_kb_payment_id(kb_payment_id) rescue nil
|
22
|
+
return stripe_transaction.stripe_response.to_payment_response unless stripe_transaction.nil?
|
23
|
+
|
24
|
+
options[:order_id] ||= kb_payment_id
|
25
|
+
options[:currency] ||= currency.to_s.upcase
|
26
|
+
options[:description] ||= Killbill::Stripe.stripe_payment_description || "Kill Bill payment for #{kb_payment_id}"
|
27
|
+
|
28
|
+
# Retrieve the Stripe payment method
|
29
|
+
pm = StripePaymentMethod.from_kb_payment_method_id(kb_payment_method_id)
|
30
|
+
options[:customer] ||= pm.stripe_customer_id
|
31
|
+
|
32
|
+
# Go to Stripe
|
33
|
+
stripe_response = Killbill::Stripe.gateway.purchase amount_in_cents, pm.stripe_card_id_or_token, options
|
34
|
+
response = save_response_and_transaction stripe_response, :charge, kb_payment_id, amount_in_cents, currency
|
35
|
+
|
36
|
+
response.to_payment_response
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_payment_info(kb_account_id, kb_payment_id, tenant_context = nil, options = {})
|
40
|
+
# We assume the payment is immutable in Stripe and only look at our tables
|
41
|
+
stripe_transaction = StripeTransaction.from_kb_payment_id(kb_payment_id)
|
42
|
+
stripe_transaction.stripe_response.to_payment_response
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_refund(kb_account_id, kb_payment_id, amount, currency, call_context = nil, options = {})
|
46
|
+
# Use Money to compute the amount in cents, as it depends on the currency (1 cent of BTC is 1 Satoshi, not 0.01 BTC)
|
47
|
+
amount_in_cents = Money.new_with_amount(amount, currency).cents.to_i
|
48
|
+
|
49
|
+
stripe_transaction = StripeTransaction.find_candidate_transaction_for_refund(kb_payment_id, amount_in_cents)
|
50
|
+
|
51
|
+
# Go to Stripe
|
52
|
+
stripe_response = Killbill::Stripe.gateway.refund amount_in_cents, stripe_transaction.stripe_txn_id, options
|
53
|
+
response = save_response_and_transaction stripe_response, :refund, kb_payment_id, amount_in_cents, currency
|
54
|
+
|
55
|
+
response.to_refund_response
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_refund_info(kb_account_id, kb_payment_id, tenant_context = nil, options = {})
|
59
|
+
# We assume the refund is immutable in Stripe and only look at our tables
|
60
|
+
stripe_transactions = StripeTransaction.refunds_from_kb_payment_id(kb_payment_id)
|
61
|
+
|
62
|
+
stripe_transactions.map { |t| t.stripe_response.to_refund_response }
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, call_context = nil, options = {})
|
66
|
+
# Do we have a customer for that account already?
|
67
|
+
stripe_customer_id = StripePaymentMethod.stripe_customer_id_from_kb_account_id(kb_account_id)
|
68
|
+
|
69
|
+
# This will either update the current customer if present, or create a new one
|
70
|
+
options[:customer] ||= stripe_customer_id
|
71
|
+
options[:set_default] ||= set_default
|
72
|
+
|
73
|
+
# Magic field, see also private_api.rb (works only when creating an account)
|
74
|
+
if options[:customer].blank?
|
75
|
+
options[:description] ||= kb_account_id
|
76
|
+
else
|
77
|
+
options[:description] = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
# Registering a card or a token from Stripe.js?
|
81
|
+
cc_or_token = find_value_from_payment_method_props(payment_method_props, 'token') || find_value_from_payment_method_props(payment_method_props, 'cardId')
|
82
|
+
if cc_or_token.blank?
|
83
|
+
# Nope - real credit card
|
84
|
+
cc_or_token = ActiveMerchant::Billing::CreditCard.new(
|
85
|
+
:number => find_value_from_payment_method_props(payment_method_props, 'ccNumber'),
|
86
|
+
:month => find_value_from_payment_method_props(payment_method_props, 'ccExpirationMonth'),
|
87
|
+
:year => find_value_from_payment_method_props(payment_method_props, 'ccExpirationYear'),
|
88
|
+
:verification_value => find_value_from_payment_method_props(payment_method_props, 'ccVerificationValue'),
|
89
|
+
:first_name => find_value_from_payment_method_props(payment_method_props, 'ccFirstName'),
|
90
|
+
:last_name => find_value_from_payment_method_props(payment_method_props, 'ccLastName')
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
options[:billing_address] ||= {
|
95
|
+
:address1 => find_value_from_payment_method_props(payment_method_props, 'address1'),
|
96
|
+
:address2 => find_value_from_payment_method_props(payment_method_props, 'address2'),
|
97
|
+
:city => find_value_from_payment_method_props(payment_method_props, 'city'),
|
98
|
+
:zip => find_value_from_payment_method_props(payment_method_props, 'zip'),
|
99
|
+
:state => find_value_from_payment_method_props(payment_method_props, 'state'),
|
100
|
+
:country => find_value_from_payment_method_props(payment_method_props, 'country')
|
101
|
+
}
|
102
|
+
|
103
|
+
# Go to Stripe
|
104
|
+
stripe_response = Killbill::Stripe.gateway.store cc_or_token, options
|
105
|
+
response = save_response_and_transaction stripe_response, :add_payment_method
|
106
|
+
|
107
|
+
if response.success
|
108
|
+
unless stripe_customer_id.blank?
|
109
|
+
card_response = stripe_response.responses.first.params
|
110
|
+
customer_response = stripe_response.responses.last.params
|
111
|
+
else
|
112
|
+
card_response = stripe_response.params['cards']['data'][0]
|
113
|
+
customer_response = stripe_response.params
|
114
|
+
end
|
115
|
+
|
116
|
+
StripePaymentMethod.create :kb_account_id => kb_account_id,
|
117
|
+
:kb_payment_method_id => kb_payment_method_id,
|
118
|
+
:stripe_customer_id => customer_response['id'],
|
119
|
+
:stripe_card_id_or_token => card_response['id'],
|
120
|
+
:cc_first_name => card_response['name'],
|
121
|
+
:cc_last_name => nil,
|
122
|
+
:cc_type => card_response['type'],
|
123
|
+
:cc_exp_month => card_response['exp_month'],
|
124
|
+
:cc_exp_year => card_response['exp_year'],
|
125
|
+
:cc_last_4 => card_response['last4'],
|
126
|
+
:address1 => card_response['address_line1'],
|
127
|
+
:address2 => card_response['address_line2'],
|
128
|
+
:city => card_response['address_city'],
|
129
|
+
:state => card_response['address_state'],
|
130
|
+
:zip => card_response['address_zip'],
|
131
|
+
:country => card_response['address_country']
|
132
|
+
else
|
133
|
+
raise response.message
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def delete_payment_method(kb_account_id, kb_payment_method_id, call_context = nil, options = {})
|
138
|
+
pm = StripePaymentMethod.from_kb_payment_method_id(kb_payment_method_id)
|
139
|
+
|
140
|
+
# Delete the card on the customer object
|
141
|
+
stripe_response = Killbill::Stripe.gateway.unstore(pm.stripe_customer_id, pm.stripe_card_id_or_token)
|
142
|
+
response = save_response_and_transaction stripe_response, :delete_payment_method
|
143
|
+
|
144
|
+
if response.success
|
145
|
+
StripePaymentMethod.mark_as_deleted! kb_payment_method_id
|
146
|
+
else
|
147
|
+
raise response.message
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_payment_method_detail(kb_account_id, kb_payment_method_id, tenant_context = nil, options = {})
|
152
|
+
StripePaymentMethod.from_kb_payment_method_id(kb_payment_method_id).to_payment_method_response
|
153
|
+
end
|
154
|
+
|
155
|
+
def set_default_payment_method(kb_account_id, kb_payment_method_id, call_context = nil, options = {})
|
156
|
+
pm = StripePaymentMethod.from_kb_payment_method_id(kb_payment_method_id)
|
157
|
+
|
158
|
+
# Update the default payment method on the customer object
|
159
|
+
stripe_response = Killbill::Stripe.gateway.update_customer(pm.stripe_customer_id, :default_card => pm.stripe_card_id_or_token)
|
160
|
+
response = save_response_and_transaction stripe_response, :set_default_payment_method
|
161
|
+
|
162
|
+
if response.success
|
163
|
+
# TODO Update our records
|
164
|
+
else
|
165
|
+
raise response.message
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def get_payment_methods(kb_account_id, refresh_from_gateway = false, call_context = nil, options = {})
|
170
|
+
StripePaymentMethod.from_kb_account_id(kb_account_id).collect { |pm| pm.to_payment_method_info_response }
|
171
|
+
end
|
172
|
+
|
173
|
+
def reset_payment_methods(kb_account_id, payment_methods)
|
174
|
+
return if payment_methods.nil?
|
175
|
+
|
176
|
+
stripe_pms = StripePaymentMethod.from_kb_account_id(kb_account_id)
|
177
|
+
|
178
|
+
payment_methods.delete_if do |payment_method_info_plugin|
|
179
|
+
should_be_deleted = false
|
180
|
+
stripe_pms.each do |stripe_pm|
|
181
|
+
# Do stripe_pm and payment_method_info_plugin represent the same Stripe payment method?
|
182
|
+
if stripe_pm.external_payment_method_id == payment_method_info_plugin.external_payment_method_id
|
183
|
+
# Do we already have a kb_payment_method_id?
|
184
|
+
if stripe_pm.kb_payment_method_id == payment_method_info_plugin.payment_method_id
|
185
|
+
should_be_deleted = true
|
186
|
+
break
|
187
|
+
elsif stripe_pm.kb_payment_method_id.nil?
|
188
|
+
# We didn't have the kb_payment_method_id - update it
|
189
|
+
stripe_pm.kb_payment_method_id = payment_method_info_plugin.payment_method_id
|
190
|
+
should_be_deleted = stripe_pm.save
|
191
|
+
break
|
192
|
+
# Otherwise the same card points to 2 different kb_payment_method_id. This should never happen,
|
193
|
+
# but we cowardly will insert a second row below
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
should_be_deleted
|
199
|
+
end
|
200
|
+
|
201
|
+
# The remaining elements in payment_methods are not in our table (this should never happen?!)
|
202
|
+
payment_methods.each do |payment_method_info_plugin|
|
203
|
+
StripePaymentMethod.create :kb_account_id => kb_account_id,
|
204
|
+
:kb_payment_method_id => payment_method_info_plugin.payment_method_id,
|
205
|
+
:stripe_card_id_or_token => payment_method_info_plugin.external_payment_method_id
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def search_payments(search_key, offset = 0, limit = 100, call_context = nil, options = {})
|
210
|
+
StripeResponse.search(search_key, offset, limit, :payment)
|
211
|
+
end
|
212
|
+
|
213
|
+
def search_refunds(search_key, offset = 0, limit = 100, call_context = nil, options = {})
|
214
|
+
StripeResponse.search(search_key, offset, limit, :refund)
|
215
|
+
end
|
216
|
+
|
217
|
+
def search_payment_methods(search_key, offset = 0, limit = 100, call_context = nil, options = {})
|
218
|
+
StripePaymentMethod.search(search_key, offset, limit)
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def find_value_from_payment_method_props(payment_method_props, key)
|
224
|
+
return payment_method_props[key] if payment_method_props.is_a? Hash
|
225
|
+
prop = (payment_method_props.properties.find { |kv| kv.key == key })
|
226
|
+
prop.nil? ? nil : prop.value
|
227
|
+
end
|
228
|
+
|
229
|
+
def save_response_and_transaction(stripe_response, api_call, kb_payment_id=nil, amount_in_cents=0, currency=nil)
|
230
|
+
@logger.warn "Unsuccessful #{api_call}: #{stripe_response.message}" unless stripe_response.success?
|
231
|
+
|
232
|
+
# Save the response to our logs
|
233
|
+
response = StripeResponse.from_response(api_call, kb_payment_id, stripe_response)
|
234
|
+
response.save!
|
235
|
+
|
236
|
+
if response.success and !kb_payment_id.blank? and !response.stripe_txn_id.blank?
|
237
|
+
# Record the transaction
|
238
|
+
transaction = response.create_stripe_transaction!(:amount_in_cents => amount_in_cents,
|
239
|
+
:currency => currency,
|
240
|
+
:api_call => api_call,
|
241
|
+
:kb_payment_id => kb_payment_id,
|
242
|
+
:stripe_txn_id => response.stripe_txn_id)
|
243
|
+
@logger.debug "Recorded transaction: #{transaction.inspect}"
|
244
|
+
end
|
245
|
+
response
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|