Stripe SCA webhooks возврат 401 - PullRequest
1 голос
/ 15 марта 2020

Я пытаюсь интегрировать новую проверку Stripe SCA в мое приложение ruby на рельсах. Я следовал инструкциям, которые bnwpro написал здесь , чтобы начать. В этот момент меня перенаправляют на страницу оплаты Stripe и обратно в мое приложение после завершения платежа.

Проблема, с которой я борюсь, - это веб-крючки, когда я смотрю на CLI Stripe, я продолжаю получать 401. ..

2020-03-15 17:22:47   --> charge.succeeded [evt_1GMzEgI1EtCroaCdHmRufFBK]
2020-03-15 17:22:47   --> payment_intent.succeeded [evt_1GMzEgI1EtCroaCdWzbnaczh]
2020-03-15 17:22:47  <--  [401] POST http://localhost:3000/stripe-webhooks [evt_1GMzEgI1EtCroaCdHmRufFBK]
2020-03-15 17:22:47  <--  [401] POST http://localhost:3000/stripe-webhooks [evt_1GMzEgI1EtCroaCdWzbnaczh]
2020-03-15 17:22:47   --> payment_method.attached [evt_1GMzEgI1EtCroaCd4quSj3kR]
2020-03-15 17:22:47  <--  [401] POST http://localhost:3000/stripe-webhooks [evt_1GMzEgI1EtCroaCd4quSj3kR]
2020-03-15 17:22:47   --> customer.created [evt_1GMzEgI1EtCroaCdHpEmU1Ai]
2020-03-15 17:22:47  <--  [401] POST http://localhost:3000/stripe-webhooks [evt_1GMzEgI1EtCroaCdHpEmU1Ai]
2020-03-15 17:22:47   --> checkout.session.completed [evt_1GMzEhI1EtCroaCdf1x9gUUR]
2020-03-15 17:22:47  <--  [401] POST http://localhost:3000/stripe-webhooks [evt_1GMzEhI1EtCroaCdf1x9gUUR]

Мой журнал показывает мне:

Started POST "/stripe-webhooks" for 127.0.0.1 at 2020-03-15 17:22:24 +0100
Processing by CheckoutsController#stripe_webhook as XML
  Parameters: {"id"=>"evt_1GMzEJI1EtCroaCdrKXWf4gV", "object"=>"event", "api_version"=>"2018-02-28", "created"=>1584289343, "data"=>{"object"=>{"id"=>"pi_1GMzEJI1EtCroaCdY3wKhKNG", "object"=>"payment_intent", "allowed_source_types"=>["card"], "amount"=>15000, "amount_capturable"=>0, "amount_received"=>0, "application"=>nil, "application_fee_amount"=>nil, "canceled_at"=>nil, "cancellation_reason"=>nil, "capture_method"=>"automatic", "charges"=>{"object"=>"list", "data"=>[], "has_more"=>false, "total_count"=>0, "url"=>"/v1/charges?payment_intent=pi_1GMzEJI1EtCroaCdY3wKhKNG"}, "client_secret"=>"pi_1GMzEJI1EtCroaCdY3wKhKNG_secret_6djH08QObem66sqpCYdB8P9A4", "confirmation_method"=>"automatic", "created"=>1584289343, "currency"=>"usd", "customer"=>nil, "description"=>nil, "invoice"=>nil, "last_payment_error"=>nil, "livemode"=>false, "metadata"=>{}, "next_action"=>nil, "next_source_action"=>nil, "on_behalf_of"=>nil, "payment_method"=>nil, "payment_method_options"=>{"card"=>{"installments"=>nil, "request_three_d_secure"=>"automatic"}}, "payment_method_types"=>["card"], "receipt_email"=>nil, "review"=>nil, "setup_future_usage"=>nil, "shipping"=>nil, "source"=>nil, "statement_descriptor"=>nil, "statement_descriptor_suffix"=>nil, "status"=>"requires_source", "transfer_data"=>nil, "transfer_group"=>nil}}, "livemode"=>false, "pending_webhooks"=>2, "request"=>{"id"=>"req_iRi1XVG06fMcld", "idempotency_key"=>nil}, "type"=>"payment_intent.created", "checkout"=>{"id"=>"evt_1GMzEJI1EtCroaCdrKXWf4gV", "object"=>"event", "api_version"=>"2018-02-28", "created"=>1584289343, "data"=>{"object"=>{"id"=>"pi_1GMzEJI1EtCroaCdY3wKhKNG", "object"=>"payment_intent", "allowed_source_types"=>["card"], "amount"=>15000, "amount_capturable"=>0, "amount_received"=>0, "application"=>nil, "application_fee_amount"=>nil, "canceled_at"=>nil, "cancellation_reason"=>nil, "capture_method"=>"automatic", "charges"=>{"object"=>"list", "data"=>[], "has_more"=>false, "total_count"=>0, "url"=>"/v1/charges?payment_intent=pi_1GMzEJI1EtCroaCdY3wKhKNG"}, "client_secret"=>"pi_1GMzEJI1EtCroaCdY3wKhKNG_secret_6djH08QObem66sqpCYdB8P9A4", "confirmation_method"=>"automatic", "created"=>1584289343, "currency"=>"usd", "customer"=>nil, "description"=>nil, "invoice"=>nil, "last_payment_error"=>nil, "livemode"=>false, "metadata"=>{}, "next_action"=>nil, "next_source_action"=>nil, "on_behalf_of"=>nil, "payment_method"=>nil, "payment_method_options"=>{"card"=>{"installments"=>nil, "request_three_d_secure"=>"automatic"}}, "payment_method_types"=>["card"], "receipt_email"=>nil, "review"=>nil, "setup_future_usage"=>nil, "shipping"=>nil, "source"=>nil, "statement_descriptor"=>nil, "statement_descriptor_suffix"=>nil, "status"=>"requires_source", "transfer_data"=>nil, "transfer_group"=>nil}}, "livemode"=>false, "pending_webhooks"=>2, "request"=>{"id"=>"req_iRi1XVG06fMcld", "idempotency_key"=>nil}, "type"=>"payment_intent.created"}}
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)

