killbill 3.1.3 → 3.1.4

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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/Jarfile +7 -5
  3. data/NEWS +3 -0
  4. data/README.md +41 -17
  5. data/VERSION +1 -1
  6. data/generators/active_merchant/templates/Jarfile.rb +7 -5
  7. data/generators/active_merchant/templates/config.yml.rb +3 -3
  8. data/generators/active_merchant/templates/db/ddl.sql.rb +4 -0
  9. data/generators/active_merchant/templates/db/schema.rb +4 -0
  10. data/generators/active_merchant/templates/lib/api.rb +42 -22
  11. data/generators/active_merchant/templates/lib/models/response.rb +3 -1
  12. data/generators/active_merchant/templates/plugin.gemspec.rb +1 -1
  13. data/lib/killbill.rb +7 -4
  14. data/lib/killbill/gen/api/account.rb +4 -3
  15. data/lib/killbill/gen/api/account_api_exception.rb +4 -3
  16. data/lib/killbill/gen/api/account_audit_logs.rb +12 -68
  17. data/lib/killbill/gen/api/account_audit_logs_for_object_type.rb +4 -3
  18. data/lib/killbill/gen/api/account_data.rb +4 -3
  19. data/lib/killbill/gen/api/account_email.rb +4 -3
  20. data/lib/killbill/gen/api/account_user_api.rb +4 -3
  21. data/lib/killbill/gen/api/audit_log.rb +4 -3
  22. data/lib/killbill/gen/api/audit_user_api.rb +4 -3
  23. data/lib/killbill/gen/api/billing_exception_base.rb +4 -3
  24. data/lib/killbill/gen/api/block.rb +4 -3
  25. data/lib/killbill/gen/api/blockable.rb +4 -3
  26. data/lib/killbill/gen/api/blocking_api_exception.rb +4 -3
  27. data/lib/killbill/gen/api/blocking_state.rb +4 -3
  28. data/lib/killbill/gen/api/call_context.rb +4 -3
  29. data/lib/killbill/gen/api/catalog.rb +4 -3
  30. data/lib/killbill/gen/api/catalog_api_exception.rb +4 -3
  31. data/lib/killbill/gen/api/catalog_user_api.rb +4 -3
  32. data/lib/killbill/gen/api/column_info.rb +4 -3
  33. data/lib/killbill/gen/api/control_tag.rb +4 -3
  34. data/lib/killbill/gen/api/currency_conversion.rb +4 -3
  35. data/lib/killbill/gen/api/currency_conversion_api.rb +4 -3
  36. data/lib/killbill/gen/api/currency_conversion_exception.rb +4 -3
  37. data/lib/killbill/gen/api/currency_value_null.rb +4 -3
  38. data/lib/killbill/gen/api/custom_field.rb +4 -3
  39. data/lib/killbill/gen/api/custom_field_api_exception.rb +4 -3
  40. data/lib/killbill/gen/api/custom_field_user_api.rb +4 -3
  41. data/lib/killbill/gen/api/database_export_output_stream.rb +4 -3
  42. data/lib/killbill/gen/api/direct_payment.rb +39 -11
  43. data/lib/killbill/gen/api/direct_payment_api.rb +643 -31
  44. data/lib/killbill/gen/api/direct_payment_transaction.rb +37 -12
  45. data/lib/killbill/gen/api/duration.rb +4 -3
  46. data/lib/killbill/gen/api/entitlement.rb +4 -3
  47. data/lib/killbill/gen/api/entitlement_ao_status_dry_run.rb +4 -3
  48. data/lib/killbill/gen/api/entitlement_api.rb +4 -3
  49. data/lib/killbill/gen/api/entitlement_api_exception.rb +4 -3
  50. data/lib/killbill/gen/api/entity.rb +4 -3
  51. data/lib/killbill/gen/api/fixed.rb +4 -3
  52. data/lib/killbill/gen/api/illegal_plan_change.rb +4 -3
  53. data/lib/killbill/gen/api/international_price.rb +4 -3
  54. data/lib/killbill/gen/api/invalid_config_exception.rb +4 -3
  55. data/lib/killbill/gen/api/invoice.rb +4 -3
  56. data/lib/killbill/gen/api/invoice_api_exception.rb +4 -3
  57. data/lib/killbill/gen/api/invoice_creation_event.rb +4 -3
  58. data/lib/killbill/gen/api/invoice_formatter.rb +4 -3
  59. data/lib/killbill/gen/api/invoice_item.rb +4 -3
  60. data/lib/killbill/gen/api/invoice_item_formatter.rb +4 -3
  61. data/lib/killbill/gen/api/invoice_payment.rb +7 -7
  62. data/lib/killbill/gen/api/invoice_payment_api.rb +7 -153
  63. data/lib/killbill/gen/api/invoice_user_api.rb +22 -3
  64. data/lib/killbill/gen/api/limit.rb +4 -3
  65. data/lib/killbill/gen/api/listing.rb +4 -3
  66. data/lib/killbill/gen/api/migration_plan.rb +4 -3
  67. data/lib/killbill/gen/api/mutable_account_data.rb +4 -3
  68. data/lib/killbill/gen/api/osgi_killbill.rb +15 -7
  69. data/lib/killbill/gen/api/osgi_plugin_properties.rb +4 -3
  70. data/lib/killbill/gen/api/pagination.rb +4 -3
  71. data/lib/killbill/gen/api/payment_api_exception.rb +4 -3
  72. data/lib/killbill/gen/api/payment_gateway_api.rb +4 -3
  73. data/lib/killbill/gen/api/payment_method.rb +11 -4
  74. data/lib/killbill/gen/api/payment_method_plugin.rb +5 -76
  75. data/lib/killbill/gen/api/payment_options.rb +68 -0
  76. data/lib/killbill/gen/api/plan.rb +4 -3
  77. data/lib/killbill/gen/api/plan_change_result.rb +4 -3
  78. data/lib/killbill/gen/api/plan_phase.rb +4 -3
  79. data/lib/killbill/gen/api/plan_phase_specifier.rb +4 -3
  80. data/lib/killbill/gen/api/plan_specifier.rb +4 -3
  81. data/lib/killbill/gen/api/plugin_config_service_api.rb +4 -3
  82. data/lib/killbill/gen/api/plugin_property.rb +4 -3
  83. data/lib/killbill/gen/api/price.rb +4 -3
  84. data/lib/killbill/gen/api/price_list.rb +4 -3
  85. data/lib/killbill/gen/api/price_list_set.rb +4 -3
  86. data/lib/killbill/gen/api/product.rb +4 -3
  87. data/lib/killbill/gen/api/rate.rb +4 -3
  88. data/lib/killbill/gen/api/record_id_api.rb +4 -3
  89. data/lib/killbill/gen/api/recurring.rb +4 -3
  90. data/lib/killbill/gen/api/refund.rb +7 -6
  91. data/lib/killbill/gen/api/require_gen.rb +5 -6
  92. data/lib/killbill/gen/api/rolled_up_usage.rb +4 -3
  93. data/lib/killbill/gen/api/security_api_exception.rb +4 -3
  94. data/lib/killbill/gen/api/static_catalog.rb +4 -3
  95. data/lib/killbill/gen/api/subscription.rb +4 -3
  96. data/lib/killbill/gen/api/subscription_api.rb +4 -3
  97. data/lib/killbill/gen/api/subscription_api_exception.rb +4 -3
  98. data/lib/killbill/gen/api/subscription_bundle.rb +4 -3
  99. data/lib/killbill/gen/api/subscription_bundle_timeline.rb +4 -3
  100. data/lib/killbill/gen/api/subscription_event.rb +4 -3
  101. data/lib/killbill/gen/api/tag.rb +4 -3
  102. data/lib/killbill/gen/api/tag_api_exception.rb +4 -3
  103. data/lib/killbill/gen/api/tag_definition.rb +4 -3
  104. data/lib/killbill/gen/api/tag_definition_api_exception.rb +4 -3
  105. data/lib/killbill/gen/api/tag_user_api.rb +4 -3
  106. data/lib/killbill/gen/api/tenant.rb +4 -3
  107. data/lib/killbill/gen/api/tenant_api_exception.rb +4 -3
  108. data/lib/killbill/gen/api/tenant_context.rb +4 -3
  109. data/lib/killbill/gen/api/tenant_data.rb +4 -3
  110. data/lib/killbill/gen/api/tenant_kv.rb +4 -3
  111. data/lib/killbill/gen/api/tenant_user_api.rb +4 -3
  112. data/lib/killbill/gen/api/tier.rb +4 -3
  113. data/lib/killbill/gen/api/tiered_block.rb +4 -3
  114. data/lib/killbill/gen/api/unit.rb +4 -3
  115. data/lib/killbill/gen/api/usage.rb +4 -3
  116. data/lib/killbill/gen/api/usage_user_api.rb +4 -3
  117. data/lib/killbill/gen/plugin-api/currency_plugin_api.rb +4 -3
  118. data/lib/killbill/gen/plugin-api/ext_bus_event.rb +4 -3
  119. data/lib/killbill/gen/plugin-api/gateway_notification.rb +4 -3
  120. data/lib/killbill/gen/plugin-api/hosted_payment_page_form_descriptor.rb +4 -3
  121. data/lib/killbill/gen/plugin-api/notification_plugin_api.rb +4 -3
  122. data/lib/killbill/gen/plugin-api/payment_method_info_plugin.rb +4 -3
  123. data/lib/killbill/gen/plugin-api/payment_plugin_api.rb +75 -81
  124. data/lib/killbill/gen/plugin-api/payment_plugin_api_exception.rb +4 -3
  125. data/lib/killbill/gen/plugin-api/{payment_info_plugin.rb → payment_transaction_info_plugin.rb} +21 -6
  126. data/lib/killbill/gen/plugin-api/require_gen.rb +5 -5
  127. data/lib/killbill/helpers/active_merchant/active_record/models/payment_method.rb +20 -36
  128. data/lib/killbill/helpers/active_merchant/active_record/models/response.rb +72 -81
  129. data/lib/killbill/helpers/active_merchant/active_record/models/transaction.rb +62 -43
  130. data/lib/killbill/helpers/active_merchant/killbill_spec_helper.rb +0 -13
  131. data/lib/killbill/helpers/active_merchant/payment_plugin.rb +127 -125
  132. data/lib/killbill/http_servlet.rb +16 -1
  133. data/lib/killbill/killbill_api.rb +0 -3
  134. data/lib/killbill/payment.rb +22 -6
  135. data/lib/killbill/rake_task.rb +93 -31
  136. data/spec/killbill/helpers/payment_method_spec.rb +153 -0
  137. data/spec/killbill/helpers/response_spec.rb +58 -15
  138. data/spec/killbill/helpers/test_schema.rb +12 -8
  139. data/spec/killbill/helpers/transaction_spec.rb +134 -0
  140. data/spec/killbill/payment_plugin_api_spec.rb +18 -18
  141. data/spec/killbill/payment_plugin_spec.rb +26 -15
  142. data/spec/killbill/payment_test.rb +6 -7
  143. data/spec/spec_helper.rb +3 -0
  144. metadata +6 -5
  145. data/lib/killbill/gen/api/payment.rb +0 -187
  146. data/lib/killbill/gen/plugin-api/refund_info_plugin.rb +0 -152
