- https://developers.line.biz/ja/ を開いてLINEアカウントでログイン
- 「プロバイダーを作成」→ 名前を入力(例:reserve-me)
- 「新規チャンネル作成」→「Messaging API」を選択
- チャンネル名(例:RESERVE ME 通知)と説明を入力して作成
- 「チャンネル基本設定」タブ → あなたのユーザーID(U から始まる文字列)をコピーしてメモ
- 「Messaging API設定」タブ → 一番下の「チャンネルアクセストークン」→「発行」→ コピーしてメモ
LINE公式アカウントの作成画面が先に出た場合は、設定 → Messaging API → 「Messaging APIを利用する」から進めてください。
メモ欄:
ユーザーID:U________________________________
アクセストークン:____________________________
- https://script.google.com/ を開いて「新しいプロジェクト」を作成
- 下のコードをコピーして「コード.gs」に貼り付ける(既存のコードは全て消してから)
- コードの上部3行を自分の情報に書き換える
const LINE_TOKEN = '【1でメモしたアクセストークン】';
const LINE_USER_ID = '【1でメモしたユーザーID】';
const SHEET_ID = '【2でメモしたスプレッドシートID】';
const CALENDAR_ID = 'primary';
function doPost(e) {
const data = JSON.parse(e.postData.contents);
let msg = '';
if (data.action === 'new') {
try { addRow(data); } catch(err) {}
msg = `【新しい予約】\n${data.name}さんから予約が届きました。\n\n📅 ${data.date}\n🕐 ${data.slotLabel}\n📚 ${data.subject}\n📝 ${data.memo || 'なし'}`;
} else if (data.action === 'approve') {
try { updateStatus(data.id, '承認済み'); } catch(err) {}
try { addCalendar(data); } catch(err) {}
msg = `【承認完了】\n${data.name}さんの予約を承認しました。\n\n📅 ${data.date}\n🕐 ${data.slotLabel}\n📚 ${data.subject}`;
} else if (data.action === 'reject') {
try { updateStatus(data.id, 'お断り'); } catch(err) {}
msg = `【お断り】\n予約をお断りしました。`;
} else if (data.action === 'cancel') {
try { updateStatus(data.id, 'キャンセル'); } catch(err) {}
msg = `【キャンセル】\n予約がキャンセルされました。`;
}
try { if (msg) sendLine(msg); } catch(err) {}
return ContentService.createTextOutput(JSON.stringify({ok:true}))
.setMimeType(ContentService.MimeType.JSON);
}
function addCalendar(data) {
const cal = CalendarApp.getCalendarById(CALENDAR_ID);
const parts = data.slotLabel.split(':');
const hour = parseInt(parts[0]);
const min = parseInt(parts[1]) || 0;
const dateParts = data.date.split('-');
const start = new Date(dateParts[0], dateParts[1]-1, dateParts[2], hour, min);
const end = new Date(start.getTime() + 60 * 60 * 1000);
cal.createEvent(`【RESERVE ME】${data.name}さん(${data.subject})`, start, end, {
description: `科目:${data.subject}\n連絡先:${data.contact}`
});
}
function addRow(data) {
const sheet = SpreadsheetApp.openById(SHEET_ID).getActiveSheet();
if (sheet.getLastRow() === 0) {
sheet.appendRow(['予約ID','お名前','連絡先','メール','希望日','時間帯','科目','メモ','ステータス','受付日時']);
}
sheet.appendRow([data.id, data.name, data.contact, data.email || '',
data.date, data.slotLabel, data.subject, data.memo || '',
'承認待ち', new Date().toLocaleString('ja-JP')]);
}
function updateStatus(id, status) {
const sheet = SpreadsheetApp.openById(SHEET_ID).getActiveSheet();
const rows = sheet.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) {
if (String(rows[i][0]) === String(id)) {
sheet.getRange(i + 1, 9).setValue(status); break;
}
}
}
function sendLine(text) {
UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
method: 'post',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + LINE_TOKEN },
payload: JSON.stringify({ to: LINE_USER_ID, messages: [{ type: 'text', text: text }] })
});
}
function testSheet() {
SpreadsheetApp.openById(SHEET_ID).getActiveSheet().appendRow(['テスト','OK']);
}
function testCalendar() {
const cal = CalendarApp.getCalendarById(CALENDAR_ID);
cal.createEvent('RESERVE ME テスト', new Date(), new Date(Date.now() + 3600000));
}
- 「デプロイ」→「新しいデプロイ」→ 種類:ウェブアプリ
- 「アクセスできるユーザー」を全員に設定 →「デプロイ」
- 「Googleアカウントへのアクセスを許可」が出たら → 「詳細」→「移動」→「許可」
- 発行されたウェブアプリURLをコピーしてメモ
メモ欄:
GAS URL:https://script.google.com/macros/s/________/exec