ecko-plugins-stripe 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f9e1cd65716b38c451d99de1930b876bd506b7ef29993679b831b27496fa042b
4
+ data.tar.gz: 15bccabf1f00fe687e35b4a28c6c065416d193c3a6bcbfcdb3c9b97cc860b3ed
5
+ SHA512:
6
+ metadata.gz: 6df3346303f4870426c5aaef107370c9e47240d1a63bf097e8f4061bbb3613cc9acab93b32ba4163491c5d403f0f9f639b509dae98c85dcb08836fd921c28de0
7
+ data.tar.gz: be237693365e670e728990f0975e24f7fc68f06a47916a52a4303c320f922336b2a12950e03a9a9f594091814feb7bcb79f4c1023e6d888f1f5b72a9756f5a63
@@ -0,0 +1,22 @@
1
+ module Ecko
2
+ module Plugins
3
+ class StripeCallbacksController < 'ApplicationController'.constantize
4
+
5
+ # This can be used to extend and run the payment success.
6
+ def success
7
+ raise Ecko::Plugins::Stripe::InvalidPaymentIntent if intent.nil?
8
+
9
+ @message = intent.metadata['success_message']
10
+ Object.const_get(intent.metadata['callback']).process(intent)
11
+
12
+ view_response
13
+ end
14
+
15
+ def intent
16
+ @intent ||= StripePaymentIntent.find_by(code: params[:state])
17
+ end
18
+
19
+ def view_response; end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require 'ecko/plugins/stripe/configurations'
3
+
4
+ module Ecko
5
+ module Plugins
6
+ module Stripe
7
+ # Base class with
8
+ class Authenticator
9
+ attr_reader :params
10
+
11
+ def initialize(params)
12
+ @params = params
13
+ ::Ecko::Plugins.stripe.authenticate
14
+ end
15
+
16
+ def run
17
+ raise Ecko::Plugins::ExecutionError
18
+ end
19
+
20
+ def state_secret
21
+ Ecko::Plugins::Stripe::Configurations.instance.state_secret
22
+ end
23
+
24
+ class << self
25
+ # Hits the run instance method.
26
+ def execute(params)
27
+ new(params).run
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Stripe
6
+ class Checkout < Authenticator
7
+ def run
8
+ session.url
9
+ end
10
+
11
+ # Creates a session based on the parameters send
12
+ def session
13
+ @session ||= ::Stripe::Checkout::Session.create(
14
+ payment_method_types: payment_method_types,
15
+ mode: 'payment',
16
+ submit_type: params[:submit_type] || 'pay',
17
+ client_reference_id: SecureRandom.uuid,
18
+ success_url: success_url,
19
+ cancel_url: cancel_url,
20
+ line_items: line_items
21
+ )
22
+ end
23
+
24
+ private
25
+
26
+ # Currently we only provide card payments, We can implment multiple types when required.
27
+ def payment_method_types
28
+ params[:types] || ['card']
29
+ end
30
+
31
+ # Creates a valid line item structure to pass it to the stipe checkout process.
32
+ def line_items
33
+ raise Ecko::Plugins::Stripe::InvalidLineItemError unless valid_line_items?
34
+
35
+ params[:line_items].map do |line_item|
36
+ # Amount ot be transferred
37
+ amount = line_item[:amount].to_i
38
+
39
+ # Raise invalid amount error if the amount is 0
40
+ raise Ecko::Plugins::Stripe::InvalidAmountError if amount.zero?
41
+
42
+ # Quantity of the item, normally its 1.
43
+ quantity = line_item[:quantity].to_i
44
+
45
+ # If Quantity is 0, then it doesnt let us go thorough by raising this error.
46
+ raise Ecko::Plugins::Stripe::InvalidQuantityError if quantity.zero?
47
+
48
+ # If Name is nil, then it doesnt let us go thorough by raising this error.
49
+ raise Ecko::Plugins::Stripe::InvalidNameError if line_item[:name].nil?
50
+
51
+ {
52
+ name: line_item[:name],
53
+ description: line_item[:description],
54
+ images: line_item[:images],
55
+ amount: amount * 100, # Stripe takes values for cents
56
+ currency: line_item[:currency] || default_currency,
57
+ quantity: quantity,
58
+ }
59
+ end
60
+ end
61
+
62
+ # When the checkout is a success, this url is triggered.
63
+ def success_url
64
+ "#{callback}/stripe_success?state=#{state}&session_id={CHECKOUT_SESSION_ID}"
65
+ end
66
+
67
+ # When the checkout is cancelled, this url is triggered.
68
+ def cancel_url
69
+ "#{callback}/stripe/callbacks/cancel?state=#{state}"
70
+ end
71
+
72
+ # The state provided as the code of the payment intent
73
+ def state
74
+ payment_intent.code
75
+ end
76
+
77
+ # Gets the currency from the configurations
78
+ def default_currency
79
+ Ecko::Plugins::Stripe::Configurations.instance.currency
80
+ end
81
+
82
+ # Callback url for the checkout process to come back to when the payment is complete or
83
+ # cancelled.
84
+ def callback
85
+ @callback ||= Ecko::Plugins::Stripe::Configurations.instance.callback
86
+ end
87
+
88
+ # Validates and returns boolean if the line item is present or not.
89
+ def valid_line_items?
90
+ params[:line_items].present? && params[:line_items].is_a?(Array)
91
+ end
92
+
93
+ # This is the payment intent provided from the checkout process only.
94
+ # It can be configured when intent is already building outside of the checkout
95
+ # process.
96
+ def intent
97
+ params[:intent]
98
+ end
99
+
100
+ # Creates an intent or pull the intent from the given checkout request
101
+ # Here we save the params to make sure to get data correctly.
102
+ def payment_intent
103
+ @payment_intent ||= intent || ::StripePaymentIntent.create(
104
+ reference: 'payment_only',
105
+ metadata: params.as_json,
106
+ payable_type: params[:payable_type],
107
+ payable_id: params[:payable_id]
108
+ )
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Stripe
6
+ class Configurations
7
+ include Singleton
8
+ attr_accessor :schema
9
+
10
+ def setup(schema)
11
+ @schema = schema
12
+ end
13
+
14
+ # Stripe API key configured through schema
15
+ def stripe_api_key
16
+ schema[:stripe_api_key]
17
+ end
18
+
19
+ # The state secret is used if we have to encrypt any state on callbacks
20
+ # Currently this hasn't been used.
21
+ def state_secret
22
+ schema[:state_secret]
23
+ end
24
+
25
+ # Configured currency while checkout process.
26
+ def currency
27
+ schema[:currency] || 'USD'
28
+ end
29
+
30
+ # Callback url which helps in returning to the correct url when a payment is complete or
31
+ # cancelled
32
+ def callback
33
+ schema[:callback]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require 'ecko/plugins/stripe/configurations'
3
+ require 'ecko/plugins/stripe/authenticator'
4
+ require 'ecko/plugins/stripe/checkout'
5
+
6
+ module Ecko
7
+ module Plugins
8
+ module Stripe
9
+ class Engine
10
+ class << self
11
+ # Configures all the schema and setups the configurations instance of the plugin
12
+ def configure(schema)
13
+ Ecko::Plugins::Stripe::Configurations.instance.setup(schema)
14
+ end
15
+
16
+ # It helps authenticate the stripe plugin api key.
17
+ def authenticate
18
+ ::Stripe.api_key = Ecko::Plugins::Stripe::Configurations.instance.stripe_api_key
19
+ end
20
+
21
+ # This will provide the checkout reference for other plugins as well
22
+ # Currently ecko sponsor plugin uses this.
23
+ def checkout_reference
24
+ Ecko::Plugins::Stripe::Checkout
25
+ end
26
+
27
+ # Creates a checkout session with a payment intent as well.
28
+ def checkout(params)
29
+ checkout_reference.execute(params)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'rails/generators'
5
+ rescue LoadError
6
+ end
7
+
8
+ if defined?(Rails::Generators::Base)
9
+ module Ecko
10
+ module Plugins
11
+ module Stripe
12
+ class PaymentIntentionGenerator < Rails::Generators::Base
13
+ DATA_TYPES = %w(binary json jsonb).freeze
14
+
15
+ source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
16
+ class_option(
17
+ :data_type,
18
+ type: :string,
19
+ default: 'binary',
20
+ desc: "Configure the data type for `data` and `meta data` fields in Postgres migration (options: #{DATA_TYPES.join('/')})"
21
+ )
22
+
23
+ def initialize(*args)
24
+ super
25
+
26
+ if DATA_TYPES.exclude?(options.fetch(:data_type))
27
+ raise Error, "Invalid value for --data-type option. Supported for options are: #{DATA_TYPES.join(", ")}."
28
+ end
29
+ end
30
+
31
+ def create_migration
32
+ template 'create_payment_intent_template.rb', "db/migrate/#{timestamp}_create_payable_intent.rb"
33
+ end
34
+
35
+ private
36
+
37
+ def data_type
38
+ options.fetch('data_type')
39
+ end
40
+
41
+ def rails_version
42
+ Rails::VERSION::STRING
43
+ end
44
+
45
+ def migration_version
46
+ return nil if Gem::Version.new(rails_version) < Gem::Version.new('5.0.0')
47
+ '[6.0]'
48
+ end
49
+
50
+ def timestamp
51
+ Time.now.strftime('%Y%m%d%H%M%S')
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreatePayableIntent < ActiveRecord::Migration[6.1]
4
+ def change
5
+ create_table(:payment_intentions, force: false) do |t|
6
+ t.string :code, null: false
7
+ t.string :reference, null: false
8
+ t.string :category, null: false, default: 'stripe'
9
+ t.references :payable, polymorphic: true
10
+ t.jsonb :metadata, null: false
11
+ t.integer :status, default: 0
12
+ end
13
+ add_index :payment_intentions, [:code], unique: true
14
+ add_index :payment_intentions, [:reference]
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ # == Schema Information
3
+ #
4
+ # Table name: payment_intentions
5
+ #
6
+ # id :bigint(8) not null, primary key
7
+ # code :string not null
8
+ # reference :string not null
9
+ # category :string default("stripe"), not null
10
+ # payable_type :string
11
+ # payable_id :bigint(8)
12
+ # metadata :jsonb not null
13
+ # status :integer default("pending")
14
+ #
15
+
16
+ class StripePaymentIntent < ApplicationRecord
17
+ self.table_name = 'payment_intentions'
18
+ before_create :set_code
19
+
20
+ enum status: {
21
+ pending: 0,
22
+ closed: 0,
23
+ }
24
+
25
+ belongs_to :payable, polymorphic: true
26
+
27
+ def set_code
28
+ self.code = SecureRandom.uuid
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ require "active_support/core_ext/object/try"
2
+ require "active_support/core_ext/hash/slice"
3
+
4
+ module ActionDispatch::Routing
5
+ class Mapper
6
+
7
+ # Sets all the stripe routes specification
8
+ def stripe_callbacks(*resources)
9
+ return if resources.first.nil?
10
+
11
+ get :stripe_success, to: "#{resources.first}#success", as: :stripe_success_callback
12
+ get :stripe_cancel, to: "#{resources.first}#cancel", as: :stripe_cancel_callback
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # This will load the custom routes set by the app
2
+ require 'ecko/plugins/stripe/rails/routes'
3
+
4
+ module Ecko
5
+ module Plugins
6
+ class Engine < ::Rails::Engine
7
+ config.ecko_plugins = Ecko::Plugins
8
+
9
+ # Force routes to be loaded if we are doing any eager load.
10
+ config.before_eager_load do |app|
11
+ app.reload_routes!
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Stripe
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "stripe/version"
4
+ require 'stripe'
5
+ require 'rails'
6
+ require 'ecko/plugins/stripe/engine'
7
+ require 'ecko/plugins/stripe/generators/payment_intent_generator'
8
+ require 'ecko/plugins/stripe/rails'
9
+ require 'ecko/plugins'
10
+
11
+ module Ecko
12
+ module Plugins
13
+ module Stripe
14
+ class ExecutionError < StandardError; end
15
+
16
+ # This error will be thrown when line items are not provided
17
+ class InvalidLineItemError < StandardError; end
18
+
19
+ # This error will be thrown if amount is not provided or it is 0
20
+ # or string is provided
21
+ class InvalidAmountError < StandardError; end
22
+
23
+ # This error will be thrown if quantity is set to zero
24
+ class InvalidQuantityError < StandardError; end
25
+
26
+ # This error will be thrown if name of a line item is not provided
27
+ class InvalidNameError < StandardError; end
28
+
29
+ # When payment Intent is not found this error is thrown
30
+ class InvalidPaymentIntent < StandardError; end
31
+
32
+ class << self
33
+ # This is the initializer for tp register the plugin to the ecko plugin registry
34
+ def register(schema)
35
+ Ecko::Plugins.register(name: 'stripe', schema: schema, engine: Ecko::Plugins::Stripe::Engine)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ autoload(:StripePaymentIntent, 'ecko/plugins/stripe/payment_intent')
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ecko-plugins-stripe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Manish Sharma
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-01-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ecko-plugins
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: stripe
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.39'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.39'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 6.1.4
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: 7.0.0
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 6.1.4
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: 7.0.0
61
+ description: ''
62
+ email:
63
+ - arnoltherasing@gmail.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - app/controllers/ecko/plugins/stripe_callbacks_controller.rb
69
+ - lib/ecko/plugins/stripe.rb
70
+ - lib/ecko/plugins/stripe/authenticator.rb
71
+ - lib/ecko/plugins/stripe/checkout.rb
72
+ - lib/ecko/plugins/stripe/configurations.rb
73
+ - lib/ecko/plugins/stripe/engine.rb
74
+ - lib/ecko/plugins/stripe/generators/payment_intent_generator.rb
75
+ - lib/ecko/plugins/stripe/generators/templates/create_payment_intent_template.rb
76
+ - lib/ecko/plugins/stripe/payment_intent.rb
77
+ - lib/ecko/plugins/stripe/rails.rb
78
+ - lib/ecko/plugins/stripe/rails/routes.rb
79
+ - lib/ecko/plugins/stripe/version.rb
80
+ homepage: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-stripe
81
+ licenses:
82
+ - GPL-3.0+
83
+ metadata:
84
+ allowed_push_host: https://rubygems.org
85
+ homepage_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-stripe
86
+ source_code_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-stripe
87
+ changelog_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-stripe
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ - app
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 2.6.0
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.1.6
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Mastodon stripe plugin, extendable to ecko-plugins sdk
108
+ test_files: []