@@ -60,19 +60,6 @@ module Killbill
60
60
  pm.should == payment_method
61
61
  pm.kb_account_id.should == kb_account_id
62
62
  pm.kb_payment_method_id.should == kb_payment_method_id
63
- # Depends on the gateway
64
- #pm.cc_first_name.should == cc_first_name + ' ' + cc_last_name
65
- #pm.cc_last_name.should == cc_last_name
66
- pm.cc_type.should == cc_type
67
- pm.cc_exp_month.should == cc_exp_month
68
- pm.cc_exp_year.should == cc_exp_year
69
- #pm.cc_last_4.should == cc_last_4
70
- pm.address1.should == address1
71
- pm.address2.should == address2
72
- pm.city.should == city
73
- pm.state.should == state
74
- pm.zip.should == zip.to_s
75
- pm.country.should == country
76
63
 
77
64
  pm
78
65
  end
@@ -33,137 +33,130 @@ module Killbill
33
33
  ::ActiveRecord::Base.connection.close
34
34
  end
35
35
 
36
- def authorize_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
37
- options = properties_to_hash(properties)
38
-
39
- # 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)
40
- amount_in_cents = Monetize.from_numeric(amount, currency).cents.to_i
36
+ def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
37
+ amount_in_cents = to_cents(amount, currency)
41
38
 
