【cluster】ワールド内課金時に課金情報をGoogleスプレッドシートに記録する実装サンプル

clusterのワールド内課金は現状誰から購入されたものかわからないようで、活用用途を広げるためにも購入時に履歴をGoogleスプレッドシート内に記入する方法をまとめてみました。

参考にされる際は情報の取り扱い、またclusterのガイドラインを遵守した上、自己責任にてご利用いただくようお願いいたします。

※わんぱくさんのDeep Lobby(https://cluster.mu/w/44f9059d-01e5-41c2-bc86-ab032fd8f65b)にて導入いただきました。

①Googleスプレッドシートの設定

Googleスプレットシートを作成

一番上の行に下記見出しを記入しましょう。他の人に見られないようにアクセス権は制限付きにしておくようにしてください。

1列目:商品ID
2列目:購入者
3列目:コイン数

4列目:ワールド名
5列目:購入日時

Google App Scriptを設定する

こちらが外部通信ファイルからデータを受信し、スプレッドシートに登録する箇所となります。

Googleスプレッドシート上部メニューの「拡張機能>Apps Script」からプロジェクトを開き、下記コードをコピペ後、「新しいデプロイ」を行ってWebアプリのURLを発行しましょう。

function doPost(e) {
  var pid = e.parameter.pid;
  var cid = e.parameter.cid;
  var cc  = e.parameter.cc;
  var wid = e.parameter.wid;
  var date = e.parameter.date;
  var spread = SpreadsheetApp.getActiveSpreadsheet();
  var lastRow = spread.getSheets()[0].getLastRow();
  spread.getSheets()[0].getRange((lastRow + 1), 1).setValue(pid);
  spread.getSheets()[0].getRange((lastRow + 1), 2).setValue(cid);
  spread.getSheets()[0].getRange((lastRow + 1), 3).setValue(cc);
  spread.getSheets()[0].getRange((lastRow + 1), 4).setValue(wid);
  spread.getSheets()[0].getRange((lastRow + 1), 5).setValue(date);
  var jsonData = {
    pid: pid,
    cid: cid,
    cc: cc,
    wid: wid,
    date: date,
    result: 'ok'
  }
  return ContentService.createTextOutput(JSON.stringify(jsonData))
    .setMimeType(ContentService.MimeType.JSON);
}

「新しいデプロイ」の際は、「Webアプリ」を指定、「次のユーザーとして実行」を「自分」に、「アクセスできるユーザー」を「全員」としてください。デプロイの際アクセス権限を求められますので、ログインしている自分のユーザーをクリックしましょう。

その後警告のダイアログが表示されますが、あくまで警告ですのでそのまま左下の「詳細」リンクから進んでゆけばデプロイが完了し、WebアプリのIDが発行されます。

②外部通信用のPHPファイルをWebサーバーに設置

ご自身のサーバーに下記PHPファイルを設置してください。コードは特にいじる必要はありません。設置後の当ファイルのURL(フルパス)が外部通信URLとなります。

payment.php(ファイル名は任意)

<?php
header('Content-Type: application/json');

// データ受信
$json  = file_get_contents("php://input");
$array = json_decode($json, true);
$in    = $array['request'];

// データの分解
$parts = explode('|', $in);
$verify = $parts[0];  // トークン
$pid    = $parts[1];  // 購入された商品ID
$cid    = $parts[2];  // 支払者のclusterId
$cc     = $parts[3];  // コイン数
$wid    = $parts[4];  // ワールドID
$gid    = $parts[5];  // GAS URLのID

// Googleスプレッドシートに送信
date_default_timezone_set('Asia/Tokyo');
$url = 'https://script.google.com/macros/s/' . $gid . '/exec';
$data = array(
  'pid' => $pid,
  'cid' => $cid,
  'cc'  => $cc,
  'wid'  => $wid,
  'date' => date("Y-m-d H:i:s"),
);
$context = array(
  'http' => array(
    'method'  => 'POST',
    'header'  => implode("\r\n", array('Content-Type: application/x-www-form-urlencoded',)),
    'content' => http_build_query($data)
  )
);
$response_json = file_get_contents($url, false, stream_context_create($context));
$response_data = json_decode($response_json);

// 通知メール送信
// mb_language("Japanese");
// mb_internal_encoding("utf-8");
// $to = 'メールアドレス'; 
// $header = "From: clusterワールド内課金";
// $subject = "clusterワールド内課金通知";
// $body = "購入者:" . $cid . "\n商品:" . $pid . "\nワールド:" . $wid . "\nコイン数:" . $cc;
// mb_send_mail($to,$subject,$body,$header);

// 返却
$out = array('verify' => $verify, 'response' => $result);
print(json_encode($out));
?>

※サーバー環境で動作が変わる可能性がございますのでご了承ください。

③ワールド内課金プログラムに送信処理を追加

clusterのワールド内課金スクリプトを下記のように改変し、productId、verify、cc、wid、gidの値(定数)を設定してください。

const productId = ""; // 商品ID
const verify = "";    // CCKで発行されたトークン
const cc = "";        // クラスターコイン数
const wid = "";       // ワールドID(名称でも可)
const gid = "";       // Google App ScriptのアプリID

$.onStart(() => {
  // 購入通知を購読する
  $.subscribePurchase(productId);
});

$.onUpdate(deltaTime => {
  // 10秒に1回、定期的にスペース内にいるすべてのプレイヤーの購入状況を確認する
  let timer = $.state.timer ?? 0;
  timer -= deltaTime;
  if (timer <= 0) {
    timer += 10;
    const allPlayers = $.getPlayersNear(new Vector3(), Infinity);
    $.getOwnProducts(productId, allPlayers, "");
  }
  $.state.timer = timer;
});

$.onInteract(player => {
    player.requestPurchase(productId, "");
});

$.onPurchaseUpdated((player, productId) => {
  // 商品が購入された場合、スペース内にいるすべてのプレイヤーの購入状況を確認する
  const allPlayers = $.getPlayersNear(new Vector3(), Infinity);
  $.getOwnProducts(productId, allPlayers, "");
});

$.onGetOwnProducts((ownProducts, meta, errorReason) => {
  //  商品の所持状況を取得したとき
  let total = 0;
  for (let ownProduct of ownProducts) {
    // スペース内での商品所持数の合計を計算
    total += ownProduct.plusAmount - ownProduct.minusAmount;
  }
  // スペース内での商品所持数の合計数を表示
  $.subNode("Text").setText("みんなのサポート数: " + total);
});

$.onRequestPurchaseStatus((meta, status, errorReason, player) => {
  if (status == PurchaseRequestStatus.Purchased) {
      // Play Audio Source Gimmickがついたアイテムにシグナルを送る
      $.sendSignalCompat("this", "SupportSE");
      // 外部通信送信処理
      $.callExternal(verify + "|" + productId + "|" + player.userId + "|" + cc + "|" + wid + "|" + gid, "check");
  }
});

執筆者:なび公

タイトルとURLをコピーしました