@Blog{zip358.com}
日常日誌からプログラムやYOUTUBER紹介、旅日記まで日々更新中です。
webpushのLaravelを使用しないパターンを箇条書き、フロントエンド側は
2024.11.14
おはようございます.webpushのLaravelを使用しないパターンを箇条書き、フロントエンドは過去記事を参照ください.まずwebpushを使用するにはパブリックキーとシークレットキーが必要になります.下記のURLより発行してみてください.
https://web-push-codelab.glitch.me
フロントエンド側でサービスワーカーの登録された識別データをバックエンドに送信.
// db.php: データベース接続の設定
function getDbConnection() {
$host = 'localhost';
$dbname = 'your_database';
$username = 'your_username';
$password = 'your_password';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch (PDOException $e) {
die("DB接続エラー: " . $e->getMessage());
}
}
// endpoint_register.php: エンドポイントをデータベースに登録
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$endpoint = $_POST['endpoint'];
$auth = $_POST['auth'];
$p256dh = $_POST['p256dh'];
if ($endpoint && $auth && $p256dh) {
$pdo = getDbConnection();
$stmt = $pdo->prepare("INSERT INTO push_subscriptions (endpoint, auth, p256dh) VALUES (?, ?, ?)");
$stmt->execute([$endpoint, $auth, $p256dh]);
echo "登録成功";
} else {
echo "エンドポイントデータが不完全です";
}
}
バックエンド側で下記のようなコードでデータを保存します.
次にminishlink/web-pushというライブラリを使用し登録されたデータを元に送信処理を行います.
composer require minishlink/web-push
// message_send.php: データベースからエンドポイントを取得し、プッシュ通知を送信
require 'db.php';
require 'vendor/autoload.php';
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
// VAPIDキーの設定
$auth = [
'VAPID' => [
'subject' => 'https://example.com',
'publicKey' => 'YOUR_PUBLIC_VAPID_KEY',
'privateKey' => 'YOUR_PRIVATE_VAPID_KEY',
],
];
$webPush = new WebPush($auth);
// データベースからサブスクリプション情報を取得
$pdo = getDbConnection();
$stmt = $pdo->query("SELECT endpoint, auth, p256dh FROM push_subscriptions");
$subscriptions = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($subscriptions as $sub) {
$subscription = Subscription::create([
'endpoint' => $sub['endpoint'],
'publicKey' => $sub['p256dh'],
'authToken' => $sub['auth'],
]);
// 送信するメッセージ
$message = json_encode(['title' => '通知タイトル', 'body' => 'メッセージ内容']);
// プッシュ通知の送信
$webPush->sendNotification($subscription, $message);
}
// 送信キューの実行
foreach ($webPush->flush() as $report) {
$endpoint = $report->getRequest()->getUri()->__toString();
if ($report->isSuccess()) {
echo "成功: {$endpoint}\n";
} else {
echo "失敗: {$endpoint}: {$report->getReason()}\n";
}
}
著者名 @taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
$stmt, catch, endpoint, FETCH_ASSOC, foreach, getDbConnection, getMessage, Laravel, minishlink, MYSQL, PDO, PDOException, prepare, query, setAttribute, subscription, VALUES, vendor, Webpush, シークレットキー,
webPush通知機能 完成!👏.これでブラウザ閉じても通知可能✌.
2024.11.12
おはようございます.金曜日の休みを使ってwebPush通知機能を追加しました、これでブラウザ閉じても通知されるようになります.Laravel側はお見せできませんがどういう技術を使用したか書いていきます.まずLaravelの拡張ライブラリを使用しました.
下記のリンクを参照しライブラリをインストールしてみてください.
https://laravel-notification-channels.com/webpush/#installation
インストール手順はリンク先に書いていますので、それを参照しその後フロント側を設定します.下記は作りかけのコードですが通知登録が可能でバックエンド側からスケジュールで通知を飛ばすことが出来ます.
フロント側はサービスワーカーのJSファイルとユーザー通知の許可行い、その情報をバックエンドに渡す処理ファイルが存在します.サービスワーカーJSコードはググれば書き方が出ているので検索してみてください.
公開するのは通知許可を行う方のファイルになります💁あとヒントとしてバックエンドも少し公開します.
const vapidPublicKey = import.meta.env.VITE_VAPID_PUBLIC_KEY;
async function setupPushNotifications() {
if (Notification.permission === 'granted') {
try {
// サービスワーカーを登録
await navigator.serviceWorker.register('/assets/js/npush-service-worker.js').then(async(registration) => {
if ('serviceWorker' in navigator && 'PushManager' in window) {
try {
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
});
const response = await fetch('/save-subscription', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('[name="csrf-token"]').content
},
body: JSON.stringify(subscription),
});
if (!response.ok) throw new Error('サブスクリプションの保存に失敗しました');
new Notification('ご登録', {
body: 'ご登録有難う御座います',
});
} catch (error) {
console.error('Push subscription error:', error);
}
} else if (result !== 'granted') {
console.log('通知の権限が拒否されました。');
}
});
console.log('サービスワーカーが正常に登録されました');
} catch (error) {
console.error('サービスワーカーの登録に失敗しました:', error);
}
}
}
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
document.getElementById('enable-notifications').addEventListener('click', async () => {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
setupPushNotifications();
} else {
console.log('通知の権限が拒否されました。');
}
});
これで通知の識別データが取得し登録が可能になります.登録されたデータを元に個別通知、全員に通知などが可能になります.なお、会員登録されたユーザーのみ通知が飛ぶシステムです.
$endpoint = $request->endpoint;
$token = $request->keys['auth'];
$key = $request->keys['p256dh'];
$user = $request->user();
$user->updatePushSubscription($endpoint, $key, $token);
上記のデータがバックエンド側に保存されます.それを使用しユーザーにどのように送信すれば良いか?
use App\Notifications\Reserved;
$user = User::find(1);
$user->notify(new Reserved($reservation));
こんな感じだと思ってください.抜粋しているのであくまでもヒントです.あとはご自身で考えて対応してください.
明日へ続く
著者名 @taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
addEventListener, assets, async, catch, document.getElementById, document.querySelector, headers, installation, keys, METHOD, padding, permission, rawData.charCodeAt, rawData.length, registration, repeat, replace, save-subscription, subscription, then,
サービスワーカー、フロント側のコード.スターウォーズみたいだね.
2024.11.09
おはようございます.サービスワーカーのプッシュ通知で使用するフロント側のコードの一部部分.このコードのregistration.pushManager等からググるとブラウザを閉じても通知できる方法などが記載しているサイトが見つかるかもしれません.尚、このサイトではこれ以上の情報を記載するつもりはないですが、後日、通知の機能の動画などを掲載するつもりではいます.
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.ready.then(function(registration) {
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('VAPID_PUBLIC_KEY')
}).then(function(subscription) {
fetch('/api/save-subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(subscription),
});
}).catch(function(error) {
console.error('Push subscription error:', error);
});
});
}
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
その時、どのようなライブラリーを使用したかや技術の一部を公開しようと思っています.ただ、全体のコードを全て公開するつもりは今の所はないです.理由は有料な情報でありこれで商売している人がいると思うので全ての技術情報を公開は控えるつもりです.
明日へ続く
著者名 @taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
API, application, applicationServerKey, atob, catch, fetch, headers, METHOD, navigator, outputArray, padding, rawData.charCodeAt, rawData.length, registration, repeat, replace, save-subscription, subscription, then, userVisibleOnly,
PayjpとLaravel
2024.02.16
おはようございます、Pay.jpで商品支払いとサブスクリプションに対応したコードを書いたので記載しときます。なお、似たようなコードがネットに落ちていると思いますがどうしても似通ってしまいますね。因みにサブスクリプションの場合、Pay.jpの管理画面からサブスクリプション(プラン)の作成して名前付けしないといけません。
また、クレジットカードの記入画面はリファレンスのサンプルから作るのが早いかなって思います。そしてクレジットカードのデモ用コードもPay.jpのリファレンスかドキュメントに記載していますので、そちらを参考にしてください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Payjp\Payjp;
use Payjp\Charge;
use Payjp\Customer;
use Payjp\Subscription;
class PaymentController extends Controller
{
//
public function index()
{
return view('payment.index');
}
public function payment(Request $request)
{
Payjp::setApiKey(config('app.secret_key'));
// クレカトークンが送られる(tok_xxxxxxxxxxxxxxxxxxxx)
$token = $request->input('tokenId');
$result = Charge::create(array(
"card" => $token,
"amount" => 3500,
"currency" => 'jpy',
'description' => 'ABC商品',
'product' => 'ABC',
'metadata' => [
'user_id' => '123',
'user_name' => 'あいうえお',
'email' => 'mail@abc.com'
]
));
return back();
}
public function subindex()
{
return view('payment.subscription');
}
public function subscription(Request $request)
{
$token = $request->input('tokenId');
Payjp::setApiKey(config('app.secret_key'));
// 顧客情報の登録
$customer = Customer::create(array(
'email' => 'mail@abc.com',
'card' => $token, // クライアントから受け取ったトークンを記載します。
'metadata' => [
'user_id' => '123',
'user_name' => 'あいうえお',
'email' => 'mail@example.com'
]
));
// 課金処理
$charge = Subscription::create(array(
'customer' => $customer->id,
'plan' => 'plan01', // あらかじめpay.jp側に登録しておいた値。
'metadata' => [
'user_id' => '123',
'user_name' => 'あいうえお',
'email' => 'mail@example.com'
]
));
return back();
}
}
著者名 @taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
array, Charge, config, create, Customer, index, input, lt, mail@example.com, namespace AppHttpControllers, PayJP, payment.subscription, request, setApiKey, subindex, subscription, use IlluminateHttpRequest, use PayjpSubscription, サブスクリプション, リファレンス,