42
- # If the authorization was already made, just return the status (one auth per kb payment id)
43
- transaction = @transaction_model.authorization_from_kb_payment_id(kb_payment_id, context.tenant_id) rescue nil
44
- return transaction.send("#{@identifier}_response").to_payment_response(transaction) unless transaction.nil?
45
-
46
- options[:order_id] ||= kb_payment_id
39
+ options = properties_to_hash(properties)
40
+ options[:order_id] ||= kb_payment_transaction_id
47
41
  options[:currency] ||= currency.to_s.upcase
48
- options[:description] ||= "Kill Bill authorization for #{kb_payment_id}"
42
+ options[:description] ||= "Kill Bill authorization for #{kb_payment_transaction_id}"
49
43
 
50
44
  # Retrieve the payment method
51
- if options[:credit_card].blank?
52
- pm = @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id)
53
- payment_source = pm.token
54
- else
55
- payment_source = ::ActiveMerchant::Billing::CreditCard.new(options[:credit_card])
56
- end
45
+ payment_source = get_payment_source(kb_payment_method_id, options, context)
57
46
 
58
47
  # Go to the gateway
59
- gw_response = gateway.authorize amount_in_cents, payment_source, options
60
- response, transaction = save_response_and_transaction gw_response, :authorize, kb_account_id, context.tenant_id, kb_payment_id, amount_in_cents, currency
48
+ gw_response = gateway.authorize(amount_in_cents, payment_source, options)
49
+ response, transaction = save_response_and_transaction(gw_response, :authorize, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :AUTHORIZE, amount_in_cents, currency)
61
50
 
