質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

3回答

6503閲覧

SyntaxError: Unexpected token < in JSON at position 0の解決方法

naofu_web

総合スコア5

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2020/04/27 07:51

編集2020/04/27 07:56

前提・実現したいこと

pay.jpで定期課金させたいです。
ajax部分でエラーが出ており、自分でも調べているのですがなかなか解決できなく悩んでおります。
お力をお貸しいただけると幸いです。

PHPでpay.jpという定期課金の組み込みをしているのですが、カード番号などを登録してボタンを押すと

Unexpected token < in JSON at position 0

と出ます。

下記のサイトにあったデモを参考にして、秘密鍵、公開鍵、DBの登録などを変更しております。
デモではエラーも無く、決済完了画面に遷移するのですが、デモ通り上手く行きません。
https://base91.net/payjp/

該当のソースコード

html

1<!--エラーがあった時はこちらに表示--> 2<div class="missArea cardmiss"></div> 3 4<!--以下、クレジットカード入力フォーム--> 5<dl> 6 <dt>カード番号</dt> 7 <dd><input type="text" name="card_number" placeholder="カード番号)4242424242424242"></dd> 8 <dt>有効期限</dt> 9 <dd><input type="number" name="card_exp_month" placeholder="月)12">/<input type="number" name="card_exp_year" placeholder="年)21"></dd> 10 <dt>カード確認コード(CVC)</dt> 11 <dd><input type="text" name="card_cvc" placeholder="CVC)123"></dd> 12 <dt>お名前</dt> 13 <dd><input type="text" name="card_name" placeholder="名前)TARO SASAKI"></dd> 14</dl> 15<button class="publishBtn" >登録する</button> 16<div style="padding-top:40px;"> 17<div>テスト用カード番号は<a href="https://pay.jp/docs/testcard" target="_blank">こちら</a>から<br> 18カード番号以外の情報は、グレーの文字通りご入力ください。<br> 19実際に決済はされません。</div> 20</div>

JavaScript

1//公開鍵を設定 2Payjp.setPublicKey("pk_test_○○○○○○○○○"); 3 4//publishBtn(buttonを押した時に以下の処理スタート) 5$(".publishBtn").click(function(){ 6 7 //一旦エラーエリアの内容をリセット(何も無い場合は変化なし)。 8 $(".missArea").empty(); 9 10 //有効期限の年を取得 11 //年を4桁すべて入力してもらうと手間がかります。 12 //よって、2019の場合、19だけ入力してもらい、20はここで付け足す。 13 var cvcdata = "20" + document.querySelector('input[name="card_exp_year"]').value; 14 15 //他の項目もすべて取得 16 var card = { 17 number: document.querySelector('input[name="card_number"]').value, 18 cvc: document.querySelector('input[name="card_cvc"]').value, 19 exp_month: document.querySelector('input[name="card_exp_month"]').value, 20 exp_year: cvcdata, 21 name: document.querySelector('input[name="card_name"]').value 22 }; 23 24 //pay.jpに送るため情報を暗号化(トークン化) 25 Payjp.createToken(card, function(status, response) { 26 27 //statusが200の場合はトークン化に問題無し。決済へ進む 28 if (status == 200) { 29 30 //トークンを取得 31 var card_token = response.id; 32 33 //ajaxで決済処理用のphpにトークンを送信 34 $.ajax({ 35 type: 'POST', 36 dataType:'json', 37 url:'functions/pay.php', 38 data:{ 39 card_token:card_token, 40 }, 41 success:function(data) { 42 if(data){ 43 //決済処理に問題があった場合、エラーを表示。 44 $(".cardmiss").append(""+data+""); 45 }else{ 46 //決済処理が成功した場合、決済顔料画面へ。 47 location.href = "success.php"; 48 }; 49 }, 50 error:function(XMLHttpRequest, textStatus, errorThrown) { 51           alert(errorThrown); 52   console.log("XMLHttpRequest : " + XMLHttpRequest.status); 53   console.log("textStatus : " + textStatus); 54   console.log("errorThrown : " + errorThrown.message); 55 } 56 }); 57 58 } else { 59 60 //フォームの時点で入力内容にエラーがあった場合。 61 var error_messege = response.error.message; 62 $(".cardmiss").append("入力内容にエラーがあるようです。再度、ご確認の上、ご登録をお願い致します。"); 63 64 }; 65 }); 66}); 67

