pay 3.0.6 → 3.0.10

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pay might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a5f1e8f94af3893db2d70bfd6f7b153213c0fc6bcc8c73b5d58465f94a35ea9
4
- data.tar.gz: 14cc1b16d5a6cfc1ff4b220cef61c4910da17bd6e896719e8ecda7284894b848
3
+ metadata.gz: edebdc875241f0a8525f970b8fd93644ca0152ce823669de0a878f655c3c6696
4
+ data.tar.gz: a27d9b3cbbb313d0c8fdc796e4e9d2dc5e85c278761e476111415909597e883b
5
5
  SHA512:
6
- metadata.gz: a2b2164b3af965a2598c1c9257ded5741c2e0631d08f36198b32a981b3a4e7edc0fb83e6dc7bc9de00c796a9dc8bdafab2a36f385e3bb47511aa7376924a5be3
7
- data.tar.gz: 6550e82d22748167fa820dbfa48bf2db33e8f98369bb37ac654492a7ea37578b8d8ccd77ab93354e677f1ef94b788afb52f3d537e52dc7fd39084356fa2d3047
6
+ metadata.gz: 810759a42f2e49d64c4d5e98c8d41a40614fc993bd578621212701c86080fcc5fcecada3bb4ebc838877e81b07c1c23a52ce757a09ebadada8367eef296a7f3f
7
+ data.tar.gz: 56986f6e8a49477b60968f03dd0ccf426d9eb702a01a146954c3a99bf97f4d25556edacfb64eccd7728437b71c880fc34d00bef9cc59b9a13d3c993b9cee005d
@@ -10,7 +10,6 @@ module Pay
10
10
  scope :sorted, -> { order(created_at: :desc) }
11
11
  scope :with_active_customer, -> { joins(:customer).merge(Customer.active) }
12
12
  scope :with_deleted_customer, -> { joins(:customer).merge(Customer.deleted) }
13
- default_scope -> { sorted }
14
13
 
15
14
  # Validations
16
15
  validates :amount, presence: true
@@ -60,6 +59,18 @@ module Pay
60
59
  payment_processor.refund!(refund_amount)
61
60
  end
62
61
 
62
+ def refunded?
63
+ amount_refunded.to_i > 0
64
+ end
65
+
66
+ def full_refund?
67
+ refunded? && amount == amount_refunded
68
+ end
69
+
70
+ def partial_refund?
71
+ refunded? && !full_refund?
72
+ end
73
+
63
74
  def charged_to
64
75
  case payment_method_type
65
76
  when "card"
@@ -65,7 +65,7 @@ module Pay
65
65
  end
66
66
 
67
67
  def customer_name
68
- [owner.try(:first_name), owner.try(:last_name)].compact.join(" ")
68
+ owner.respond_to?(:name) ? owner.name : [owner.try(:first_name), owner.try(:last_name)].compact.join(" ")
69
69
  end
70
70
 
71
71
  def active?
@@ -4,7 +4,7 @@ module Pay
4
4
 
5
5
  # Associations
6
6
  belongs_to :customer
7
- has_many :charges, class_name: "Pay::Charge", foreign_key: :pay_subscription_id
7
+ has_many :charges
8
8
 
9
9
  # Scopes
10
10
  scope :for_name, ->(name) { where(name: name) }
@@ -24,41 +24,41 @@
24
24
 
25
25
  <div class="bg-white rounded-lg shadow-xl p-4 sm:py-6 sm:px-10 mb-5">
26
26
  <% if @payment.succeeded? %>
27
- <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "successful.header" %></h1>
28
- <p class="mb-6"><%=t "successful.description" %></p>
27
+ <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "pay.successful.header" %></h1>
28
+ <p class="mb-6"><%=t "pay.successful.description" %></p>
29
29
 
30
30
  <% elsif @payment.canceled? %>
31
- <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "cancelled.header" %></h1>
32
- <p class="mb-6"><%=t "cancelled.description" %></p>
31
+ <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "pay.cancelled.header" %></h1>
32
+ <p class="mb-6"><%=t "pay.cancelled.description" %></p>
33
33
 
34
34
  <% else %>
35
35
  <div data-payment-intent-target="form" id="payment-elements">
36
36
  <!-- Instructions -->
37
- <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "requires_action.header", amount: number_to_currency(@payment.amount / 100.0) %></h1>
38
- <p class="mb-6"><%=t "requires_action.description" %></p>
37
+ <h1 class="text-xl mt-2 mb-4 text-gray-700"><%=t "pay.requires_action.header", amount: number_to_currency(@payment.amount / 100.0) %></h1>
38
+ <p class="mb-6"><%=t "pay.requires_action.description" %></p>
39
39
 
40
40
  <div data-payment-intent-target="cardFields" class="hidden">
41
41
  <!-- Name -->
42
- <label for="cardholder-name" class="inline-block text-sm text-gray-700 font-semibold mb-2"><%=t "requires_action.full_name" %></label>
42
+ <label for="cardholder-name" class="inline-block text-sm text-gray-700 font-semibold mb-2"><%=t "pay.requires_action.full_name" %></label>
43
43
  <input data-payment-intent-target="name" id="cardholder-name" type="text" placeholder="Jane Doe" required autofocus class="mt-1 mb-6 block w-full px-3 py-2 rounded-md border border-gray-300 shadow-sm focus:outline-none focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
44
44
 
45
45
  <!-- Card -->
46
- <label for="card-element" class="inline-block text-sm text-gray-700 font-semibold mb-2"><%=t "requires_action.card" %></label>
46
+ <label for="card-element" class="inline-block text-sm text-gray-700 font-semibold mb-2"><%=t "pay.requires_action.card" %></label>
47
47
  <div data-payment-intent-target="card" id="card-element" class="mt-1 mb-6 block w-full px-3 py-4 rounded-md border border-gray-300 shadow-sm focus:outline-none focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50"></div>
48
48
  </div>
49
49
 
50
50
  <!-- Pay Button -->
51
51
  <button data-payment-intent-target="button" data-action="click->payment-intent#confirmPayment" class="inline-block w-full px-4 py-3 mb-4 text-white rounded-lg bg-blue-400 hover:bg-blue-500">
52
- <%=t "requires_action.button", amount: number_to_currency(@payment.amount / 100.0) %>
52
+ <%=t "pay.requires_action.button", amount: number_to_currency(@payment.amount / 100.0) %>
53
53
  </button>
54
54
  </div>
55
55
  <% end %>
56
56
 
57
- <%= link_to t("back"), @redirect_to, class: "inline-block w-full px-4 py-3 bg-gray-100 hover:bg-gray-200 text-center text-gray-600 rounded-lg" %>
57
+ <%= link_to t("pay.back"), @redirect_to, class: "inline-block w-full px-4 py-3 bg-gray-100 hover:bg-gray-200 text-center text-gray-600 rounded-lg" %>
58
58
  </div>
59
59
 
60
60
  <p class="text-center text-gray-500 text-sm">
61
- © <%= Date.current.year %> <%= Pay.business_name %> <%=t "all_rights_reserved" %>
61
+ © <%= Date.current.year %> <%= Pay.business_name %> <%=t "pay.all_rights_reserved" %>
62
62
  </p>
63
63
  </div>
64
64
  </div>
@@ -119,14 +119,14 @@
119
119
  if (result.error) {
120
120
  if (result.error.code === 'parameter_invalid_empty' &&
121
121
  result.error.param === 'payment_method_data[billing_details][name]') {
122
- this.errorMessageValue = '<%=t "requires_action.name_missing" %>'
122
+ this.errorMessageValue = '<%=t "pay.requires_action.name_missing" %>'
123
123
  } else {
124
124
  this.errorMessageValue = result.error.message
125
125
  this.statusValue = result.error.payment_intent.status
126
126
  }
127
127
  } else {
128
128
  this.completeValue = true;
129
- this.successMessageValue = '<%=t "requires_action.success" %>'
129
+ this.successMessageValue = '<%=t "pay.requires_action.success" %>'
130
130
  }
131
131
  }
132
132
 
@@ -1,36 +1,44 @@
1
1
  en:
2
- successful:
3
- header: Payment Successful
4
- description: This payment was already successfully confirmed.
5
- cancelled:
6
- header: Payment Cancelled
7
- description: This payment was cancelled.
8
- requires_action:
9
- header: Confirm your %{amount} payment
10
- description: Extra confirmation is needed to process your payment. Please confirm your payment by filling out your payment details below.
11
- full_name: Full name
12
- card: Credit or debit card
13
- button: Pay %{amount}
14
- name_missing: Please provide your name.
15
- success: The payment was successful.
16
- all_rights_reserved: All rights reserved.
17
- back: Go back
18
- receipt:
19
- date: Date
20
- account_billed: Account Billed
21
- product: Product
22
- amount: Amount
23
- charged_to: Charged to
24
- additional_info: Additional Info
25
- errors:
26
- action_required: "This payment attempt failed because additional action is required before it can be completed."
27
- invalid_payment: "This payment attempt failed because of an invalid payment method."
28
- email_required: "Email is required to create a customer"
29
- no_processor: "No payment processor selected. Make sure to set the %{class_name}'s `processor` attribute to either 'stripe' or 'braintree'."
30
- braintree:
31
- authorization: "Either the data you submitted is malformed and does not match the API or the API key you used may not be authorized to perform this action."
32
-
33
2
  pay:
3
+ successful:
4
+ header: Payment Successful
5
+ description: This payment was already successfully confirmed.
6
+ cancelled:
7
+ header: Payment Cancelled
8
+ description: This payment was cancelled.
9
+ requires_action:
10
+ header: Confirm your %{amount} payment
11
+ description: Extra confirmation is needed to process your payment. Please confirm your payment by filling out your payment details below.
12
+ full_name: Full name
13
+ card: Credit or debit card
14
+ button: Pay %{amount}
15
+ name_missing: Please provide your name.
16
+ success: The payment was successful.
17
+ all_rights_reserved: All rights reserved.
18
+ back: Go back
19
+ receipt:
20
+ date: Date
21
+ account_billed: Account Billed
22
+ product: Product
23
+ amount: Amount
24
+ charged_to: Charged to
25
+ additional_info: Additional Info
26
+ refunded: Refunded
27
+ paid: Paid
28
+ invoice:
29
+ amount: "Amount"
30
+ product: "Product"
31
+ quantity: "Quantity"
32
+ subtotal: "Subtotal"
33
+ total: "Total"
34
+ unit_price: "Unit Price"
35
+ errors:
36
+ action_required: "This payment attempt failed because additional action is required before it can be completed."
37
+ invalid_payment: "This payment attempt failed because of an invalid payment method."
38
+ email_required: "Email is required to create a customer"
39
+ no_processor: "No payment processor selected. Make sure to set the %{class_name}'s `processor` attribute to either 'stripe' or 'braintree'."
40
+ braintree:
41
+ authorization: "Either the data you submitted is malformed and does not match the API or the API key you used may not be authorized to perform this action."
34
42
  user_mailer:
35
43
  receipt:
36
44
  subject: "Payment receipt"
@@ -2,7 +2,7 @@ module Pay
2
2
  module Braintree
3
3
  class AuthorizationError < Braintree::Error
4
4
  def message
5
- I18n.t("errors.braintree.authorization")
5
+ I18n.t("pay.errors.braintree.authorization")
6
6
  end
7
7
  end
8
8
  end
data/lib/pay/errors.rb CHANGED
@@ -13,13 +13,13 @@ module Pay
13
13
 
14
14
  class ActionRequired < PaymentError
15
15
  def message
16
- I18n.t("errors.action_required")
16
+ I18n.t("pay.errors.action_required")
17
17
  end
18
18
  end
19
19
 
20
20
  class InvalidPaymentMethod < PaymentError
21
21
  def message
22
- I18n.t("errors.invalid_payment")
22
+ I18n.t("pay.errors.invalid_payment")
23
23
  end
24
24
  end
25
25
  end
data/lib/pay/receipts.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module Pay
2
2
  module Receipts
3
+ include ActionView::Helpers::NumberHelper
4
+
3
5
  def product
4
6
  Pay.application_name
5
7
  end
@@ -13,17 +15,30 @@ module Pay
13
15
  receipt_pdf.render
14
16
  end
15
17
 
