ecko-plugins-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 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: []