◉RORK LABEN
●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主
記事一覧/ビジネス
⟐ ビジネス/2026-06-28上級

リワード広告の報酬を、端末からの合図だけで配らない — Rork(Expo)アプリのSSV検証をWorkerで組む

リワード広告の「視聴完了」を端末側のコールバックだけで信じると、報酬の二重付与やなりすましが起こります。AdMobのサーバーサイド検証(SSV)コールバックをCloudflare Workerで署名検証し、transaction_idで冪等化して報酬を安全に配るまでの実装をまとめます。

AdMob71RewardedSSVCloudflare Workers25個人開発215Rork577収益化67

✦ プレミアム記事

私自身、壁紙アプリと癒し系アプリをいくつか個人開発で運用していて、リワード広告は「広告を見てくれた人にだけ、もう一歩だけ良い体験を返す」ための大事な仕組みになっています。ある時、解析ログを眺めていて、特定のユーザーだけ報酬付与の回数が視聴回数より明らかに多いことに気づきました。端末側の onUserEarnedReward をそのまま信じて報酬を配っていたので、改造されたクライアントから同じ合図を何度も送られていたのです。

リワード広告の報酬は、端末からの「見終わりました」という合図だけで配ってはいけません。そこを守ってくれるのが、AdMobのサーバーサイド検証(SSV)です。ここからは、Rorkで生成したExpoアプリにSSVを組み込み、検証用のエンドポイントをCloudflare Workerで実装するところまでを、実際に運用しているコードに近い形でたどっていきます。

端末からの合図を信じるとどこが破れるのか

クライアント側のコールバックは、便利ですが信頼境界の外にあります。改造アプリ、プロキシによるリプレイ、エミュレータからの連打。どれも端末の中で完結する処理なので、こちらからは真偽を区別できません。報酬がアプリ内通貨やサブスク日数のように「価値のあるもの」だと、ここが直接の収益漏れになります。

SSVは、この合図をGoogleのサーバー経由に置き換えます。ユーザーが広告を最後まで見ると、AdMobのサーバーがこちらの指定したURLに対して署名付きのコールバックを送ってきます。署名はGoogleの秘密鍵で作られているので、こちらは対応する公開鍵で検証するだけで「これは本当にAdMobから来た、改ざんされていない通知だ」と確認できます。端末は一切信じません。

観点端末側コールバックのみSSV併用
なりすまし区別できない署名検証で弾ける
リプレイ(連打)そのまま通るtransaction_idで冪等化
報酬確定の場所端末(信頼境界外)自前サーバー(境界内)
オフライン時即時付与できるサーバー到達後に確定

ここで大切なのは、SSVは端末側コールバックを置き換えるのではなく、報酬の「確定」だけをサーバーに移す、という線引きです。UIの「報酬が付きました」という即時フィードバックは端末側で出してよいのですが、残高を本当に増やすのはWorkerが署名検証を終えた後にします。

端末側 — 報酬を誰に渡すかをSSVに教える

まず端末側で、SSVコールバックに自分のユーザーIDを載せます。react-native-google-mobile-ads では、広告リクエスト時に serverSideVerificationOptions を渡します。userId と customData が、後でコールバックの custom_data パラメータとして戻ってきます。

import { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads';
 
const adUnitId = __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxx/yyyyyyyy';
 
export function loadRewardedAd(userId: string, purpose: string) {
  const rewarded = RewardedAd.createForAdRequest(adUnitId, {
    serverSideVerificationOptions: {
      // SSVコールバックの custom_data に入って戻ってくる
      userId,
      customData: JSON.stringify({ purpose, ts: Date.now() }),
    },
  });
 
  rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => rewarded.show());
 
  // 端末側の合図は「UIの即時演出」だけに使う。残高は触らない
  rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD, () => {
    showOptimisticRewardUI(); // 「付与処理中…」の表示にとどめる
  });
 
  rewarded.load();
}

customData に時刻や目的を載せておくと、後でサーバー側のログと突き合わせる時に役立ちます。ここで端末側の EARNED_REWARD に残高更新を書かないのがポイントです。書いてしまうと、せっかくSSVを入れても元の穴がそのまま残ります。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦AdMobの公開鍵を24時間以内キャッシュで取得し、署名対象のクエリ文字列を取り違えずにECDSAで検証するWorkerの完全コード
✦transaction_idをKVで冪等キーにして、リトライ5回でも報酬を一度しか配らない二重付与防止の設計
✦custom_dataにユーザーIDを載せて端末と無関係に報酬を確定する、不正視聴に強い報酬確定フロー
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

⟐ ビジネス2026-05-02
個人開発で月10万円を超えるアプリ収益化の実践戦略 — Rork で作って試した収益チューニングの全工程
個人開発のアプリで月10万円の壁を超えるための実践戦略。Rork で作ったアプリで実際に試した広告収益最大化、IAP 価格チューニング、サブスク継続率向上、ASO 強化までの全工程を、12 年間の収益化試行錯誤に基づく数値とコードで解説します。
⟐ ビジネス2026-05-02
Rork で作るモバイルアプリの収益化入門 — 広告・課金・サブスクの選び方を実例で整理する
Rork で作ったモバイルアプリの収益化入門として、広告・アプリ内課金・サブスクリプションの三つを向き不向きと実装の急所で整理します。自分のアプリの数字で三モデルを試算する式、AdMob メディエーションで eCPM を底上げする実務、コホートで見る継続率まで一通り扱います。
⟐ ビジネス2026-04-26
Rork Max のネイティブアプリを App Store 上位へ — 設計から AdMob・StoreKit 2・サブスクまでの順番
Rork Max で作った SwiftUI ネイティブアプリを、カテゴリ上位に残るアプリへ育てるための順番を書き残します。広告を出すかどうかを1か所で決める AdGate、StoreKit 2 の Transaction.updates 監視、ASO とリテンションの線引きまで、動くコード付きです。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます