mochi93kou
@mochi93kou (まるも)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Railsアプリでpayjpをテストでエラーが発生。

解決したいこと

Railsアプリでpayjpを使ってカードの登録を
テストした際にエラーが発生してしまった。

発生している問題・エラー

Failure/Error: customer_id: customer.id,

NoMethodError:
       undefined method `id' for {:cards=>{:count=>1, :data=>[{:id=>"car_a96c76b044d7ae21439d7b9840b7", :address_city=>nil, :address_line1=>nil, :address_line2=>nil, :address_state=>nil, :address_zip=>nil, :address_zip_check=>"unchecked", :brand=>"Visa", :country=>nil, :created=>1578830630, :customer=>"cus_ca9d1d98900ec1f2595aebefd9a6", :cvc_check=>"passed", :exp_month=>12, :exp_year=>2020, :fingerprint=>"e1d8225886e3a7211127df751c86787f", :last4=>"4242", :livemode=>false, :metadata=>{}, :name=>nil, :object=>"card"}], :has_more=>false, :object=>"list", :url=>"/v1/customers/cus_ca9d1d98900ec1f2595aebefd9a6/cards"}, :id=>"cus_ca9d1d98900ec1f2595aebefd9a6", :created=>1578830631, :default_card=>"car_a96c76b044d7ae21439d7b9840b7", :description=>nil, :email=>nil, :livemode=>false, :metadata=>{}, :object=>"customer", :subscriptions=>{:count=>0, :data=>[], :has_more=>false, :object=>"list", :url=>"/v1/customers/cus_ca9d1d98900ec1f2595aebefd9a6/subscriptions"}}:Hash
     
               customer_id: customer.id,

該当コード

テスト

context '登録成功' do
  let(:user) { create(:user) }
  it '適切な情報が存在' do
    login(user)
    get new_card_path
    expect{
      allow(Payjp::Customer).to receive(:create).and_return(PayjpMock.customer_information)
      post card_path, params: { payjp_token: 'sk_test_c62fade9d045b54cd76d7036',
                                card_token: 'car_a96c76b044d7ae21439d7b9840b7'}
    }.to change{ Card.count }.by(1)
  end
end

モック

$(function () {
  if (document.URL.match(/card/)) {
    var payjp = Payjp(process.env.PAYJP_PUBLIC_KEY);

    var elements = payjp.elements();
    var numberElement = elements.create('cardNumber', {placeholder: "1111 2222 3333 4444"});
    var expiryElement = elements.create('cardExpiry');
    var cvcElement    = elements.create('cardCvc');

    numberElement.mount('#number-form')
    expiryElement.mount('#expiry-form')
    cvcElement.mount('#cvc-form')

    var submit_btn = $("#card_submit");
    submit_btn.on('click', function(e){
      e.preventDefault();
      payjp.createToken(numberElement).then(function (response) {
        if (response.error) {
          alert(response.error.message)
        } else {
          $("#card_token").append(
            `<input type="hidden" name="payjp_token" value=${response.id}>
            <input type="hidden" name="card_token" value=${response.card.id}>`
          );
          $('#card_form')[0].submit();

          $("#card_number").removeAttr("name");
          $("#cvc-from").removeAttr("name");
          $("#exp_month").removeAttr("name");
          $("#exp_year").removeAttr("name");
        };
      })
    });
  }
});

コントローラー

class CardsController < ApplicationController
  require 'payjp'

  before_action :logged_in_user
  before_action :exists_card, only:[:new, :create]

  def new
    card = Card.where(user_id: current_user.id)
  end

  def create
    @user = current_user
    Payjp.api_key = Rails.application.credentials[:payjp][:secret_key]
    if params[:payjp_token].blank?
      redirect_to 'new'
    else
      customer = Payjp::Customer.create(
        description: '登録テスト',
        email: current_user.email,
        card: params['payjp_token'],
        metadata: {user_id: current_user.id}
      )
      @card = Card.new(
        user_id: current_user.id,
        customer_id: customer.id,
        token_id: customer.default_card
      )
      if @card.save
        flash[:notice] = "カードを登録しました"
        redirect_to @user
      else
        redirect_to 'new'
      end
    end
  end

  def destroy
    card = Card.find_by(user_id: current_user.id)
    if card.blank?
      redirect_to user_path(current_user)
    else
      Payjp.api_key = Rails.application.credentials[:payjp][:secret_key]
      customer = Payjp::Customer.retrieve(card.customer_id)
      customer.delete
      card.delete
    end
    flash[:notice] = "カード情報を削除しました"
    redirect_to user_path(current_user)
  end

  private
    def exists_card
      unless current_user.card.blank?
        flash[:notice] = "登録できるカードは1枚までです"
        redirect_to current_user
      end
    end
end
0

No Answers yet.

Your answer might help someone💌