62
- response.to_payment_response(transaction)
51
+ response.to_transaction_info_plugin(transaction)
63
52
  end
64
53
 
65
- def capture_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
66
- options = properties_to_hash(properties)
54
+ def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
55
+ amount_in_cents = to_cents(amount, currency)
67
56
 
68
- # 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)
69
- amount_in_cents = Monetize.from_numeric(amount, currency).cents.to_i
70
-
71
- options[:order_id] ||= kb_payment_id
57
+ options = properties_to_hash(properties)
58
+ options[:order_id] ||= kb_payment_transaction_id
72
59
  options[:currency] ||= currency.to_s.upcase
73
- options[:description] ||= "Kill Bill capture for #{kb_payment_id}"
60
+ options[:description] ||= "Kill Bill capture for #{kb_payment_transaction_id}"
74
61
 
75
62
  # Retrieve the authorization
76
- authorization = @transaction_model.authorization_from_kb_payment_id(kb_payment_id, context.tenant_id).txn_id
63
+ # TODO We use the last AUTH transaction at the moment, is it good enough?
64
+ authorization = @transaction_model.authorizations_from_kb_payment_id(kb_payment_id, context.tenant_id).last.txn_id
77
65
 
78
66
  # Go to the gateway
79
- gw_response = gateway.capture amount_in_cents, authorization, options
80
- response, transaction = save_response_and_transaction gw_response, :capture, kb_account_id, context.tenant_id, kb_payment_id, amount_in_cents, currency
67
+ gw_response = gateway.capture(amount_in_cents, authorization, options)
68
+ response, transaction = save_response_and_transaction(gw_response, :capture, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :CAPTURE, amount_in_cents, currency)
81
69
 
82
- response.to_payment_response(transaction)
70
+ response.to_transaction_info_plugin(transaction)
83
71
  end
84
72
 
85
- def void_payment(kb_account_id, kb_payment_id, kb_payment_method_id, properties, context)
86
- options = properties_to_hash(properties)
87
- options[:description] ||= "Kill Bill void for #{kb_payment_id}"
73
+ def purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
74
+ amount_in_cents = to_cents(amount, currency)
88
75
 
89
- # Retrieve the authorization
90
- authorization = @transaction_model.authorization_from_kb_payment_id(kb_payment_id, context.tenant_id).txn_id
76
+ options = properties_to_hash(properties)
77
+ options[:order_id] ||= kb_payment_transaction_id
78
+ options[:currency] ||= currency.to_s.upcase
79
+ options[:description] ||= "Kill Bill purchase for #{kb_payment_transaction_id}"
80
+
81
+ # Retrieve the payment method
82
+ payment_source = get_payment_source(kb_payment_method_id, options, context)
91
83
 
92
84
  # Go to the gateway
93
- gw_response = gateway.void authorization, options
94
- response, transaction = save_response_and_transaction gw_response, :void, kb_account_id, context.tenant_id, kb_payment_id
85
+ gw_response = gateway.purchase(amount_in_cents, payment_source, options)
86
+ response, transaction = save_response_and_transaction(gw_response, :purchase, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :PURCHASE, amount_in_cents, currency)
95
87
 
96
- response.to_payment_response(transaction)
88
+ response.to_transaction_info_plugin(transaction)
97
89
  end
98
90
 
99
- def process_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
100
- options = properties_to_hash(properties)
91
+ def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
92
+ options = properties_to_hash(properties)
93
+ options[:description] ||= "Kill Bill void for #{kb_payment_transaction_id}"
101
94
 
102
- # 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)
103
- amount_in_cents = Monetize.from_numeric(amount, currency).cents.to_i
95
+ # Retrieve the authorization
96
+ # TODO We use the last AUTH transaction at the moment, is it good enough?
97
+ authorization = @transaction_model.authorizations_from_kb_payment_id(kb_payment_id, context.tenant_id).last.txn_id
98
+
99
+ # Go to the gateway
100
+ gw_response = gateway.void(authorization, options)
101
+ response, transaction = save_response_and_transaction(gw_response, :void, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :VOID)
102
+
103
+ response.to_transaction_info_plugin(transaction)
104
+ end
104
105
 
105
- # If the payment was already made, just return the status
106
- transaction = @transaction_model.charge_from_kb_payment_id(kb_payment_id, context.tenant_id) rescue nil
107
- return transaction.send("#{@identifier}_response").to_payment_response(transaction) unless transaction.nil?
106
+ def credit_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
107
+ amount_in_cents = to_cents(amount, currency)
108
108
 
109
- options[:order_id] ||= kb_payment_id
109
+ options = properties_to_hash(properties)
110
+ options[:order_id] ||= kb_payment_transaction_id
110
111
  options[:currency] ||= currency.to_s.upcase
111
- options[:description] ||= "Kill Bill payment for #{kb_payment_id}"
112
+ options[:description] ||= "Kill Bill credit for #{kb_payment_transaction_id}"
112
113
 
113
114
  # Retrieve the payment method
114
- if options[:credit_card].blank?
115
- pm = @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id)
116
- payment_source = pm.token
117
- else
118
- payment_source = ::ActiveMerchant::Billing::CreditCard.new(options[:credit_card])
119
- end
115
+ payment_source = get_payment_source(kb_payment_method_id, options, context)
120
116
 
121
117
  # Go to the gateway
122
- gw_response = gateway.purchase amount_in_cents, payment_source, options
123
- response, transaction = save_response_and_transaction gw_response, :charge, kb_account_id, context.tenant_id, kb_payment_id, amount_in_cents, currency
118
+ gw_response = gateway.credit(amount_in_cents, payment_source, options)
119
+ response, transaction = save_response_and_transaction(gw_response, :credit, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :CREDIT, amount_in_cents, currency)
124
120
 
125
- response.to_payment_response(transaction)
121
+ response.to_transaction_info_plugin(transaction)
126
122
  end
127
123
 
128
- def process_refund(kb_account_id, kb_payment_id, amount, currency, properties, context)
129
- options = properties_to_hash(properties)
124
+ def refund_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
125
+ amount_in_cents = to_cents(amount, currency)
130
126
 
131
- # 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)
132
- amount_in_cents = Monetize.from_numeric(amount, currency).cents.to_i
127
+ options = properties_to_hash(properties)
128
+ options[:order_id] ||= kb_payment_transaction_id
129
+ options[:currency] ||= currency.to_s.upcase
130
+ options[:description] ||= "Kill Bill refund for #{kb_payment_transaction_id}"
133
131
 
132
+ # Find a transaction to refund
134
133
  transaction = @transaction_model.find_candidate_transaction_for_refund(kb_payment_id, context.tenant_id, amount_in_cents)
135
134
 
136
135
  # Go to the gateway
137
- gw_response = gateway.refund amount_in_cents, transaction.txn_id, options
138
- response, transaction = save_response_and_transaction gw_response, :refund, kb_account_id, context.tenant_id, kb_payment_id, amount_in_cents, currency
136
+ gw_response = gateway.refund(amount_in_cents, transaction.txn_id, options)
137
+ response, transaction = save_response_and_transaction(gw_response, :refund, kb_account_id, context.tenant_id, kb_payment_id, kb_payment_transaction_id, :REFUND, amount_in_cents, currency)
139
138
 
