|
| 1 | +# SOLAPI PHP SDK |
| 2 | + |
| 3 | +**Generated:** 2026-01-27 |
| 4 | +**Commit:** a27d32f |
| 5 | +**Branch:** master |
| 6 | + |
| 7 | +## OVERVIEW |
| 8 | + |
| 9 | +PHP SDK for SOLAPI messaging API (SMS, LMS, MMS, Kakao Alimtalk/BMS, Voice, Fax) targeting Korean telecom. PSR-18 HTTP client abstraction, PHP 7.1+. |
| 10 | + |
| 11 | +## STRUCTURE |
| 12 | + |
| 13 | +``` |
| 14 | +solapi-php/ |
| 15 | +├── src/ |
| 16 | +│ ├── Services/ # Entry point (SolapiMessageService) |
| 17 | +│ ├── Libraries/ # HTTP client, auth, utilities (4 files) |
| 18 | +│ ├── Models/ |
| 19 | +│ │ ├── Request/ # API request DTOs (7 files) |
| 20 | +│ │ ├── Response/ # API response DTOs (17 files) |
| 21 | +│ │ ├── Kakao/ # Kakao options (4 files) |
| 22 | +│ │ │ └── Bms/ # Brand Message Service (14 files) ← See Bms/AGENTS.md |
| 23 | +│ │ ├── Voice/ # Voice options (3 files) |
| 24 | +│ │ └── Fax/ # Fax options (1 file) |
| 25 | +│ └── Exceptions/ # Custom exceptions (5 files) |
| 26 | +├── tests/ |
| 27 | +│ ├── Models/ # Unit tests |
| 28 | +│ └── E2E/ # Integration tests |
| 29 | +├── composer.json # PSR-4: Nurigo\Solapi\ → src/ |
| 30 | +└── phpunit.xml # Test configuration |
| 31 | +``` |
| 32 | + |
| 33 | +## WHERE TO LOOK |
| 34 | + |
| 35 | +| Task | Location | Notes | |
| 36 | +|------|----------|-------| |
| 37 | +| Send messages | `Services/SolapiMessageService.php` | Main entry point, all public methods | |
| 38 | +| Build message | `Models/Message.php` | Fluent builder, extends BaseMessage | |
| 39 | +| HTTP requests | `Libraries/Fetcher.php` | Singleton, PSR-18 client | |
| 40 | +| Auth header | `Libraries/Authenticator.php` | HMAC-SHA256, static method | |
| 41 | +| HTTP transport | `Libraries/HttpClient.php` | stream_context-based, PSR-18 compliant | |
| 42 | +| Kakao Alimtalk | `Models/Kakao/KakaoOption.php` | pfId, templateId, buttons, variables | |
| 43 | +| Kakao BMS | `Models/Kakao/KakaoBms.php` | Brand messages, 8 chatBubbleTypes | |
| 44 | +| BMS validation | `Models/Kakao/Bms/BmsValidator.php` | Field requirements by type | |
| 45 | +| Voice options | `Models/Voice/VoiceOption.php` | voiceType, headerMessage, tailMessage | |
| 46 | +| Fax options | `Models/Fax/FaxOption.php` | fileIds array | |
| 47 | +| Error handling | `Exceptions/` | BaseException, HttpException, BmsValidationException | |
| 48 | +| Request DTOs | `Models/Request/` | SendRequest, GetMessagesRequest, etc. | |
| 49 | +| Response DTOs | `Models/Response/` | SendResponse, GroupMessageResponse, etc. | |
| 50 | + |
| 51 | +## CODE MAP |
| 52 | + |
| 53 | +**Entry Point:** |
| 54 | +```php |
| 55 | +$service = new SolapiMessageService($apiKey, $apiSecret); |
| 56 | +$response = $service->send($message); |
| 57 | +``` |
| 58 | + |
| 59 | +**Call Flow:** |
| 60 | +``` |
| 61 | +SolapiMessageService |
| 62 | + → Fetcher::getInstance() [singleton] |
| 63 | + → Authenticator::getAuthorizationHeaderInfo() [static] |
| 64 | + → NullEliminator::array_null_eliminate() [static] |
| 65 | + → HttpClient::sendRequest() [PSR-18] |
| 66 | + → stream_context + file_get_contents |
| 67 | + → Response DTOs |
| 68 | +``` |
| 69 | + |
| 70 | +**Key Classes:** |
| 71 | +| Class | Type | Role | |
| 72 | +|-------|------|------| |
| 73 | +| `SolapiMessageService` | Service | Primary API (send, uploadFile, getMessages, getGroups, getBalance) | |
| 74 | +| `Message` | Model | Fluent builder with 12 setters | |
| 75 | +| `Fetcher` | Library | Singleton HTTP client, credential storage | |
| 76 | +| `HttpClient` | Library | PSR-18 stream-based implementation | |
| 77 | +| `Authenticator` | Library | HMAC-SHA256 auth header generation | |
| 78 | +| `NullEliminator` | Library | Recursive null removal for JSON | |
| 79 | +| `BmsValidator` | Validator | BMS field validation by chatBubbleType | |
| 80 | + |
| 81 | +**Model Hierarchy:** |
| 82 | +``` |
| 83 | +BaseMessage → Message (fluent builder) |
| 84 | +BaseKakaoOption → KakaoOption (fluent builder) |
| 85 | + └── KakaoBms (fluent builder, 8 types) |
| 86 | + └── Bms/* components (14 files) |
| 87 | +``` |
| 88 | + |
| 89 | +## CONVENTIONS |
| 90 | + |
| 91 | +**Namespace:** `Nurigo\Solapi\*` (PSR-4 from `src/`) |
| 92 | + |
| 93 | +**Patterns:** |
| 94 | +- Fluent builder: `$msg->setTo("...")->setFrom("...")->setText("...")` |
| 95 | +- Singleton: `Fetcher::getInstance($key, $secret)` |
| 96 | +- Public properties with getter/setter pairs on models |
| 97 | +- Korean PHPDoc comments (수신번호, 발신번호, 메시지 내용) |
| 98 | + |
| 99 | +**Type Safety:** |
| 100 | +- Full type hints on method params/returns |
| 101 | +- PHPDoc `@var`, `@param`, `@return`, `@throws` annotations |
| 102 | +- PHP 7.1 compatible (no union types, no enums) |
| 103 | + |
| 104 | +**Enum-Like Constants:** |
| 105 | +- `VoiceType::FEMALE`, `VoiceType::MALE` |
| 106 | +- `BmsChatBubbleType::TEXT`, `IMAGE`, `WIDE`, etc. |
| 107 | +- All have `values()` static method |
| 108 | + |
| 109 | +**Tidy First (Kent Beck):** |
| 110 | +- Separate structural and behavioral changes into distinct commits |
| 111 | +- Tidy related code before making feature changes |
| 112 | +- Guard clauses, helper variables/functions, code proximity |
| 113 | + |
| 114 | +## ANTI-PATTERNS |
| 115 | + |
| 116 | +- **Silent null returns:** get* methods return `null` on any exception — always check response validity |
| 117 | +- **Singleton state:** Fetcher retains credentials — don't mix API keys in same process |
| 118 | +- **No interfaces:** Service/Fetcher have no contracts — mocking requires concrete class extension |
| 119 | +- **Hardcoded timezone:** `Asia/Seoul` set in Authenticator — affects global timezone |
| 120 | +- **Hardcoded country:** `"82"` default in BaseMessage — Korean-only by default |
| 121 | + |
| 122 | +## UNIQUE STYLES |
| 123 | + |
| 124 | +- **Korean comments:** PHPDoc descriptions in Korean |
| 125 | +- **PSR-18 via stream:** Uses `file_get_contents` + `stream_context_create`, not cURL |
| 126 | +- **Null elimination:** Removes nulls before JSON serialization |
| 127 | + |
| 128 | +## COMMANDS |
| 129 | + |
| 130 | +```bash |
| 131 | +# Install |
| 132 | +composer require solapi/sdk |
| 133 | + |
| 134 | +# Run all tests |
| 135 | +composer test |
| 136 | + |
| 137 | +# Run unit tests only |
| 138 | +composer test:unit |
| 139 | + |
| 140 | +# Run E2E tests only |
| 141 | +composer test:e2e |
| 142 | + |
| 143 | +# Run with coverage |
| 144 | +composer test:coverage |
| 145 | +``` |
| 146 | + |
| 147 | +## NOTES |
| 148 | + |
| 149 | +- **Examples:** External repo at `github.com/solapi/solapi-php-examples` |
| 150 | +- **API docs:** `developers.solapi.com` |
| 151 | +- **PHP requirement:** 7.1+ (ext-json, allow_url_fopen or custom PSR-18 client) |
| 152 | +- **Dependencies:** psr/http-client, psr/http-message, nyholm/psr7 |
| 153 | +- **BMS details:** See `src/Models/Kakao/Bms/AGENTS.md` for Brand Message Service specifics |
0 commit comments