PHP code example of lemoba / mobile-monetization

1. Go to this page and download the library: Download lemoba/mobile-monetization library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

lemoba / mobile-monetization example snippets


use Illuminate\Support\Facades\Route;
use Lemoba\MobileMonetization\Facades\MobileMonetization;

Route::post('/auth/apple', function () {
    $data = request()->validate([
        'identity_token' => ['

// config/mobile-monetization.php
'cache' => [
    'store' => env('MOBILE_MONETIZATION_CACHE_STORE', 'redis'),
    'key_prefix' => env('MOBILE_MONETIZATION_CACHE_PREFIX', 'mobile_monetization'),
    'jwks_ttl' => 3600,
    'oauth_token_ttl' => 3300,
],

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$identity = MobileMonetization::verifyAppleIdentityToken($identityToken, $nonce);

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$identity = MobileMonetization::verifyGoogleIdToken($idToken, $nonce);

[
    'provider' => 'apple',
    'provider_user_id' => '...',
    'email' => '...',
    'email_verified' => true,
    'claims' => [],
]

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$purchase = MobileMonetization::verifyAppleTransactionId($transactionId);

// 或者客户端已拿到 signedTransactionInfo:
$purchase = MobileMonetization::verifyAppleSignedTransaction($signedTransactionInfo);

use Lemoba\MobileMonetization\Facades\MobileMonetization;

// StoreKit 1 / StoreKit 2 Product.SubscriptionOffer.Signature 使用。
$offer = MobileMonetization::applePromotionalOfferSignature(
    productIdentifier: 'vip_month',
    subscriptionOfferId: 'intro_month_50',
    appAccountToken: (string) $user->id, // 如果客户端传 UUID,这里传同一个 UUID。
);

// 返回:
// [
//     'keyIdentifier' => 'PROMO12345',
//     'nonce' => '47f8a4b5-5957-4d56-bf0f-c7416f33c701',
//     'timestamp' => 1714567890123,
//     'signature' => 'base64-encoded-signature',
// ]

MobileMonetization::applePromotionalOfferSignature(
    string $productIdentifier,
    string $subscriptionOfferId,
    string $appAccountToken = '',
    ?string $nonce = null,
    ?int $timestamp = null,
);

[
    'identifier' => 'intro_month_50',
    'keyIdentifier' => $offer['keyIdentifier'],
    'nonce' => $offer['nonce'],
    'signature' => $offer['signature'],
    'timestamp' => $offer['timestamp'],
]

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$compactJws = MobileMonetization::applePromotionalOfferJws(
    productId: 'vip_month',
    offerIdentifier: 'intro_month_50',
    transactionId: $originalTransactionId, // 可选。
);

MobileMonetization::applePromotionalOfferJws(
    string $productId,
    string $offerIdentifier,
    ?string $transactionId = null,
    ?string $nonce = null,
);

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$parsed = MobileMonetization::parseGoogleOrderNo($purchaseToken);

$orderNo = $parsed['order_no'];     // 客户端放入 obfuscatedExternalProfileId 的业务订单号。
$productId = $parsed['product_id']; // Google Play 返回的商品 ID。

// 1. 根据 $orderNo 查询自己的订单。
// 2. 校验订单里的 product_id 是否等于 $productId。
// 3. 根据订单类型选择订阅验单或一次性商品验单。
if ($order->is_subscription) {
    $purchase = MobileMonetization::verifyGoogleSubscription(
        productId: $productId,
        purchaseToken: $purchaseToken,
    );
} else {
    $purchase = MobileMonetization::verifyAndConsumeGoogleProduct(
        productId: $productId,
        purchaseToken: $purchaseToken,
    );
}

[
    'order_no' => 'ORDER_202601010001',
    'product_id' => 'vip_month',
    'type' => 'subscription', // 或 consumable
    'transaction_id' => 'GPA.0000-0000-0000-00000',
    'purchase_token' => $purchaseToken,
    'raw' => $googleResponse,
]

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$purchase = MobileMonetization::verifyAndConsumeGoogleProduct(
    productId: 'coins_100',
    purchaseToken: $purchaseToken,
);

if ($purchase->valid) {
    // 1. 用 transaction_id 做唯一索引或幂等锁。
    // 2. 根据 product_id 查自己的金币配置。
    // 3. 写订单、写金币流水、增加余额。
}

$purchase = MobileMonetization::verifyAndConsumeGoogleProduct(
    purchaseToken: $purchaseToken,
);

if ($purchase->valid) {
    $orderNo = $purchase->externalProfileId; // 客户端 setObfuscatedProfileId() 传入的业务订单号。
    $productId = $purchase->productId;       // Google Play 返回的商品 ID。

    // 1. 根据 $orderNo 查自己的订单。
    // 2. 校验订单里的 product_id 是否等于 $productId。
    // 3. 完成幂等发货。
}

$purchase = MobileMonetization::verifyGoogleProduct(
    purchaseToken: $purchaseToken,
);

if ($purchase->valid) {
    // 调用方完成自己的幂等入库 / 发货流程。

    MobileMonetization::consumeGoogleProduct(
        productId: $purchase->productId,
        purchaseToken: $purchaseToken,
    );
}

$purchase = MobileMonetization::verifyGoogleSubscription(
    productId: 'vip_month',
    purchaseToken: $purchaseToken,
);

if ($purchase->active()) {
    // 1. 用 original_transaction_id 或 transaction_id 做幂等。
    // 2. 用 expires_at_ms 更新自己的会员到期时间。
    // 3. 保存 raw 字段,方便排查 Google Play 返回的原始状态。
}

$offer = MobileMonetization::verifyGoogleSubscriptionOffer(
    productId: 'vip_month',
    purchaseToken: $purchaseToken,
    expectedBasePlanId: 'monthly',
    expectedOfferId: 'intro_month_50',
);

if ($offer['purchase']->active()) {
    // 确认 base_plan_id / offer_id 匹配后,更新会员权益。
    $offer['base_plan_id']; // monthly
    $offer['offer_id'];     // intro_month_50
    $offer['offer_tags'];   // Google Play Console 配置的标签
}

[
    'purchase' => $purchase,
    'base_plan_id' => 'monthly',
    'offer_id' => 'intro_month_50',
    'offer_tags' => [],
    'pricing_phase' => null,
    'raw_offer_details' => [],
]

$purchase->toArray();

[
    'platform' => 'ios|android',
    'product_id' => 'coins_60',
    'transaction_id' => '...',
    'original_transaction_id' => '...',
    'type' => 'consumable|subscription',
    'valid' => true,
    'active' => true,
    'consumable' => true,
    'purchased_at_ms' => 1710000000000,
    'expires_at_ms' => null,
    'raw' => [],
]

if ($purchase->valid && $purchase->consumable) {
    // 1. 用 transaction_id 建唯一索引或幂等锁。
    // 2. 根据 product_id 查自己的金币配置。
    // 3. 写订单、写金币流水、增加余额。
}

if ($purchase->active() && $purchase->type === 'subscription') {
    // 1. 用 original_transaction_id 关联订阅。
    // 2. 用 expires_at_ms 更新 VIP 到期时间。
}

use Illuminate\Http\Request;
use Lemoba\MobileMonetization\Facades\MobileMonetization;

public function reward(Request $request)
{
    $reward = MobileMonetization::verifyLevelPlayRewardCallback($request);

    // 调用方业务逻辑:
    // 1. 用 event_id 做唯一幂等,event_id 对应 LevelPlay eventId。
    // 2. 用 user_id/app_user_id 或 dynamic_user_id 映射自己的用户。
    // 3. 用 order_id 关联前端传入的自定义订单号(如果配置了 customParameters)。
    // 4. 根据 reward_amount 或自己的广告奖励配置给金币。
    // 5. 写金币流水、余额变化、任务记录等。

    return response(MobileMonetization::levelPlayOkResponse($reward['event_id']), 200)
        ->header('Content-Type', 'text/plain');
}

$reward = MobileMonetization::verifyLevelPlayRewardCallback($request, dev: true);

[
    'event_id' => '...',
    'user_id' => '...',
    'app_user_id' => '...',
    'dynamic_user_id' => '...',
    'reward_item' => 'coins',
    'reward_amount' => 10,
    'rewards' => '10',
    'country' => 'SG',
    'publisher_sub_id' => '0',
    'custom_parameters' => [
        'order_id' => 'ORD-20260429-001',
    ],
    'order_id' => 'ORD-20260429-001',
    'ad_unit' => '...',
    'placement' => '...',
    'network' => '...',
    'timestamp' => 1710000000,
    'raw' => [],
]

'fcm' => [
    'android' => [
        'project_id' => env('FCM_ANDROID_PROJECT_ID'),
        'service_account_json_path' => env('FCM_ANDROID_SERVICE_ACCOUNT_JSON_PATH'),
    ],
    'ios' => [
        'project_id' => env('FCM_IOS_PROJECT_ID'),
        'service_account_json_path' => env('FCM_IOS_SERVICE_ACCOUNT_JSON_PATH'),
    ],
],

use Lemoba\MobileMonetization\Facades\MobileMonetization;

$message = MobileMonetization::sendFcmToToken(
    platform: 'ios',
    token: $deviceToken,
    title: 'VIP 到期提醒',
    body: '你的会员即将到期',
    data: [
        'type' => 'vip_expiring',
        'user_id' => (string) $userId,
    ],
    options: [
        'apns' => [
            'payload' => [
                'aps' => [
                    'sound' => 'default',
                ],
            ],
        ],
    ]
);

$message->toArray();

$message = MobileMonetization::sendFcmToToken(
    platform: 'android',
    token: $deviceToken,
    title: '金币到账',
    body: '看广告奖励已发放',
    data: [
        'type' => 'coins_granted',
        'amount' => '10',
    ],
    options: [
        'android' => [
            'priority' => 'HIGH',
        ],
    ]
);

$message = MobileMonetization::sendFcmToTopic(
    platform: 'android',
    topic: 'vip_users',
    title: '新剧上线',
    body: '会员可抢先观看'
);
bash
php artisan vendor:publish --tag=mobile-monetization-config
text
config/mobile-monetization.php  # Redis cache store、cache key 前缀、TTL
config/mobile-auth.php          # Apple / Google 登录
config/mobile-payments.php      # App Store / Google Play 支付
config/mobile-ads.php           # LevelPlay 广告
config/mobile-push.php          # FCM 推送,Android/iOS 两套 Firebase 文件