php

1 require_once "db.php"; 2 3 //公開鍵を設定するファイルを読み込みます。 4 require_once 'secret.php'; 5 6 //アップロードしたpay.jpのライブラリから必要なファイルを読み込みます。 7 require_once 'payjp-php-master/init.php'; 8 9 //JavaScriptからポストされたトークンを受け取ります。 10 $card_token = htmlspecialchars($_POST['card_token'], ENT_QUOTES); 11 12 //管理画面で決めた、今回課金するプランのidを指定します。 13 $plan_data = "plan001"; 14 15 //ユーザーのメールアドレスを取得します。 16 //今回はユーザーのメールアドレスをセッションで保持、セッションから取得。 17 $mail = $_SESSION['mail']; 18 19 try { 20 21 //pay.jpの管理画面に顧客データを作成します。 22 Payjp\Payjp::setApiKey($secret); 23 $result = Payjp\Customer::create( 24 array( 25 "email" => $mail, 26 "card" => $card_token, 27 ) 28 ); 29 30 //作成された顧客idを取得します。 31 $resultid = $result['id']; 32 33 //ユーザーをプランに加入する処理を実行。 34 Payjp\Payjp::setApiKey($secret); 35 $resultsub = Payjp\Subscription::create( 36 array( 37 "customer" => $resultid, 38 "plan" => $plan_data 39 ) 40 ); 41 42 //プランとユーザーを紐付けるidを取得 43 $resultsubid = $resultsub['id']; 44 45 //データベースにあるユーザーデータに、決済関連のidをまとめて保存 46 $userplandata = mysqli_select_db($mysqli,'userdata'); 47 //今回はplanrank=プランのランク(s0001) planid=プラン決済id payid=顧客id registrationtime=決済時間を登録しています。 48 //データベースにも予めカラムを作っておいてください。 49 $userplandata = mysqli_query($mysqli,"UPDATE userdata SET planrank='$plan_data',planid='$resultsubid',payid='$resultid',registrationtime='$today' where mail = '$mail'"); 50 51 } catch (Exception $e) { 52 53 //もしエラーがあった場合はエラーメッセージを返します。 54 $miss = $getmessage = $e->getMessage(); 55 56 }; 57 58 //最後にjsonでエラーがあった場合のエラーメッセージを返します。 59 header('Content-type: application/json'); 60 echo json_encode( $miss ); 61

試したこと

ajaxのerror:functionのalert(errorThrown)付近を
console.logでステータスを見ると下記のように返ってきました。

JavaScript

1XMLHttpRequest : 200 2textStatus : parsererror 3errorThrown : Unexpected token < in JSON at position 0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/04/27 07:54

pay.php の内容をご提示ください。
naofu_web

2020/04/27 07:56

失礼しました。追記させていだたきました。
guest

回答3

0

Unexpected token < in JSON at position 0は直訳でJSONへ変換する文字列の[0]位置に無効な文字列<が含まれているということを意味します。
先頭が<ということは十中八九, functions/pay.phpの出力がjsonの形式に沿っていない、この場合エラー等が発生してHTMLコードが吐き出されているというこのなので、functions/pay.phpがちゃんと意図した出力をしているか、確認してみてください。
Google Chromeであれば、Developer ConsoleのNetworkタブから問い合わせ結果の内容が見れるかと思います。

投稿2020/04/27 07:56

rozeo_s

総合スコア110

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naofu_web

2020/04/27 08:56

ありがとうございます。pay.jpのレスポンスを見ると <b>Notice</b>: Undefined variable: miss in <b>/Applications/MAMP/htdocs/site04/functions/pay.php</b> on line <b>63</b> と出ていたので、該当箇所を見ると echo json_encode( $miss ); の部分でした。 どこかで$missをどこかで定義する必要があるのでしょうか、、?色々試しているのですが進まず、、 お力をお貸しいただけると幸いです。
rozeo_s

2020/04/27 09:03

一つ下の回答で指摘されていますが、 $miss が定義されるのは catch 側のみで catchに捕まらない(=例外がなかった)場合は $missが未定義になってしまうのでたとえば、 $missは予め成功時のレスポンス用のデータを try-catch よりも外でいれておき、エラーであれば $miss を エラー用のレスポンスで置き換えるようにすればどうでしょうか。 (missという変数名だとおかしな気がするので結果を洗わすような変数名にしたほうが無難です) ただ、気になるのが catch 側でも$missに配列ではなく文字列が入っているため、こちらも同じようなエラーでおちるはずなのでcatch側の$missも配列が入るようにしてあげてください。
guest

0

typeをjsonではなく単にtextにすると分かるのではないでしょうか。
jsonとして正しい形式に変換できる出力内容かどうか。
どこかでエラー起きてるとか。

気になるのは$missがException起きたときしか定義されないところですかね。
成功したら変数未定義です。

投稿2020/04/27 08:30

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

お二方にアドバイスをいただいた通りに実装すると、successページに遷移することができました。
try-catch以外の部分で定義しております。

tryの方にも定義すると、遷移が止まって文字列が表示されてしまうので、定義せず進めてみようかと思います。

ご回答くださったお二方、誠にありがとうございました。

php

1 //データベースと接続するファイルを読み込みます。 2 require_once "db.php"; 3 4 //公開鍵を設定するファイルを読み込みます。 5 require_once 'secret.php'; 6 7 //アップロードしたpay.jpのライブラリから必要なファイルを読み込みます。 8 require_once 'payjp-php-master/init.php'; 9 10 //JavaScriptからポストされたトークンを受け取ります。 11 $card_token = htmlspecialchars($_POST['card_token'], ENT_QUOTES); 12 13 //管理画面で決めた、今回課金するプランのidを指定します。 14 $plan_data = "plan001"; 15 16 //ユーザーのメールアドレスを取得します。 17 //今回はユーザーのメールアドレスをセッションで保持、セッションから取得。 18 $mail = "メールアドレス"; 19 $miss = ""; 20 try { 21 22 //pay.jpの管理画面に顧客データを作成します。 23 Payjp\Payjp::setApiKey($secret); 24 $result = Payjp\Customer::create( 25 array( 26 "email" => $mail, 27 "card" => $card_token, 28 ) 29 ); 30 31 //作成された顧客idを取得します。 32 $resultid = $result['id']; 33 34 //ユーザーをプランに加入する処理を実行。 35 Payjp\Payjp::setApiKey($secret); 36 $resultsub = Payjp\Subscription::create( 37 array( 38 "customer" => $resultid, 39 "plan" => $plan_data 40 ) 41 ); 42 43 //プランとユーザーを紐付けるidを取得 44 $resultsubid = $resultsub['id']; 45 46 //データベースにあるユーザーデータに、決済関連のidをまとめて保存 47 $userplandata = mysqli_select_db($mysqli,'userdata'); 48 //今回はplanrank=プランのランク(s0001) planid=プラン決済id payid=顧客id registrationtime=決済時間を登録しています。 49 //データベースにも予めカラムを作っておいてください。 50 $userplandata = mysqli_query($mysqli,"UPDATE userdata SET planrank='$plan_data',planid='$resultsubid',payid='$resultid' where mail = '$mail'"); 51 52 53 } catch (Exception $e) { 54 55 //もしエラーがあった場合はエラーメッセージを返します。 56 $miss = $getmessage = $e->getMessage(); 57 58 }; 59 60 //最後にjsonでエラーがあった場合のエラーメッセージを返します。 61 header('Content-Type: application/json; charset=utf-8'); 62 echo json_encode( $miss );

投稿2020/04/27 09:28

naofu_web

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/04/27 09:35

んーでも、エラーの時のエラーメッセージだけしか返さないならJSONにする意味ないような気がします。 reult:0 / 1 で設定して、0の時だけerror にメッセージ定義して返し、JavaScript側で参照するようにした方が、使い方としては適切です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問