[Rails] Error resolution when generating tokens with PAYJP

While learning programming, this keeps what you want to make a note of in a way that is easy for you to understand.

I want to introduce PAYJP and implement a payment system!

Here is the goal I want to bring this time. スクリーンショット 2020-09-20 9.45.56.png

You have entered the test card information and the payment has been completed.

Payment is not successful ...

First of all, I introduced the payjp gem, created a JavaScript file as I learned, and wrote it in the controller and view.

Then type in the test card information and スクリーンショット 2020-09-20 10.01.28.png

Press the buy button, スクリーンショット 2020-09-20 10.14.43.png

It returns to the original screen ... (Hmm ??? Token is empty ???)

This is because the controller is set so that the screen does not change if the payment is not successful, and the error is also displayed, but at first I did not understand the cause ...

Here is the code for the current controller. (It may be difficult to read, but since it will be long, only the create action part is excerpted.)

****_controller.rb


  def create
    @order = ItemOrder.new(order_params)
    if @order.valid?
      pay_item
      @order.save
      return redirect_to root_path
    else
      render 'new'
    end
  end

Here is the JavaScript description for receiving the card information and generating the token.

****.js



const pay = () => {
  Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY);
  const form = document.getElementById("charge-form");
  form.addEventListener("submit", (e) => {
    e.preventDefault();
 
    const formResult = document.getElementById("charge-form");
    const formData = new FormData(formResult);

    const card = {
      card_number: formData.get("card-number"),
      card_cvc: formData.get("card-cvc"),
      card_exp_month: formData.get("card-exp-month"),
      card_exp_year: `20${formData.get("card-exp-year")}`,
    };
    Payjp.createToken(card, (status, response) => {
      if (status == 200) {
        const token = response.id;
        const renderDom = document.getElementById("charge-form");
        const tokenObj = `<input value=${token} type="hidden" name='token'>`;
        renderDom.insertAdjacentHTML("beforeend", tokenObj);
      }
      document.getElementById("card-number").removeAttribute("name");
      document.getElementById("card-cvc").removeAttribute("name");
      document.getElementById("card-exp-month").removeAttribute("name");
      document.getElementById("card-exp-year").removeAttribute("name");
 
      document.getElementById("charge-form").submit();
      document.getElementById("charge-form").reset();
    });
  });
 };
 window.addEventListener("load", pay);

Understanding the current situation

To see what went wrong, I introduced the pry-rails gem, wrote binding.pry in the create action, and checked the contents of the params.

