• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sleede / fab-manager / #98

pending completion
#98

push

coveralls-ruby

sylvainbx
Merge branch 'dev' for release 5.7.0

1368 of 1368 new or added lines in 161 files covered. (100.0%)

7383 of 12030 relevant lines covered (61.37%)

14.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.33
/app/controllers/api/stripe_controller.rb
1
# frozen_string_literal: true
2

3
# API Controller for handling the payments process in the front-end, using the Stripe gateway
4
class API::StripeController < API::PaymentsController
1✔
5
  require 'stripe/helper'
1✔
6
  require 'stripe/service'
1✔
7

8
  before_action :check_keys, except: :online_payment_status
1✔
9

10
  ##
11
  # Client requests to confirm a card payment will ask this endpoint.
12
  # It will check for the need of a strong customer authentication (SCA) to confirm the payment or confirm that the payment
13
  # was successfully made. After the payment was made, the reservation/subscription will be created
14
  ##
15
  def confirm_payment
1✔
16
    render(json: { error: 'Bad gateway or online payment is disabled' }, status: :bad_gateway) and return unless Stripe::Helper.enabled?
24✔
17

18
    intent = nil # stripe's payment intent
24✔
19
    res = nil # json of the API answer
24✔
20

21
    cart = shopping_cart
24✔
22
    render json: { error: cart.errors }, status: :unprocessable_entity and return unless cart.valid?
24✔
23

24
    begin
25
      amount = debit_amount(cart) # will contains the amount and the details of each invoice lines
19✔
26
      if params[:payment_method_id].present?
19✔
27
        # Create the PaymentIntent
28
        intent = Stripe::PaymentIntent.create(
19✔
29
          {
30
            payment_method: params[:payment_method_id],
31
            amount: Stripe::Service.new.stripe_amount(amount[:amount]),
32
            currency: Setting.get('stripe_currency'),
33
            confirmation_method: 'manual',
34
            confirm: true,
35
            customer: cart.customer.payment_gateway_object.gateway_object_id
36
          }, { api_key: Setting.get('stripe_secret_key') }
37
        )
38
      elsif params[:payment_intent_id].present?
×
39
        intent = Stripe::PaymentIntent.confirm(params[:payment_intent_id], {}, { api_key: Setting.get('stripe_secret_key') })
×
40
      end
41
    rescue Stripe::CardError => e
42
      # Display error on client
43
      res = { status: 200, json: { error: e.message } }
2✔
44
    rescue InvalidCouponError
45
      res = { json: { coupon_code: 'wrong coupon code or expired' }, status: :unprocessable_entity }
×
46
    rescue InvalidGroupError
47
      res = { json: { plan_id: 'this plan is not compatible with your current group' }, status: :unprocessable_entity }
×
48
    end
49

50
    res = on_payment_success(intent, cart) if intent&.status == 'succeeded'
19✔
51

52
    render generate_payment_response(intent, 'payment', res)
19✔
53
  end
54

55
  def online_payment_status
1✔
56
    authorize :payment
×
57

58
    key = Setting.get('stripe_secret_key')
×
59
    render json: { status: false } and return unless key&.present?
×
60

61
    charges = Stripe::Charge.list({ limit: 1 }, { api_key: key })
×
62
    render json: { status: charges.data.length.positive? }
×
63
  rescue Stripe::AuthenticationError
64
    render json: { status: false }
×
65
  end
66

67
  def setup_intent
1✔
68
    user = User.find(params[:user_id])
×
69
    key = Setting.get('stripe_secret_key')
×
70
    @intent = Stripe::SetupIntent.create({ customer: user.payment_gateway_object.gateway_object_id }, { api_key: key })
×
71
    render json: { id: @intent.id, client_secret: @intent.client_secret }
×
72
  end
73

74
  def setup_subscription
1✔
75
    cart = shopping_cart
5✔
76
    render json: { error: cart.errors }, status: :unprocessable_entity and return unless cart.valid?
5✔
77

78
    service = Stripe::Service.new
