bored-programmers / laravel-wolt
Wolt is a Laravel package that allows you to integrate your restaurant with the Wolt platform. It provides a simple and easy-to-use API for syncing your menu and managing orders.
Requires
- php: >=8.1
- laravel/framework: >=10.0
- spatie/laravel-data: >=4.6
README
Wolt is a Laravel package that allows you to integrate your restaurant with the Wolt platform. It provides a simple and easy-to-use API for syncing your menu and managing orders.
Table of Contents
- Requirements
- Installation
- Usage
- Contribution Guidelines
- Changelog
- License
- Contact Information
- Acknowledgments
Requirements
- PHP 8.1 or higher
- Laravel 10.0 or higher
Installation
To install Wolt, you need to run the following command:
composer require bored-programmers/laravel-wolt
Publish the configuration file and set up your environment variables.
php artisan vendor:publish --tag=wolt-config
Update your .env
file with the following variables:
WOLT_MENU_API_USERNAME=your_menu_api_username WOLT_MENU_API_PASSWORD=your_menu_api_password WOLT_ORDER_API_KEY=your_order_api_key WOLT_VENUE_ID=your_venue_id WOLT_IS_SANDBOX=true/false
Usage
Sync Menu
To sync your menu with Wolt, use the WoltService::syncMenu
method.
Here is an example of how you can use the DTOs to create a menu and sync it with Wolt.
use BoredProgrammers\Wolt\DTO\MenuData; use BoredProgrammers\Wolt\DTO\CategoryData; use BoredProgrammers\Wolt\DTO\SubcategoryData; use BoredProgrammers\Wolt\DTO\ItemData; use BoredProgrammers\Wolt\DTO\TranslationData; use BoredProgrammers\Wolt\DTO\CaffeineContentData; use BoredProgrammers\Wolt\DTO\WeeklyAvailabilityData; use BoredProgrammers\Wolt\DTO\WeeklyVisibilityData; use BoredProgrammers\Wolt\DTO\OptionData; use BoredProgrammers\Wolt\DTO\SelectionRangeData; use BoredProgrammers\Wolt\DTO\OptionValueData; use BoredProgrammers\Wolt\DTO\SubOptionValueData; use BoredProgrammers\Wolt\DTO\ProductInformationData; use BoredProgrammers\Wolt\DTO\NutritionInformationData; use BoredProgrammers\Wolt\DTO\NutritionValuesData; use BoredProgrammers\Wolt\DTO\NutrientData; use Spatie\LaravelData\DataCollection; // Example Translations for Category $categoryNameTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Beverages']), TranslationData::from(['lang' => 'fr', 'value' => 'Boissons']) ]); // Example Translations for Subcategory $subCategoryNameTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Hot Drinks']), TranslationData::from(['lang' => 'fr', 'value' => 'Boissons Chaudes']) ]); // Example Translations for Item $itemNameTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Espresso']), TranslationData::from(['lang' => 'fr', 'value' => 'Espresso']) ]); $itemDescriptionTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Rich and bold espresso coffee']), TranslationData::from(['lang' => 'fr', 'value' => 'Café espresso riche et audacieux']) ]); // Example Translations for Options $optionNameTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Milk Type']), TranslationData::from(['lang' => 'fr', 'value' => 'Type de Lait']) ]); $optionValueNameTranslation1 = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Whole Milk']), TranslationData::from(['lang' => 'fr', 'value' => 'Lait entier']) ]); $optionValueNameTranslation2 = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Soy Milk']), TranslationData::from(['lang' => 'fr', 'value' => 'Lait de soja']) ]); // Example Sub-option Value $subOptionValueNameTranslation = new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Vanilla Syrup']), TranslationData::from(['lang' => 'fr', 'value' => 'Sirop de vanille']) ]); // Example Nutrition Information $nutritionInformation = NutritionInformationData::from([ 'serving_size' => 'per_100_ml', 'nutrition_values' => NutritionValuesData::from([ 'energy_kcal' => NutrientData::from(['unit' => 'kcal', 'value' => 5]), 'energy_kj' => NutrientData::from(['unit' => 'kj', 'value' => 20]), 'fats' => NutrientData::from(['unit' => 'g', 'value' => 0.1]), 'saturated_fats' => NutrientData::from(['unit' => 'g', 'value' => 0.05]), 'mono_unsaturated_fats' => NutrientData::from(['unit' => 'g', 'value' => 0.01]), 'poly_unsaturated_fats' => NutrientData::from(['unit' => 'g', 'value' => 0.01]), 'carbohydrate' => NutrientData::from(['unit' => 'g', 'value' => 0.5]), 'sugar' => NutrientData::from(['unit' => 'g', 'value' => 0.1]), 'starch' => NutrientData::from(['unit' => 'g', 'value' => 0.2]), 'polyols' => NutrientData::from(['unit' => 'g', 'value' => 0.0]), 'protein' => NutrientData::from(['unit' => 'g', 'value' => 0.2]), 'salt' => NutrientData::from(['unit' => 'g', 'value' => 0.01]), 'sodium' => NutrientData::from(['unit' => 'mg', 'value' => 5]), 'fibres' => NutrientData::from(['unit' => 'g', 'value' => 0.1]), 'vitamin_c' => NutrientData::from(['unit' => 'mg', 'value' => 0.0]), 'potassium' => NutrientData::from(['unit' => 'mg', 'value' => 80]), 'calcium' => NutrientData::from(['unit' => 'mg', 'value' => 10]), 'magnesium' => NutrientData::from(['unit' => 'mg', 'value' => 2]), 'chloride' => NutrientData::from(['unit' => 'mg', 'value' => 5]), 'fluoride' => NutrientData::from(['unit' => 'mg', 'value' => 0.0]) ]) ]); // Example Product Information $productInformation = ProductInformationData::from([ 'ingredients' => new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Water, Coffee Beans']), TranslationData::from(['lang' => 'fr', 'value' => 'Eau, Grains de café']) ]), 'additives' => new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'None']), TranslationData::from(['lang' => 'fr', 'value' => 'Aucun']) ]), 'nutrition_facts' => new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Low calories']), TranslationData::from(['lang' => 'fr', 'value' => 'Faible en calories']) ]), 'nutrition_information' => $nutritionInformation, 'allergens' => new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'None']), TranslationData::from(['lang' => 'fr', 'value' => 'Aucun']) ]), 'producer_information' => new DataCollection([ TranslationData::from(['lang' => 'en', 'value' => 'Local Roastery']), TranslationData::from(['lang' => 'fr', 'value' => 'Torréfacteur local']) ]) ]); // Example Option with Sub-option Values $optionValue1 = OptionValueData::from([ 'name' => $optionValueNameTranslation1, 'selection_range' => SelectionRangeData::from(['min' => 0, 'max' => 1]), 'price' => 0.50, 'enabled' => true, 'default' => true, 'external_data' => 'option-value-1', 'sub_option_values' => new DataCollection([ SubOptionValueData::from([ 'name' => $subOptionValueNameTranslation, 'selection_range' => SelectionRangeData::from(['min' => 0, 'max' => 1]), 'price' => 0.20, 'enabled' => true, 'default' => false, 'external_data' => 'sub-option-value-1' ]) ]) ]); $optionValue2 = OptionValueData::from([ 'name' => $optionValueNameTranslation2, 'selection_range' => SelectionRangeData::from(['min' => 0, 'max' => 1]), 'price' => 0.60, 'enabled' => true, 'default' => false, 'external_data' => 'option-value-2', 'sub_option_values' => null ]); $option = OptionData::from([ 'name' => $optionNameTranslation, 'type' => 'SingleChoice', 'selection_range' => SelectionRangeData::from(['min' => 1, 'max' => 1]), 'external_data' => 'option-1', 'values' => new DataCollection([$optionValue1, $optionValue2]) ]); // Example Item $item = ItemData::from([ 'name' => $itemNameTranslation, 'description' => $itemDescriptionTranslation, 'image_url' => 'https://example.com/espresso.jpg', 'price' => 2.99, 'sales_tax_percentage' => 0.07, 'alcohol_percentage' => null, 'caffeine_content' => CaffeineContentData::from(['serving_size' => 'per_100_ml', 'value' => 212.0]), 'weekly_availability' => new DataCollection([ WeeklyAvailabilityData::from([ 'opening_day' => 'MONDAY', 'opening_time' => '08:00', 'closing_day' => 'MONDAY', 'closing_time' => '20:00' ]) ]), 'weekly_visibility' => new DataCollection([ WeeklyVisibilityData::from([ 'opening_day' => 'MONDAY', 'opening_time' => '08:00', 'closing_day' => 'MONDAY', 'closing_time' => '20:00' ]) ]), 'enabled' => true, 'delivery_methods' => ['takeaway', 'homedelivery'], 'options' => new DataCollection([$option]), 'external_data' => 'item-espresso-001', 'product_information' => $productInformation ]); // Example Subcategory $subcategory = SubcategoryData::from([ 'name' => $subCategoryNameTranslation, 'description' => null, 'items' => new DataCollection([$item]) ]); // Example Category $category = CategoryData::from([ 'name' => $categoryNameTranslation, 'description' => null, 'subcategories' => new DataCollection([$subcategory]) ]); // Example Menu $menu = MenuData::from([ 'currency' => 'USD', 'primary_language' => 'en', 'categories' => new DataCollection([$category]) ]); $response = WoltService::syncMenu($menuData);
Get Order
To retrieve an order, use the WoltService::getOrder
method.
You will get Order ID from your webhook called by Wolt.
More about it > here: Wolt Webhook Documentation.
I recommend using
spatie/laravel-webhook-client
package for handling webhooks.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::getOrder($orderId);
Accept Order
To accept an order, use the WoltService::acceptOrder
method.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::acceptOrder($orderId);
Reject Order
To reject an order, use the WoltService::rejectOrder
method.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::rejectOrder($orderId);
Mark Order as Ready
To mark an order as ready, use the WoltService::markReadyOrder
method.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::markReadyOrder($orderId);
Mark Order as Delivered
To mark an order as delivered, use the WoltService::markDeliveredOrder
method.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::markDeliveredOrder($orderId);
Confirm Preorder
To confirm a preorder, use the WoltService::confirmPreorder
method.
use BoredProgrammers\Wolt\WoltService; $orderId = 'your_wolt_order_id'; $response = WoltService::confirmPreorder($orderId);
Contribution Guidelines
We welcome contributions to Wolt. If you'd like to contribute, please fork the repository, make your changes, and submit a pull request. We have a few requirements for contributions:
- Follow the PSR-2 coding standard.
- Only use pull requests for contributions.
Changelog
For a detailed history of changes, see releases on GitHub.
License
This project is licensed under the MIT license.
Contact Information
For any questions or concerns, please feel free to create a discussion on GitHub.
Credits
Created by Matěj Černý from Bored Programmers.
Acknowledgments
We would like to thank all the contributors who have helped to make Wolt a better package.