Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/controllers/api/payments/payment_intents_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
class API::Payments::PaymentIntentsController < API::BaseController
before_action :authenticate_user!

MAX_AMOUNT_IN_CENTS = 99_999_999

def create
amount_in_cents = params[:amount_in_cents].to_i
unless amount_in_cents.between?(1, MAX_AMOUNT_IN_CENTS)
return render json: { error: "Amount must be between 1 and #{MAX_AMOUNT_IN_CENTS} cents" }, status: :ok
end

payment_intent = ::Payments::Stripe::PaymentIntent::Create.(
current_user || params[:email],
params[:type],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, { useCallback } from 'react'
import currency from 'currency.js'

const MAX_AMOUNT = '999999.99'

export const CustomAmountInput = ({
onChange,
selected,
placeholder,
defaultValue,
value,
min = '0',
max = MAX_AMOUNT,
className = '',
onBlur,
}: {
Expand All @@ -18,6 +21,7 @@ export const CustomAmountInput = ({
defaultValue?: currency
value?: currency | string
min?: string
max?: string
className?: string
}): JSX.Element => {
const handleCustomAmountChange = useCallback(
Expand All @@ -34,9 +38,14 @@ export const CustomAmountInput = ({
return
}

if (parseFloat(e.target.value) > parseFloat(max)) {
onChange(currency(NaN))
return
}

onChange(currency(e.target.value))
},
[onChange]
[onChange, max]
)

const classNames = [
Expand All @@ -51,6 +60,7 @@ export const CustomAmountInput = ({
<input
type="number"
min={min}
max={max}
step="0.01"
onBlur={onBlur}
placeholder={placeholder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ class API::Payments::PaymentIntentsControllerTest < API::BaseTestCase
)
end

test "rejects amount over maximum" do
setup_user
post api_payments_payment_intents_path(
type: 'payment', amount_in_cents: 100_000_000
), headers: @headers, as: :json

assert_response :ok
assert_includes JSON.parse(response.body)["error"], "Amount must be between"
end

test "rejects zero amount" do
setup_user
post api_payments_payment_intents_path(
type: 'payment', amount_in_cents: 0
), headers: @headers, as: :json

assert_response :ok
assert_includes JSON.parse(response.body)["error"], "Amount must be between"
end

test "rejects negative amount" do
setup_user
post api_payments_payment_intents_path(
type: 'payment', amount_in_cents: -100
), headers: @headers, as: :json

assert_response :ok
assert_includes JSON.parse(response.body)["error"], "Amount must be between"
end

test "returns an error if raised" do
error = "oh dear!!"
::Payments::Stripe::PaymentIntent::Create.expects(:call).raises(Stripe::InvalidRequestError.new(error, nil))
Expand Down
Loading