docs: consolidate 53 files into 15 structured files in 3 folders

- business/ (5): club-commission, payment, ecommerce, membership, content
- technical/ (5): cms-arch, ui, deployment, migration, api
- overview/ (5): flowcharts, index, changelog, glossary, roadmap
- Removed all old folders: backoffice, cms, deployment, docs, frontoffice, migration, ui-modernization, business (old)
- Updated internal links with relative folder paths
This commit is contained in:
masoodafar-web
2026-02-18 22:29:37 +03:30
parent d7c32dab2a
commit efff5e9cd5
71 changed files with 3632 additions and 32267 deletions
+329
View File
@@ -0,0 +1,329 @@
# 🔌 API، Protobuf و یکپارچه‌سازی خارجی
> **منابع ادغام‌شده:** `FRONTOFFICE-CMS-API-COMPATIBILITY.md`, `REMAINING-TASKS.md`, `chatika-integration.md`, `payment-gateway.md`, `club-feature-management-services.md`
> **آخرین بروزرسانی:** اسفند ۱۴۰۴
---
## ۱. معماری ارتباطات
```
┌──────────────────────────────────────────────────────────────────┐
│ External Services │
│ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐ │
│ │ ZarinPal│ │ Kavenegar│ │ DayaLoan│ │ Chatika │ │
│ │ (IPG) │ │ (SMS) │ │ (Loan) │ │ (AI) │ │
│ └────┬────┘ └────┬─────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ ┌────▼───────────▼────────────▼────────────▼────┐ │
│ │ CMS Microservice │ │
│ │ (gRPC Server + Hangfire + EF Core) │ │
│ └────────────────┬───────────────────────────────┘ │
│ │ gRPC (Protobuf v3) │
│ ┌───────────┼───────────┐ │
│ ┌────▼────┐ ┌────▼────┐ │
│ │BackOffice│ │FrontOffice│ │
│ │(Blazor │ │(Blazor │ │
│ │ WASM) │ │ Server) │ │
│ └─────────┘ └──────────┘ │
└──────────────────────────────────────────────────────────────────┘
```
---
## ۲. gRPC Proto Definitions
### ۲.۱ لیست کامل سرویس‌ها
```protobuf
// ===== product.proto =====
service ProductService {
rpc GetProducts (GetProductsRequest) returns (GetProductsResponse);
rpc GetProductById (GetProductByIdRequest) returns (ProductMessage);
rpc CreateProduct (CreateProductRequest) returns (CreateProductResponse);
rpc UpdateProduct (UpdateProductRequest) returns (UpdateProductResponse);
rpc DeleteProduct (DeleteProductRequest) returns (Empty);
rpc GetProductsPaged (GetProductsPagedRequest) returns (GetProductsPagedResponse);
}
// ===== order.proto =====
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (CreateOrderResponse);
rpc GetOrders (GetOrdersRequest) returns (GetOrdersResponse);
rpc GetOrderById (GetOrderByIdRequest) returns (OrderMessage);
rpc UpdateOrderStatus (UpdateOrderStatusRequest) returns (Empty);
}
// ===== user.proto =====
service UserService {
rpc Register (RegisterRequest) returns (AuthResponse);
rpc Login (LoginRequest) returns (AuthResponse);
rpc GetProfile (GetProfileRequest) returns (UserProfileMessage);
rpc UpdateProfile (UpdateProfileRequest) returns (Empty);
rpc SendOtp (SendOtpRequest) returns (SendOtpResponse);
rpc VerifyOtp (VerifyOtpRequest) returns (VerifyOtpResponse);
}
// ===== club.proto =====
service ClubService {
rpc GetNetworkTree (GetNetworkTreeRequest) returns (NetworkTreeResponse);
rpc GetBalance (GetBalanceRequest) returns (BalanceResponse);
rpc ReadContract (ReadContractRequest) returns (ContractResponse);
rpc RequestContractOtp (RequestOtpRequest) returns (OtpResponse);
rpc VerifyContractOtp (VerifyOtpRequest) returns (VerifyOtpResponse);
rpc AcceptContract (AcceptContractRequest) returns (AcceptContractResponse);
rpc GetClubFeatures (GetFeaturesRequest) returns (FeaturesResponse);
}
// ===== payment.proto =====
service PaymentService {
rpc CreatePayment (CreatePaymentRequest) returns (CreatePaymentResponse);
rpc VerifyPayment (VerifyPaymentRequest) returns (VerifyPaymentResponse);
rpc GetPaymentStatus (PaymentStatusRequest) returns (PaymentStatusResponse);
}
// ===== blog.proto =====
service BlogService {
rpc GetPosts (GetPostsRequest) returns (GetPostsResponse);
rpc GetPostBySlug (GetPostBySlugRequest) returns (BlogPostMessage);
rpc CreatePost (CreatePostRequest) returns (CreatePostResponse);
rpc UpdatePost (UpdatePostRequest) returns (Empty);
rpc DeletePost (DeletePostRequest) returns (Empty);
}
// ===== inventory.proto =====
service InventoryService {
rpc GetInventory (GetInventoryRequest) returns (InventoryMessage);
rpc UpdateStock (UpdateStockRequest) returns (Empty);
rpc GetAllInventories (GetAllRequest) returns (InventoryListResponse);
}
// ===== sitepage.proto =====
service SitePageService {
rpc GetPage (GetPageRequest) returns (SitePageMessage);
rpc SaveSettings (SaveSettingsRequest) returns (Empty);
rpc GetAllPages (Empty) returns (PageListResponse);
}
// ===== file.proto =====
service FileService {
rpc Upload (stream UploadRequest) returns (UploadResponse);
rpc Download (DownloadRequest) returns (stream DownloadResponse);
rpc Delete (DeleteFileRequest) returns (Empty);
}
// ===== category.proto =====
service CategoryService {
rpc GetCategories (GetCategoriesRequest) returns (CategoryListResponse);
rpc CreateCategory (CreateCategoryRequest) returns (CreateCategoryResponse);
rpc UpdateCategory (UpdateCategoryRequest) returns (Empty);
}
// ===== config.proto =====
service SystemConfigService {
rpc GetConfig (GetConfigRequest) returns (ConfigResponse);
rpc UpdateConfig (UpdateConfigRequest) returns (Empty);
rpc GetAllConfigs (Empty) returns (ConfigListResponse);
}
```
### ۲.۲ Shared Messages
```protobuf
// ===== common.proto =====
message PaginationState {
int32 skip = 1;
int32 take = 2;
}
message PaginatedResponse {
int32 totalCount = 1;
int32 pageSize = 2;
int32 currentPage = 3;
}
message Empty {}
```
---
## ۳. External Service Integration
### ۳.۱ ZarinPal (پرداخت)
```csharp
public class ZarinPalService : IPaymentGateway
{
// Config
private readonly string _merchantId;
private readonly bool _isSandbox;
// Endpoints
const string PAYMENT_URL = "https://api.zarinpal.com/pg/v4/payment/request.json";
const string VERIFY_URL = "https://api.zarinpal.com/pg/v4/payment/verify.json";
const string SANDBOX_URL = "https://sandbox.zarinpal.com/pg/v4/payment/request.json";
// Flow
// 1. CreatePayment → Authority token
// 2. Redirect → https://www.zarinpal.com/pg/StartPay/{Authority}
// 3. Callback → VerifyPayment(Authority, Amount)
// 4. Result → RefID (reference number)
}
```
### ۳.۲ Kavenegar (SMS)
```csharp
public class KavenegarService : ISmsService
{
// Templates
const string OTP_TEMPLATE = "verify-foursat";
const string CONTRACT_TEMPLATE = "contract-verify";
const string WELCOME_TEMPLATE = "club-welcome";
// Rate Limiting
// ۱ SMS per phone per 60 seconds
// ۵ SMS per phone per hour
// ۲۰ SMS per phone per day
public async Task SendOtpAsync(string phone, string code)
{
await _api.VerifyLookup(phone, code, OTP_TEMPLATE);
}
}
```
### ۳.۳ Daya Loan (وام)
```csharp
public class DayaLoanService : ILoanService
{
// Hangfire job — هر ۱۵ دقیقه
// Polly retry: 3 attempts, exponential backoff (2s, 4s, 8s)
// Mock mode for staging (auto-approve)
public async Task<LoanResult> RequestLoanAsync(Guid userId, decimal amount)
{
if (_options.UseMock)
return LoanResult.Approved(amount);
var response = await _httpClient.PostAsync(
$"{_baseUrl}/api/loans/request",
new { UserId = userId, Amount = amount });
return MapResponse(response);
}
}
```
### ۳.۴ Chatika (AI)
```csharp
public class ChatikaService : IAiChatService
{
// Hangfire job — هر ۵ دقیقه
// Polly retry: 3 attempts
// Only for active club members
public async Task<string> GetResponseAsync(string userMessage)
{
var response = await _httpClient.PostAsync(
$"{_baseUrl}/api/chat",
new { Message = userMessage });
return response.Content.ReadAsStringAsync();
}
}
```
---
## ۴. API Compatibility Layer
### ۴.۱ FrontOffice Service Pattern
```csharp
// هر سرویس در FrontOffice یک wrapper بر gRPC client است
public class ProductService : IProductService
{
private readonly ProductServiceClient _client;
public ProductService(ProductServiceClient client)
{
_client = client;
}
public async Task<ProductListResult> GetProductsPagedAsync(
int skip, int take, Guid? categoryId = null, string? search = null)
{
try
{
var request = new GetProductsPagedRequest {
Pagination = new PaginationState { Skip = skip, Take = take },
CategoryId = categoryId?.ToString() ?? "",
SearchTerm = search ?? ""
};
var response = await _client.GetProductsPagedAsync(request);
return new ProductListResult(
response.Products.Select(MapToDto).ToList(),
response.TotalCount);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.Unavailable)
{
// CMS is down — show cached data or error
throw new ServiceUnavailableException("CMS service unavailable");
}
}
}
```
### ۴.۲ Error Handling
| gRPC Status | HTTP Equivalent | Handling |
|------------|-----------------|----------|
| `OK` | 200 | Return data |
| `NotFound` | 404 | Show "not found" message |
| `InvalidArgument` | 400 | Show validation errors |
| `Unauthenticated` | 401 | Redirect to login |
| `PermissionDenied` | 403 | Show "access denied" |
| `Unavailable` | 503 | Show "service down" |
| `Internal` | 500 | Show generic error |
---
## ۵. Proto Package Distribution
```
CMS/src/Protos/*.proto
pack-protos.sh
Foursat.CMSMicroservice.Protobuf.nupkg (v1.0.x)
Push to BaGet (http://localhost:5555) or Nexus
BackOffice: <PackageReference Include="Foursat.CMSMicroservice.Protobuf" />
FrontOffice: <PackageReference Include="Foursat.CMSMicroservice.Protobuf" />
```
---
## ۶. Remaining Tasks / Integration Gaps
| آیتم | اولویت | وضعیت |
|------|---------|--------|
| Product Bundle API | Medium | ⬜ Proto + Handler needed |
| Manual Payment API | Low | ⬜ Design only |
| SignalR for Chatika | Low | ⬜ Replace polling |
| File upload streaming | Done | ✅ |
| Blog search | Done | ✅ |
| Inventory autocomplete | Done | ✅ |
| Lazy load pagination | Done | ✅ |
| Rate limiting (API level) | Medium | ⬜ |
| API versioning | Low | ⬜ |