概要
Payjpでcustomerを作成しようとした際、No such tokenというエラーを解決するのに時間を要したため、解決した流れを記載しておきます。
エラーの内容
上記のように、そのようなトークンはありませんと言われてしまいました。
- トークンはJs→Rails側に送信できている
- Completed 500 Internal Server Error
となっているため、サーバーサイド側のエラーだと思い、秘密鍵が合っているか等、色々試してみましたが解決できませんでした。
card.jsの記述
サーバーサイド側のエラーだと踏んでいたのですが、jsの記述も確認してみました。
card.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 = {
number: formData.get("number"),
cvc: formData.get("cvc"),
exp_month: formData.get("exp_month"),
exp_year: `20${formData.get("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="card_token">`;
renderDom.insertAdjacentHTML("beforeend", tokenObj);
}
document.getElementById("card-number").removeAttribute("name");
document.getElementById("card-exp-month").removeAttribute("name");
document.getElementById("card-exp-year").removeAttribute("name");
document.getElementById("card-cvc").removeAttribute("name");
document.getElementById("charge-form").submit();
document.getElementById("charge-form").reset();
});
});
};
window.addEventListener("load", pay);
特におかしなところは無いように思えます・・・。
ある違和感
同じような記述で、jsを使って商品の合計金額(total_price)をサーバーサイドに送信するコードも書いていました。
sendTotalPrice.js
function sendTotalPrice() {
const totalPriceDom = document.getElementById("cart-total-price")
const totalPrice = parseInt(totalPriceDom.innerHTML);
const renderDom = document.getElementById("charge-form");
const totalPriceObj = `<input value=${totalPrice}, type="hidden", name="total_price">`;
renderDom.insertAdjacentHTML("beforeend", totalPriceObj);
};
window.addEventListener('load', sendTotalPrice);
ここでおかしいと感じたことがあります。
送信されたparamsのtotal_priceの中に
不要な " , " が入ってしまっています。
原因はjs内の記述だった
トークンの値をフォームに含めるための記載に間違いがありました。
間違い
const tokenObj = `<input value=${token}, type="hidden", name="card_token">`;
正しい
const tokenObj = `<input value=${token} type="hidden" name="card_token">`;
value=${token}のあとのカンマ "," は不要でした!
勉強になったこと
Rails等のform_withなどでは属性を区切るためにカンマが必要ですが、HTML要素では属性を区切るカンマは不要ですね・・・。
同じような内容で悩まれている方がもしいらっしゃったら、参考になれば幸いです。