2016-07-01 9 views
1

Ich erhielt eine E-Mail von einem Kunden sagen, dass sie nie ihr Produkt nach der Zahlung auf Bitcoin/Stripe erhalten haben. Das Problem ist, dass ich keinen Weg finden konnte, Bitcoin in einer Sandbox gründlich zu testen, also bin ich mir nicht sicher, ob meine Implementierung so funktioniert wie sie sein sollte. Die Sandbox füllt den Empfänger automatisch, so dass ich die Zahlungsbenachrichtigung erhalte und alles in Ordnung ist. Aber wenn ich live laufe, bin ich mir nicht sicher, ob mein Polling korrekt funktioniert. Ich habe alle meinen relevanten Code unten veröffentlicht, kann jemand irgendwelche Fehler im Code sehen?benutzerdefinierte Bitcoin Stripe Rails Zahlungen

* mein Speicher läuft Rubin (2.3.1p112) auf Schienen (4.2.6)

meine payment_bitcoin.html.erb

<%= render :partial => "offsite_checkout_summary" %> 

<p>Your license key, along with your purchase receipt, will be sent to <strong><%= @order.licensee_name %></strong> at <strong><%= @order.email %></strong> once payment has been confirmed.</p> 

<div id="extra_purchase_notes"> 
    <em><strong>Note:</strong> The bitcoin link and price provided is only valid for <span id="countdown_time">10:00</span> minutes.</em> 
</div> 

<div class="d cl"></div> 
<%= render :partial => "items_checkout_summary", :locals => { order: @order } %> 
    <div id="bitcoin_payment_address"> 
    <script src="https://js.stripe.com/v2/stripe.js"></script> 
    <script type="text/javascript"> 
     Stripe.setPublishableKey('<%= $STRIPE_PREFS['stripe_publishable_key'] %>'); 
     function populateBitcoinCheckout(status, response) { 
     if (status === 200) { 
      document.getElementById("bitcoin_total").innerHTML = " (" + response.bitcoin_amount/100000000 + " BTC)"; 
      document.getElementById("bitcoin_payment_string").innerHTML = 'Please send: <strong>' + response.bitcoin_amount/100000000 + ' BTC</strong> to <strong>' + '<a href="' + response.bitcoin_uri + '&label=Software+Purchase">' + response.inbound_address + '</a></strong>'; 
      document.getElementById("btc-button").href = response.bitcoin_uri + '&label=Software+Purchase'; 

        //poll reciever 
        Stripe.bitcoinReceiver.pollReceiver(response.id, filledReceiverHandler(response)); 

      //configure timer 
      function startTimer(duration, countdown) { 
       var timer = duration,minutes,seconds; 
       var t = setInterval(function() { 
        minutes = parseInt(timer/60, 10) 
        seconds = parseInt(timer % 60, 10); 

        minutes = minutes < 10 ? "0" + minutes : minutes; 
        seconds = seconds < 10 ? "0" + seconds : seconds; 

        countdown.textContent = minutes + ":" + seconds; 

        if (--timer < 0) { 
         clearInterval(t); 
         document.getElementById("bitcoin_total").innerHTML = ""; 
         document.getElementById("bitcoin_payment_string").innerHTML = ""; 
         document.getElementById("bitcoin_button_text").innerHTML = "Refresh Order" 
         document.getElementById("btc-button").href = "javascript:history.back()" 
         document.getElementById("extra_purchase_notes").innerHTML = "<em><strong>Oops...</strong> This order has expired, use the Refresh Order button to retry.</em>" 
         Stripe.bitcoinReceiver.cancelReceiverPoll(response.id); 
        } 
       }, 1000); 
      } 

      //start timer 
      var countdown = document.getElementById('countdown_time'); 
      startTimer(600, countdown); 

     } else { 
      document.getElementById("bitcoin_uri_string").innerHTML = JSON.stringify(response); 
      Stripe.bitcoinReceiver.cancelReceiverPoll(response.id); 
     } 
     } 

     Stripe.bitcoinReceiver.createReceiver({ 
     amount: "<%= (@order.total * 100).round %>", 
     currency: 'usd', 
     description: 'Software purchase', 
     email: "<%= @order.email %>" 
     }, populateBitcoinCheckout); 

      function filledReceiverHandler(response) 
      { 
       if (response.filled === true) { 
        function post(path, parameters) { 
       var form = $('<form></form>'); 
       form.attr("method", "post"); 
       form.attr("action", path); 

       $.each(parameters, function(key, value) { 
      if (typeof value == 'object' || typeof value == 'array'){ 
       $.each(value, function(subkey, subvalue) { 
        var field = $('<input />'); 
        field.attr("type", "hidden"); 
        field.attr("name", key+'[]'); 
        field.attr("value", subvalue); 
        form.append(field); 
       }); 
      } else { 
       var field = $('<input />'); 
       field.attr("type", "hidden"); 
       field.attr("name", key); 
       field.attr("value", value); 
       form.append(field); 
      } 
      }); 
      $(document.body).append(form); 
      form.submit(); 
      } 
       post('purchase_bitcoin', response); 
      } 
     } 
    </script> 
    </div> 
