130 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| class Contributions::DonationsController < ApplicationController
 | |
|   include BtcpayHelper
 | |
| 
 | |
|   before_action :authenticate_user!
 | |
|   before_action :set_donation_methods, only: [:index, :create]
 | |
|   before_action :require_donation_method_enabled, only: [:create]
 | |
|   before_action :validate_donation_params, only: [:create]
 | |
|   before_action :set_donation, only: [:confirm_btcpay]
 | |
| 
 | |
|   # GET /contributions/donations
 | |
|   def index
 | |
|     @current_section = :contributions
 | |
|     @donations_completed = current_user.donations.completed.order('paid_at desc')
 | |
|     @donations_pending = current_user.donations.processing.order('created_at desc')
 | |
| 
 | |
|     if Setting.lndhub_enabled?
 | |
|       begin
 | |
|         lndhub_authenticate
 | |
|         lndhub_fetch_balance
 | |
|       rescue
 | |
|         @balance = 0
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   # POST /contributions/donations
 | |
|   def create
 | |
|     if params[:currency] == "sats"
 | |
|       fiat_amount = nil
 | |
|       fiat_currency = nil
 | |
|       amount_sats = params[:amount]
 | |
|     else
 | |
|       fiat_amount = params[:amount].to_i
 | |
|       fiat_currency = params[:currency]
 | |
|       amount_sats = nil
 | |
|     end
 | |
| 
 | |
|     @donation = current_user.donations.create!(
 | |
|       donation_method: params[:donation_method],
 | |
|       payment_method: nil,
 | |
|       paid_at: nil,
 | |
|       amount_sats: amount_sats,
 | |
|       fiat_amount: (fiat_amount.nil? ? nil : fiat_amount * 100), # store in cents
 | |
|       fiat_currency: fiat_currency,
 | |
|       public_name: params[:public_name]
 | |
|     )
 | |
| 
 | |
|     case params[:donation_method]
 | |
|     when "btcpay"
 | |
|       res = BtcpayManager::CreateInvoice.call(
 | |
|         amount: fiat_amount || (amount_sats.to_f / 100000000),
 | |
|         currency: fiat_currency || "BTC",
 | |
|         redirect_url: confirm_btcpay_contributions_donation_url(@donation)
 | |
|       )
 | |
| 
 | |
|       @donation.update! btcpay_invoice_id: res["id"]
 | |
| 
 | |
|       redirect_to btcpay_checkout_url(res["id"]), allow_other_host: true
 | |
|     else
 | |
|       redirect_to contributions_donations_url, flash: {
 | |
|         error: "Donation method currently not available"
 | |
|       }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def confirm_btcpay
 | |
|     redirect_to contributions_donations_url and return if @donation.completed?
 | |
| 
 | |
|     invoice = BtcpayManager::FetchInvoice.call(invoice_id: @donation.btcpay_invoice_id)
 | |
| 
 | |
|     if @donation.amount_sats.present?
 | |
|       # TODO make default fiat currency configurable and/or determine from user's
 | |
|       # i18n browser settings
 | |
|       @donation.fiat_currency = "EUR"
 | |
|       exchange_rate = BtcpayManager::FetchExchangeRate.call(fiat_currency: @donation.fiat_currency)
 | |
|       @donation.fiat_amount = (((@donation.amount_sats.to_f / 100000000) * exchange_rate) * 100).to_i
 | |
|     else
 | |
|       amt_str = invoice["paymentMethods"].first["amount"]
 | |
|       @donation.amount_sats = amt_str.tr(".","").sub(/0*$/, "").to_i
 | |
|     end
 | |
| 
 | |
|     case invoice["status"]
 | |
|     when "Settled"
 | |
|       @donation.paid_at = DateTime.now
 | |
|       @donation.payment_status = "settled"
 | |
|       @donation.save!
 | |
|       flash_message = { success: "Thank you!" }
 | |
|     when "Processing"
 | |
|       unless @donation.processing?
 | |
|         @donation.payment_status = "processing"
 | |
|         @donation.save!
 | |
|         flash_message = { success: "Thank you! We will send you an email when the payment is confirmed." }
 | |
|         BtcpayCheckDonationJob.set(wait: 20.seconds).perform_later(@donation)
 | |
|       end
 | |
|     when "Expired"
 | |
|       flash_message = { warning: "The payment request for this donation has expired" }
 | |
|     else
 | |
|       flash_message = { warning: "Could not determine status of payment" }
 | |
|     end
 | |
| 
 | |
|     redirect_to contributions_donations_url, flash: flash_message
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|     def set_donation
 | |
|       @donation = current_user.donations.find_by(id: params[:id])
 | |
|       http_status :not_found unless @donation.present?
 | |
|     end
 | |
| 
 | |
|     def set_donation_methods
 | |
|       @donation_methods = []
 | |
|       @donation_methods.push :btcpay if Setting.btcpay_enabled?
 | |
|       @donation_methods.push :lndhub if Setting.lndhub_enabled?
 | |
|       @donation_methods.push :opencollective if Setting.opencollective_enabled?
 | |
|     end
 | |
| 
 | |
|     def require_donation_method_enabled
 | |
|       http_status :forbidden unless @donation_methods.include?(
 | |
|         params[:donation_method].to_sym
 | |
|       )
 | |
|     end
 | |
| 
 | |
|     def validate_donation_params
 | |
|       if !%w[EUR USD sats].include?(params[:currency]) || (params[:amount].to_i <= 0)
 | |
|         http_status :unprocessable_entity
 | |
|       end
 | |
|     end
 | |
| end
 |