While learning programming, this keeps what you want to make a note of in a way that is easy for you to understand.
Here is the goal I want to bring this time.
You have entered the test card information and the payment has been completed.
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
Press the buy button,
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);
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,
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? ?? ??
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
Becomes 200
I was able to make a successful payment!
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