</div> 
<p id="bitcoin_payment_string"></p> 
<div class="d"></div> 

<p style="text-align: right;"> 
    <a id="btc-button"><button class="bitcoin-button" style="visibility: visible;"><span id="bitcoin_button_text">Pay with Bitcoin</span></button></a> 
</p> 

und die entsprechende Controller-Methode:

#bitcoin purchase 
    def purchase_bitcoin 
    require 'stripe' 
    if check_if_order_exists() == false 
     if session[:failure_reason] != nil 
     render :action => 'failed' 
     return 
     end 
     redirect_to :action => 'index' 
     return 
    end 

    if session[:item_number] == nil 
     flash[:notice] = 'Nothing to purchase' 
     redirect_to :action => 'index' 
     return 
    end 

    #create the order 
    generateNewOrder("Bitcoin") 

    #total in cents 
    the_total = @order.total.to_f 
    the_total_cents = (the_total*100).to_i 

    Stripe.api_key = $STRIPE_PREFS['stripe_secret'] 

    #add order details 
    @order.transaction_number = params[:id] 

    # Create the charge on Stripe's servers - this will charge the user's card 
    session[:coin_total] = (params[:bitcoin_amount].to_f/100000000).to_s 

    charge = Stripe::Charge.create(
     :amount => params[:amount], 
     :currency => params[:currency], 
     :source => params[:id], 
     :description => 'Software purchase' 
    ) 

    #re-add completed order details 
    the_id = charge["id"] 
    @order.transaction_number = the_id 
    @order.comment = 'Total = ' + (params[:bitcoin_amount].to_f/100000000).to_s + 'BTC; payment address = ' + params[:inbound_address] 

    @order.status = 'C' 
    @order.finish_and_save() 
    session[:order_id] = @order.id 

    #send license 
    Thread.new do 
     OrderMailer.thankyou(@order).deliver 
    end 

    #logger.info session.inspect 
    render :action => 'thankyou_bitcoin' 
    end 

Antwort

0

ich mehr Revisionen gemacht, und eigentlich alle Logik Polling entfernt von meiner .erb, anstatt einen Web-Haken zu verwenden. https://stripe.com/docs/webhooks

require 'json' 
require 'stripe' 

class Store::BitcoinController < ApplicationController 

    def payment_recieved 
    type = params[:type] 
    data = params[:data] 

    if (type.blank? || type != "bitcoin.receiver.filled" || data.blank?) 
     logger.warn("Got request to Bitcoin IPN with invalid receiver email from #{request.remote_addr || request.remote_ip}") 
     render :nothing => true, :status => 200 
     return 
    end 

..process order here... 

hoffentlich wird dies einige andere mit den gleichen Problemen helfen. :)

0

Ich fügte schließlich die Abfragelogik in den Timer ein, und das scheint zu funktionieren .... obwohl es in den Dokumenten impliziert wurde, dass ich nicht manuell abfragen musste? zumindest das ist, wie ich es gelesen ...

hier ist meine komplette geänderte payment_bitcoin.html.erb für alle anderen Probleme auftreten dieses

arbeiten immer
<%= render :partial => "offsite_checkout_summary" %> 

<p>Your license key, along with your purchase receipt, will be sent to <strong><%= @order.licensee_name %></strong> at <strong><%= @order.email %></strong> once payment has been confirmed.</p> 

