在条带中创建订阅

时间:2020-01-13 19:49:42

标签: ruby-on-rails stripe-payments

我收到此错误

`Stripe::InvalidRequestError (This customer has no attached payment source):



app/controllers/subscriptions_controller.rb:24:in `create`

当我尝试订阅计划时。

这是我的代码

`

class SubscriptionsController < ApplicationController
  layout "subscribe"
  before_action :authenticate_user!, except: [:new, :create]

  def new
    if user_signed_in? && current_user.subscribed?
      redirect_to root_path, notice: "You are already a subscriber"
    end
  end

  def create
    Stripe.api_key = Rails.application.credentials.stripe_api_key

    plan_id = params[:plan_id]
    plan = Stripe::Plan.retrieve(plan_id)
    token = params[:stripeToken]

    customer = if current_user.stripe_id?
                Stripe::Customer.retrieve(current_user.stripe_id)
               else
                Stripe::Customer.create(email: current_user.email, source: token)
              end

    subscription = customer.subscriptions.create(plan: plan.id)

    options = {
      stripe_id: customer.id,
      stripe_subscription_id: subscription.id,
      subscribed: true
    }

    options.merge!(
      card_last4: params[:user][:card_last4],
      card_exp_month: params[:user][:card_exp_month],
      card_exp_year: params[:user][:card_exp_year],
      card_type: params[:user][:card_type]
    ) if params[:user][:card_last4]

    current_user.update(options)

    redirect_to root_path, notice: "Your subscription was setup successfully!"
  end

  def destroy
    customer = Stripe::Customer.retrieve(current_user.stripe_id)
    customer.subscriptions.retrieve(current_user.stripe_subscription_id).delete
    current_user.update(stripe_subscription_id: nil)
    current_user.subscribed = false

    redirect_to root_path, notice: "Your subscription has been canceled."
  end
end
`

stripe.js

document.addEventListener("turbolinks:load", () => {
    const publishableKey = document.querySelector("meta[name='stripe-key']").content;
    const stripe = Stripe(publishableKey);

    const elements = stripe.elements({
        fonts: [{
            cssSrc: "https://rsms.me/inter/inter-ui.css"
        }],
        locale: "auto"
    });

    const style = {
        base: {
            color: "#32325d",
            fontWeight: 500,
            fontFamily: "Inter UI, Open Sans, Segoe UI, sans-serif",
            fontSize: "16px",
            fontSmoothing: "antialiased",

            "::placeholder": {
                color: "#CFD7DF"
            }
        },
        invalid: {
            color: "#E25950"
        }
    };

    const card = elements.create('card', {
        style
    });

    card.mount("#card-element");

    card.addEventListener('change', ({
        error
    }) => {
        const displayError = document.getElementById('card-errors');
        if (error) {
            displayError.textContent = error.message;
        } else {
            displayError.textContent = "";
        }
    });

    const form = document.getElementById('payment-form');

    form.addEventListener('submit', async(event) => {
        event.preventDefault();

        const {
            token,
            error
        } = await stripe.createToken(card);

        if (error) {
            const errorElement = document.getElementById('card-errors');
            errorElement.textContent = error.message;
        } else {
            stripeTokenHandler(token);
        }
    });


    const stripeTokenHandler = (token) => {
        const form = document.getElementById('payment-form');
        const hiddenInput = document.createElement('input');
        hiddenInput.setAttribute('type', 'hidden');
        hiddenInput.setAttribute('name', 'stripeToken');
        hiddenInput.setAttribute('value', token.id);
        form.appendChild(hiddenInput);

        ["type", "last4", "exp_month", "exp_year"].forEach(function(field) {
            addCardField(form, token, field);
        });

        form.submit();
    }

    function addCardField(form, token, field) {
        let hiddenInput = document.createElement('input');
        hiddenInput.setAttribute('type', 'hidden');
        hiddenInput.setAttribute('name', "user[card_" + field + "]");
        hiddenInput.setAttribute('value', token.card[field]);
        form.appendChild(hiddenInput);
    }

});

我已经正确配置了所有计划和数据条Api,但是代码出了点问题。我的Js不太好。因此,大多数代码是复制和粘贴并进行修改以满足我的需求

我到处搜索,找不到解决方案。我需要帮助。

0 个答案:

没有答案