140
- response.to_refund_response(transaction)
139
+ response.to_transaction_info_plugin(transaction)
141
140
  end
142
141
 
143
142
  def get_payment_info(kb_account_id, kb_payment_id, properties, context)
144
- options = properties_to_hash(properties)
145
-
146
143
  # We assume the payment is immutable in the Gateway and only look at our tables
147
- transaction = @transaction_model.charge_from_kb_payment_id(kb_payment_id, context.tenant_id)
148
-
149
- transaction.send("#{@identifier}_response").to_payment_response(transaction)
144
+ @transaction_model.transactions_from_kb_payment_id(kb_payment_id, context.tenant_id).collect do |transaction|
145
+ transaction.send("#{@identifier}_response").to_transaction_info_plugin(transaction)
146
+ end
150
147
  end
151
148
 
152
- def get_refund_info(kb_account_id, kb_payment_id, properties, context)
149
+ def search_payments(search_key, offset = 0, limit = 100, properties, context)
153
150
  options = properties_to_hash(properties)
154
-
155
- # We assume the refund is immutable in the Gateway and only look at our tables
156
- transactions = @transaction_model.refunds_from_kb_payment_id(kb_payment_id, context.tenant_id)
157
-
158
- transactions.map { |t| t.send("#{@identifier}_response").to_refund_response(t) }
151
+ @response_model.search(search_key, context.tenant_id, offset, limit, :payment)
159
152
  end
160
153
 
161
154
  def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
162
- options = properties_to_hash(properties)
155
+ options = properties_to_hash(properties)
163
156
  options[:set_default] ||= set_default
164
157
 
165
158
  # Registering a card or a token
166
- cc_or_token = find_value_from_payment_method_props(payment_method_props, 'token') || find_value_from_payment_method_props(payment_method_props, 'cardId')
159
+ cc_or_token = find_value_from_payment_method_props(payment_method_props, 'token') || find_value_from_payment_method_props(payment_method_props, 'cardId')
167
160
  if cc_or_token.blank?
168
161
  # Nope - real credit card
169
162
  cc_or_token = ::ActiveMerchant::Billing::CreditCard.new(
@@ -188,7 +181,7 @@ module Killbill
188
181
  }
189
182
 
190
183
  # To make various gateway implementations happy...
191
- options[:billing_address].each { |k,v| options[k] ||= v }
184
+ options[:billing_address].each { |k, v| options[k] ||= v }
192
185
 
193
186
  options[:order_id] ||= kb_payment_method_id
194
187
 
@@ -227,12 +220,21 @@ module Killbill
227
220
 
228
221
  def get_payment_method_detail(kb_account_id, kb_payment_method_id, properties, context)
229
222
  options = properties_to_hash(properties)
230
- @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id).to_payment_method_response
223
+ @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id).to_payment_method_plugin
231
224
  end
232
225
 
226
+ # No default implementation
227
+ #def set_default_payment_method(kb_account_id, kb_payment_method_id, properties, context)
228
+ #end
229
+
233
230
  def get_payment_methods(kb_account_id, refresh_from_gateway = false, properties, context)
234
231
  options = properties_to_hash(properties)
235
- @payment_method_model.from_kb_account_id(kb_account_id, context.tenant_id).collect { |pm| pm.to_payment_method_info_response }
232
+ @payment_method_model.from_kb_account_id(kb_account_id, context.tenant_id).collect { |pm| pm.to_payment_method_info_plugin }
233
+ end
234
+
235
+ def search_payment_methods(search_key, offset = 0, limit = 100, properties, context)
236
+ options = properties_to_hash(properties)
237
+ @payment_method_model.search(search_key, context.tenant_id, offset, limit)
236
238
  end
237
239
 
238
240
  def reset_payment_methods(kb_account_id, payment_methods, properties, context)
@@ -273,26 +275,11 @@ module Killbill
273
275
  end
274
276
  end
275
277
 