16
- def receipt_pdf
17
- ::Receipts::Receipt.new(
18
+ def receipt_pdf(**options)
19
+ line_items = [
20
+ [I18n.t("pay.receipt.date"), I18n.l(created_at, format: :long)],
21
+ [I18n.t("pay.receipt.account_billed"), "#{customer.customer_name} (#{customer.email})"],
22
+ [I18n.t("pay.receipt.product"), product],
23
+ [I18n.t("pay.receipt.amount"), number_to_currency(amount / 100.0)],
24
+ [I18n.t("pay.receipt.charged_to"), charged_to]
25
+ ]
26
+ line_items << [I18n.t("pay.receipt.additional_info"), customer.owner.extra_billing_info] if customer.owner.extra_billing_info?
27
+ line_items << [I18n.t("pay.receipt.refunded"), number_to_currency(amount_refunded / 100.0)] if refunded?
28
+
29
+ defaults = {
18
30
  id: id,
19
31
  product: product,
20
32
  company: {
21
33
  name: Pay.business_name,
22
34
  address: Pay.business_address,
23
- email: Pay.support_email
35
+ email: Pay.support_email,
36
+ logo: Pay.business_logo
24
37
  },
25
38
  line_items: line_items
26
- )
39
+ }
40
+
41
+ ::Receipts::Receipt.new(defaults.deep_merge(options))
27
42
  end
28
43
 
29
44
  def invoice_filename
@@ -34,35 +49,40 @@ module Pay
34
49
  invoice_pdf.render
35
50
  end
36
51
 
37
- def invoice_pdf
38
- ::Receipts::Invoice.new(
52
+ def invoice_pdf(**options)
53
+ bill_to = [owner.name]
54
+ bill_to += [owner.extra_billing_info] if owner.extra_billing_info?
55
+ bill_to += [nil, owner.email]
56
+
57
+ total = ActionController::Base.helpers.number_to_currency(amount / 100.0)
58
+
59
+ line_items = [
60
+ ["<b>#{I18n.t("pay.invoice.product")}</b>", nil, "<b>#{I18n.t("pay.invoice.amount")}</b>"],
61
+ [product, nil, total],
62
+ [nil, I18n.t("pay.invoice.subtotal"), total],
63
+ [nil, I18n.t("pay.invoice.total"), total]
64
+ ]
65
+
66
+ defaults = {
39
67
  id: id,
40
- issue_date: created_at,
41
- due_date: created_at,
42
- status: "<b><color rgb='#5eba7d'>PAID</color></b>",
43
- bill_to: [
44
- customer.customer_name,
45
- customer.email
46
- ].compact,
68
+ issue_date: I18n.l(created_at, format: :long),
69
+ due_date: I18n.l(created_at, format: :long),
70
+ status: "<b><color rgb='#5eba7d'>#{I18n.t("pay.receipt.paid").upcase}</color></b>",
71
+ bill_to: bill_to,
47
72
  product: product,
48
73
  company: {
49
74
  name: Pay.business_name,
50
75
  address: Pay.business_address,
51
- email: Pay.support_email
76
+ email: Pay.support_email,
77
+ logo: Pay.business_logo
52
78
  },
53
79
  line_items: line_items
54
- )
80
+ }
81
+
82
+ ::Receipts::Invoice.new(defaults.deep_merge(options))
55
83
  end
56
84
 
57
85
  def line_items
58
- line_items = [
59
- [I18n.t("receipt.date"), created_at.to_s],
60
- [I18n.t("receipt.account_billed"), "#{customer.customer_name} (#{customer.email})"],
61
- [I18n.t("receipt.product"), product],
62
- [I18n.t("receipt.amount"), ActionController::Base.helpers.number_to_currency(amount / 100.0)],
63
- [I18n.t("receipt.charged_to"), charged_to]
64
- ]
65
- line_items << [I18n.t("receipt.additional_info"), customer.owner.extra_billing_info] if customer.owner.extra_billing_info?
66
86
  line_items
67
87
  end
68
88
  end
data/lib/pay/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pay
2
- VERSION = "3.0.6"
2
+ VERSION = "3.0.10"
3
3
  end
data/lib/pay.rb CHANGED
@@ -31,6 +31,7 @@ module Pay
31
31
  mattr_accessor :application_name
32
32
  mattr_accessor :business_address
33
33
  mattr_accessor :business_name
34
+ mattr_accessor :business_logo
34
35
  mattr_accessor :support_email
35
36
 
36
37
  # Email configuration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 3.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Charnes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-09-04 00:00:00.000000000 Z
12
+ date: 2021-09-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails