stripe docs address ruby-on-rails ruby subscription stripe-payments

ruby on rails - docs - Cambiar información de la tarjeta de crédito(banda)



stripe checkout docs (6)

2015-02-18 Las tarjetas y los atributos de default_card ya no se devuelven a los clientes. Ahora deberías usar fuentes y default_source respectivamente. Los webhooks customer.card. * Y customer.bank_account. * Ahora se denominan customer.source. *. Si solo tiene tarjetas adjuntas a los clientes (a diferencia de las fuentes de pago de otros tipos), puede utilizar los nuevos atributos exactamente como lo haría con los antiguos. Si tiene fuentes de pago de varios tipos, entonces la lista de fuentes contiene objetos heterogéneos y puede verificar el atributo de objeto de cada fuente para determinar su formato. Las versiones de API más antiguas devuelven los atributos nuevos y antiguos.

Finalmente, descubrí cómo implementar Stripes Monthly Billing usando este tutorial. http://railscasts.com/episodes/288-billing-with-stripe

Hasta ahora, un usuario puede crear y eliminar sus suscripciones con Stripe.

Pero, ¿cómo puede un usuario cambiar su información de tarjeta de crédito una vez que ha creado una suscripción?

Este es mi código con comentarios y preguntas. Por favor, ayuda a los nuevos rieles. :)

CONTROLADOR

class SubscriptionsController < ApplicationController def new plan = Plan.find(params[:plan_id]) @subscription = plan.subscriptions.build @subscription.user_id = current_user.id end def create @subscription = Subscription.new(params[:subscription]) if @subscription.save_with_payment redirect_to @subscription, :notice => "Thank you for subscribing!" else render :new end end def update @subscription = current_user.subscription if @subscription.save redirect_to edit_subscription_path, :success => ''Updated Card.'' else flash.alert = ''Unable to update card.'' render :edit end end end

Los modelos

class Subscription < ActiveRecord::Base attr_accessible :plan_id, :user_id, :email, :stripe_customer_token, :last_4_digits, :card_token, :card_name, :exp_month, :exp_year, :stripe_card_token attr_accessor :stripe_card_token belongs_to :plan belongs_to :user def save_with_payment if valid? save_with_stripe_payment end end def save_with_stripe_payment customer = Stripe::Customer.create(card: stripe_card_token, email: email, plan: plan_id, description: "Unlimited Comics") self.stripe_customer_token = customer.id self.card_token = customer.cards.data.first["id"] self.card_name = customer.cards.data.first["type"] self.exp_month = customer.cards.data.first["exp_month"] self.exp_year = customer.cards.data.first["exp_year"] self.last_4_digits = customer.cards.data.first["last4"] save! rescue Stripe::InvalidRequestError => e logger.error "Stripe error while creating customer: #{e.message}" errors.add :base, "There was a problem with your credit card." false end def update_card customer = Stripe::Customer.retrieve(stripe_customer_token) card = customer.cards.retrieve(card_token) *** This Update works, but how do I pass a new Credit Card Number, Expiration Date etc. card.name = "My new name" customer.save rescue Stripe::StripeError => e logger.error "Stripe Error: " + e.message errors.add :base, "#{e.message}." false end end

PUNTOS DE VISTA

<%= form_for @subscription do |f| %> <%= render ''shared/error_messages'', object: f.object %> <%= f.hidden_field :plan_id %> <%= f.hidden_field :user_id %> <%= f.hidden_field :stripe_card_token %> <h4>Change Credit Card</h4> <div class="field"> <%= label_tag :card_number, "Credit Card Number" %> <%= text_field_tag :card_number, nil, name: nil %> </div> <div class="field"> <%= label_tag :card_code, "Security Code on Card (CVV)" %> <%= text_field_tag :card_code, nil, name: nil %> </div> <div class="field"> <%= label_tag :card_month, "Card Expiration" %> <%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %> <%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"} %> </div> <%= f.submit "Change Credit Card", :class => "btn btn-primary" %> <% end %>

RUTAS

App::Application.routes.draw do resources :subscriptions end

ESQUEMA