В результате веб-скачок не запускается и код не выполняется.

Кто может указать мне правильное направление? Поиск Google и Stack на этот раз меня не устроил ...

Редактировать 1: app> контроллеры> checkouts_controller.rb

class CheckoutsController < ApplicationController
  require 'stripe'
  before_action :setplans
  skip_before_action :checkStatus
  protect_from_forgery except: :stripe_webhook


  Stripe.api_key = 'sk_test_...'
  endpoint_secret = "whsec_..."



  def index
  end

  def new
    Stripe.api_key = 'sk_test_...'

    @product = Product.find(params[:id])

    session = Stripe::Checkout::Session.create(
      payment_method_types: ['card'],
      line_items: [{
        name: @product.title,
        amount: @product.price,
        currency: 'usd',
        quantity: 1,
      }],
      "metadata": {days: "#{@product.days}"},
      success_url: 'http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: 'http://localhost:3000/cancel',
    )
    @stripe_session = session
  end

  def success
  ### the Stripe {CHECKOUT_SESSION_ID} will be available in params[:session_id]
    if params[:session_id]
      flash[:success] = "Thank you! Your license has been updated!"
    else
      flash[:danger] = "Session expired error..."
      redirect_to checkouts_path
    end
  end

  def cancel
    redirect_to checkouts_path
  end

  def stripe_webhook
    stripe_response = StripeWebhooks.subscription_events(request)
  end


  private

  def setplans
    @licenseplans = Product.where(active: true)
  end


end

stripe_webhook живет под app> services > stripe_webhooks.rb

class StripeWebhooks
  require 'stripe'
  STRIPE_API_KEY = "sk_test_..."

  def self.subscription_events(request)
    new(request).subscription_lifecycle_events
  end

  def initialize(request)
    @webhook_request = request
  end

  def subscription_lifecycle_events
    authorize_webhook

    case event.type
    when 'customer.created'
      handle_customer_created
    when 'checkout.session.completed'
      handle_checkout_session_completed
    when # etc.
    end
  end

  private

  attr_reader :webhook_request, :event

  def handle_customer_created(event)
    ## custom actions
  end

  def handle_checkout_session_completed(event)
    ## custom actions
  end

  def authorize_webhook
    Stripe.api_key = 'sk_test_...'

    endpoint_secret = "whsec_..."

    payload = webhook_request.body.read
    sig_header = webhook_request.env['HTTP_STRIPE_SIGNATURE']
    @event = nil

    begin
      @event = Stripe::Webhook.construct_event(
        payload, sig_header, endpoint_secret
      )
    rescue JSON::ParserError => e
      puts e.message
    rescue Stripe::SignatureVerificationError => e
      puts e.message
    end
  end
end

config> rout.rb

...
  # Stripe SCA checkout routes
  get 'success', to: 'checkouts#success'
  get 'cancel', to: 'checkouts#cancel'
  resources :checkouts
  post '/stripe-webhooks', to: 'checkouts#stripe_webhook'
...

На данный момент существует несколько жестко закодированных ключей, которые необходимо переместить и сохранить в более безопасном месте после того, как я исправить ошибку аутентификации

1 Ответ

0 голосов
/ 17 марта 2020

Я переместил webhook из службы в контроллер на данный момент и снова добавил skip_before_filter, НО переместил ключ endpoint_secret в webhook и получил красивые 200 сейчас!

Теперь мне просто нужно извлечь Часть метаданных и приступайте к работе над соответствующим действием после успешного платежа ...

Обновлен контроллер:

class CheckoutsController < ApplicationController
  require 'stripe'
  before_action :setplans
  skip_before_action :checkStatus
  protect_from_forgery except: :stripe_webhook
  skip_before_action :authenticate_user!, only: [:stripe_webhook]


  Stripe.api_key = 'sk_test_...'


  def index
  end

  def new
    Stripe.api_key = 'sk_test_...'

    @product = Product.find(params[:id])

    session = Stripe::Checkout::Session.create(
      payment_method_types: ['card'],
      line_items: [{
        name: @product.title,
        amount: @product.price,
        currency: 'usd',
        quantity: 1,
      }],
      metadata: {days: :"#{@product.days.to_s}"},
      success_url: 'http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: 'http://localhost:3000/cancel',
    )
    @stripe_session = session
  end

  def success
  ### the Stripe {CHECKOUT_SESSION_ID} will be available in params[:session_id]
    if params[:session_id]
      flash[:success] = "Thank you! Your license has been updated!"
    else
      flash[:danger] = "Session expired error..."
      redirect_to checkouts_path
    end
  end

  def cancel
    redirect_to checkouts_path
  end

  def stripe_webhook
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    endpoint_secret = "whsec_..."

    begin
      event = Stripe::Webhook.construct_event(request.body.read, sig_header, endpoint_secret)
    rescue JSON::ParserError
      return head :bad_request
    rescue Stripe::SignatureVerificationError
      return head :bad_request
    end

    webhook_checkout_session_completed(event) if event['type'] == 'checkout.session.completed'

    head :ok
  end


  private

  def setplans
    @licenseplans = Product.where(active: true)
  end

  def webhook_checkout_session_completed(event)
    object = event['data']['object']

  end

end
...