276
- def search_payments(search_key, offset = 0, limit = 100, properties, context)
277
- options = properties_to_hash(properties)
278
- @response_model.search(search_key, context.tenant_id, offset, limit, :payment)
279
- end
280
-
281
- def search_refunds(search_key, offset = 0, limit = 100, properties, context)
282
- options = properties_to_hash(properties)
283
- @response_model.search(search_key, context.tenant_id, offset, limit, :refund)
284
- end
285
-
286
- def search_payment_methods(search_key, offset = 0, limit = 100, properties, context)
287
- options = properties_to_hash(properties)
288
- @payment_method_model.search(search_key, context.tenant_id, offset, limit)
289
- end
290
-
291
278
  def build_form_descriptor(kb_account_id, descriptor_fields, properties, context)
292
- options = properties_to_hash(descriptor_fields)
293
- order = options.delete(:order_id)
294
- account = options.delete(:account_id)
295
- service_options = {
279
+ options = properties_to_hash(descriptor_fields)
280
+ order = options.delete(:order_id)
281
+ account = options.delete(:account_id)
282
+ service_options = {
296
283
  :amount => options.delete(:amount),
297
284
  :currency => options.delete(:currency),
298
285
  :test => options.delete(:test),
@@ -311,8 +298,8 @@ module Killbill
311
298
 
312
299
  # Retrieve the ActiveMerchant integration
313
300
  integration_module = get_active_merchant_module
314
- service_class = integration_module.const_get('Helper')
315
- service = service_class.new(order, account, service_options)
301
+ service_class = integration_module.const_get('Helper')
302
+ service = service_class.new(order, account, service_options)
316
303
 
317
304
  # Add the specified fields
318
305
  options.each do |field, value|
@@ -320,10 +307,10 @@ module Killbill
320
307
  next if mapping.nil?
321
308
  case mapping
322
309
  when Array
323
- mapping.each{ |field2| service.add_field(field2, value) }
310
+ mapping.each { |field2| service.add_field(field2, value) }
324
311
  when Hash
325
312
  options2 = value.is_a?(Hash) ? value : {}
326
- mapping.each{ |key, field2| service.add_field(field2, options2[key]) }
313
+ mapping.each { |key, field2| service.add_field(field2, options2[key]) }
327
314
  else
328
315
  service.add_field(mapping, value)
329
316
  end
@@ -338,35 +325,35 @@ module Killbill
338
325
  end
339
326
 
340
327
  # Build the response object
341
- descriptor = ::Killbill::Plugin::Model::HostedPaymentPageFormDescriptor.new
328
+ descriptor = ::Killbill::Plugin::Model::HostedPaymentPageFormDescriptor.new
342
329
  descriptor.kb_account_id = kb_account_id
343
- descriptor.form_method = service.form_method || 'POST'
344
- descriptor.form_url = service.respond_to?(:credential_based_url) ? service.credential_based_url : integration_module.service_url
345
- descriptor.form_fields = hash_to_properties(form_fields)
330
+ descriptor.form_method = service.form_method || 'POST'
331
+ descriptor.form_url = service.respond_to?(:credential_based_url) ? service.credential_based_url : integration_module.service_url
332
+ descriptor.form_fields = hash_to_properties(form_fields)
346
333
  # Any other custom property
347
- descriptor.properties = hash_to_properties({})
334
+ descriptor.properties = hash_to_properties({})
348
335
 
349
336
  descriptor
350
337
  end
351
338
 
352
339
  def process_notification(notification, properties, context, &proc)
353
- options = properties_to_hash(properties)
340
+ options = properties_to_hash(properties)
354
341
 
355
342
  # Retrieve the ActiveMerchant integration
356
343
  integration_module = get_active_merchant_module
357
- service_class = integration_module.const_get('Notification')
344
+ service_class = integration_module.const_get('Notification')
358
345
  # notification is either a body or a query string
359
- service = service_class.new(notification, options)
346
+ service = service_class.new(notification, options)
360
347
 
361
348
  if service.respond_to? :acknowledge
362
349
  service.acknowledge
363
350
  end
364
351
 
365
- gw_notification = ::Killbill::Plugin::Model::GatewayNotification.new
352
+ gw_notification = ::Killbill::Plugin::Model::GatewayNotification.new
366
353
  gw_notification.kb_payment_id = nil
367
- gw_notification.status = service.status == 'Completed' ? 200 : 400
368
- gw_notification.headers = {}
369
- gw_notification.properties = []
354
+ gw_notification.status = service.status == 'Completed' ? 200 : 400
355
+ gw_notification.headers = {}
356
+ gw_notification.properties = []
370
357
 
371
358
  if service.respond_to? :success_response
372
359
  gw_notification.entity = service.success_response(properties_to_hash(properties))
@@ -381,8 +368,21 @@ module Killbill
381
368
 
382
369
  # Utilities
383
370
 
384
- # Deprecated
371
+ def to_cents(amount, currency)
372
+ # 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)
373
+ Monetize.from_numeric(amount, currency).cents.to_i
374
+ end
375
+
376
+ def get_payment_source(kb_payment_method_id, options, context)
377
+ if options[:credit_card].blank?
378
+ @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id).token
379
+ else
380
+ ::ActiveMerchant::Billing::CreditCard.new(options[:credit_card])
381
+ end
382
+ end
383
+
385
384
  def find_value_from_payment_method_props(payment_method_props, key)
385
+ return nil if payment_method_props.nil?
386
386
  find_value_from_properties(payment_method_props.properties, key)
387
387
  end
388
388
 
@@ -396,11 +396,11 @@ module Killbill
396
396
  account.currency
397
397
  end
398
398
 
399
- def save_response_and_transaction(response, api_call, kb_account_id, kb_tenant_id, kb_payment_id=nil, amount_in_cents=0, currency=nil)
399
+ def save_response_and_transaction(response, api_call, kb_account_id, kb_tenant_id, kb_payment_id=nil, kb_payment_transaction_id=nil, transaction_type=nil, amount_in_cents=0, currency=nil)
400
400
  @logger.warn "Unsuccessful #{api_call}: #{response.message}" unless response.success?
401
401
 
402
402
  # Save the response to our logs
403
- response = @response_model.from_response(api_call, kb_account_id, kb_payment_id, kb_tenant_id, response)
403
+ response = @response_model.from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id, response)
404
404
  response.save!
