Chrome拡張に買い物かごボタンを追加した
いやもう、タイトルの通りでございます。いつものAmazon to Rakutenに買い物かごをしれっと追加しました。まあ、つけた方が個人的に便利やし。そこで工夫した点など。
必要な情報
まず、実際の楽天ブックスの商品ページの買い物かごボタンを見て、どんなデータをPOSTしてやればいいのかを調べます。
1
2
3
4
5
6
7
8
9
10
<form method="post" action="https://books.step.rakuten.co.jp/rms/mall/book/bs/Cart">
<div>
<span class="unit">個数 </span>
<input value="1" type="text" size="4" name="units" id="units">
<input value="買い物かごに入れる" type="submit">
<input type="hidden" value="213310" name="shop_bid">
<input type="hidden" value="14034556" name="item_id" id="ScItemGet">
<input type="hidden" value="1" name="inventory_flag">
</div>
</form>
見た感じ、いじる必要がありそうなとこは、
2. "item_id"を商品に合わせて変更
の2点。楽天ブックスは楽天市場の1店舗なので、"shop_bid"は全部一緒のはず。"inventory_flag"は、まあようわからんけどこのままでいいっしょ。
実装
ということで、実質コードを書く必要があるのは"item_id"だけ。ところが厄介なことに、"item_id"はなんとAPIに入っていないので、もっかいXMLHttpRequestを叩いて無理矢理取ってくることに。http通信2回分なんて待ってられないので、一回目のAPI通信で取得したデータはすぐ表示しつつ、続けてitem_idが取得出来次第ボタンを表示っていう仕様にしました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
chrome.extension.onConnect.addListener(function(port) {
console.assert(port.name == "AtoR");
port.onMessage.addListener(function(msg) {
if(msg.status == "start"){
//ページアクションのアイコンを表示
chrome.pageAction.show(port.sender.tab.id);</p>
//楽天APIから商品を検索
query = "http://api.rakuten.co.jp/rws/3.0/json?" +
"developerId=" + devId +
"&affiliateId=" + afiId +
"&operation=" + opr +
"&version=" + ver+
"&keyword=" + encodeURI(msg.title);</p>
api.open("GET",query,true);
api.onreadystatechange = sourceGet(port);
api.send(null);
}
else if(msg.status == "null"){
content = "このページでは使用できません。";
}
else{
sourceGet(port);
}
});
});
//タブが変更された時の処理
chrome.tabs.onSelectionChanged.addListener(function(tabid){
chrome.tabs.getSelected(null, function(tab) {
・・・
});
});
function sourceGet(port){
if (api.readyState == 4 && api.status == 200){
response = eval('[' + api.responseText + ']')[0];</p>
if(response['Header']['Status'] == 'Success'){
items = response['Body']['BooksTotalSearch']['Items']['Item'];</p>
//商品データを1つずつhtmlに出力
content = '<table width="300">';
for(i=0;i<items.length;i++){
content = content+'<tr><td><a href="'+items[i]['affiliateUrl']+'"><img src="'+items[i]['mediumImageUrl']+'" /></a></td><td style="width:200px;vertical-align:top;">タイトル:<a href="'+items[i]['affiliateUrl']+'" target="_blank">'+items[i]['title']+'</a><br />著者:'+items[i]['author']+'<br />価格(税込):'+setComma(items[i]['itemPrice'])+'円<br />ポイント:'+Math.floor(items[i]['itemPrice']/1.05/100)+'ポイント<br /><img src="img/star_';
if(items[i]['reviewAverage'] == 0) content = content + '0';
else if(items[i]['reviewAverage'] > 0 && items[i]['reviewAverage'] < 1) content = content + '0.5';
else if(items[i]['reviewAverage'] == 1) content = content + '1';
else if(items[i]['reviewAverage'] > 1 && items[i]['reviewAverage'] < 2) content = content + '1.5';
else if(items[i]['reviewAverage'] == 2) content = content + '2';
else if(items[i]['reviewAverage'] > 2 && items[i]['reviewAverage'] < 3) content = content + '2.5';
else if(items[i]['reviewAverage'] == 3) content = content + '3';
else if(items[i]['reviewAverage'] > 3 && items[i]['reviewAverage'] < 4) content = content + '3.5';
else if(items[i]['reviewAverage'] == 4) content = content + '4';
else if(items[i]['reviewAverage'] > 4 && items[i]['reviewAverage'] < 5) content = content + '4.5';
else if(items[i]['reviewAverage'] == 5) content = content + '5';
content = content + '.png" />('+items[i]['reviewCount']+')<br />買い物かごに入れる</td></tr>';
rakuten.open("GET",items[i]["itemUrl"],true);
rakuten.onreadystatechange = function(){
if (rakuten.readyState == 4 && rakuten.status == 200){
rr = rakuten.responseText;
rr.match(/value="([^"]*)"[^>]*id="ScItemGet"/);
rr = RegExp.$1;
//買い物かご
cart = '<form method="post" action="https://books.step.rakuten.co.jp/rms/mall/book/bs/Cart" target="_blank">';
cart = cart + '<div>';
cart = cart + '<input value="1" type="hidden" name="units" id="units">';
cart = cart + '<input value="買い物かごに入れる" type="submit">';
cart = cart + '<input type="hidden" value="213310" name="shop_bid">';
cart = cart + '<input type="hidden" value="'+rr+'" name="item_id" id="ScItemGet">';
cart = cart + '<input type="hidden" value="1" name="inventory_flag">'
cart = cart + '</div>'
cart = cart + '</form>'
content = content.replace("買い物かごに入れる", cart);
viewContent();
}
};
rakuten.send(null);
}
content = content+'</table>';
viewContent();
}
・・・
}
・・・
}
61行目で、まずベタ文字で「買い物かごに入れる」って表示しつつ、63行目以下で2度目の通信を行ってます。item_idは67行目の正規表現で強引にゲット。正規表現が一発で決まると気持ちいい。
無事にitem_idが取れたらベタ文字をformタグで置換。めでたしめでたし。
「最短で学ぶReactとReduxの基礎から実践まで」10%OFFクーポン
UdemyでReactとReduxの動画講座を公開しています。
このブログの読者限定クーポンを使って、基礎から実践までを学びましょう。
「最短で学ぶReactとReduxの基礎から実践まで」10%OFFクーポン
UdemyでReactとReduxの動画講座を公開しています。
このブログの読者限定クーポンを使って、基礎から実践までを学びましょう。