早速ソース
- misoca-callback.php
今回、$_GETパラメータにて送信する値を受け取っているので、
適宜ここは環境に合わせて調整が必要
<?php
session_start();
const APP_ID = "{MisocaのAPP ID}";
const SECRET = "{MisocaのAPP SECRET}"
// このファイルのパス
const REDIRECT_URL = "{ドメイン}/misoca-callback.php";
// トークン情報保存用
if (!isset($_SESSION['tokens'])) {
$_SESSION['tokens'] = [
'access_token' => null,
'refresh_token' => null,
'expires_in' => 0,
];
}
// アクセストークンが無効な場合
if (empty($_SESSION['tokens']['access_token']) || $_SESSION['tokens']['expires_in'] < time()) {
// アクセストークン発行
getAccessToken();
}
// 請求書作成
createInvoice($_SESSION['tokens']['access_token']);
/**
* 請求書を作成する
*
* @param $accessToken
* @return void
*/
function createInvoice($accessToken) {
// 請求書情報作成
$invoiceData = array(
'subject' => $_GET['subject'] ?? '請求書タイトル',
'contact_id' => $_GET['contact_id'] ?? 1,
'issue_date' => isset($_GET['issue_date']) && strtotime($_GET['issue_date']) ? $_GET['issue_date'] : date('Y-m-d'),
'items' => [],
);
// 商品がある場合は追加
foreach ($_GET['items'] ?? [] as $item) {
$invoiceData['items'][] = [
'name' => $item['name'],
'quantity' => $item['quantity'],
'unit_price' => $item['price']
];
}
// 請求書作成
$ch = curl_init('https://app.misoca.jp/api/v3/invoice');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Authorization: Bearer $accessToken",
"Content-Type: application/json",
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($invoiceData));
$response = curl_exec($ch);
$response = json_decode($response, true);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
exit("cURL Error #:" . $err);
} elseif (empty($response['id'])) {
echo "エラーが発生しました<br>";
foreach ($response['reasons'] ?? [] as $reason) {
echo $reason . "<br>";
}
} else {
$invoiceId = $response['id'];
// 請求書PDF取得
$pdfUrl = "https://app.misoca.jp/api/v3/invoice/{$invoiceId}/pdf";
$ch = curl_init($pdfUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Authorization: Bearer $accessToken",
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$pdfContent = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
exit("cURL Error #:" . $err);
} else {
// PDFファイルを保存
$pdfFilePath = "invoices/invoice_{$invoiceId}.pdf";
file_put_contents($pdfFilePath, $pdfContent);
echo "請求書を作成しました。保存先パス: {$pdfFilePath}";
// ダウンロード
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="invoice_' . $invoiceId . '.pdf"');
header('Content-Length: ' . strlen($pdfContent));
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Expires: 0');
echo $pdfContent;
exit;
}
}
}
/**
* アクセストークンを取得
*
* @return mixed|void
*/
function getAccessToken()
{
$client_id = APP_ID;
$client_secret = SECRET;
$redirect_uri = REDIRECT_URL;
// 認証コードがある場合、アクセストークンを取得
if (isset($_GET['code'])) {
$code = $_GET['code'];
$url = 'https://app.misoca.jp/oauth2/token';
$data = array(
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $redirect_uri,
'client_id' => $client_id,
'client_secret' => $client_secret,
);
$options = array(
'http' => array(
'header' => "Content-Type: application/x-www-form-urlencoded",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$tokens = json_decode($result, true);
if (!empty($tokens['access_token'])) {
// セッションに保存
$_SESSION['tokens'] = [
'access_token' => $tokens['access_token'],
'refresh_token' => $tokens['refresh_token'],
'expires_in' => time() + $tokens['expires_in'],
];
} else {
exit('Failed to obtain access token');
}
// リフレッシュトークンがある場合リフレッシュする
} elseif (!empty($_SESSION['tokens']['refresh_token']) && $_SESSION['tokens']['expires_in'] < time()) {
refreshToken();
} else {
// ユーザーを認証用URLにリダイレクト
$scope = 'write';
$response_type = 'code';
$auth_url = "https://app.misoca.jp/oauth2/authorize?response_type={$response_type}&client_id={$client_id}&redirect_uri={$redirect_uri}&scope={$scope}";
header('Location: ' . $auth_url);
exit;
}
}
/**
* トークンをリフレッシュする
*
* @return void
*/
function refreshToken()
{
$refresh_token = $_SESSION['tokens']['refresh_token'];
$url = 'https://app.misoca.jp/oauth2/token';
$data = array(
'grant_type' => 'refresh_token',
'refresh_token' => $refresh_token,
'client_id' => APP_ID,
'client_secret' => SECRET,
);
$options = array(
'http' => array(
'header' => "Content-Type: application/x-www-form-urlencoded",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$tokens = json_decode($result, true);
if (!empty($tokens['access_token'])) {
// 新しいアクセストークンとリフレッシュトークンをセッションに保存
$_SESSION['tokens'] = [
'access_token' => $tokens['access_token'],
'refresh_token' => isset($tokens['refresh_token']) ? $tokens['refresh_token'] : $refresh_token, // 新しいリフレッシュトークンがあれば更新
'expires_in' => time() + $tokens['expires_in'],
];
} else {
exit('Failed to refresh access token');
}
}
PHPにて、Misoca APIと連携して請求書を作成 & ダウンロードした時のメモ