405
405
 
406
406
  transaction = nil
@@ -408,13 +408,15 @@ module Killbill
408
408
  if response.success and !kb_payment_id.blank? and !txn_id.blank?
409
409
  # Record the transaction
410
410
  transaction = response.send("create_#{@identifier}_transaction!",
411
- :kb_account_id => kb_account_id,
412
- :kb_tenant_id => kb_tenant_id,
413
- :amount_in_cents => amount_in_cents,
414
- :currency => currency,
415
- :api_call => api_call,
416
- :kb_payment_id => kb_payment_id,
417
- :txn_id => txn_id)
411
+ :kb_account_id => kb_account_id,
412
+ :kb_tenant_id => kb_tenant_id,
413
+ :amount_in_cents => amount_in_cents,
414
+ :currency => currency,
415
+ :api_call => api_call,
416
+ :kb_payment_id => kb_payment_id,
417
+ :kb_payment_transaction_id => kb_payment_transaction_id,
418
+ :transaction_type => transaction_type,
419
+ :txn_id => txn_id)
418
420
 
419
421
  @logger.debug "Recorded transaction: #{transaction.inspect}"
420
422
  end
@@ -10,9 +10,24 @@ module Killbill
10
10
  class RackHandler < Java::javax.servlet.http.HttpServlet
11
11
  include Singleton
12
12
 
13
+ # A bit convoluted but the Rack API doesn't seem to let you
14
+ # configure these things out of the command line
15
+ class KillBillOptions < Rack::Server::Options
16
+ def parse!(args)
17
+ super.merge(default_options)
18
+ end
19
+
20
+ def default_options
21
+ {
22
+ # Make sure plugins are started in production mode by default
23
+ :environment => :production
24
+ }
25
+ end
26
+ end
27
+
13
28
  def configure(logger, config_ru)
14
29
  @logger = logger
15
- @app = Rack::Builder.parse_file(config_ru).first
30
+ @app = Rack::Builder.parse_file(config_ru, KillBillOptions.new).first
16
31
  end
17
32
 
18
33
  def unconfigure
@@ -42,9 +42,6 @@ module Killbill
42
42
  private
43
43
 
44
44
  def create_proxy_api(api_name, java_api)
45
- if api_name == "overdue_user_api"
46
- return nil
47
- end
48
45
  proxy_class_name = "Killbill::Plugin::Api::#{api_name.to_s.split('_').map{|e| e.capitalize}.join}"
49
46
  proxy_class_name.to_class.new(java_api)
50
47
  end