1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-21 15:54:22 +01:00

(bug) unable to reserve if user's subscription plan is disabled

This commit is contained in:
Sylvain 2022-07-20 17:46:09 +02:00
parent 7134b8ffac
commit 2705b9f6bd
13 changed files with 230 additions and 169 deletions

View File

@ -5,6 +5,7 @@
- Improved calendars loading time - Improved calendars loading time
- Refactored and documented the availability-slot-reservation data model - Refactored and documented the availability-slot-reservation data model
- Display bookers names to connected users now apply to all resources - Display bookers names to connected users now apply to all resources
- Fix a bug: unable to reserve if user's subscription plan is disabled
- Fix a bug: for admins and managers, the current password is not requested before changing their own password - Fix a bug: for admins and managers, the current password is not requested before changing their own password
- Fix a bug: missing translations - Fix a bug: missing translations
- Fix a bug: unable to book a space's slot with an existing reservation - Fix a bug: unable to book a space's slot with an existing reservation

View File

@ -55,7 +55,7 @@ class API::PayzenController < API::PaymentsController
def check_cart def check_cart
cart = shopping_cart cart = shopping_cart
render json: { error: 'invalid shopping cart' }, status: :unprocessable_entity and return unless cart.valid? render json: { error: cart.errors }, status: :unprocessable_entity and return unless cart.valid?
render json: { cart: 'ok' }, status: :ok render json: { cart: 'ok' }, status: :ok
end end

View File