create_table "subscriptions", :force => true do |t| t.integer "plan_id" t.integer "user_id" t.string "email" t.string "card_name" t.string "exp_month" t.string "exp_year" t.string "card_token" t.string "stripe_customer_token" t.string "last_4_digits" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end


Así que la biblioteca ruby ​​de Stripe tiene el método de actualización , ya tienes card.name pero para la fecha de vencimiento puedes usar card.exp_month y card.exp_year , revisa el método de actualización para todos los argumentos.

Notará que no tiene un número de tarjeta de actualización allí, por lo que mi sugerencia sería que el usuario cree otra tarjeta si desea cambiar su número de tarjeta de crédito y luego actualizar al cliente para que tenga esa tarjeta como su crédito predeterminado. tarjeta (revise crear tarjeta y actualizar a un cliente en la documentación de la biblioteca Ruby de banda).

Espero que esto ayude


Puede actualizar los detalles de la tarjeta de crédito de esta manera (CÓDIGO PHP)

  1. Primero recopile los detalles de la tarjeta y la identificación de la franja del cliente (que debe haber guardado en su base de datos mientras crea este cliente).
  2. Cree el token de banda y reenvíe el mismo al servidor de esta manera:

    Stripe.setPublishableKey(''pk_test_6pRNASCoBOKtIshFeQd4XMUh''); function stripeResponseHandler(status, response) { var $form = $(''#payment-form''); if (response.error) { // Show the errors on the form $form.find(''.payment-errors'').text(response.error.message); $form.find(''button'').prop(''disabled'', false); } else { // response contains id and card, which contains additional card details var token = response.id; alert(''The Token Is: ''+token); // Insert the token into the form so it gets submitted to the server $form.append($(''<input type="hidden" name="stripeToken" />'').val(token)); // and submit $form.get(0).submit(); } }; jQuery(function($) { $(''#payment-form'').submit(function(event) { var $form = $(this); // Disable the submit button to prevent repeated clicks $form.find(''button'').prop(''disabled'', true); Stripe.card.createToken($form, stripeResponseHandler); // Prevent the form from submitting with the default action return false; }); });

  3. y en el servidor puedes actualizar los detalles así:

    $customer_id = trim($_REQUEST[''cus_select'']); $query = "SELECT cus_stripe_id FROM customer_details_tbl WHERE id=$customer_id"; $customer_query = mysqli_query($db_conn,$query); $row_customer = mysqli_fetch_row($customer_query); $cus_stripe_id = $row_customer[0]; Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2"); $error = ''''; $success = ''''; try { if (!isset($_POST[''stripeToken''])) throw new Exception("The Stripe Token was not generated correctly"); $customer = Stripe_Customer::retrieve($cus_stripe_id); $customer->source = $_POST[''stripeToken'']; $customer->save(); echo "Card Details Updated Successfully"; } catch (Exception $e) { $error = $e->getMessage(); echo $error; } }

Eso es. Esto sobrescribirá la tarjeta existente con los nuevos detalles.


Usa Stripe.js como sugiere Tim Sullivan. Aquí está su código actualizado para la API Stripe más nueva.

def update_card(subscriber, stripe_token) customer = Stripe::Customer.retrieve({CUSTOMER_ID}) card = customer.sources.create(card: params[:stripeToken]) customer.default_source = card.id customer.save rescue Stripe::InvalidRequestError => e logger.error "Stripe error while updating card info: #{e.message}" errors.add :base, "#{e.message}" false end


Esta respuesta ha sido actualizada gracias a la nota de @TimSullivan.

Tuve que hacer lo mismo en mi aplicación. Stripe no permite actualizar el número de tarjeta. Esto te deja con dos opciones: 1) Crear una nueva tarjeta y eliminar la tarjeta original; y 2) Cree una nueva tarjeta, configúrela como la tarjeta_defecto y deje la tarjeta original. Elegí la segunda ruta.

Así es como lo hice:

modelos / suscriptor.rb

