payify 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d216f59c7636963919c2774a1195bc53ae6e4e4f9b79bc12e1bd47db4eb8f06
4
- data.tar.gz: c2f985796ec1b313c1369f0c44bff5cc6bccf79bc9b63578b471912771399a3f
3
+ metadata.gz: f5cf7eb6359e3f095e4eaade8ed118042a3eb933588240ee0a34d3af0947e8a5
4
+ data.tar.gz: e9ee5e294c8a45a24304d47c15c1f8886601cf6f04c480e03ee503226abd5137
5
5
  SHA512:
6
- metadata.gz: 70ccef8894ddfe68b963f5cbcccdd51057b0b9c20e58da32a0de405be8a5d3fc84905cffa5920a428847b91db76ffe859385a3d8b0d3c37dc92f123ec5554097
7
- data.tar.gz: db027a8efbd2294636be447d5de397cbb3c0000fd1eb03b6683fc5ad6675b9fe3362daa0fc02e42e74230b85d4b0ea203d0ff62f093df6f8d8f6fa7297adccf6
6
+ metadata.gz: bb091698b89e880398366b24a12006dfbddb44bf7311da2257557a1f953fbfcae1221af550ef41f7e78afa7fc3dfaa0a8305c7ce9835023fc44252f65996320d
7
+ data.tar.gz: b2c5728bdf7222d5fa00a58ad4e585114c5ffb0ca91a726d27e3088de40f59c21fd9463a31516cc8ebc108f9de499e50d1b81c032af2bc023f992a492c33bb61
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Lopez
@@ -73,34 +73,7 @@ email:
73
73
  executables: []
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
- files:
77
- - README.md
78
- - app/assets/config/payify_manifest.js
79
- - app/assets/images/payify/screenshot.png
80
- - app/assets/images/payify/vat.png
81
- - app/assets/stylesheets/payify/application.css
82
- - app/controllers/payify/payments_controller.rb
83
- - app/helpers/payify/application_helper.rb
84
- - app/jobs/payify/application_job.rb
85
- - app/mailers/payify/application_mailer.rb
86
- - app/models/concerns/payify/has_payment_concern.rb
87
- - app/models/concerns/payify/stripe_payment_concern.rb
88
- - app/models/payify/application_record.rb
89
- - app/models/payify/payment.rb
90
- - app/serializers/payify/payment_serializer.rb
91
- - app/views/payify/application.html.erb
92
- - app/views/payify/payments/_form.html.erb
93
- - app/views/payify/payments/complete.html.erb
94
- - app/views/payify/payments/new.html.erb
95
- - config/locales/payify.en.yml
96
- - config/routes.rb
97
- - db/migrate/20230611124944_create_payment.rb
98
- - db/migrate/20230617052430_add_stripe_payment_intent_id.rb
99
- - lib/payify.rb
100
- - lib/payify/engine.rb
101
- - lib/payify/version.rb
102
- - lib/stripe/client.rb
103
- - lib/tasks/payify_tasks.rake
76
+ files: []
104
77
  homepage: https://github.com/andrewdsilva/payify
105
78
  licenses:
106
79
  - MIT