pry(#<OrdersController>)> params
=> <ActionController::Parameters {"authenticity_token"=>"pvPlrZPKlxtcYotX8kK4N/OjbTuWNkiq5bOCJxqNI+OYt59wXZuTClFnz7XDmAVWelWQJraGSTdIccYspnstlw==", "item_order"=>{"postal_code"=>"555-0000", "prefecture_id"=>"3", "city"=>"Municipality", "block_number"=>"address", "building_name"=>"Building name", "phone_number"=>"09012345678"}, "controller"=>"orders", "action"=>"create", "id"=>"1"} permitted: false>

Certainly, there is no token ... (ʻAuthenticity_token` seems to be completely different.)

This means that the token may not have been generated properly.

Next, I used console.log () to look up the description in JavaScript.

const pay = () => {
  Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY);
  console.log(process.env.PAYJP_PUBLIC_KEY)
  //Check if environment variables can be defined
  const form = document.getElementById("charge-form");
  form.addEventListener("submit", (e) => {
    e.preventDefault();
 
    const formResult = document.getElementById("charge-form");
    const formData = new FormData(formResult);

    const card = {
      card_number: formData.get("card-number"),
      card_cvc: formData.get("card-cvc"),
      card_exp_month: formData.get("card-exp-month"),
      card_exp_year: `20${formData.get("card-exp-year")}`,
    };
    console.log(card)
    //Check if you have received the card information
    Payjp.createToken(card, (status, response) => {
      console.log(status)
      //Check the status number
      if (status == 200) {
        const token = response.id;
        const renderDom = document.getElementById("charge-form");
        const tokenObj = `<input value=${token} type="hidden" name='token'>`;
        renderDom.insertAdjacentHTML("beforeend", tokenObj);
      }
      document.getElementById("card-number").removeAttribute("name");
      document.getElementById("card-cvc").removeAttribute("name");
      document.getElementById("card-exp-month").removeAttribute("name");
      document.getElementById("card-exp-year").removeAttribute("name");
 
      document.getElementById("charge-form").submit();
      document.getElementById("charge-form").reset();
    });
  });
 };
 window.addEventListener("load", pay);

And since it is stopped at binding_pry, if you check the console there, スクリーンショット 2020-09-20 10.41.00.png It seems that the card information has been received firmly! However, the status is 400, so the token cannot be generated ...

Why did I receive the card information? ?? ??

Solution

Therefore, I consulted with a knowledgeable person and finally solved it! It seems that there was an error in the description that stores the card information to be acquired.

Of the description of this part

****.js


const card = {
      card_number: formData.get("card-number"),
      card_cvc: formData.get("card-cvc"),
      card_exp_month: formData.get("card-exp-month"),
      card_exp_year: `20${formData.get("card-exp-year")}`,
    };

If you write card_number:, card_cvc:, card_exp_month:, card_exp_year:, it seems that it does not communicate correctly with Payjp.

I was told that this shape is fixed, Corrected the description as number:, cvc:, ʻexp_month:, ʻexp_year:.

const card = {
      number: formData.get("card-number"),
      cvc: formData.get("card-cvc"),
      exp_month: formData.get("card-exp-month"),
      exp_year: `20${formData.get("card-exp-year")}`,
    };

By writing

The status is also safe スクリーンショット 2020-09-20 10.59.02.png Becomes 200

I was able to make a successful payment! スクリーンショット 2020-09-20 11.02.39.png

Summary

When introducing PAYJP, it is necessary to describe the acquired card information in a fixed format. You can use binding_pry andconsole.log ()to find out where the problem is.

Recommended Posts

[Rails] Error resolution when generating tokens with PAYJP
rails error resolution summary
[Rails] About error resolution when installing devise and activeadmin
Error encountered with notes when deploying docker on rails
[Rails] Error resolution after PAYJP token generation (separate route)
Error when playing with java
Error when using rails capybara
How to set environment variables when using Payjp with Rails
exited with code 1 error resolution with docker-compose up in rails environment
Error when building infrastructure with aws app
rails test fails with database reference error
Let's make an error screen with Rails
[Rails / Heroku] Error resolution procedure after push
Dealing with NameError: uninitialized constant :: Analyzable error when installing Active Storage in Rails6
[Error resolution] Occurs when trying to build an environment for spring with docker
Error in bundle install when running rails new
[Rails] Solution when migration error occurs in acts-as-taggable-on
error code 400 appears when deploying with release: perform
Rails <% = expression%> Why no error occurs when empty
Error deploying rails5 + Mysql to heroku with Docker-compose
After installing'devise''bootstrap' of gemfile with rails, what to do when url is an error
Ruby on Rails Incorrect string value error resolution when posting a form in Japanese
ITMS-90626 Error Resolution
[Review] When creating a web application with Rails, syntax error, unexpected')', expecting => ...]}% ","% # {params [: content]}% "]) ...
[Rails] How to solve the error "undefined method` visit'" when using Capybara with Rspec
Error when starting JUnit with deprecated version of POI
Rails uninitialized constant A simple checklist for error resolution
Workaround for Bundler.require error when executing ruby with crontab
Nuxt.js x Rails app creation CORS policy Error resolution
[Rails] "private method` String' called ~ "error when db: migrate
[Rails] Precautions when comparing date and time with DateTime
Using PAY.JP API with Rails ~ Implementation Preparation ~ (payjp.js v2)
When I bcrypt with node + docker, I got an error
Using PAY.JP API with Rails ~ Card Registration ~ (payjp.js v2)
When the server does not start with rails s