supercharged 1.0.0 → 2.0.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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Supercharged
2
2
 
3
3
  [![Build Status](https://travis-ci.org/divineforest/supercharged.png?branch=master)](https://travis-ci.org/divineforest/supercharged)
4
- [![CodeClimate](https://codeclimate.com/github/divineforest/supercharged.png)](https://codeclimate.com/github/divineforest/supercharged)
4
+ [![Code Climate](https://codeclimate.com/github/divineforest/supercharged.png)](https://codeclimate.com/github/divineforest/supercharged)
5
5
 
6
6
  Complete MVC solution to accept charges from users on your Ruby on Rails site
7
7
 
@@ -25,6 +25,13 @@ In your application.js manifest:
25
25
  //= require supercharged
26
26
  ```
27
27
 
28
+ And then in some assets file:
29
+
30
+ ```
31
+ $ ->
32
+ new SuperchargedForm("[role='gateway-charge-form']")
33
+ ```
34
+
28
35
  Create config/initializers/supercharged.rb
29
36
 
30
37
  ```ruby
@@ -84,9 +91,27 @@ class Charge < Supercharged::Charge::Base
84
91
  super
85
92
  end
86
93
  end
94
+
95
+ def min_amount
96
+ # specify min value for amount field here
97
+ # default is 1
98
+ 42
99
+ end
87
100
  end
88
101
  ```
89
102
 
103
+ ## Form
104
+
105
+ To display validation, supercharged form class has `onValidationError` callback:
106
+
107
+ ```
108
+ $ ->
109
+ new SuperchargedForm("[role='gateway-charge-form']", {
110
+ onValidationError: (errors)->
111
+ console.log "supercharged validation errors: ", errors
112
+ })
113
+ ```
114
+
90
115
  # Contributing
91
116
 
92
117
  The example app is at https://github.com/divineforest/supercharged-example-app
@@ -1,43 +1,57 @@
1
- class ChargeForm
2
- constructor: (selector, options = {}) ->
1
+ class @SuperchargedForm
2
+ constructor: (selector, @options = {}) ->
3
3
  @form = $(selector)
4
4
  return if @form.length == 0
5
5
 
6
6
  @amount_input = @form.find("[role='charge-amount']")
7
- @id_input = @form.find("[value='<%= Supercharged::ChargesHelper::FAKE_ORDER_ID %>']")
7
+ @gateway_name_input = @form.find("[role='charge-gateway-name']")
8
+ @id_input = if @form.find("[role='charge-id']").length then @form.find("[role='charge-id']") else @form.find("[value='<%= Supercharged::ChargesHelper::FAKE_ORDER_ID %>']")
8
9
 
9
10
  @form.submit =>
10
- @start_payment()
11
+ valid = @startPayment()
12
+
13
+ unless valid
14
+ return false
11
15
 
12
16
  unless parseInt(@id_input.val())
13
17
  alert("Error: undefined charge id")
14
18
  return false
15
19
 
16
- start_payment: ->
17
- @create_internal_transaction(
18
- success: (charge) =>
19
- @prepare_gateway_form(charge)
20
+ startPayment: ->
21
+ valid = true
22
+ @createInternalTransaction(
23
+ success: (charge)=>
24
+ @prepareGatewayForm(charge)
25
+ validationError: (errors)=>
26
+ valid = false
27
+
28
+ handler = @options.onValidationError
29
+ handler.call(this, errors) if handler?
20
30
  )
21
31
 
22
- create_internal_transaction: (options) ->
23
- charge_attributes = @get_charge_attributes()
32
+ valid
33
+
34
+ createInternalTransaction: (options) ->
35
+ charge_attributes = @getChargeAttributes()
24
36
  $.ajax(
25
37
  url: "/charges.json",
26
38
  type: "POST",
27
39
  async: false,
28
- data: { charge: charge_attributes},
29
- success: (response, a) ->
40
+ data: {charge: charge_attributes},
41
+ success: (response) ->
30
42
  options.success(response)
43
+ error: (jqXHR, status, errorThrown)=>
44
+ return unless jqXHR.status == 422
45
+
46
+ response = $.parseJSON(jqXHR.responseText)
47
+ options.validationError(response.errors)
31
48
  )
32
49
 
33
- get_charge_attributes: ->
50
+ getChargeAttributes: ->
34
51
  {
35
- amount: @amount_input.val()
52
+ amount: @amount_input.val(),
53
+ gateway_name: @gateway_name_input.val()
36
54
  }
37
55
 
38
- prepare_gateway_form: (charge) ->
56
+ prepareGatewayForm: (charge) ->
39
57
  @id_input.val(charge.id)
40
-
41
- $ ->
42
- window.widgets ||= {}
43
- window.widgets.charge_form = new ChargeForm("[role='gateway-charge-form']")
@@ -4,16 +4,47 @@ class Supercharged::ChargesController < ApplicationController
4
4
  end
5
5
 
6
6
  def create
7
- @charge = Charge.new(charge_params)
8
- @charge.user = current_user
9
- @charge.save!
10
- render json: @charge.as_json(only: [:id])
7
+ charge = Charge.new(charge_params)
8
+ charge.user = current_user
9
+
10
+ if charge.save
11
+ render json: charge.as_json(only: [:id])
12
+ else
13
+ render json: { errors: charge.errors }, status: :unprocessable_entity
14
+ end
15
+ end
16
+
17
+ # For example for PayPal Express, which requires getting token before purchase action.
18
+ def setup_purchase
19
+ charge = Charge.find(params[:charge_id])
20
+
21
+ token = charge.setup_purchase(
22
+ ip: request.remote_ip,
23
+ return_url: complete_charges_url,
24
+ cancel_return_url: new_charge_url
25
+ )
26
+
27
+ redirect_to charge.gateway.redirect_url_for(token)
28
+ end
29
+
30
+ def complete
31
+ params.require(:token)
32
+
33
+ @charge = Charge.with_token(params[:token])
34
+
35
+ if @charge
36
+ @charge.complete(params)
37
+
38
+ redirect_to root_url
39
+ else
40
+ head :not_found
41
+ end
11
42
  end
12
43
 
13
44
  private
14
45
 
15
46
  def charge_params
16
- params.require(:charge).permit(:amount)
47
+ params.require(:charge).permit(:amount, :gateway_name)
17
48
  end
18
49
 
19
50
  end
@@ -1,5 +1,6 @@
1
1
  class Supercharged::GatewayNotificationsController < ApplicationController
2
2
  skip_before_filter :verify_authenticity_token
3
+ before_filter :check_any_params, only: :create
3
4
 
4
5
  def create
5
6
  persistent_logger.info("Notification for #{params[:gateway]}")
@@ -50,4 +51,11 @@ class Supercharged::GatewayNotificationsController < ApplicationController
50
51
  @persistent_logger ||= Logger.new("log/supercharged/gateway_notifications.log")
51
52
  end
52
53
 
54
+ def check_any_params
55
+ if request.raw_post.blank?
56
+ head :bad_request
57
+ false
58
+ end
59
+ end
60
+
53
61
  end
@@ -3,12 +3,6 @@ module Supercharged::ChargesHelper
3
3
  # JS finds order input by this fake id because id and name will be integration specific
4
4
  FAKE_ORDER_ID = "[payment_order_id]"
5
5
 
6
- DEFAULT_AMOUNT_FIELD_OPTIONS = {
7
- role: "charge-amount",
8
- required: true,
9
- min: 0
10
- }
11
-
12
6
  def charge_form_for(service_name, options = {}, &block)
13
7
  raise ArgumentError, "Missing block" unless block_given?
14
8
 
@@ -27,9 +21,9 @@ module Supercharged::ChargesHelper
27
21
  end
28
22
 
29
23
  def charge_form_amount_field(service, options = {})
30
- amount_field_name = service.mappings[:amount] || raise("Undefined amount field mapping")
24
+ amount_field_name = service.mappings[:amount] || raise(ArgumentError, "Undefined amount field mapping")
31
25
 
32
- options = options.merge(DEFAULT_AMOUNT_FIELD_OPTIONS)
26
+ options = default_amount_field_options.merge(options)
33
27
 
34
28
  number_field_tag amount_field_name, nil, options
35
29
  end
@@ -42,4 +36,14 @@ module Supercharged::ChargesHelper
42
36
  options
43
37
  end
44
38
 
39
+ def default_amount_field_options
40
+ {
41
+ role: "charge-amount",
42
+ required: true,
43
+ data: {
44
+ min_value: Charge.min_amount
45
+ }
46
+ }
47
+ end
48
+
45
49
  end
@@ -0,0 +1,17 @@
1
+ class GatewayResponse < ActiveRecord::Base
2
+ belongs_to :charge
3
+
4
+ serialize :params
5
+
6
+ def response=(response)
7
+ self.success = response.success?
8
+ self.authorization = response.authorization
9
+ self.message = response.message
10
+ self.params = response.params
11
+ rescue ActiveMerchant::ActiveMerchantError => e
12
+ self.success = false
13
+ self.authorization = nil
14
+ self.message = e.message
15
+ self.params = {}
16
+ end
17
+ end
@@ -8,10 +8,16 @@ module Supercharged
8
8
 
9
9
  belongs_to :user
10
10
  has_many :gateway_input_notifications
11
+ has_many :gateway_responses
11
12
 
12
- validates :amount, presence: true
13
+ validates :amount, presence: true, numericality: {
14
+ greater_than_or_equal_to: ->(model) {
15
+ model.class.min_amount
16
+ }
17
+ }
13
18
 
14
19
  scope :latest, order("created_at DESC")
20
+ scope :by_gateway, ->(gateway_name) { where(gateway_name: gateway_name.to_s) }
15
21
 
16
22
  state_machine :state, initial: :new do
17
23
  # store_audit_trail
@@ -34,12 +40,77 @@ module Supercharged
34
40
  end
35
41
  end
36
42
 
43
+ def self.with_token(token)
44
+ where(gateway_token: token).first
45
+ end
46
+
37
47
  # require implicit amount from gateway, not from user
38
48
  def approve(real_amount)
39
49
  self.real_amount = real_amount
40
50
  set_ok!
41
51
  end
42
52
 
53
+ def self.min_amount
54
+ 1
55
+ end
56
+
57
+ def setup_purchase(options)
58
+ response = gateway.setup_purchase(amount_in_cents,
59
+ ip: options[:id],
60
+ return_url: options[:return_url],
61
+ cancel_return_url: options[:cancel_return_url]
62
+ )
63
+
64
+ if response.success?
65
+ update_attributes!(
66
+ gateway_token: response.token,
67
+ ip_address: options[:id]
68
+ )
69
+ end
70
+
71
+ response.token
72
+ end
73
+
74
+ def complete(options = {})
75
+ get_purchase_details
76
+
77
+ response = process_purchase
78
+
79
+ approve(amount) if response.success?
80
+
81
+ response.success?
82
+ end
83
+
84
+ def gateway
85
+ Supercharged::Helpers.gateway(gateway_name)
86
+ end
87
+
88
+ private
89
+
90
+ def amount_in_cents
91
+ amount * 100
92
+ end
93
+
94
+ def get_purchase_details
95
+ details = gateway.details_for(gateway_token)
96
+ self.gateway_payer_id = details.payer_id
97
+ end
98
+
99
+ def process_purchase
100
+ response = gateway.purchase(amount_in_cents,
101
+ ip: ip_address,
102
+ token: gateway_token,
103
+ payer_id: gateway_payer_id
104
+ )
105
+
106
+ save_gateway_response(response)
107
+
108
+ response
109
+ end
110
+
111
+ def save_gateway_response(response)
112
+ GatewayResponse.create!(charge: self, action: "purchase", amount: amount, response: response)
113
+ end
43
114
  end
44
115
  end
45
116
  end
data/config/routes.rb CHANGED
@@ -8,7 +8,12 @@ module ActionDispatch::Routing
8
8
  }
9
9
  controllers.merge!(options[:controllers]) if options[:controllers]
10
10
 
11
- resources :charges, only: [:new, :create], controller: controllers[:charges]
11
+ resources :charges, only: [:new, :create], controller: controllers[:charges] do
12
+ collection do
13
+ post :setup_purchase
14
+ get :complete
15
+ end
16
+ end
12
17
 
13
18
  match "gateways/:gateway/result" => "#{controllers[:gateway_notifications]}#create", as: :gateways_result
14
19
  end
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record'
4
+
5
+ module Supercharged
6
+ module Generators
7
+ class MigrationsGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ desc "Generates migration for Supercharged"
13
+
14
+ def self.next_migration_number(dirname)
15
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
16
+ end
17
+
18
+ def copy_migration
19
+ migration_template 'install_migration.rb', 'db/migrate/install_supercharged.rb'
20
+ end
21
+
22
+ def mount_engine
23
+ route "supercharged"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ class InstallSupercharged < ActiveRecord::Migration
2
+ def change
3
+ create_table "gateway_notifications", :force => true do |t|
4
+ t.text "params"
5
+ t.string "status"
6
+ t.string "external_transaction_id"
7
+ t.integer "charge_id"
8
+ t.datetime "created_at", :null => false
9
+ t.datetime "updated_at", :null => false
10
+ t.string "gateway"
11
+ end
12
+
13
+ add_index "gateway_notifications", ["charge_id"], :name => "index_gateway_input_notifications_on_charge_id"
14
+
15
+ create_table "gateway_responses", :force => true do |t|
16
+ t.integer "charge_id", :null => false
17
+ t.string "action", :null => false
18
+ t.decimal "amount"
19
+ t.boolean "success", :null => false
20
+ t.string "authorization"
21
+ t.string "message"
22
+ t.text "params"
23
+ t.datetime "created_at", :null => false
24
+ t.datetime "updated_at", :null => false
25
+ end
26
+
27
+ add_index "gateway_responses", ["charge_id"], :name => "index_gateway_responses_on_charge_id"
28
+
29
+ create_table "charges_state_transitions", :force => true do |t|
30
+ t.integer "charges_id"
31
+ t.string "charges_type"
32
+ t.string "event"
33
+ t.string "from"
34
+ t.string "to"
35
+ t.datetime "created_at"
36
+ end
37
+
38
+ add_index "charges_state_transitions", ["charges_id"], :name => "index_charges_state_transitions_on_charges_id"
39
+
40
+ create_table "charges", :force => true do |t|
41
+ t.integer "amount", :null => false
42
+ t.integer "user_id", :null => false
43
+ t.string "external_transaction_id"
44
+ t.text "params"
45
+ t.string "state", :default => "new", :null => false
46
+ t.datetime "created_at", :null => false
47
+ t.datetime "updated_at", :null => false
48
+ t.string "error"
49
+ t.integer "approved_by"
50
+ t.text "reject_reason"
51
+ t.decimal "real_amount"
52
+ t.string "gateway_name"
53
+ t.string "gateway_token"
54
+ t.string "gateway_payer_id"
55
+ t.string "ip_address"
56
+ end
57
+
58
+ add_index "charges", ["approved_by"], :name => "index_charges_on_approved_by"
59
+ add_index "charges", ["gateway_name"], :name => "index_charges_on_gateway_name"
60
+ add_index "charges", ["gateway_token"], :name => "index_charges_on_gateway_token"
61
+ add_index "charges", ["state"], :name => "index_charges_on_state"
62
+ add_index "charges", ["user_id"], :name => "index_charges_on_user_id"
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ module Supercharged::Helpers
2
+
3
+ @gateways = {}
4
+
5
+ def self.gateway(name)
6
+ @gateways[name.to_sym] || raise("Gateway not registered")
7
+ end
8
+
9
+ def self.init_gateway(name, options)
10
+ klass = gateway_class_by_name(name)
11
+ gateway = klass.new(options)
12
+ add_gateway(name, gateway)
13
+ end
14
+
15
+ private
16
+
17
+ def self.gateway_class_by_name(name)
18
+ "ActiveMerchant::Billing::#{name.to_s.camelcase}Gateway".classify.constantize
19
+ rescue NameError
20
+ raise "Unknown gateway '#{name}'"
21
+ end
22
+
23
+ def self.add_gateway(name, gateway)
24
+ @gateways[name.to_sym] = gateway
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Supercharged
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/supercharged.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config/routes'))
2
2
  require 'supercharged/activemerchant'
3
+ require 'supercharged/helpers'
3
4
 
4
5
  require 'state_machine'
5
6
 
data/test/fake_app.rb CHANGED
@@ -2,11 +2,7 @@ require 'active_record'
2
2
  require 'action_controller/railtie'
3
3
 
4
4
  # database
5
- if ENV['TRAVIS'].present?
6
- ActiveRecord::Base.configurations = {'test' => {:adapter => 'postgresql', :database => 'supercharged_test', :username => "postgres"}}
7
- else
8
- ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
9
- end
5
+ ActiveRecord::Base.configurations = {'test' => {adapter: 'sqlite3', database: ':memory:'}}
10
6
  ActiveRecord::Base.establish_connection('test')
11
7
 
12
8
  # config
@@ -39,6 +35,20 @@ ActiveRecord::Base.silence do
39
35
 
40
36
  add_index "gateway_notifications", ["charge_id"], :name => "index_gateway_input_notifications_on_charge_id"
41
37
 
38
+ create_table "gateway_responses", :force => true do |t|
39
+ t.integer "charge_id", :null => false
40
+ t.string "action", :null => false
41
+ t.decimal "amount"
42
+ t.boolean "success", :null => false
43
+ t.string "authorization"
44
+ t.string "message"
45
+ t.text "params"
46
+ t.datetime "created_at", :null => false
47
+ t.datetime "updated_at", :null => false
48
+ end
49
+
50
+ add_index "gateway_responses", ["charge_id"], :name => "index_gateway_responses_on_charge_id"
51
+
42
52
  create_table "charges_state_transitions", :force => true do |t|
43
53
  t.integer "charges_id"
44
54
  t.string "charges_type"
@@ -48,6 +58,11 @@ ActiveRecord::Base.silence do
48
58
  t.datetime "created_at"
49
59
  end
50
60
 
61
+ create_table "users", :force => true do |t|
62
+ t.datetime "created_at", :null => false
63
+ t.datetime "updated_at", :null => false
64
+ end
65
+
51
66
  add_index "charges_state_transitions", ["charges_id"], :name => "index_charges_state_transitions_on_charges_id"
52
67
 
53
68
  create_table "charges", :force => true do |t|
@@ -58,14 +73,19 @@ ActiveRecord::Base.silence do
58
73
  t.string "state", :default => "new", :null => false
59
74
  t.datetime "created_at", :null => false
60
75
  t.datetime "updated_at", :null => false
61
- t.integer "user_transaction_id"
62
76
  t.string "error"
63
77
  t.integer "approved_by"
64
78
  t.text "reject_reason"
65
79
  t.decimal "real_amount"
80
+ t.string "gateway_name"
81
+ t.string "gateway_token"
82
+ t.string "gateway_payer_id"
83
+ t.string "ip_address"
66
84
  end
67
85
 
68
86
  add_index "charges", ["approved_by"], :name => "index_charges_on_approved_by"
87
+ add_index "charges", ["gateway_name"], :name => "index_charges_on_gateway_name"
88
+ add_index "charges", ["gateway_token"], :name => "index_charges_on_gateway_token"
69
89
  add_index "charges", ["state"], :name => "index_charges_on_state"
70
90
  add_index "charges", ["user_id"], :name => "index_charges_on_user_id"
71
91
 
@@ -92,3 +112,6 @@ end
92
112
 
93
113
  # helpers
94
114
  Object.const_set(:ApplicationHelper, Module.new)
115
+
116
+ class User < ActiveRecord::Base
117
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ describe Supercharged::ChargesController do
4
+ describe "create action" do
5
+ context "authorized" do
6
+ let(:fake_user) { User.create! }
7
+
8
+ before do
9
+ Supercharged::ChargesController.any_instance.stubs(:current_user).returns(fake_user)
10
+ end
11
+
12
+ context "correct conditions" do
13
+ it "response contains id in json" do
14
+ post :create, charge: { amount: 100 }
15
+
16
+ assert_response :success
17
+
18
+ expected = {"charge"=>{"id"=>1}}
19
+ JSON.parse(@response.body).must_equal(expected)
20
+ end
21
+ end
22
+
23
+ context "bad conditions" do
24
+ it "response contains errors in json" do
25
+ post :create, charge: { amount: 0 }
26
+
27
+ assert_response 422
28
+
29
+ expected = {"errors"=>{"amount"=>["must be greater than or equal to 1"]}}
30
+ JSON.parse(@response.body).must_equal(expected)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -17,7 +17,7 @@ describe Supercharged::GatewayNotificationsController do
17
17
 
18
18
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
19
19
 
20
- post :create, gateway: "webmoney"
20
+ post :create, gateway: "webmoney", amount: 100
21
21
 
22
22
  charge.reload
23
23
  charge.state_name.must_equal :ok
@@ -33,7 +33,7 @@ describe Supercharged::GatewayNotificationsController do
33
33
 
34
34
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
35
35
 
36
- post :create, gateway: "webmoney"
36
+ post :create, gateway: "webmoney", amount: 100
37
37
 
38
38
  charge.reload
39
39
  charge.state_name.must_equal :error
@@ -47,7 +47,7 @@ describe Supercharged::GatewayNotificationsController do
47
47
 
48
48
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
49
49
 
50
- post :create, gateway: "webmoney"
50
+ post :create, gateway: "webmoney", amount: 100
51
51
 
52
52
  charge.reload
53
53
  charge.state_name.must_equal :error
@@ -58,5 +58,14 @@ describe Supercharged::GatewayNotificationsController do
58
58
 
59
59
  end
60
60
  end
61
+
62
+ context "without any payload params" do
63
+ it "returns bad_request" do
64
+ # head :bad_request
65
+ post :create, gateway: "paypal"
66
+
67
+ assert_response :bad_request
68
+ end
69
+ end
61
70
  end
62
71
  end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class Supercharged::ChargesHelperTest < ActionView::TestCase
4
+ def test_min_value
5
+ field = charge_form_amount_field(sample_service, { min: 500 })
6
+ field.must_include 'min="500"'
7
+ end
8
+
9
+ def sample_service
10
+ stub(mappings: { amount: "amount" })
11
+ end
12
+ end
@@ -8,11 +8,27 @@ describe Charge do
8
8
 
9
9
  subject.errors[:amount][0].must_equal "can't be blank"
10
10
  end
11
+
12
+ it "min amount is required" do
13
+ subject.amount = 0
14
+ subject.valid?
15
+
16
+ subject.errors[:amount][0].must_equal "must be greater than or equal to 1"
17
+
18
+ subject.amount = 100
19
+ subject.valid?.must_equal true
20
+ end
11
21
  end
12
22
 
13
23
  describe "states" do
14
24
  subject { Charge.create!({user_id: 1, amount: 10}, without_protection: true) }
15
25
 
26
+ describe "initial state" do
27
+ it "initial state is new" do
28
+ Charge.new.state_name.must_equal :new
29
+ end
30
+ end
31
+
16
32
  describe "#approve" do
17
33
  it "changes state and real_amount" do
18
34
  subject.approve(5)
@@ -7,5 +7,15 @@ describe GatewayNotification do
7
7
  GatewayNotification.create!(gateway: "webmoney")
8
8
  }.must_raise GatewayNotification::EmptyChargeIdError
9
9
  end
10
+
11
+ it "charge id is inherited from adapter" do
12
+ gateway_notification = GatewayNotification.new
13
+
14
+ adapter = stub(item_id: 42)
15
+ gateway_notification.stubs(:adapter).returns(adapter)
16
+
17
+ gateway_notification.save!
18
+ gateway_notification.charge_id.must_equal 42
19
+ end
10
20
  end
11
21
  end
data/test/test_helper.rb CHANGED
@@ -9,7 +9,6 @@ require "mocha/setup"
9
9
  require 'rails'
10
10
  require 'active_record'
11
11
  require 'action_view'
12
- # require 'action_controller'
13
12
 
14
13
  require "rails/test_help"
15
14
  require "minitest/rails"
metadata CHANGED
@@ -1,153 +1,182 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: supercharged
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 0
8
- - 0
9
- version: 1.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - divineforest
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2013-05-07 00:00:00 +04:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- type: :runtime
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- segments:
27
- - 3
28
- - 1
29
- version: "3.1"
12
+ date: 2013-06-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
30
15
  name: rails
31
- requirement: *id001
32
- prerelease: false
33
- - !ruby/object:Gem::Dependency
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
34
22
  type: :runtime
35
- version_requirements: &id002 !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
- version: "0"
42
- name: state_machine
43
- requirement: *id002
44
23
  prerelease: false
45
- - !ruby/object:Gem::Dependency
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '3.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: state_machine
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
46
38
  type: :runtime
47
- version_requirements: &id003 !ruby/object:Gem::Requirement
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- segments:
52
- - 0
53
- version: "0"
54
- name: state_machine-audit_trail
55
- requirement: *id003
56
39
  prerelease: false
57
- - !ruby/object:Gem::Dependency
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: state_machine-audit_trail
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
58
54
  type: :runtime
59
- version_requirements: &id004 !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- version: "0"
66
- name: activemerchant
67
- requirement: *id004
68
55
  prerelease: false
69
- - !ruby/object:Gem::Dependency
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activemerchant
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
70
  type: :runtime
71
- version_requirements: &id005 !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- segments:
76
- - 0
77
- version: "0"
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
78
79
  name: strong_parameters
79
- requirement: *id005
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
80
87
  prerelease: false
81
- - !ruby/object:Gem::Dependency
82
- type: :development
83
- version_requirements: &id006 !ruby/object:Gem::Requirement
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- segments:
88
- - 0
89
- version: "0"
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
90
95
  name: sqlite3
91
- requirement: *id006
92
- prerelease: false
93
- - !ruby/object:Gem::Dependency
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
94
102
  type: :development
95
- version_requirements: &id007 !ruby/object:Gem::Requirement
96
- requirements:
97
- - - ~>
98
- - !ruby/object:Gem::Version
99
- segments:
100
- - 3
101
- - 0
102
- version: "3.0"
103
- name: minitest
104
- requirement: *id007
105
103
  prerelease: false
106
- - !ruby/object:Gem::Dependency
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: minitest
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
107
118
  type: :development
108
- version_requirements: &id008 !ruby/object:Gem::Requirement
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- segments:
113
- - 0
114
- version: "0"
115
- name: minitest-spec-context
116
- requirement: *id008
117
119
  prerelease: false
118
- - !ruby/object:Gem::Dependency
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '3.0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: minitest-spec-context
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
119
134
  type: :development
120
- version_requirements: &id009 !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- segments:
125
- - 0
126
- version: "0"
127
- name: minitest-rails
128
- requirement: *id009
129
135
  prerelease: false
130
- - !ruby/object:Gem::Dependency
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: minitest-rails
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
131
150
  type: :development
132
- version_requirements: &id010 !ruby/object:Gem::Requirement
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- segments:
137
- - 0
138
- version: "0"
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
139
159
  name: mocha
140
- requirement: *id010
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
141
167
  prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
142
174
  description:
143
175
  email:
144
176
  executables: []
145
-
146
177
  extensions: []
147
-
148
178
  extra_rdoc_files: []
149
-
150
- files:
179
+ files:
151
180
  - app/assets/javascripts/charge_form.js.coffee.erb
152
181
  - app/assets/javascripts/supercharged.js
153
182
  - app/controllers/supercharged/charges_controller.rb
@@ -155,49 +184,61 @@ files:
155
184
  - app/helpers/supercharged/charges_helper.rb
156
185
  - app/models/charge.rb
157
186
  - app/models/gateway_notification.rb
187
+ - app/models/gateway_response.rb
158
188
  - app/models/payment_state_transition.rb
159
189
  - app/models/supercharged/charge/base.rb
160
190
  - config/routes.rb
191
+ - lib/generators/supercharged/migrations_generator.rb
192
+ - lib/generators/supercharged/templates/install_migration.rb
161
193
  - lib/supercharged/activemerchant.rb
194
+ - lib/supercharged/helpers.rb
162
195
  - lib/supercharged/version.rb
163
196
  - lib/supercharged.rb
164
- - lib/tasks/supercharged_tasks.rake
165
197
  - MIT-LICENSE
166
198
  - Rakefile
167
199
  - README.md
168
- has_rdoc: true
200
+ - test/fake_app.rb
201
+ - test/supercharged/controllers/charges_controller_test.rb
202
+ - test/supercharged/controllers/gateway_notifications_controller_test.rb
203
+ - test/supercharged/helpers/charges_helper_test.rb
204
+ - test/supercharged/models/charge_test.rb
205
+ - test/supercharged/models/geneway_notification_test.rb
206
+ - test/test_helper.rb
169
207
  homepage:
170
208
  licenses: []
171
-
172
209
  post_install_message:
173
210
  rdoc_options: []
174
-
175
- require_paths:
211
+ require_paths:
176
212
  - lib
177
- required_ruby_version: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - ">="
180
- - !ruby/object:Gem::Version
181
- segments:
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ none: false
215
+ requirements:
216
+ - - ! '>='
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ segments:
182
220
  - 0
183
- version: "0"
184
- required_rubygems_version: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - ">="
187
- - !ruby/object:Gem::Version
188
- segments:
221
+ hash: -708610607516919495
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ none: false
224
+ requirements:
225
+ - - ! '>='
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ segments:
189
229
  - 0
190
- version: "0"
230
+ hash: -708610607516919495
191
231
  requirements: []
192
-
193
232
  rubyforge_project:
194
- rubygems_version: 1.3.6
233
+ rubygems_version: 1.8.23
195
234
  signing_key:
196
235
  specification_version: 3
197
236
  summary: MVC solution for charges in rails
198
- test_files:
237
+ test_files:
199
238
  - test/fake_app.rb
239
+ - test/supercharged/controllers/charges_controller_test.rb
200
240
  - test/supercharged/controllers/gateway_notifications_controller_test.rb
241
+ - test/supercharged/helpers/charges_helper_test.rb
201
242
  - test/supercharged/models/charge_test.rb
202
243
  - test/supercharged/models/geneway_notification_test.rb
203
244
  - test/test_helper.rb
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :supercharged do
3
- # # Task goes here
4
- # end