def update_card(subscriber, stripe_card_token) customer = Stripe::Customer.retrieve(subscriber.stripe_customer_token) card = customer.sources.create(card: stripe_card_token) card.save customer.default_source = card.id customer.save rescue Stripe::InvalidRequestError => e logger.error "Stripe error while updating card info: #{e.message}" errors.add :base, "#{e.message}" false end

controladores / suscriptores_controller.rb

def edit_card @subscriber = current_subscriber end def update_card @subscriber = current_subscriber if @subscriber.update_card(@subscriber, params[:stripe_card_token]) flash[:success] = ''Saved. Your card information has been updated.'' redirect_to @subscriber else flash[:warning] = ''Stripe reported an error while updating your card. Please try again.'' redirect_to @subscriber end end

vistas / suscriptores / edit_card.html.erb

<%= form_for @subscriber, url: update_card_path, html: { class: ''update_subscriber'' } do |f| %> <div class=''form-group''> <%= label_tag :number, ''Card Number'', class: ''col-sm-3 control-label'' %> <div class=''col-sm-9''> <%= text_field_tag :number, nil, class: ''form-control'', placeholder: ''We accept Visa, MasterCard, AMEX and Discover'' %> </div> </div> <div class=''form-group''> <%= label_tag :cvc, ''Security Code'', class: ''col-sm-3 control-label'' %> <div class=''col-sm-9''> <%= text_field_tag :cvc, nil, class: ''form-control'', placeholder: ''The code on the back of your card (CVC)'' %> </div> </div> <div class=''form-group''> <%= label_tag :exp_month, ''Expiration Date'', class: ''col-sm-3 control-label'' %> <div class=''col-sm-5''> <%= select_month nil, { add_month_numbers: true }, { id: ''exp_month'', class: ''form-control btm-space'' } %> </div> <div class=''col-sm-4''> <%= select_year nil, { start_year: Date.today.year, end_year: Date.today.year+15 }, { id: ''exp_year'', class: ''form-control btm-space'' } %> </div> </div> <div class=''form-group''> <div class=''col-sm-4 col-sm-offset-8''> <%= submit_tag ''Update'', class: ''btn btn-success btn-block'' %> </div> </div> <%= f.hidden_field :stripe_card_token %> <% end %>

config / route.rb

match ''/edit_card'', to: ''subscribers#edit_card'', via: ''get'' match ''/update_card'', to: ''subscribers#update_card'', via: ''post''

app / js / update_card.js

var subscription; jQuery(function() { Stripe.setPublishableKey($(''meta[name="stripe-key"]'').attr(''content'')); return subscription.setUpForm(); }); subscription = { setUpForm: function() { return $(''.update_subscriber'').submit(function() { $(''input[type="submit"]'').attr(''disabled'', true); if ($(''#card_number'').length) { subscription.updateCard(); return false; } else { return true; } }); }, updateCard: function() { var card; card = { number: $(''#card_number'').val(), cvc: $(''#card_code'').val(), expMonth: $(''#card_month'').val(), expYear: $(''#card_year'').val() }; return Stripe.createToken(card, subscription.handleStripeResponse); }, handleStripeResponse: function(status, response) { if (status === 200) { $(''#subscriber_stripe_card_token'').val(response.id); return $(''.update_subscriber'')[0].submit(); } else { $(''#stripe_error'').text(response.error.message); return $(''input[type="submit"]'').attr(''disabled'', false); } } };

Espero que esto ayude.


La respuesta aceptada aquí es peligrosamente insegura de usar . Hace un recorrido final alrededor de la seguridad que Stripe alienta. Su propio servidor nunca debe obtener los datos de la tarjeta de crédito.

En su lugar, debe usar Stripe.js para pasar la tarjeta a Stripe directamente (de manera similar a como se hace en el Railscast al que está vinculado) y recuperar un token, luego crear la tarjeta basada en el token.

def update_card(subscriber, stripe_token) customer = Stripe::Customer.retrieve(subscriber.stripe_customer_token) card = customer.cards.create(card: stripe_token) card.save customer.default_card = card.id customer.save rescue Stripe::InvalidRequestError => e logger.error "Stripe error while updating card info: #{e.message}" errors.add :base, "#{e.message}" false end