Added purchase/item endpoint.

The endpoints checks if you can afford the item and have completed the required challenges when any exist.

It also throws an error if you try to buy an item you already have in your inventory.
This commit is contained in:
Vari
2024-02-28 17:17:39 +01:00
parent 223f94a07b
commit 1d133cfefe
5 changed files with 208 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Http\Controllers\Api\Player;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Player\PurchaseItemRequest;
use App\Http\Responses\Api\Player\Purchase\PurchaseItemResponse;
use App\Http\Responses\Api\Player\Purchase\WalletEntry;
use App\Models\Game\CatalogItem;
use App\Models\Game\Challenge;
use App\Models\Game\CharacterData;
use App\Models\Game\PickedChallenge;
use App\Models\User\PlayerData;
use Illuminate\Database\UniqueConstraintViolationException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Ramsey\Uuid\Uuid;
class PurchaseController extends Controller
{
public function purchaseItem(PurchaseItemRequest $request)
{
$user = Auth::user();
$playerData = $user->playerData();
$quantityToBuy = $request->wantedQuantity - $request->oldQuantity;
$itemToBuy = CatalogItem::find($request->objectId);
if(!$this->hasCompletedChallengeForItem($itemToBuy, $playerData))
return response('Not completed required challenge/s', 418);
if( $playerData->currency_a < ($itemToBuy->default_cost_currency_a * $quantityToBuy) ||
$playerData->currency_b < ($itemToBuy->default_cost_currency_b * $quantityToBuy) ||
$playerData->currency_c < ($itemToBuy->default_cost_currency_c * $quantityToBuy))
return response('Not enough Currency', 418);
try {
$playerData->inventory()->attach($itemToBuy);
}
catch (UniqueConstraintViolationException $e) {
return response('Item already in inventory.', 418);
}
$playerData->currency_a -= $itemToBuy->default_cost_currency_a * $quantityToBuy;
$playerData->currency_b -= $itemToBuy->default_cost_currency_b * $quantityToBuy;
$playerData->currency_c -= $itemToBuy->default_cost_currency_c * $quantityToBuy;
$playerData->save();
$hexItemId = Uuid::fromString($itemToBuy->id)->getHex()->toString();
$response = new PurchaseItemResponse(
$user->id,
$hexItemId,
$quantityToBuy,
new WalletEntry(
$playerData->currency_a,
$itemToBuy->default_cost_currency_a * $quantityToBuy,
$playerData->currency_b,
$itemToBuy->default_cost_currency_b * $quantityToBuy,
$playerData->currency_c,
$itemToBuy->default_cost_currency_c * $quantityToBuy,
),
[$hexItemId],
);
return json_encode($response);
}
protected function hasCompletedChallengeForItem(CatalogItem &$item, PlayerData &$playerData)
{
/** @var Challenge $foundChallenge */
$foundChallenge = $item->requiredChallenges()->first();
if ($foundChallenge !== null) {
return $foundChallenge->getProgressForPlayer($playerData->id) >= $foundChallenge->completion_value;
}
$characterIds = [];
$playerData->characterData()->get(['id'])->each(function (CharacterData $data) use ($characterIds) {
$characterIds[] = $data->id;
});
$foundChallenge = PickedChallenge::where('catalog_item_id', '=', $item->id)
->whereIn('character_data_id', $characterIds)->first();
if($foundChallenge === null)
return true;
return $foundChallenge->progress >= $foundChallenge->completion_value;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace App\Http\Requests\Api\Player;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Ramsey\Uuid\Uuid;
class PurchaseItemRequest extends FormRequest
{
public string $objectId;
public int $oldQuantity;
public int $wantedQuantity;
public string $currencyGroup;
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'data.objectId' => 'required|string',
'data.oldQuantity' => 'required|int',
'data.wantedQuantity' => 'required|int',
'data.currencyGroup' => 'required|string',
];
}
protected function passedValidation()
{
$this->objectId = Uuid::fromString($this->input('data.objectId'))->toString();
$this->oldQuantity = $this->input('data.oldQuantity');
$this->wantedQuantity = $this->input('data.wantedQuantity');
$this->currencyGroup =$this->input('data.currencyGroup');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Responses\Api\Player\Purchase;
class PurchaseItemResponse
{
public function __construct(
public string $playerId,
public string $objectId,
public int $quantity,
public WalletEntry $walletEntry,
public array $rewardItems = [],
)
{
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Http\Responses\Api\Player\Purchase;
class WalletEntry implements \JsonSerializable
{
public function __construct(
public int $currencyA,
public int $debitCurrencyA,
public int $currencyB,
public int $debitCurrencyB,
public int $currencyC,
public int $debitCurrencyC,
)
{
}
public function jsonSerialize(): mixed
{
$result = [];
if($this->debitCurrencyA > 0)
$result[] = [
'balance' => $this->currencyA,
'currency' => 'CurrencyA',
'currencyGroup' => 'SoftCurrencyGroup',
'debited' => $this->debitCurrencyA
];
if($this->debitCurrencyB > 0)
$result[] = [
'balance' => $this->currencyB,
'currency' => 'CurrencyB',
'currencyGroup' => 'SoftCurrencyGroup',
'debited' => $this->debitCurrencyB
];
if($this->debitCurrencyC > 0)
$result[] = [
'balance' => $this->currencyC,
'currency' => 'CurrencyC',
'currencyGroup' => 'SoftCurrencyGroup',
'debited' => $this->debitCurrencyC
];
return $result;
}
}

View File

@@ -7,6 +7,7 @@
use App\Http\Controllers\Api\Player\MetadataController;
use App\Http\Controllers\Api\Player\ModifierCenterController;
use App\Http\Controllers\Api\Player\PlayerController;
use App\Http\Controllers\Api\Player\PurchaseController;
use App\Http\Controllers\Api\VersionController;
use Illuminate\Support\Facades\Route;
@@ -46,6 +47,8 @@
Route::post('extensions/challenges/getChallengeProgressionBatch', [ChallengeController::class, 'getProgressionBatch']);
Route::post('extensions/challenges/getChallenges', [ChallengeController::class, 'getChallenges']);
Route::post('extensions/purchase/item', [PurchaseController::class, 'purchaseItem']);
Route::get('wallet/currencies', [CurrencyController::class, 'getCurrencies']);
Route::get('inventories', [PlayerController::class, 'getInventory']);