@ -19,7 +19,7 @@ class API::StripeController < API::PaymentsController
res = nil # json of the API answer res = nil # json of the API answer
cart = shopping_cart cart = shopping_cart
render json: { error: 'invalid shopping cart' }, status: :unprocessable_entity and return unless cart.valid? render json: { error: cart.errors }, status: :unprocessable_entity and return unless cart.valid?
begin begin
amount = debit_amount(cart) # will contains the amount and the details of each invoice lines amount = debit_amount(cart) # will contains the amount and the details of each invoice lines
@ -73,7 +73,7 @@ class API::StripeController < API::PaymentsController
def setup_subscription def setup_subscription
cart = shopping_cart cart = shopping_cart
raise InvalidSubscriptionError unless cart.valid? render json: { error: cart.errors }, status: :unprocessable_entity and return unless cart.valid?
service = Stripe::Service.new service = Stripe::Service.new
method = service.attach_method_as_default( method = service.attach_method_as_default(

View File

@ -25,6 +25,22 @@ class CartItem::MachineReservation < CartItem::Reservation
'machine' 'machine'
end end
def valid?(all_items)
@slots.each do |slot|
same_hour_slots = SlotsReservation.joins(:reservation).where(
reservations: { reservable: @reservable },
slot_id: slot[:slot_id],
canceled_at: nil
).count
if same_hour_slots.positive?
@errors[:slot] = 'slot is reserved'
return false
end
end
super
end
protected protected
def credits def credits

View File

@ -36,6 +36,8 @@ class CartItem::PaymentSchedule
end end
def valid?(_all_items) def valid?(_all_items)
return true unless @requested && @plan&.monthly_payment
if @plan&.disabled if @plan&.disabled
@errors[:item] = 'plan is disabled' @errors[:item] = 'plan is disabled'
return false return false

View File

@ -43,42 +43,27 @@ class CartItem::Reservation < CartItem::BaseItem
def valid?(all_items) def valid?(all_items)
pending_subscription = all_items.find { |i| i.is_a?(CartItem::Subscription) } pending_subscription = all_items.find { |i| i.is_a?(CartItem::Subscription) }
@slots.each do |slot| @slots.each do |slot|
if Slot.find(slot[:slot_id]).nil? slot_db = Slot.find(slot[:slot_id])
if slot_db.nil?
@errors[:slot] = 'slot does not exist' @errors[:slot] = 'slot does not exist'
return false return false
end end
availability = Availability.find_by(id: slot[:slot_attributes][:availability_id]) availability = Availability.find_by(id: slot[:slot_attributes][:availability_id])
if availability.nil? if availability.nil?
@errors[:slot] = 'slot availability does not exist' @errors[:availability] = 'availability does not exist'
return false return false
end end
if availability.available_type == 'machines' if slot_db.full?
same_hour_slots = SlotsReservation.joins(:reservation).where( @errors[:slot] = 'availability is full'
reservations: { reservable: @reservable },
slot_id: slot[:slot_id],
canceled_at: nil
).count
if same_hour_slots.positive?
@errors[:slot] = 'slot is reserved'
return false
end
elsif availability.available_type == 'space' && availability.spaces.first.disabled
@errors[:slot] = 'space is disabled'
return false
elsif availability.full?
@errors[:slot] = 'availability is complete'
return false return false
end end
next if availability.plan_ids.empty? next if availability.plan_ids.empty?
next if (@customer.subscribed_plan && availability.plan_ids.include?(@customer.subscribed_plan.id)) || next if required_subscription?(availability, pending_subscription)
(pending_subscription && availability.plan_ids.include?(pending_subscription.plan.id)) ||
(@operator.manager? && @customer.id != @operator.id) ||
@operator.admin?
@errors[:slot] = 'slot is restricted for subscribers' @errors[:availability] = 'availability is restricted for subscribers'
return false return false
end end
@ -211,4 +196,15 @@ class CartItem::Reservation < CartItem::BaseItem
def slots_params def slots_params
@slots.map { |slot| slot.permit(:id, :slot_id, :offered) } @slots.map { |slot| slot.permit(:id, :slot_id, :offered) }
end end
##
# Check if the given availability requires a valid subscription. If so, check if the current customer
# has the required susbcription, otherwise, check if the operator is privileged
##
def required_subscription?(availability, pending_subscription)
(@customer.subscribed_plan && availability.plan_ids.include?(@customer.subscribed_plan.id)) ||
(pending_subscription && availability.plan_ids.include?(pending_subscription.plan.id)) ||
(@operator.manager? && @customer.id != @operator.id) ||
@operator.admin?
end
end end

View File

@ -9,6 +9,7 @@ class CartItem::SpaceReservation < CartItem::Reservation
super(customer, operator, space, slots) super(customer, operator, space, slots)
@plan = plan @plan = plan
@space = space
@new_subscription = new_subscription @new_subscription = new_subscription
end end
@ -25,6 +26,15 @@ class CartItem::SpaceReservation < CartItem::Reservation
'space' 'space'
end end
def valid?(all_items)
if @space.disabled
@errors[:reservable] = 'space is disabled'
return false
end
super
end
protected protected
def credits def credits

View File

@ -2,7 +2,7 @@
# Stores data about a shopping data # Stores data about a shopping data
class ShoppingCart class ShoppingCart
attr_accessor :customer, :operator, :payment_method, :items, :coupon, :payment_schedule attr_accessor :customer, :operator, :payment_method, :items, :coupon, :payment_schedule, :errors
# @param items {Array<CartItem::BaseItem>} # @param items {Array<CartItem::BaseItem>}
# @param coupon {CartItem::Coupon} # @param coupon {CartItem::Coupon}
@ -18,6 +18,7 @@ class ShoppingCart
@items = items @items = items
@coupon = coupon @coupon = coupon
@payment_schedule = payment_schedule @payment_schedule = payment_schedule
@errors = {}
end end
# compute the price details of the current shopping cart # compute the price details of the current shopping cart
@ -87,11 +88,18 @@ class ShoppingCart
items.each do |item| items.each do |item|
next if item.valid?(@items) next if item.valid?(@items)
@errors = item.errors
return false
end
unless @coupon.valid?(items)
@errors = @coupon.errors
return false return false
end end
return false unless @coupon.valid?([])
return false unless @payment_schedule.valid?([]) unless @payment_schedule.valid?(items)
@errors = @payment_schedule.errors
return false
end
true true
end end

View File

@ -526,7 +526,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
login_as(@user_without_subscription, scope: :user) login_as(@user_without_subscription, scope: :user)
machine = Machine.find(6) machine = Machine.find(6)
plan = Plan.find_by(group_id: @user_without_subscription.group_id) plan = Plan.find(4)
availability = machine.availabilities.first availability = machine.availabilities.first
reservations_count = Reservation.count reservations_count = Reservation.count

View File

@ -142,7 +142,7 @@ class Reservations::RestrictedTest < ActionDispatch::IntegrationTest
end end
assert_equal 422, response.status assert_equal 422, response.status
assert_match(/invalid shopping cart/, response.body) assert_match(/availability is restricted for subscribers/, response.body)
assert_equal reservations_count, Reservation.count assert_equal reservations_count, Reservation.count
assert_equal invoices_count, Invoice.count assert_equal invoices_count, Invoice.count

View File

@ -44,9 +44,10 @@ class AvailabilitiesServiceTest < ActiveSupport::TestCase
slots = service.trainings([Training.find(2)], @no_subscription, { start: 1.month.ago.beginning_of_day, end: 1.day.ago.end_of_day }) slots = service.trainings([Training.find(2)], @no_subscription, { start: 1.month.ago.beginning_of_day, end: 1.day.ago.end_of_day })
assert_not_empty slots assert_not_empty slots
assert_equal Availability.find(20).slots.count, slots.count availability = Availability.find(20)
assert_equal Availability.find(20).start_at, slots.first.start_at assert_equal availability.slots.count, slots.count
assert_equal Availability.find(20).end_at, slots.first.end_at assert_equal availability.start_at, slots.first.start_at
assert_equal availability.end_at, slots.first.end_at
end end
test 'machines availabilities' do test 'machines availabilities' do
@ -54,9 +55,10 @@ class AvailabilitiesServiceTest < ActiveSupport::TestCase
slots = service.machines([Machine.find(1)], @no_subscription, { start: 2.days.from_now.beginning_of_day, end: 4.days.from_now.end_of_day }) slots = service.machines([Machine.find(1)], @no_subscription, { start: 2.days.from_now.beginning_of_day, end: 4.days.from_now.end_of_day })
assert_not_empty slots assert_not_empty slots
assert_equal Availability.find(7).slots.count, slots.count availability = Availability.find(7)
assert_equal Availability.find(7).start_at, slots.first.start_at assert_equal availability.slots.count, slots.count
assert_equal Availability.find(7).end_at, slots.last.end_at assert_equal availability.start_at, slots.min_by(&:start_at).start_at
assert_equal availability.end_at, slots.max_by(&:end_at).end_at
end end
test 'spaces availabilities' do test 'spaces availabilities' do
@ -64,9 +66,10 @@ class AvailabilitiesServiceTest < ActiveSupport::TestCase
slots = service.spaces([Space.find(1)], @no_subscription, { start: 2.days.from_now.beginning_of_day, end: 4.days.from_now.end_of_day }) slots = service.spaces([Space.find(1)], @no_subscription, { start: 2.days.from_now.beginning_of_day, end: 4.days.from_now.end_of_day })
assert_not_empty slots assert_not_empty slots
assert_equal Availability.find(18).slots.count, slots.count availability = Availability.find(18)
assert_equal Availability.find(18).start_at, slots.first.start_at assert_equal availability.slots.count, slots.count
assert_equal Availability.find(18).end_at, slots.last.end_at assert_equal availability.start_at, slots.min_by(&:start_at).start_at
assert_equal availability.end_at, slots.max_by(&:end_at).end_at
end end
test 'trainings availabilities' do test 'trainings availabilities' do
@ -87,8 +90,9 @@ class AvailabilitiesServiceTest < ActiveSupport::TestCase
slots = service.events([Event.find(4)], @no_subscription, { start: DateTime.current.beginning_of_day, end: 30.days.from_now.end_of_day }) slots = service.events([Event.find(4)], @no_subscription, { start: DateTime.current.beginning_of_day, end: 30.days.from_now.end_of_day })
assert_not_empty slots assert_not_empty slots
assert_equal Availability.find(17).slots.count, slots.count availability = Availability.find(17)
assert_equal Availability.find(17).start_at, slots.first.start_at assert_equal availability.slots.count, slots.count
assert_equal Availability.find(17).end_at, slots.first.end_at assert_equal availability.start_at, slots.first.start_at
assert_equal availability.end_at, slots.first.end_at
end end
end end

View File

@ -2,7 +2,7 @@
http_interactions: http_interactions:
- request: - request:
method: get method: get
uri: https://api.stripe.com/v1/payment_intents/pi_3JZDIB2sOmf47Nz91NCWzYP6 uri: https://api.stripe.com/v1/payment_intents/pi_3LNevR2sOmf47Nz90G2zL7T3
body: body:
encoding: US-ASCII encoding: US-ASCII
string: '' string: ''
@ -14,13 +14,13 @@ http_interactions:
Content-Type: Content-Type:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
X-Stripe-Client-Telemetry: X-Stripe-Client-Telemetry:
- '{"last_request_metrics":{"request_id":"req_TAv2FNDcsNhZ0x","request_duration_ms":477}}' - '{"last_request_metrics":{"request_id":"req_g3z6KJauuKa7Ob","request_duration_ms":838}}'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-Client-User-Agent: X-Stripe-Client-User-Agent:
- '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.3 p62 (2019-04-16)","platform":"x86_64-darwin18","engine":"ruby","publisher":"stripe","uname":"Darwin - '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.10 p210 (2022-04-12)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
MacBook-Pro-Sleede-Peng 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 version 5.18.10-arch1-1 (linux@archlinux) (gcc (GCC) 12.1.0, GNU ld (GNU Binutils)
PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64","hostname":"MacBook-Pro-Sleede-Peng"}' 2.38) #1 SMP PREEMPT_DYNAMIC Thu, 07 Jul 2022 17:18:13 +0000","hostname":"Sylvain-laptop"}'
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: Accept:
@ -33,11 +33,11 @@ http_interactions:
Server: Server:
- nginx - nginx
Date: Date:
- Mon, 13 Sep 2021 11:25:46 GMT - Wed, 20 Jul 2022 15:35:05 GMT
Content-Type: Content-Type:
- application/json - application/json
Content-Length: Content-Length:
- '4286' - '4461'
Connection: Connection:
- keep-alive - keep-alive
Access-Control-Allow-Credentials: Access-Control-Allow-Credentials:
@ -53,24 +53,26 @@ http_interactions:
Cache-Control: Cache-Control:
- no-cache, no-store - no-cache, no-store
Request-Id: Request-Id:
- req_kM3vfzGXrrL9Yq - req_uTSAidTgNhke0j
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-C-Cost:
- '0'
Strict-Transport-Security: Strict-Transport-Security:
- max-age=31556926; includeSubDomains; preload - max-age=31556926; includeSubDomains; preload
body: body:
encoding: UTF-8 encoding: UTF-8
string: | string: |-
{ {
"id": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "id": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"object": "payment_intent", "object": "payment_intent",
"amount": 3825, "amount": 97410,
"amount_capturable": 0, "amount_capturable": 0,
"amount_received": 3825, "amount_details": {
"tip": {}
},
"amount_received": 97410,
"application": null, "application": null,
"application_fee_amount": null, "application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null, "canceled_at": null,
"cancellation_reason": null, "cancellation_reason": null,
"capture_method": "automatic", "capture_method": "automatic",
@ -78,15 +80,15 @@ http_interactions:
"object": "list", "object": "list",
"data": [ "data": [
{ {
"id": "ch_3JZDIB2sOmf47Nz91buHMX2j", "id": "ch_3LNevR2sOmf47Nz90Mvq9kVm",
"object": "charge", "object": "charge",
"amount": 3825, "amount": 97410,
"amount_captured": 3825, "amount_captured": 97410,
"amount_refunded": 0, "amount_refunded": 0,
"application": null, "application": null,
"application_fee": null, "application_fee": null,
"application_fee_amount": null, "application_fee_amount": null,
"balance_transaction": "txn_3JZDIB2sOmf47Nz9120KuoH9", "balance_transaction": "txn_3LNevR2sOmf47Nz90JS5wwi9",
"billing_details": { "billing_details": {
"address": { "address": {
"city": null, "city": null,
@ -102,34 +104,33 @@ http_interactions:
}, },
"calculated_statement_descriptor": "Stripe", "calculated_statement_descriptor": "Stripe",
"captured": true, "captured": true,
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": null, "description": null,
"destination": null, "destination": null,
"dispute": null, "dispute": null,
"disputed": false, "disputed": false,
"failure_balance_transaction": null,
"failure_code": null, "failure_code": null,
"failure_message": null, "failure_message": null,
"fraud_details": { "fraud_details": {},
},
"invoice": null, "invoice": null,
"livemode": false, "livemode": false,
"metadata": { "metadata": {},
},
"on_behalf_of": null, "on_behalf_of": null,
"order": null, "order": null,
"outcome": { "outcome": {
"network_status": "approved_by_network", "network_status": "approved_by_network",
"reason": null, "reason": null,
"risk_level": "normal", "risk_level": "normal",
"risk_score": 32, "risk_score": 51,
"seller_message": "Payment complete.", "seller_message": "Payment complete.",
"type": "authorized" "type": "authorized"
}, },
"paid": true, "paid": true,
"payment_intent": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "payment_intent": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_details": { "payment_method_details": {
"card": { "card": {
"brand": "visa", "brand": "visa",
@ -140,11 +141,12 @@ http_interactions:
}, },
"country": "US", "country": "US",
"exp_month": 4, "exp_month": 4,
"exp_year": 2022, "exp_year": 2023,
"fingerprint": "o52jybR7bnmNn6AT", "fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit", "funding": "credit",
"installments": null, "installments": null,
"last4": "4242", "last4": "4242",
"mandate": null,
"network": "visa", "network": "visa",
"three_d_secure": null, "three_d_secure": null,
"wallet": null "wallet": null
@ -153,16 +155,14 @@ http_interactions:
}, },
"receipt_email": null, "receipt_email": null,
"receipt_number": null, "receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3JZDIB2sOmf47Nz91buHMX2j/rcpt_KDebb83SAs8TQggfARcBOMotuxQ1Vxj", "receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3LNevR2sOmf47Nz90Mvq9kVm/rcpt_M5qcIvwnjpj7tlCm4ws6NUyPXIeLpSL",
"refunded": false, "refunded": false,
"refunds": { "refunds": {
"object": "list", "object": "list",
"data": [ "data": [],
],
"has_more": false, "has_more": false,
"total_count": 0, "total_count": 0,
"url": "/v1/charges/ch_3JZDIB2sOmf47Nz91buHMX2j/refunds" "url": "/v1/charges/ch_3LNevR2sOmf47Nz90Mvq9kVm/refunds"
}, },
"review": null, "review": null,
"shipping": null, "shipping": null,
@ -177,25 +177,25 @@ http_interactions:
], ],
"has_more": false, "has_more": false,
"total_count": 1, "total_count": 1,
"url": "/v1/charges?payment_intent=pi_3JZDIB2sOmf47Nz91NCWzYP6" "url": "/v1/charges?payment_intent=pi_3LNevR2sOmf47Nz90G2zL7T3"
}, },
"client_secret": "pi_3JZDIB2sOmf47Nz91NCWzYP6_secret_oIY9Vwdf4coECaCgx0zgmkYMF", "client_secret": "pi_3LNevR2sOmf47Nz90G2zL7T3_secret_EqcVW2yHHRtYlWJG4Qcx0qC1i",
"confirmation_method": "manual", "confirmation_method": "manual",
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": "Invoice reference: 2109001/VL", "description": "Invoice reference: 2207001/VL",
"invoice": null, "invoice": null,
"last_payment_error": null, "last_payment_error": null,
"livemode": false, "livemode": false,
"metadata": { "metadata": {},
},
"next_action": null, "next_action": null,
"on_behalf_of": null, "on_behalf_of": null,
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_options": { "payment_method_options": {
"card": { "card": {
"installments": null, "installments": null,
"mandate_options": null,
"network": null, "network": null,
"request_three_d_secure": "automatic" "request_three_d_secure": "automatic"
} }
@ -203,6 +203,7 @@ http_interactions:
"payment_method_types": [ "payment_method_types": [
"card" "card"
], ],
"processing": null,
"receipt_email": null, "receipt_email": null,
"review": null, "review": null,
"setup_future_usage": null, "setup_future_usage": null,
@ -214,5 +215,5 @@ http_interactions:
"transfer_data": null, "transfer_data": null,
"transfer_group": null "transfer_group": null
} }
recorded_at: Mon, 13 Sep 2021 11:25:46 GMT recorded_at: Wed, 20 Jul 2022 15:35:06 GMT
recorded_with: VCR 6.0.0 recorded_with: VCR 6.0.0

View File

@ -5,7 +5,7 @@ http_interactions:
uri: https://api.stripe.com/v1/payment_methods uri: https://api.stripe.com/v1/payment_methods
body: body:
encoding: UTF-8 encoding: UTF-8
string: type=card&card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2022&card[cvc]=314 string: type=card&card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2023&card[cvc]=314
headers: headers:
User-Agent: User-Agent:
- Stripe/v1 RubyBindings/5.29.0 - Stripe/v1 RubyBindings/5.29.0
@ -14,13 +14,13 @@ http_interactions:
Content-Type: Content-Type:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
X-Stripe-Client-Telemetry: X-Stripe-Client-Telemetry:
- '{"last_request_metrics":{"request_id":"req_tlpIDMIqln9wab","request_duration_ms":616}}' - '{"last_request_metrics":{"request_id":"req_RmcFNPXaqrPUG5","request_duration_ms":2}}'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-Client-User-Agent: X-Stripe-Client-User-Agent:
- '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.3 p62 (2019-04-16)","platform":"x86_64-darwin18","engine":"ruby","publisher":"stripe","uname":"Darwin - '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.10 p210 (2022-04-12)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
MacBook-Pro-Sleede-Peng 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 version 5.18.10-arch1-1 (linux@archlinux) (gcc (GCC) 12.1.0, GNU ld (GNU Binutils)
PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64","hostname":"MacBook-Pro-Sleede-Peng"}' 2.38) #1 SMP PREEMPT_DYNAMIC Thu, 07 Jul 2022 17:18:13 +0000","hostname":"Sylvain-laptop"}'
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: Accept:
@ -33,11 +33,11 @@ http_interactions:
Server: Server:
- nginx - nginx
Date: Date:
- Mon, 13 Sep 2021 11:25:42 GMT - Wed, 20 Jul 2022 15:35:00 GMT
Content-Type: Content-Type:
- application/json - application/json
Content-Length: Content-Length:
- '934' - '930'
Connection: Connection:
- keep-alive - keep-alive
Access-Control-Allow-Credentials: Access-Control-Allow-Credentials:
@ -52,19 +52,23 @@ http_interactions:
- '300' - '300'
Cache-Control: Cache-Control:
- no-cache, no-store - no-cache, no-store
Idempotency-Key:
- 25a0718d-2479-4458-9741-b67628d9f46c
Original-Request:
- req_OGHLOjhvZGzaDh
Request-Id: Request-Id:
- req_nAADKjXEme5vlz - req_OGHLOjhvZGzaDh
Stripe-Should-Retry:
- 'false'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-C-Cost:
- '6'
Strict-Transport-Security: Strict-Transport-Security:
- max-age=31556926; includeSubDomains; preload - max-age=31556926; includeSubDomains; preload
body: body:
encoding: UTF-8 encoding: UTF-8
string: | string: |-
{ {
"id": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "id": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"object": "payment_method", "object": "payment_method",
"billing_details": { "billing_details": {
"address": { "address": {
@ -88,7 +92,7 @@ http_interactions:
}, },
"country": "US", "country": "US",
"exp_month": 4, "exp_month": 4,
"exp_year": 2022, "exp_year": 2023,
"fingerprint": "o52jybR7bnmNn6AT", "fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit", "funding": "credit",
"generated_from": null, "generated_from": null,
@ -104,20 +108,19 @@ http_interactions:
}, },
"wallet": null "wallet": null
}, },
"created": 1631532342, "created": 1658331300,
"customer": null, "customer": null,
"livemode": false, "livemode": false,
"metadata": { "metadata": {},
},
"type": "card" "type": "card"
} }
recorded_at: Mon, 13 Sep 2021 11:25:42 GMT recorded_at: Wed, 20 Jul 2022 15:35:00 GMT
- request: - request:
method: post method: post
uri: https://api.stripe.com/v1/payment_intents uri: https://api.stripe.com/v1/payment_intents
body: body:
encoding: UTF-8 encoding: UTF-8
string: payment_method=pm_1JZDIA2sOmf47Nz9rl1nigpQ&amount=3825&currency=usd&confirmation_method=manual&confirm=true&customer=cus_8Di1wjdVktv5kt string: payment_method=pm_1LNevQ2sOmf47Nz9khvl8vC0&amount=97410&currency=usd&confirmation_method=manual&confirm=true&customer=cus_8Di1wjdVktv5kt
headers: headers:
User-Agent: User-Agent:
- Stripe/v1 RubyBindings/5.29.0 - Stripe/v1 RubyBindings/5.29.0
@ -126,13 +129,13 @@ http_interactions:
Content-Type: Content-Type:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
X-Stripe-Client-Telemetry: X-Stripe-Client-Telemetry:
- '{"last_request_metrics":{"request_id":"req_nAADKjXEme5vlz","request_duration_ms":583}}' - '{"last_request_metrics":{"request_id":"req_OGHLOjhvZGzaDh","request_duration_ms":991}}'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-Client-User-Agent: X-Stripe-Client-User-Agent:
- '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.3 p62 (2019-04-16)","platform":"x86_64-darwin18","engine":"ruby","publisher":"stripe","uname":"Darwin - '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.10 p210 (2022-04-12)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
MacBook-Pro-Sleede-Peng 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 version 5.18.10-arch1-1 (linux@archlinux) (gcc (GCC) 12.1.0, GNU ld (GNU Binutils)
PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64","hostname":"MacBook-Pro-Sleede-Peng"}' 2.38) #1 SMP PREEMPT_DYNAMIC Thu, 07 Jul 2022 17:18:13 +0000","hostname":"Sylvain-laptop"}'
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: Accept:
@ -145,11 +148,11 @@ http_interactions:
Server: Server:
- nginx - nginx
Date: Date:
- Mon, 13 Sep 2021 11:25:44 GMT - Wed, 20 Jul 2022 15:35:03 GMT
Content-Type: Content-Type:
- application/json - application/json
Content-Length: Content-Length:
- '4259' - '4434'
Connection: Connection:
- keep-alive - keep-alive
Access-Control-Allow-Credentials: Access-Control-Allow-Credentials:
@ -164,25 +167,33 @@ http_interactions:
- '300' - '300'
Cache-Control: Cache-Control:
- no-cache, no-store - no-cache, no-store
Idempotency-Key:
- 0e16450f-e8fa-4565-b41d-fe54b0aa033b
Original-Request:
- req_oqY6Y4FnzGhvIE
Request-Id: Request-Id:
- req_9IAUcJuiq87CeO - req_oqY6Y4FnzGhvIE
Stripe-Should-Retry:
- 'false'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-C-Cost:
- '10'
Strict-Transport-Security: Strict-Transport-Security:
- max-age=31556926; includeSubDomains; preload - max-age=31556926; includeSubDomains; preload
body: body:
encoding: UTF-8 encoding: UTF-8
string: | string: |-
{ {
"id": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "id": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"object": "payment_intent", "object": "payment_intent",
"amount": 3825, "amount": 97410,
"amount_capturable": 0, "amount_capturable": 0,
"amount_received": 3825, "amount_details": {
"tip": {}
},
"amount_received": 97410,
"application": null, "application": null,
"application_fee_amount": null, "application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null, "canceled_at": null,
"cancellation_reason": null, "cancellation_reason": null,
"capture_method": "automatic", "capture_method": "automatic",
@ -190,15 +201,15 @@ http_interactions:
"object": "list", "object": "list",
"data": [ "data": [
{ {
"id": "ch_3JZDIB2sOmf47Nz91buHMX2j", "id": "ch_3LNevR2sOmf47Nz90Mvq9kVm",
"object": "charge", "object": "charge",
"amount": 3825, "amount": 97410,
"amount_captured": 3825, "amount_captured": 97410,
"amount_refunded": 0, "amount_refunded": 0,
"application": null, "application": null,
"application_fee": null, "application_fee": null,
"application_fee_amount": null, "application_fee_amount": null,
"balance_transaction": "txn_3JZDIB2sOmf47Nz9120KuoH9", "balance_transaction": "txn_3LNevR2sOmf47Nz90JS5wwi9",
"billing_details": { "billing_details": {
"address": { "address": {
"city": null, "city": null,
@ -214,34 +225,33 @@ http_interactions:
}, },
"calculated_statement_descriptor": "Stripe", "calculated_statement_descriptor": "Stripe",
"captured": true, "captured": true,
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": null, "description": null,
"destination": null, "destination": null,
"dispute": null, "dispute": null,
"disputed": false, "disputed": false,
"failure_balance_transaction": null,
"failure_code": null, "failure_code": null,
"failure_message": null, "failure_message": null,
"fraud_details": { "fraud_details": {},
},
"invoice": null, "invoice": null,
"livemode": false, "livemode": false,
"metadata": { "metadata": {},
},
"on_behalf_of": null, "on_behalf_of": null,
"order": null, "order": null,
"outcome": { "outcome": {
"network_status": "approved_by_network", "network_status": "approved_by_network",
"reason": null, "reason": null,
"risk_level": "normal", "risk_level": "normal",
"risk_score": 32, "risk_score": 51,
"seller_message": "Payment complete.", "seller_message": "Payment complete.",
"type": "authorized" "type": "authorized"
}, },
"paid": true, "paid": true,
"payment_intent": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "payment_intent": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_details": { "payment_method_details": {
"card": { "card": {
"brand": "visa", "brand": "visa",
@ -252,11 +262,12 @@ http_interactions:
}, },
"country": "US", "country": "US",
"exp_month": 4, "exp_month": 4,
"exp_year": 2022, "exp_year": 2023,
"fingerprint": "o52jybR7bnmNn6AT", "fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit", "funding": "credit",
"installments": null, "installments": null,
"last4": "4242", "last4": "4242",
"mandate": null,
"network": "visa", "network": "visa",
"three_d_secure": null, "three_d_secure": null,
"wallet": null "wallet": null
@ -265,16 +276,14 @@ http_interactions:
}, },
"receipt_email": null, "receipt_email": null,
"receipt_number": null, "receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3JZDIB2sOmf47Nz91buHMX2j/rcpt_KDebb83SAs8TQggfARcBOMotuxQ1Vxj", "receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3LNevR2sOmf47Nz90Mvq9kVm/rcpt_M5qcIvwnjpj7tlCm4ws6NUyPXIeLpSL",
"refunded": false, "refunded": false,
"refunds": { "refunds": {
"object": "list", "object": "list",
"data": [ "data": [],
],
"has_more": false, "has_more": false,
"total_count": 0, "total_count": 0,
"url": "/v1/charges/ch_3JZDIB2sOmf47Nz91buHMX2j/refunds" "url": "/v1/charges/ch_3LNevR2sOmf47Nz90Mvq9kVm/refunds"
}, },
"review": null, "review": null,
"shipping": null, "shipping": null,
@ -289,25 +298,25 @@ http_interactions:
], ],
"has_more": false, "has_more": false,
"total_count": 1, "total_count": 1,
"url": "/v1/charges?payment_intent=pi_3JZDIB2sOmf47Nz91NCWzYP6" "url": "/v1/charges?payment_intent=pi_3LNevR2sOmf47Nz90G2zL7T3"
}, },
"client_secret": "pi_3JZDIB2sOmf47Nz91NCWzYP6_secret_oIY9Vwdf4coECaCgx0zgmkYMF", "client_secret": "pi_3LNevR2sOmf47Nz90G2zL7T3_secret_EqcVW2yHHRtYlWJG4Qcx0qC1i",
"confirmation_method": "manual", "confirmation_method": "manual",
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": null, "description": null,
"invoice": null, "invoice": null,
"last_payment_error": null, "last_payment_error": null,
"livemode": false, "livemode": false,
"metadata": { "metadata": {},
},
"next_action": null, "next_action": null,
"on_behalf_of": null, "on_behalf_of": null,
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_options": { "payment_method_options": {
"card": { "card": {
"installments": null, "installments": null,
"mandate_options": null,
"network": null, "network": null,
"request_three_d_secure": "automatic" "request_three_d_secure": "automatic"
} }
@ -315,6 +324,7 @@ http_interactions:
"payment_method_types": [ "payment_method_types": [
"card" "card"
], ],
"processing": null,
"receipt_email": null, "receipt_email": null,
"review": null, "review": null,
"setup_future_usage": null, "setup_future_usage": null,
@ -326,13 +336,13 @@ http_interactions:
"transfer_data": null, "transfer_data": null,
"transfer_group": null "transfer_group": null
} }
recorded_at: Mon, 13 Sep 2021 11:25:44 GMT recorded_at: Wed, 20 Jul 2022 15:35:03 GMT
- request: - request:
method: post method: post
uri: https://api.stripe.com/v1/payment_intents/pi_3JZDIB2sOmf47Nz91NCWzYP6 uri: https://api.stripe.com/v1/payment_intents/pi_3LNevR2sOmf47Nz90G2zL7T3
body: body:
encoding: UTF-8 encoding: UTF-8
string: description=Invoice+reference%3A+2109001%2FVL string: description=Invoice+reference%3A+2207001%2FVL
headers: headers:
User-Agent: User-Agent:
- Stripe/v1 RubyBindings/5.29.0 - Stripe/v1 RubyBindings/5.29.0
@ -341,13 +351,13 @@ http_interactions:
Content-Type: Content-Type:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
X-Stripe-Client-Telemetry: X-Stripe-Client-Telemetry:
- '{"last_request_metrics":{"request_id":"req_9IAUcJuiq87CeO","request_duration_ms":1477}}' - '{"last_request_metrics":{"request_id":"req_oqY6Y4FnzGhvIE","request_duration_ms":2680}}'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-Client-User-Agent: X-Stripe-Client-User-Agent:
- '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.3 p62 (2019-04-16)","platform":"x86_64-darwin18","engine":"ruby","publisher":"stripe","uname":"Darwin - '{"bindings_version":"5.29.0","lang":"ruby","lang_version":"2.6.10 p210 (2022-04-12)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
MacBook-Pro-Sleede-Peng 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 version 5.18.10-arch1-1 (linux@archlinux) (gcc (GCC) 12.1.0, GNU ld (GNU Binutils)
PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64","hostname":"MacBook-Pro-Sleede-Peng"}' 2.38) #1 SMP PREEMPT_DYNAMIC Thu, 07 Jul 2022 17:18:13 +0000","hostname":"Sylvain-laptop"}'
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: Accept:
@ -360,11 +370,11 @@ http_interactions:
Server: Server:
- nginx - nginx
Date: Date:
- Mon, 13 Sep 2021 11:25:44 GMT - Wed, 20 Jul 2022 15:35:04 GMT
Content-Type: Content-Type:
- application/json - application/json
Content-Length: Content-Length:
- '4286' - '4500'
Connection: Connection:
- keep-alive - keep-alive
Access-Control-Allow-Credentials: Access-Control-Allow-Credentials:
@ -379,25 +389,34 @@ http_interactions:
- '300' - '300'
Cache-Control: Cache-Control:
- no-cache, no-store - no-cache, no-store
Idempotency-Key:
- 650ff0fe-0d75-4a3d-9942-d6403534a323
Original-Request:
- req_g3z6KJauuKa7Ob
Request-Id: Request-Id:
- req_TAv2FNDcsNhZ0x - req_g3z6KJauuKa7Ob
Stripe-Should-Retry:
- 'false'
Stripe-Version: Stripe-Version:
- '2019-08-14' - '2019-08-14'
X-Stripe-C-Cost:
- '0'
Strict-Transport-Security: Strict-Transport-Security:
- max-age=31556926; includeSubDomains; preload - max-age=31556926; includeSubDomains; preload
body: body:
encoding: UTF-8 encoding: UTF-8
string: | string: |
{ {
"id": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "id": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"object": "payment_intent", "object": "payment_intent",
"amount": 3825, "amount": 97410,
"amount_capturable": 0, "amount_capturable": 0,
"amount_received": 3825, "amount_details": {
"tip": {
}
},
"amount_received": 97410,
"application": null, "application": null,
"application_fee_amount": null, "application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null, "canceled_at": null,
"cancellation_reason": null, "cancellation_reason": null,
"capture_method": "automatic", "capture_method": "automatic",
@ -405,15 +424,15 @@ http_interactions:
"object": "list", "object": "list",
"data": [ "data": [
{ {
"id": "ch_3JZDIB2sOmf47Nz91buHMX2j", "id": "ch_3LNevR2sOmf47Nz90Mvq9kVm",
"object": "charge", "object": "charge",
"amount": 3825, "amount": 97410,
"amount_captured": 3825, "amount_captured": 97410,
"amount_refunded": 0, "amount_refunded": 0,
"application": null, "application": null,
"application_fee": null, "application_fee": null,
"application_fee_amount": null, "application_fee_amount": null,
"balance_transaction": "txn_3JZDIB2sOmf47Nz9120KuoH9", "balance_transaction": "txn_3LNevR2sOmf47Nz90JS5wwi9",
"billing_details": { "billing_details": {
"address": { "address": {
"city": null, "city": null,
@ -429,13 +448,14 @@ http_interactions:
}, },
"calculated_statement_descriptor": "Stripe", "calculated_statement_descriptor": "Stripe",
"captured": true, "captured": true,
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": null, "description": null,
"destination": null, "destination": null,
"dispute": null, "dispute": null,
"disputed": false, "disputed": false,
"failure_balance_transaction": null,
"failure_code": null, "failure_code": null,
"failure_message": null, "failure_message": null,
"fraud_details": { "fraud_details": {
@ -450,13 +470,13 @@ http_interactions:
"network_status": "approved_by_network", "network_status": "approved_by_network",
"reason": null, "reason": null,
"risk_level": "normal", "risk_level": "normal",
"risk_score": 32, "risk_score": 51,
"seller_message": "Payment complete.", "seller_message": "Payment complete.",
"type": "authorized" "type": "authorized"
}, },
"paid": true, "paid": true,
"payment_intent": "pi_3JZDIB2sOmf47Nz91NCWzYP6", "payment_intent": "pi_3LNevR2sOmf47Nz90G2zL7T3",
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_details": { "payment_method_details": {
"card": { "card": {
"brand": "visa", "brand": "visa",
@ -467,11 +487,12 @@ http_interactions:
}, },
"country": "US", "country": "US",
"exp_month": 4, "exp_month": 4,
"exp_year": 2022, "exp_year": 2023,
"fingerprint": "o52jybR7bnmNn6AT", "fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit", "funding": "credit",
"installments": null, "installments": null,
"last4": "4242", "last4": "4242",
"mandate": null,
"network": "visa", "network": "visa",
"three_d_secure": null, "three_d_secure": null,
"wallet": null "wallet": null
@ -480,7 +501,7 @@ http_interactions:
}, },
"receipt_email": null, "receipt_email": null,
"receipt_number": null, "receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3JZDIB2sOmf47Nz91buHMX2j/rcpt_KDebb83SAs8TQggfARcBOMotuxQ1Vxj", "receipt_url": "https://pay.stripe.com/receipts/acct_103rE62sOmf47Nz9/ch_3LNevR2sOmf47Nz90Mvq9kVm/rcpt_M5qcIvwnjpj7tlCm4ws6NUyPXIeLpSL",
"refunded": false, "refunded": false,
"refunds": { "refunds": {
"object": "list", "object": "list",
@ -489,7 +510,7 @@ http_interactions:
], ],
"has_more": false, "has_more": false,
"total_count": 0, "total_count": 0,
"url": "/v1/charges/ch_3JZDIB2sOmf47Nz91buHMX2j/refunds" "url": "/v1/charges/ch_3LNevR2sOmf47Nz90Mvq9kVm/refunds"
}, },
"review": null, "review": null,
"shipping": null, "shipping": null,
@ -504,14 +525,14 @@ http_interactions:
], ],
"has_more": false, "has_more": false,
"total_count": 1, "total_count": 1,
"url": "/v1/charges?payment_intent=pi_3JZDIB2sOmf47Nz91NCWzYP6" "url": "/v1/charges?payment_intent=pi_3LNevR2sOmf47Nz90G2zL7T3"
}, },
"client_secret": "pi_3JZDIB2sOmf47Nz91NCWzYP6_secret_oIY9Vwdf4coECaCgx0zgmkYMF", "client_secret": "pi_3LNevR2sOmf47Nz90G2zL7T3_secret_EqcVW2yHHRtYlWJG4Qcx0qC1i",
"confirmation_method": "manual", "confirmation_method": "manual",
"created": 1631532343, "created": 1658331301,
"currency": "usd", "currency": "usd",
"customer": "cus_8Di1wjdVktv5kt", "customer": "cus_8Di1wjdVktv5kt",
"description": "Invoice reference: 2109001/VL", "description": "Invoice reference: 2207001/VL",
"invoice": null, "invoice": null,
"last_payment_error": null, "last_payment_error": null,
"livemode": false, "livemode": false,
@ -519,10 +540,11 @@ http_interactions:
}, },
"next_action": null, "next_action": null,
"on_behalf_of": null, "on_behalf_of": null,
"payment_method": "pm_1JZDIA2sOmf47Nz9rl1nigpQ", "payment_method": "pm_1LNevQ2sOmf47Nz9khvl8vC0",
"payment_method_options": { "payment_method_options": {
"card": { "card": {
"installments": null, "installments": null,
"mandate_options": null,
"network": null, "network": null,
"request_three_d_secure": "automatic" "request_three_d_secure": "automatic"
} }
@ -530,6 +552,7 @@ http_interactions:
"payment_method_types": [ "payment_method_types": [
"card" "card"
], ],
"processing": null,
"receipt_email": null, "receipt_email": null,
"review": null, "review": null,
"setup_future_usage": null, "setup_future_usage": null,
@ -541,5 +564,5 @@ http_interactions:
"transfer_data": null, "transfer_data": null,
"transfer_group": null "transfer_group": null
} }
recorded_at: Mon, 13 Sep 2021 11:25:44 GMT recorded_at: Wed, 20 Jul 2022 15:35:04 GMT
recorded_with: VCR 6.0.0 recorded_with: VCR 6.0.0