data/README.md DELETED
@@ -1,164 +0,0 @@
1
- # Payify
2
-
3
- PayifyRails is a Ruby gem that simplifies payment integration into Ruby on Rails projects. It allows to easily add payment functionality to your models. For example, by applying the HasPaymentConcern to a reservation model, you can manage the payment process for reservations seamlessly.
4
-
5
- ![Screenshot](./app/assets/images/payify/screenshot.png)
6
-
7
- ## Installation
8
-
9
- To install the gem add it into a Gemfile (Bundler):
10
-
11
- ```ruby
12
- gem 'payify', '~> 0.1.0'
13
- ```
14
-
15
- And then execute:
16
-
17
- ```
18
- bundle install
19
- ```
20
-
21
- ## Features ✅
22
-
23
- - Includes a Payment model
24
- - Provides concerns to easily add a payment system to your model
25
- - Enables payment with Stripe
26
- - Offers a payment form to integrate into your application
27
- - Allows payment status to be checked via an api route
28
- - Allows configuration of payment (currency, VAT)
29
- - Provides a user interface for payment processing
30
- - Enables management of payment status (pending, paid)
31
-
32
- ## Configuration
33
-
34
- For now, Payify uses Stripe as the payment gateway. You can configure the currency using an initializer.
35
-
36
- ```ruby
37
- # initializers/payify.rb
38
- Payify.setup do |config|
39
- config.currency = "usd"
40
- config.default_tax_rates_id = "eur"
41
- end
42
- ```
43
-
44
- To handle VAT or different tax rates on your payments, you need to create tax rates on Stripe and define the default_tax_rates_id or, alternatively, define the tax_rates_id method on your payment-related models. Leave it empty if you don't manage any taxes.
45
-
46
- You can set your Stripe API credentials using environment variables. (Secret key, Publishable key)
47
-
48
- ```ruby
49
- # .env
50
- STRIPE_API_KEY="..."
51
- STRIPE_PUBLISHABLE_KEY="..."
52
- ```
53
-
54
- ## Usage
55
-
56
- To enable payment functionality for a model, simply include the HasPayment concern:
57
-
58
- ```ruby
59
- class Reservation < ApplicationRecord
60
- include Payify::HasPaymentConcern
61
-
62
- def amount_to_pay
63
- self.price
64
- end
65
-
66
- # Optional : Override the default tax rates id
67
- def tax_rates_id
68
- 'txr_1234567890'
69
- end
70
- end
71
- ```
72
-
73
- When you want to request a payment for a model on which you added the concern, you just need to call the create_payment method.
74
-
75
- ```ruby
76
- reservation_1.create_payment
77
- ```
78
-
79
- Then you can find the id of the new pending payment with payment.id.
80
-
81
- ```ruby
82
- reservation_1.payment.id
83
- ```
84
-
85
- Now you just have to redirect the user to `/payments/:id/new` or include the payment form in your page.
86
-
87
- ```ruby
88
- # reservation/show.html.erb
89
- <%= render "payify/payments/form", payment: @payment %>
90
- ```
91
-
92
- After completing the payment process, the user will be redirected to:
93
-
94
- ```
95
- /payments/:id/complete
96
- ```
97
-
98
- The application will then verify the payment status with Stripe. You can do it manually calling the following method:
99
-
100
- ```ruby
101
- @payment.stripe_confirm_payment
102
- ```
103
-
104
- If the payment has been successfully processed, a confirmation message will be displayed to the user. The payment method `paid?` will return `true`.
105
-
106
- To customize the page that displays the payment status, you can create the following file:
107
-
108
- ```ruby
109
- # views/payify/payments/complete.html.erb
110
-
111
- <% if @payment.paid? %>
112
- <div class="alert alert-success" role="alert">
113
- <%= I18n.t("payments.complete.paid") %>
114
- </div>
115
- <% else %>
116
- <div class="alert alert-danger" role="alert">
117
- <%= I18n.t("payments.complete.pending") %>
118
- </div>
119
- <% end %>
120
- ```
121
-
122
- ## API
123
-
124
- If you prefer using the Payify API, after creating the payment object, you can initialize a new Stripe payment by making a request to: `/payments/:id/new.json`
125
-
126
- This request will return a JSON response containing the `stripe_payment_intent_id` and `stripe_client_secret` required to process a payment using Stripe.
127
-
128
- After making the payment, you can make a request to the following endpoint to update the payment status and retrieve its current state:
129
-
130
- ```
131
- /payments/:id/complete.json
132
- ```
133
-
134
- ## Status
135
-
136
- You can access the payment status using `@payment.status`. The possible statuses are:
137
-
138
- - `pending`: The payment is still being processed.
139
- - `paid`: The payment has been successfully completed.
140
- - `failed`: The payment has failed.
141
-
142
- ## Tests
143
-
144
- To run the tests, execute `rspec` command.
145
-
146
- You can test the payment process in your web browser by following these steps:
147
-
148
- 1. Navigate to the `test/dummy` directory.
149
- 2. Run the following commands:
150
- - `rails db:create`
151
- - `rails db:migrate`
152
- - `rails db:seed`
153
- - `rails s`
154
- 3. Open your browser and go to: [http://localhost:3000/](http://localhost:3000/).
155
-
156
- Each time you run the seed command, your test database will be reset with a reservation that has a payment with an ID of 1. This allows you to test the payment process at the following address: [http://localhost:3000/payments/1/new](http://localhost:3000/payments/1/new).
157
-
158
- ## Contributing
159
-
160
- Bug reports and pull requests are welcome on GitHub at https://github.com/andrewdsilva/payify.
161
-
162
- ## License
163
-
164
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1 +0,0 @@
1
- //= link_directory ../stylesheets/payify .css
Binary file
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,29 +0,0 @@
1
- module Payify
2
- class PaymentsController < ActionController::Base
3
- before_action :set_object, only: %i[new complete]
4
-
5
- def new
6
- @payment.stripe_init_intent
7
-
8
- respond_to do |format|
9
- format.html
10
- format.json { render json: @payment }
11
- end
12
- end
13
-
14
- def complete
15
- @payment.stripe_confirm_payment unless @payment.paid?
16
-
17
- respond_to do |format|
18
- format.html
19
- format.json { render json: @payment }
20
- end
21
- end
22
-
23
- private
24
-
25
- def set_object
26
- @payment = Payment.find(params[:id])
27
- end
28
- end
29
- end
@@ -1,4 +0,0 @@
1
- module Payify
2
- module ApplicationHelper
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module Payify
2
- class ApplicationJob < ActiveJob::Base
3
- end
4
- end
@@ -1,6 +0,0 @@
1
- module Payify
2
- class ApplicationMailer < ActionMailer::Base
3
- default from: "from@example.com"
4
- layout "mailer"
5
- end
6
- end
@@ -1,28 +0,0 @@
1
- module Payify
2
- module HasPaymentConcern
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- has_one :payment, as: :model, dependent: :destroy, class_name: "Payify::Payment"
7
- end
8
-
9
- def create_payment
10
- build_payment(amount: amount_to_pay)
11
-
12
- payment.save
13
- payment
14
- end
15
-
16
- def cancel_payment
17
- payment.destroy if payment.present?
18
- end
19
-
20
- def amount_to_pay
21
- raise NotImplementedError, "The 'amount_to_pay' method must be implemented in the including model."
22
- end
23
-
24
- def tax_rates_id
25
- nil
26
- end
27
- end
28
- end
@@ -1,33 +0,0 @@
1
- require "stripe/client"
2
-
3
- module Payify
4
- module StripePaymentConcern
5
- extend ActiveSupport::Concern
6
-
7
- def stripe_client
8
- @stripe_client ||= ::Stripe::Client.new
9
- end
10
-
11
- def stripe_init_intent
12
- return unless stripe_payment_inent_id.nil? && !paid?
13
-
14
- intent = stripe_client.create_payment_intent(amount, tax_id)
15
-
16
- update_attribute(:stripe_payment_inent_id, intent.id)
17
- update_attribute(:stripe_client_secret, intent.client_secret)
18
- end
19
-
20
- def stripe_confirm_payment
21
- intent = stripe_client.find_intent(stripe_payment_inent_id)
22
-
23
- return unless intent["status"] == "succeeded"
24
-
25
- update_attribute(:paid_at, Time.now)
26
- update_attribute(:status, Payify::Payment.statuses[:paid])
27
- end
28
-
29
- def tax_id
30
- model&.tax_rates_id || Payify.default_tax_rates_id
31
- end
32
- end
33
- end
@@ -1,5 +0,0 @@
1
- module Payify
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
- end
5
- end
@@ -1,35 +0,0 @@
1
- module Payify
2
- class Payment < ApplicationRecord
3
- include ::Payify::StripePaymentConcern
4
-
5
- enum status: { pending: 0, paid: 1, failed: 2 }
6
- enum payment_method: { stripe: 0 }
7
-
8
- belongs_to :model, polymorphic: true, optional: true
9
-
10
- validates :amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
11
- validates :status, presence: true
12
-
13
- before_destroy :cannot_destroy_if_paid
14
-
15
- def make_payment(transaction_id)
16
- self.transaction_id = transaction_id
17
- self.paid_at = Time.current
18
- self.status = :paid
19
- end
20
-
21
- def can_destroy?
22
- !paid?
23
- end
24
-
25
- def paid?
26
- paid_at.present?
27
- end
28
-
29
- private
30
-
31
- def cannot_destroy_if_paid
32
- raise ActiveRecord::RecordNotDestroyed if paid?
33
- end
34
- end
35
- end
@@ -1,10 +0,0 @@
1
- module Payify
2
- class PaymentSerializer < ActiveModel::Serializer
3
- attributes :id, :amount, :status, :payment_method, :transaction_id, :paid_at
4
-
5
- attributes :stripe_payment_inent_id, :stripe_client_secret
6
-
7
- attribute(:paid) { object.paid? }
8
- attribute(:can_destroy) { object.can_destroy? }
9
- end
10
- end
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Payify</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "payify/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>
@@ -1,46 +0,0 @@
1
- <script src="https://js.stripe.com/v3/"></script>
2
-
3
- <%= form_with(id: "payment-form", url: payify.complete_payment_path, method: "post") do |form| %>
4
- <div id="payment-element">
5
- </div>
6
-
7
- <div id="error-message">
8
- </div>
9
-
10
- <%= form.submit I18n.t("payments.submit"), id: "submit", class: "btn btn-primary w-100 mt-4" %>
11
- <% end %>
12
-
13
- <script>
14
- const stripe = Stripe("<%= Payify.stripe_publishable_key %>");
15
-
16
- const options = {
17
- clientSecret: "<%= payment.stripe_client_secret %>",
18
- };
19
-
20
- const elements = stripe.elements(options);
21
-
22
- const paymentElement = elements.create("payment");
23
- paymentElement.mount("#payment-element");
24
-
25
- const form = document.getElementById("payment-form");
26
-
27
- form.addEventListener("submit", async (event) => {
28
- event.preventDefault();
29
-
30
- const {error} = await stripe.confirmPayment({
31
- elements,
32
- confirmParams: {
33
- return_url: "<%= request.base_url %>/payify/payments/<%= payment.id %>/complete",
34
- },
35
- });
36
-
37
- if (error) {
38
- const messageContainer = document.querySelector("#error-message");
39
- messageContainer.textContent = error.message;
40
- } else {
41
- // Your customer will be redirected to your `return_url`. For some payment
42
- // methods like iDEAL, your customer will be redirected to an intermediate
43
- // site first to authorize the payment, then redirected to the `return_url`.
44
- }
45
- });
46
- </script>
@@ -1,26 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
-
7
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
8
-
9
- <title>Payment</title>
10
- </head>
11
- <body>
12
-
13
- <div class="container py-5 my-5" style="max-width: 500px;">
14
- <% if @payment.paid? %>
15
- <div class="alert alert-success" role="alert">
16
- <%= I18n.t("payments.complete.paid") %>
17
- </div>
18
- <% else %>
19
- <div class="alert alert-danger" role="alert">
20
- <%= I18n.t("payments.complete.pending") %>
21
- </div>
22
- <% end %>
23
- </div>
24
-
25
- </body>
26
- </html>
@@ -1,24 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
-
7
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
8
-
9
- <title>Payment</title>
10
- </head>
11
- <body>
12
-
13
- <div class="container py-5 my-5" style="max-width: 500px;">
14
- <% if @payment.paid? %>
15
- <div class="alert alert-info" role="alert">
16
- <%= I18n.t("payments.already_paid") %>
17
- </div>
18
- <% else %>
19
- <%= render "form", payment: @payment %>
20
- <% end %>
21
- </div>
22
-
23
- </body>
24
- </html>
@@ -1,7 +0,0 @@
1
- en:
2
- payments:
3
- submit: Submit
4
- already_paid: Payment has already been completed.
5
- complete:
6
- pending: Payment pending.
7
- paid: Successful payment!
data/config/routes.rb DELETED
@@ -1,8 +0,0 @@
1
- ::Payify::Engine.routes.draw do
2
- resources :payments do
3
- member do
4
- get "new"
5
- get "complete", as: "complete"
6
- end
7
- end
8
- end
@@ -1,15 +0,0 @@
1
- class CreatePayment < ActiveRecord::Migration[7.0]
2
- def change
3
- create_table :payify_payments do |t|
4
- t.decimal :amount, precision: 10, scale: 2, null: false
5
- t.integer :status, default: 0, null: false
6
- t.integer :payment_method
7
- t.string :transaction_id
8
- t.datetime :paid_at
9
- t.string :model_type
10
- t.integer :model_id
11
-
12
- t.timestamps
13
- end
14
- end
15
- end
@@ -1,6 +0,0 @@
1
- class AddStripePaymentIntentId < ActiveRecord::Migration[7.0]
2
- def change
3
- add_column :payify_payments, :stripe_payment_inent_id, :string
4
- add_column :payify_payments, :stripe_client_secret, :string
5
- end
6
- end
data/lib/payify/engine.rb DELETED
@@ -1,5 +0,0 @@
1
- module Payify
2
- class Engine < ::Rails::Engine
3
- isolate_namespace Payify
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Payify
4
- VERSION = "0.1.2"
5
- end
data/lib/payify.rb DELETED
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "payify/version"
4
- require "payify/engine"
5
- require "dotenv/load"
6
-
7
- module Payify
8
- class Error < StandardError; end
9
-
10
- mattr_accessor :currency
11
- @@currency = "usd"
12
-
13
- mattr_accessor :default_tax_rates_id
14
- @@default_tax_rates_id = nil
15
-
16
- mattr_accessor :stripe_api_key
17
- @@stripe_api_key = ENV["STRIPE_API_KEY"]
18
-
19
- mattr_accessor :stripe_publishable_key
20
- @@stripe_publishable_key = ENV["STRIPE_PUBLISHABLE_KEY"]
21
-
22
- def self.setup
23
- yield self
24
- end
25
- end
data/lib/stripe/client.rb DELETED
@@ -1,31 +0,0 @@
1
- module Stripe
2
- class Client
3
- def initialize
4
- stripe
5
-
6
- Stripe.api_key = Payify.stripe_api_key
7
- end
8
-
9
- def stripe
10
- @stripe ||= Stripe::StripeClient.new
11
- end
12
-
13
- def create_payment_intent(amount, tax_id = nil, object_invoice = "")
14
- infos = {
15
- amount: (amount * 100).to_i,
16
- currency: Payify.currency,
17
- description: object_invoice,
18
- setup_future_usage: "off_session",
19
- metadata: {
20
- "tax_id": tax_id
21
- }
22
- }
23
-
24
- Stripe::PaymentIntent.create(infos)
25
- end
26
-
27
- def find_intent(payment_intent_id)
28
- Stripe::PaymentIntent.retrieve(payment_intent_id)
29
- end
30
- end
31
- end
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :payify do
3
- # # Task goes here
4
- # end