5✔
79
    method = service.attach_method_as_default(
5✔
80
      params[:payment_method_id],
81
      cart.customer.payment_gateway_object.gateway_object_id
82
    )
83

84
    stp_subscription = service.subscribe(method.id, cart)
5✔
85

86
    res = on_payment_success(stp_subscription, cart) if %w[active not_started].include?(stp_subscription&.status)
5✔
87
    render generate_payment_response(stp_subscription.try(:latest_invoice)&.payment_intent, 'subscription', res, stp_subscription.id)
5✔
88
  end
89

90
  def confirm_subscription
1✔
91
    key = Setting.get('stripe_secret_key')
1✔
92
    subscription = Stripe::Subscription.retrieve(
1✔
93
      { id: params[:subscription_id], expand: %w[latest_invoice.payment_intent] },
94
      { api_key: key }
95
    )
96

97
    cart = shopping_cart
1✔
98
    if subscription&.status == 'active'
1✔
99
      res = on_payment_success(subscription, cart)
×
100
      render generate_payment_response(subscription.latest_invoice.payment_intent, 'subscription', res)
×
101
    else
102
      render generate_payment_response(subscription.latest_invoice.payment_intent, 'subscription', nil, subscription.id)
1✔
103
    end
104
  rescue Stripe::InvalidRequestError => e
105
    render json: e, status: :unprocessable_entity
×
106
  end
107

108
  def update_card
1✔
109
    user = User.find(params[:user_id])
×
110
    key = Setting.get('stripe_secret_key')
×
111
    Stripe::Customer.update(user.payment_gateway_object.gateway_object_id,
×
112
                            { invoice_settings: { default_payment_method: params[:payment_method_id] } },
113
                            { api_key: key })
114
    if params[:payment_schedule_id]
×
115
      schedule = PaymentSchedule.find(params[:payment_schedule_id])
×
116
      subscription = schedule.gateway_subscription.retrieve
×
117
      Stripe::Subscription.update(subscription.id, { default_payment_method: params[:payment_method_id] }, { api_key: key })
×
118
    end
119
    render json: { updated: true }, status: :ok
×
120
  rescue Stripe::StripeError => e
121
    render json: { updated: false, error: e }, status: :unprocessable_entity
×
122
  end
123

124
  private
1✔
125

126
  def post_save(intent_id, intent_type, payment_document)
1✔
127
    return unless intent_type == 'Stripe::PaymentIntent'
21✔
128

129
    Stripe::PaymentIntent.update(
17✔
130
      intent_id,
131
      { description: "#{payment_document.class.name} reference: #{payment_document.reference}" },
132
      { api_key: Setting.get('stripe_secret_key') }
133
    )
134
  end
135

136
  def on_payment_success(intent, cart)
1✔
137
    super(intent.id, intent.class.name, cart)
21✔
138
  end
139

140
  def generate_payment_response(intent, type, res = nil, stp_subscription_id = nil)
1✔
141
    return res unless res.nil?
25✔
142

143
    if intent.status == 'requires_action' && intent.next_action.type == 'use_stripe_sdk'
2✔
144
      # Tell the client to handle the action
145
      {
146
        status: 200,
2✔
147
        json: {
148
          requires_action: true,
149
          payment_intent_client_secret: intent.client_secret,
150
          type: type,
151
          subscription_id: stp_subscription_id
152
        }
153
      }
154
    elsif intent.status == 'succeeded'
×
155
      # The payment didn't need any additional actions and is completed!
156
      # Handle post-payment fulfillment
157
      { status: 200, json: { success: true } }
×
158
    else
159
      # Invalid status
160
      { status: 500, json: { error: 'Invalid PaymentIntent status' } }
×
161
    end
162
  end
163

164
  def check_keys
1✔
165
    key = Setting.get('stripe_secret_key')
30✔
166
    raise Stripe::StripeError, 'Using live keys in development mode' if key&.match(/^sk_live_/) && Rails.env.development?
30✔
167
  end
168
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc