Compare commits
32 Commits
kub-stage
...
491b8a0d0f
| Author | SHA1 | Date | |
|---|---|---|---|
| 491b8a0d0f | |||
| be80136ae8 | |||
| 5e9984f0e5 | |||
| 1d07ae4f71 | |||
| 775a9bd75d | |||
| 2620a24597 | |||
| def3b94d89 | |||
| 3ebe0f9f48 | |||
| f4e24f7449 | |||
| 540a2ce4fc | |||
| e57f01965a | |||
| f97c4b0812 | |||
| fd32e15192 | |||
| 4456e504d4 | |||
| cec1e74f6c | |||
| dd9ac48474 | |||
| eb1b249869 | |||
| e8e964f9a0 | |||
| 9050c00297 | |||
| 6048824b33 | |||
| 62a247f097 | |||
| af12f996f1 | |||
| 3b0d9eadd3 | |||
| db07838ecb | |||
| 167991890c | |||
| 1a425f0d93 | |||
| 6f8aefc2ce | |||
| 2bd5c7db78 | |||
| 0728ec2b76 | |||
| 1425fb187b | |||
| 81d2b39ee1 | |||
| fce194a195 |
@@ -0,0 +1,2 @@
|
||||
# Keep production config from current branch during merges — never overwrite
|
||||
src/CMSMicroservice.WebApi/appsettings.Production.json merge=ours
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
name: Push nuget and docker image Actions Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- stage_new
|
||||
jobs:
|
||||
Deploy:
|
||||
runs-on: windows
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://git.afrino.co/actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: https://git.afrino.co/actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
|
||||
- name: Remove Package Source
|
||||
run: dotnet nuget remove source FourSat
|
||||
continue-on-error: true
|
||||
- name: Add Package Source
|
||||
run: dotnet nuget add source --name FourSat --username systemuser --password sZSA7PTiv3pUSQZ https://git.afrino.co/api/packages/FourSat/nuget/index.json --store-password-in-clear-text
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore ".\src\CMSMicroservice.WebApi\CMSMicroservice.WebApi.csproj"
|
||||
- name: Build
|
||||
run: dotnet build ".\src\CMSMicroservice.WebApi\CMSMicroservice.WebApi.csproj" --configuration Release --no-restore
|
||||
- name: Test
|
||||
run: dotnet test ".\src\CMSMicroservice.WebApi\CMSMicroservice.WebApi.csproj" --no-restore --verbosity normal
|
||||
- name: Recycle Apppool
|
||||
run: |
|
||||
& "C:\Windows\System32\inetsrv\appcmd.exe" recycle apppool /apppool.name:cms.kbs1.ir
|
||||
shell: powershell
|
||||
- name: Stop Website
|
||||
run: |
|
||||
& "C:\Windows\System32\inetsrv\appcmd.exe" stop site /site.name:cms.kbs1.ir
|
||||
shell: powershell
|
||||
- name: Publish
|
||||
run: dotnet publish ".\src\CMSMicroservice.WebApi\CMSMicroservice.WebApi.csproj" -c Release -o publish
|
||||
- name: Copy Publish To IIS Directory
|
||||
run: Get-ChildItem -Path "publish\*" | Copy-Item -Destination "E:\kbs1.ir\cms.kbs1.ir\" -Recurse -Force
|
||||
- name: Start Website
|
||||
run: |
|
||||
& "C:\Windows\System32\inetsrv\appcmd.exe" start site /site.name:cms.kbs1.ir
|
||||
shell: powershell
|
||||
@@ -1,93 +0,0 @@
|
||||
name: Build and Deploy to Kubernetes
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- kub-stage
|
||||
|
||||
env:
|
||||
REGISTRY: 194.5.195.53:30080
|
||||
IMAGE_NAME: admin/cms
|
||||
K8S_SERVER: 194.5.195.53
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: 194.5.195.53:32082/docker-sshpass:latest
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Start Docker daemon
|
||||
run: |
|
||||
mkdir -p /etc/docker
|
||||
cat > /etc/docker/daemon.json << 'DAEMON'
|
||||
{
|
||||
"insecure-registries": ["194.5.195.53:30080", "194.5.195.53:32500", "194.5.195.53:32082"]
|
||||
}
|
||||
DAEMON
|
||||
echo "🚀 Starting Docker daemon..."
|
||||
dockerd --iptables=false --ip6tables=false --bridge=none --storage-driver=vfs &
|
||||
|
||||
# Wait up to 3 minutes for Docker to be ready
|
||||
for i in $(seq 1 90); do
|
||||
if docker info >/dev/null 2>&1; then
|
||||
echo "✅ Docker daemon is ready (attempt $i)"
|
||||
docker version
|
||||
break
|
||||
else
|
||||
echo "⏳ Waiting for Docker daemon... (attempt $i/90)"
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
# Final check
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "❌ Docker daemon failed to start after 3 minutes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout code
|
||||
run: |
|
||||
git clone --depth 1 --branch kub-stage http://gitea-svc:3000/admin/CMS.git .
|
||||
|
||||
- name: Login to Docker registries
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 194.5.195.53:32082 -u admin --password-stdin
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
|
||||
|
||||
- name: Publish Protobuf packages
|
||||
run: |
|
||||
echo "📦 Publishing Protobuf packages..."
|
||||
docker run --rm --network host -v $(pwd):/src -w /src \
|
||||
194.5.195.53:32082/dotnet/sdk:9.0 sh -c '
|
||||
for proj in $(find . -name "*Protobuf*.csproj" -type f); do
|
||||
echo "📦 $proj"
|
||||
dotnet restore "$proj" --configfile src/NuGet.config
|
||||
dotnet build "$proj" -c Release --no-restore
|
||||
dotnet pack "$proj" -c Release --no-build -o "$(dirname $proj)/nupkg"
|
||||
for nupkg in $(dirname $proj)/nupkg/*.nupkg; do
|
||||
[ -f "$nupkg" ] && dotnet nuget push "$nupkg" \
|
||||
--source "http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json" \
|
||||
--api-key "admin:87zH26nbqT" \
|
||||
--skip-duplicate --allow-insecure-connections || true
|
||||
done
|
||||
done
|
||||
'
|
||||
echo "✅ Protobuf packages done!"
|
||||
|
||||
- name: Build Docker Image
|
||||
run: |
|
||||
DOCKER_BUILDKIT=0 docker build --network host -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest .
|
||||
|
||||
- name: Push to Registry
|
||||
run: |
|
||||
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
- name: Deploy to Kubernetes
|
||||
run: |
|
||||
export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
|
||||
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
|
||||
kubectl rollout restart deployment/cms
|
||||
kubectl rollout status deployment/cms --timeout=180s
|
||||
"
|
||||
echo "✅ Deployed!"
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
done
|
||||
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "❌ Docker daemon failed to start after 3 minutes"
|
||||
echo "❌ Docker daemon failed to start"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -75,8 +75,10 @@ jobs:
|
||||
|
||||
- name: Build Docker Image
|
||||
run: |
|
||||
DOCKER_BUILDKIT=0 docker build --network host -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod .
|
||||
DOCKER_BUILDKIT=0 docker build --network host \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod \
|
||||
.
|
||||
|
||||
- name: Push to Registry
|
||||
run: |
|
||||
@@ -86,8 +88,17 @@ jobs:
|
||||
- name: Deploy to Production
|
||||
run: |
|
||||
export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
|
||||
|
||||
# Copy K8s manifests to server
|
||||
sshpass -e scp -o StrictHostKeyChecking=no k8s/production/cms-config.yaml root@${{ env.K8S_SERVER }}:/tmp/cms-config.yaml
|
||||
sshpass -e scp -o StrictHostKeyChecking=no k8s/production/cms-deployment.yaml root@${{ env.K8S_SERVER }}:/tmp/cms-deployment.yaml
|
||||
|
||||
# Apply config (Secret) first, then deployment and update image
|
||||
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
|
||||
kubectl set image deployment/cms cms=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
kubectl rollout status deployment/cms --timeout=300s
|
||||
kubectl apply -f /tmp/cms-config.yaml &&
|
||||
kubectl apply -f /tmp/cms-deployment.yaml &&
|
||||
kubectl set image deployment/cms cms=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} &&
|
||||
kubectl rollout status deployment/cms --timeout=300s &&
|
||||
rm -f /tmp/cms-config.yaml /tmp/cms-deployment.yaml
|
||||
"
|
||||
echo "✅ Deployed to Production!"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
# CMS Application Configuration Secret (Production)
|
||||
# This Secret stores appsettings.Production.json externally in K8s
|
||||
# so configuration persists independently of Docker image rebuilds.
|
||||
#
|
||||
# To edit config without redeploying:
|
||||
# kubectl edit secret cms-appsettings
|
||||
# kubectl rollout restart deployment/cms
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cms-appsettings
|
||||
namespace: default
|
||||
labels:
|
||||
app: cms
|
||||
environment: production
|
||||
type: Opaque
|
||||
stringData:
|
||||
appsettings.Production.json: |
|
||||
{
|
||||
"ZarinPal": {
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": false
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.kbs2.ir",
|
||||
"FrontOfficeBaseUrl": "https://kbs2.ir",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=mssql-svc;Database=KBS;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;"
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"FileStorage": {
|
||||
"UploadPath": "/app/Uploads"
|
||||
},
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"Seq": {
|
||||
"ServerUrl": "http://seq-svc:5341",
|
||||
"ApiKey": "oxpvpUzU1pZxMS4s3Fqq"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
---
|
||||
# CMS Uploads PersistentVolumeClaim (Production)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: cms-uploads-pvc
|
||||
namespace: default
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
|
||||
---
|
||||
# CMS Microservice Deployment (Production)
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cms
|
||||
namespace: default
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cms
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
containers:
|
||||
- name: cms
|
||||
image: 194.5.195.53:30080/admin/cms:prod
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: "Production"
|
||||
- name: ASPNETCORE_URLS
|
||||
value: "http://+:8080"
|
||||
volumeMounts:
|
||||
- name: cms-uploads
|
||||
mountPath: /app/Uploads
|
||||
- name: cms-config
|
||||
mountPath: /app/appsettings.Production.json
|
||||
subPath: appsettings.Production.json
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health/live
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: cms-uploads
|
||||
persistentVolumeClaim:
|
||||
claimName: cms-uploads-pvc
|
||||
- name: cms-config
|
||||
secret:
|
||||
secretName: cms-appsettings
|
||||
|
||||
---
|
||||
# CMS Service (Production)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cms-svc
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: cms
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
# CMS Ingress (Production)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: cms-ingress
|
||||
namespace: default
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- cms.kbs1.ir
|
||||
- cms.kbs2.ir
|
||||
secretName: cms-tls
|
||||
rules:
|
||||
- host: cms.kbs2.ir
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: cms-svc
|
||||
port:
|
||||
number: 8080
|
||||
- host: cms.kbs1.ir
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: cms-svc
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
# CMS Application Configuration Secret (Staging)
|
||||
# This Secret stores appsettings.Staging.json externally in K8s
|
||||
# so configuration persists independently of Docker image rebuilds.
|
||||
#
|
||||
# To edit config without redeploying:
|
||||
# kubectl edit secret cms-appsettings
|
||||
# kubectl rollout restart deployment/cms
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cms-appsettings
|
||||
namespace: default
|
||||
labels:
|
||||
app: cms
|
||||
environment: staging
|
||||
type: Opaque
|
||||
stringData:
|
||||
appsettings.Staging.json: |
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"FMS": {
|
||||
"Address": "https://dl.afrino.co"
|
||||
},
|
||||
"JwtSecurityKey": "TvlZVx5TJaHs8e9HgUdGzhGP2CIidoI444nAj+8+g7c=",
|
||||
"JwtIssuer": "https://localhost",
|
||||
"JwtAudience": "https://localhost",
|
||||
"JwtExpiryInDays": 5,
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data Source=194.5.195.53,31433; Initial Catalog=Foursat;User ID=sa;Password=87zH26nbqT;Connection Timeout=300000;MultipleActiveResultSets=True;Encrypt=False",
|
||||
"providerName": "System.Data.SqlClient"
|
||||
},
|
||||
"Otp": {
|
||||
"Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M="
|
||||
},
|
||||
"Monitoring": {
|
||||
"SentryEnabled": false,
|
||||
"SentryDsn": "",
|
||||
"SlackEnabled": false,
|
||||
"SlackWebhookUrl": "",
|
||||
"EmailAlertsEnabled": false,
|
||||
"AdminEmails": ["admin@example.com"],
|
||||
"SmsNotificationsEnabled": false,
|
||||
"SmsApiKey": "",
|
||||
"SmsGatewayUrl": ""
|
||||
},
|
||||
"Email": {
|
||||
"Enabled": true,
|
||||
"SmtpHost": "smtp.gmail.com",
|
||||
"SmtpPort": 587,
|
||||
"SmtpUsername": "your-email@gmail.com",
|
||||
"SmtpPassword": "your-app-password",
|
||||
"FromEmail": "noreply@foursat.com",
|
||||
"FromName": "FourSat CMS",
|
||||
"EnableSsl": true
|
||||
},
|
||||
"Sms": {
|
||||
"Enabled": true,
|
||||
"Provider": "Kavenegar",
|
||||
"KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D",
|
||||
"Sender": "1000001110100"
|
||||
},
|
||||
"DayaPayment": {
|
||||
"BaseUrl": "https://api.daya.ir",
|
||||
"ApiKey": "YOUR_DAYA_API_KEY"
|
||||
},
|
||||
"DayaApi": {
|
||||
"UseMock": false,
|
||||
"BaseAddress": "https://Dayadiamond.ir",
|
||||
"MerchantPermissionKey": "56146364$04sXjethI5WxhItR1Q9xnmFdJzl2BB8Bclsq8dAy7YVSZp3vtt-wP7ivrcCvmKLq",
|
||||
"CacheDurationMinutes": 20
|
||||
},
|
||||
"Chatika": {
|
||||
"Enabled": true,
|
||||
"BaseUrl": "https://api.chatika.ir",
|
||||
"ApiKey": "tIukvL8dnV4cB3yVWcCD9Xyfbj8rBxm5wPt2mLyJCgTsBBoMTWjt6mFEqQwpw-er"
|
||||
},
|
||||
"BackgroundJobs": {
|
||||
"WeeklyCommissionCalculation": {
|
||||
"Enabled": true,
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"FileStorage": {
|
||||
"UploadPath": "/app/Uploads"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http1AndHttp2"
|
||||
}
|
||||
},
|
||||
"Authentication": {
|
||||
"Authority": "https://ids.domain.com/",
|
||||
"Audience": "domain_api"
|
||||
},
|
||||
"Seq": {
|
||||
"ServerUrl": "https://seq.afrino.co",
|
||||
"ApiKey": "oxpvpUzU1pZxMS4s3Fqq"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
# CMS Uploads PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: cms-uploads-pvc
|
||||
namespace: foursat
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
|
||||
---
|
||||
# CMS Microservice Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cms
|
||||
namespace: foursat
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cms
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cms
|
||||
spec:
|
||||
containers:
|
||||
- name: cms
|
||||
image: 194.5.195.53:30080/admin/cms:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: "Staging"
|
||||
- name: ASPNETCORE_URLS
|
||||
value: "http://+:8080"
|
||||
volumeMounts:
|
||||
- name: cms-uploads
|
||||
mountPath: /app/Uploads
|
||||
- name: cms-config
|
||||
mountPath: /app/appsettings.Staging.json
|
||||
subPath: appsettings.Staging.json
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health/live
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: cms-uploads
|
||||
persistentVolumeClaim:
|
||||
claimName: cms-uploads-pvc
|
||||
- name: cms-config
|
||||
secret:
|
||||
secretName: cms-appsettings
|
||||
|
||||
---
|
||||
# CMS Service
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cms-svc
|
||||
namespace: foursat
|
||||
spec:
|
||||
selector:
|
||||
app: cms
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
# CMS Ingress
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: cms-ingress
|
||||
namespace: foursat
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- cms.se.kbs1.ir
|
||||
secretName: cms-tls
|
||||
rules:
|
||||
- host: cms.se.kbs1.ir
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: cms-svc
|
||||
port:
|
||||
number: 8080
|
||||
+15
-1
@@ -62,9 +62,23 @@ public class CompleteOrderPaymentCommandHandler : IRequestHandler<CompleteOrderP
|
||||
var userWallet = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == order.UserId, cancellationToken);
|
||||
|
||||
if (userWallet != null)
|
||||
if (userWallet != null && order.DiscountBalanceUsed > 0)
|
||||
{
|
||||
userWallet.DiscountBalance -= order.DiscountBalanceUsed;
|
||||
|
||||
// ثبت لاگ تغییرات کیف پول
|
||||
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
|
||||
{
|
||||
WalletId = userWallet.Id,
|
||||
CurrentBalance = userWallet.Balance,
|
||||
ChangeValue = 0,
|
||||
CurrentNetworkBalance = userWallet.NetworkBalance,
|
||||
ChangeNerworkValue = 0,
|
||||
CurrentDiscountBalance = userWallet.DiscountBalance,
|
||||
ChangeDiscountValue = -order.DiscountBalanceUsed,
|
||||
IsIncrease = false,
|
||||
RefrenceId = transaction.Id
|
||||
});
|
||||
}
|
||||
|
||||
// تایید فروش و کسر موجودی از طریق InventoryService
|
||||
|
||||
+29
-2
@@ -111,7 +111,18 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
|
||||
|
||||
// Always apply maximum possible discount (100%) — user cannot choose less
|
||||
var maxDiscountBalanceUsable = totalDiscountAmount;
|
||||
var actualDiscountBalanceUsed = Math.Min(maxDiscountBalanceUsable, userWallet.DiscountBalance);
|
||||
|
||||
// بررسی کافی بودن موجودی کیف پول اعتباری (تخفیفی)
|
||||
if (userWallet.DiscountBalance < maxDiscountBalanceUsable)
|
||||
{
|
||||
return new PlaceOrderResponseDto
|
||||
{
|
||||
Success = false,
|
||||
Message = $"موجودی کیف پول اعتباری کافی نیست. مبلغ مورد نیاز: {maxDiscountBalanceUsable:N0} ریال، موجودی شما: {userWallet.DiscountBalance:N0} ریال"
|
||||
};
|
||||
}
|
||||
|
||||
var actualDiscountBalanceUsed = maxDiscountBalanceUsable;
|
||||
|
||||
_logger.LogInformation(
|
||||
"Discount auto-applied: max allowed={MaxAllowed}, wallet balance={WalletBalance}, used={Used}",
|
||||
@@ -263,9 +274,25 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
|
||||
|
||||
var walletForDeduct = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken);
|
||||
if (walletForDeduct != null)
|
||||
if (walletForDeduct != null && actualDiscountBalanceUsed > 0)
|
||||
{
|
||||
walletForDeduct.DiscountBalance -= actualDiscountBalanceUsed;
|
||||
|
||||
// ثبت لاگ تغییرات کیف پول
|
||||
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
|
||||
{
|
||||
WalletId = walletForDeduct.Id,
|
||||
CurrentBalance = walletForDeduct.Balance,
|
||||
ChangeValue = 0,
|
||||
CurrentNetworkBalance = walletForDeduct.NetworkBalance,
|
||||
ChangeNerworkValue = 0,
|
||||
CurrentDiscountBalance = walletForDeduct.DiscountBalance,
|
||||
ChangeDiscountValue = -actualDiscountBalanceUsed,
|
||||
IsIncrease = false,
|
||||
RefrenceId = transaction.Id
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var cartItem in cartItems)
|
||||
{
|
||||
await _inventoryService.ConfirmSaleAsync(
|
||||
|
||||
+15
@@ -114,6 +114,21 @@ public class VerifyDiscountWalletChargeCommandHandler
|
||||
_context.Transactions.Add(transaction);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// ثبت لاگ تغییرات کیف پول (بعد از ایجاد Transaction برای داشتن TransactionId)
|
||||
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
|
||||
{
|
||||
WalletId = wallet.Id,
|
||||
CurrentBalance = wallet.Balance,
|
||||
ChangeValue = 0,
|
||||
CurrentNetworkBalance = wallet.NetworkBalance,
|
||||
ChangeNerworkValue = 0,
|
||||
CurrentDiscountBalance = wallet.DiscountBalance,
|
||||
ChangeDiscountValue = request.Amount,
|
||||
IsIncrease = true,
|
||||
RefrenceId = transaction.Id
|
||||
});
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// لینک PaymentTransaction به Transaction داخلی
|
||||
if (paymentTx != null)
|
||||
{
|
||||
|
||||
+2
-3
@@ -74,12 +74,11 @@ public class VerifyMagicWalletChargeCommandHandler
|
||||
throw new BadRequestException("پرداخت توسط کاربر لغو شد");
|
||||
}
|
||||
|
||||
// 3. Verify با درگاه (زرینپال نیاز به مبلغ دارد)
|
||||
var amountInToman = depositAmount / 10m;
|
||||
// 3. Verify با درگاه (مبلغ به ریال)
|
||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||
request.Authority,
|
||||
request.Status,
|
||||
amountInToman,
|
||||
depositAmount,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ public class ExpirePendingOrdersService : BackgroundService
|
||||
private readonly ILogger<ExpirePendingOrdersService> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// مدت زمان انقضا (۳۰ دقیقه)
|
||||
/// مدت زمان انقضا (۱۵ دقیقه)
|
||||
/// </summary>
|
||||
private static readonly TimeSpan ExpirationTime = TimeSpan.FromMinutes(30);
|
||||
private static readonly TimeSpan ExpirationTime = TimeSpan.FromMinutes(15);
|
||||
|
||||
/// <summary>
|
||||
/// هر ۵ دقیقه چک میشود
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20260222160755_u21")]
|
||||
[Migration("20260222155925_u21")]
|
||||
partial class u21
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -66,8 +66,8 @@ public class ZarinPalPaymentService : IPaymentGatewayService
|
||||
{
|
||||
try
|
||||
{
|
||||
// زرینپال مبلغ را به ریال میخواهد — تبدیل تومان به ریال
|
||||
var amountInRials = (long)(request.Amount * 10);
|
||||
// مبلغ از caller به ریال میرسد — مستقیم ارسال به زرینپال
|
||||
var amountInRials = (long)request.Amount;
|
||||
|
||||
var zarinPalRequest = new ZarinPalPaymentRequest
|
||||
{
|
||||
@@ -85,12 +85,26 @@ public class ZarinPalPaymentService : IPaymentGatewayService
|
||||
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||||
|
||||
_logger.LogInformation(
|
||||
"ZarinPal payment request: Amount={AmountToman} Toman ({AmountRial} Rial), User={UserId}, Sandbox={Sandbox}",
|
||||
request.Amount, amountInRials, request.UserId, _useSandbox);
|
||||
"ZarinPal payment request: Amount={AmountRial} Rial ({AmountToman} Toman), User={UserId}, Sandbox={Sandbox}",
|
||||
amountInRials, amountInRials / 10m, request.UserId, _useSandbox);
|
||||
|
||||
var response = await _httpClient.PostAsync(RequestEndpoint, content, cancellationToken);
|
||||
var responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
|
||||
// لاگ HTTP status — مهم برای دیباگ
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogError(
|
||||
"ZarinPal HTTP error: StatusCode={StatusCode}, Body={Body}",
|
||||
(int)response.StatusCode, responseBody);
|
||||
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = $"خطای ارتباط با زرینپال (HTTP {(int)response.StatusCode}). لطفاً MerchantId و IP سرور در پنل زرینپال بررسی شود."
|
||||
};
|
||||
}
|
||||
|
||||
_logger.LogDebug("ZarinPal request response: {StatusCode} - {Body}",
|
||||
response.StatusCode, responseBody);
|
||||
|
||||
@@ -153,21 +167,21 @@ public class ZarinPalPaymentService : IPaymentGatewayService
|
||||
|
||||
/// <summary>
|
||||
/// تأیید پرداخت با مبلغ — نسخه اصلی برای زرینپال
|
||||
/// refId = Authority، verificationToken = Status (OK/NOK)، amountInToman = مبلغ به تومان
|
||||
/// refId = Authority، verificationToken = Status (OK/NOK)، amount = مبلغ به ریال
|
||||
/// </summary>
|
||||
public Task<PaymentVerificationResult> VerifyPaymentAsync(
|
||||
string refId,
|
||||
string verificationToken,
|
||||
decimal amountInToman,
|
||||
decimal amount,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return VerifyPaymentWithAmountAsync(refId, verificationToken, amountInToman, cancellationToken);
|
||||
return VerifyPaymentWithAmountAsync(refId, verificationToken, amount, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<PaymentVerificationResult> VerifyPaymentWithAmountAsync(
|
||||
string refId,
|
||||
string verificationToken,
|
||||
decimal amountInToman,
|
||||
decimal amountInRials,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -184,21 +198,18 @@ public class ZarinPalPaymentService : IPaymentGatewayService
|
||||
};
|
||||
}
|
||||
|
||||
// تبدیل تومان → ریال (×۱۰)
|
||||
var amountInRials = (long)(amountInToman * 10);
|
||||
|
||||
var verifyRequest = new ZarinPalVerifyRequest
|
||||
{
|
||||
MerchantId = _merchantId,
|
||||
Authority = refId,
|
||||
Amount = amountInRials
|
||||
Amount = (long)amountInRials
|
||||
};
|
||||
|
||||
var jsonContent = JsonSerializer.Serialize(verifyRequest, JsonOptions);
|
||||
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||||
|
||||
_logger.LogInformation("ZarinPal verify request: Authority={Authority}, Amount={Amount} Rial",
|
||||
refId, amountInRials);
|
||||
_logger.LogInformation("ZarinPal verify request: Authority={Authority}, Amount={Amount} Rial ({AmountToman} Toman)",
|
||||
refId, (long)amountInRials, amountInRials / 10m);
|
||||
|
||||
var response = await _httpClient.PostAsync(VerifyEndpoint, content, cancellationToken);
|
||||
var responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
@@ -220,7 +231,7 @@ public class ZarinPalPaymentService : IPaymentGatewayService
|
||||
IsSuccess = true,
|
||||
RefId = refId,
|
||||
TrackingCode = result.Data.RefId?.ToString(),
|
||||
Amount = (result.Data.Amount ?? 0) / 10m, // ریال → تومان
|
||||
Amount = result.Data.Amount ?? 0, // ریال — بدون تبدیل
|
||||
CardPan = result.Data.CardPan,
|
||||
CardHash = result.Data.CardHash,
|
||||
VerificationCode = result.Data.Code,
|
||||
|
||||
@@ -82,11 +82,11 @@ public class PaymentCallbackController : ControllerBase
|
||||
if (string.Equals(status, "OK", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.IsNullOrEmpty(authority))
|
||||
{
|
||||
// Verify با مبلغ از دیتابیس (تومان)
|
||||
// Verify با مبلغ از دیتابیس (ریال)
|
||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||
authority,
|
||||
status!,
|
||||
order.GatewayAmountPaid, // مبلغ به تومان
|
||||
order.GatewayAmountPaid, // مبلغ به ریال
|
||||
cancellationToken);
|
||||
|
||||
paymentSuccess = verifyResult.IsSuccess;
|
||||
|
||||
@@ -1,23 +1,87 @@
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": false
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.kbs1.ir",
|
||||
"FrontOfficeBaseUrl": "https://kbs1.ir",
|
||||
"CmsBaseUrl": "https://cms.kbs2.ir",
|
||||
"FrontOfficeBaseUrl": "https://kbs2.ir",
|
||||
"JwtSecurityKey": "TvlZVx5TJaHs8e9HgUdGzhGP2CIidoI444nAj+8+g7c=",
|
||||
"JwtIssuer": "https://localhost",
|
||||
"JwtAudience": "https://localhost",
|
||||
"JwtExpiryInDays": 5,
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=mssql-svc;Database=KBS;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;"
|
||||
"DefaultConnection": "Server=mssql-svc;Database=KBS;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;",
|
||||
"providerName": "System.Data.SqlClient"
|
||||
},
|
||||
"Otp": {
|
||||
"Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M="
|
||||
},
|
||||
"Monitoring": {
|
||||
"SentryEnabled": false,
|
||||
"SentryDsn": "",
|
||||
"SlackEnabled": false,
|
||||
"SlackWebhookUrl": "",
|
||||
"EmailAlertsEnabled": false,
|
||||
"AdminEmails": [
|
||||
"admin@example.com"
|
||||
],
|
||||
"SmsNotificationsEnabled": false,
|
||||
"SmsApiKey": "",
|
||||
"SmsGatewayUrl": ""
|
||||
},
|
||||
"Email": {
|
||||
"Enabled": true,
|
||||
"SmtpHost": "smtp.gmail.com",
|
||||
"SmtpPort": 587,
|
||||
"SmtpUsername": "your-email@gmail.com",
|
||||
"SmtpPassword": "your-app-password",
|
||||
"FromEmail": "noreply@foursat.com",
|
||||
"FromName": "FourSat CMS",
|
||||
"EnableSsl": true
|
||||
},
|
||||
"Sms": {
|
||||
"Enabled": true,
|
||||
"Provider": "Kavenegar",
|
||||
"KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D",
|
||||
"Sender": "1000001110100"
|
||||
},
|
||||
"DayaPayment": {
|
||||
"BaseUrl": "https://api.daya.ir",
|
||||
"ApiKey": "YOUR_DAYA_API_KEY"
|
||||
},
|
||||
"DayaApi": {
|
||||
"UseMock": false,
|
||||
"BaseAddress": "https://Dayadiamond.ir",
|
||||
"MerchantPermissionKey": "56146364$04sXjethI5WxhItR1Q9xnmFdJzl2BB8Bclsq8dAy7YVSZp3vtt-wP7ivrcCvmKLq",
|
||||
"CacheDurationMinutes": 20
|
||||
},
|
||||
"Chatika": {
|
||||
"Enabled": true,
|
||||
"BaseUrl": "https://api.chatika.ir",
|
||||
"ApiKey": "tIukvL8dnV4cB3yVWcCD9Xyfbj8rBxm5wPt2mLyJCgTsBBoMTWjt6mFEqQwpw-er"
|
||||
},
|
||||
"BackgroundJobs": {
|
||||
"WeeklyCommissionCalculation": {
|
||||
"Enabled": false,
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"Authentication": {
|
||||
"Authority": "https://ids.domain.com/",
|
||||
"Audience": "domain_api"
|
||||
},
|
||||
"Seq": {
|
||||
"ServerUrl": "http://seq-svc:5341",
|
||||
"ApiKey": "oxpvpUzU1pZxMS4s3Fqq"
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"FMS": {
|
||||
"Address": "https://dl.afrino.co"
|
||||
},
|
||||
"JwtSecurityKey": "TvlZVx5TJaHs8e9HgUdGzhGP2CIidoI444nAj+8+g7c=",
|
||||
"JwtIssuer": "https://localhost",
|
||||
"JwtAudience": "https://localhost",
|
||||
"JwtExpiryInDays": 5,
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data Source=194.5.195.53,31433; Initial Catalog=Foursat;User ID=sa;Password=87zH26nbqT;Connection Timeout=300000;MultipleActiveResultSets=True;Encrypt=False",
|
||||
"providerName": "System.Data.SqlClient"
|
||||
},
|
||||
"Otp": {
|
||||
"Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M="
|
||||
},
|
||||
"Monitoring": {
|
||||
"SentryEnabled": false,
|
||||
"SentryDsn": "",
|
||||
"SlackEnabled": false,
|
||||
"SlackWebhookUrl": "",
|
||||
"EmailAlertsEnabled": false,
|
||||
"AdminEmails": [
|
||||
"admin@example.com"
|
||||
],
|
||||
"SmsNotificationsEnabled": false,
|
||||
"SmsApiKey": "",
|
||||
"SmsGatewayUrl": ""
|
||||
},
|
||||
"Email": {
|
||||
"Enabled": true,
|
||||
"SmtpHost": "smtp.gmail.com",
|
||||
"SmtpPort": 587,
|
||||
"SmtpUsername": "your-email@gmail.com",
|
||||
"SmtpPassword": "your-app-password",
|
||||
"FromEmail": "noreply@foursat.com",
|
||||
"FromName": "FourSat CMS",
|
||||
"EnableSsl": true
|
||||
},
|
||||
"Sms": {
|
||||
"Enabled": true,
|
||||
"Provider": "Kavenegar",
|
||||
"KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D",
|
||||
"Sender": "1000001110100"
|
||||
},
|
||||
"DayaPayment": {
|
||||
"BaseUrl": "https://api.daya.ir",
|
||||
"ApiKey": "YOUR_DAYA_API_KEY"
|
||||
},
|
||||
"DayaApi": {
|
||||
"UseMock": false,
|
||||
"BaseAddress": "https://Dayadiamond.ir",
|
||||
"MerchantPermissionKey": "56146364$04sXjethI5WxhItR1Q9xnmFdJzl2BB8Bclsq8dAy7YVSZp3vtt-wP7ivrcCvmKLq",
|
||||
"CacheDurationMinutes": 20
|
||||
},
|
||||
"Chatika": {
|
||||
"Enabled": true,
|
||||
"BaseUrl": "https://api.chatika.ir",
|
||||
"ApiKey": "tIukvL8dnV4cB3yVWcCD9Xyfbj8rBxm5wPt2mLyJCgTsBBoMTWjt6mFEqQwpw-er"
|
||||
},
|
||||
"BackgroundJobs": {
|
||||
"WeeklyCommissionCalculation": {
|
||||
"Enabled": true,
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"Authentication": {
|
||||
"Authority": "https://ids.domain.com/",
|
||||
"Audience": "domain_api"
|
||||
},
|
||||
"Seq": {
|
||||
"ServerUrl": "https://seq.afrino.co",
|
||||
"ApiKey": "oxpvpUzU1pZxMS4s3Fqq"
|
||||
}
|
||||
}
|
||||
@@ -2,24 +2,16 @@
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.se.kbs1.ir",
|
||||
"FrontOfficeBaseUrl": "https://foursat.se.kbs1.ir",
|
||||
"FMS": {
|
||||
"Address": "https://dl.afrino.co"
|
||||
"UseSandbox": false
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.kbs2.ir",
|
||||
"FrontOfficeBaseUrl": "https://kbs2.ir",
|
||||
"JwtSecurityKey": "TvlZVx5TJaHs8e9HgUdGzhGP2CIidoI444nAj+8+g7c=",
|
||||
"JwtIssuer": "https://localhost",
|
||||
"JwtAudience": "https://localhost",
|
||||
"JwtExpiryInDays": 5,
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http1AndHttp2"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data Source=194.5.195.53,31433; Initial Catalog=Foursat;User ID=sa;Password=87zH26nbqT;Connection Timeout=300000;MultipleActiveResultSets=True;Encrypt=False",
|
||||
"DefaultConnection": "Server=mssql-svc;Database=KBS;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;",
|
||||
"providerName": "System.Data.SqlClient"
|
||||
},
|
||||
"Otp": {
|
||||
@@ -27,12 +19,12 @@
|
||||
},
|
||||
"Monitoring": {
|
||||
"SentryEnabled": false,
|
||||
"SentryDsn": "",
|
||||
"SentryDsn": "",
|
||||
"SlackEnabled": false,
|
||||
"SlackWebhookUrl": "",
|
||||
"EmailAlertsEnabled": false,
|
||||
"AdminEmails": [
|
||||
"admin@example.com"
|
||||
"admin@example.com"
|
||||
],
|
||||
"SmsNotificationsEnabled": false,
|
||||
"SmsApiKey": "",
|
||||
@@ -71,7 +63,7 @@
|
||||
},
|
||||
"BackgroundJobs": {
|
||||
"WeeklyCommissionCalculation": {
|
||||
"Enabled": true,
|
||||
"Enabled": false,
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
@@ -81,12 +73,23 @@
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"Authentication": {
|
||||
"Authority": "https://ids.domain.com/",
|
||||
"Audience": "domain_api"
|
||||
},
|
||||
"Seq": {
|
||||
"ServerUrl": "https://seq.afrino.co",
|
||||
"ServerUrl": "http://seq-svc:5341",
|
||||
"ApiKey": "oxpvpUzU1pZxMS4s3Fqq"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user