<div id="extra_purchase_notes"> 
    <em><strong>Note:</strong> The bitcoin link and price provided is only valid for <span id="countdown_time">10:00</span> minutes.</em> 
</div> 

<div class="d cl"></div> 
<%= render :partial => "items_checkout_summary", :locals => { order: @order } %> 
    <div id="bitcoin_payment_address"> 
    <script src="https://js.stripe.com/v2/stripe.js"></script> 
    <script type="text/javascript"> 
     Stripe.setPublishableKey('<%= $STRIPE_PREFS['stripe_publishable_key'] %>'); 
     function populateBitcoinCheckout(status, response) { 
     if (status === 200) { 
      document.getElementById("bitcoin_total").innerHTML = " (" + response.bitcoin_amount/100000000 + " BTC)"; 
      document.getElementById("bitcoin_payment_string").innerHTML = 'Please send: <strong>' + response.bitcoin_amount/100000000 + ' BTC</strong> to <strong>' + '<a href="' + response.bitcoin_uri + '&label=Software+Purchase">' + response.inbound_address + '</a></strong>'; 
      document.getElementById("btc-button").href = response.bitcoin_uri + '&label=Software+Purchase'; 

      //configure timer 
      function startTimer(duration, countdown) { 
       var timer = duration,minutes,seconds; 
       var t = setInterval(function() { 

        minutes = parseInt(timer/60, 10) 
        seconds = parseInt(timer % 60, 10); 

        minutes = minutes < 10 ? "0" + minutes : minutes; 
        seconds = seconds < 10 ? "0" + seconds : seconds; 

        //poll reciever 
        Stripe.bitcoinReceiver.pollReceiver(response.id, filledReceiverHandler(response)); 

        countdown.textContent = minutes + ":" + seconds; 

        if (--timer < 0) { 
         clearInterval(t); 
         document.getElementById("bitcoin_total").innerHTML = ""; 
         document.getElementById("bitcoin_payment_string").innerHTML = ""; 
         document.getElementById("bitcoin_button_text").innerHTML = "Refresh Order" 
         document.getElementById("btc-button").href = "javascript:history.back()" 
         document.getElementById("extra_purchase_notes").innerHTML = "<em><strong>Oops...</strong> This order has expired, use the Refresh Order button to retry.</em>" 
         Stripe.bitcoinReceiver.cancelReceiverPoll(response.id); 
        } 
       }, 1000); 
      } 

      //start timer 
      var countdown = document.getElementById('countdown_time'); 
      startTimer(600, countdown); 

     } else { 
      document.getElementById("bitcoin_uri_string").innerHTML = JSON.stringify(response); 
     } 
     } 

     Stripe.bitcoinReceiver.createReceiver({ 
     amount: "<%= (@order.total * 100).round %>", 
     currency: 'usd', 
     description: 'Software purchase', 
     email: "<%= @order.email %>" 
     }, populateBitcoinCheckout); 

      function filledReceiverHandler(response) 
      { 
       if (response.filled === true) { 
        function post(path, parameters) { 
       var form = $('<form></form>'); 
       form.attr("method", "post"); 
       form.attr("action", path); 

       $.each(parameters, function(key, value) { 
      if (typeof value == 'object' || typeof value == 'array'){ 
       $.each(value, function(subkey, subvalue) { 
        var field = $('<input />'); 
        field.attr("type", "hidden"); 
        field.attr("name", key+'[]'); 
        field.attr("value", subvalue); 
        form.append(field); 
       }); 
      } else { 
       var field = $('<input />'); 
       field.attr("type", "hidden"); 
       field.attr("name", key); 
       field.attr("value", value); 
       form.append(field); 
      } 
      }); 
      $(document.body).append(form); 
      form.submit(); 
      } 
       post('purchase_bitcoin', response); 
      } 
     } 
    </script> 
    </div> 
</div> 
<p id="bitcoin_payment_string"></p> 
<div class="d"></div> 

<p style="text-align: right;"> 
    <a id="btc-button"><button class="bitcoin-button" style="visibility: visible;"><span id="bitcoin_button_text">Pay with Bitcoin</span></button></a> 
</p>