chore: parsian

This commit is contained in:
mahyargdz
2025-06-07 15:01:38 +03:30
parent f4ce67c00c
commit 4a7003a532
14 changed files with 582 additions and 19 deletions
+137
View File
@@ -2,6 +2,7 @@
/dist /dist
/node_modules /node_modules
/build /build
/IPGSW1Sale
# Logs # Logs
logs logs
@@ -54,3 +55,139 @@ pids
# Diagnostic reports (https://nodejs.org/api/report.html) # Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# vitepress build output
**/.vitepress/dist
# vitepress cache directory
**/.vitepress/cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
+8 -8
View File
@@ -1,11 +1,11 @@
import { Logger } from "@nestjs/common"; import { Logger } from "@nestjs/common";
import { connectionSource } from "./connection"; import { connectionSource } from "./connection";
import { seedAdmin } from "./seeders/admin.seeder"; // import { seedAdmin } from "./seeders/admin.seeder";
import { seedCityAndProvince } from "./seeders/iran-city.seeder"; // import { seedCityAndProvince } from "./seeders/iran-city.seeder";
import { seedNotifSettings } from "./seeders/notif-setting.seeder"; // import { seedNotifSettings } from "./seeders/notif-setting.seeder";
import { seedPaymentGateways } from "./seeders/payment-gateway.seeder"; import { seedPaymentGateways } from "./seeders/payment-gateway.seeder";
import { seedPermissionsAndRoles } from "./seeders/role.seeder"; // import { seedPermissionsAndRoles } from "./seeders/role.seeder";
const logger = new Logger("Seeder"); const logger = new Logger("Seeder");
@@ -13,11 +13,11 @@ export const runSeeder = async () => {
await connectionSource.initialize(); await connectionSource.initialize();
logger.log("start seeding database"); logger.log("start seeding database");
// //
await seedPermissionsAndRoles(connectionSource, logger); // await seedPermissionsAndRoles(connectionSource, logger);
await seedAdmin(connectionSource, logger); // await seedAdmin(connectionSource, logger);
await seedNotifSettings(connectionSource, logger); // await seedNotifSettings(connectionSource, logger);
await seedPaymentGateways(connectionSource, logger); await seedPaymentGateways(connectionSource, logger);
await seedCityAndProvince(connectionSource, logger); // await seedCityAndProvince(connectionSource, logger);
logger.log("seeding completed"); logger.log("seeding completed");
process.exit(0); process.exit(0);
@@ -11,6 +11,12 @@ const paymentGateways: Partial<PaymentGateway>[] = [
logoUrl: "https://www.zarinpal.com/docs/logo/fa-dark.svg", logoUrl: "https://www.zarinpal.com/docs/logo/fa-dark.svg",
description: "درگاه پرداخت زرین پال", description: "درگاه پرداخت زرین پال",
}, },
{
name: GatewayEnum.PARSIAN,
nameFa: "پارسیان",
logoUrl: "https://www.parsian.ir/docs/logo/fa-dark.svg",
description: "درگاه پرداخت پارسیان",
},
]; ];
export const seedPaymentGateways = async (dataSource: DataSource, logger: Logger) => { export const seedPaymentGateways = async (dataSource: DataSource, logger: Logger) => {
@@ -18,6 +24,11 @@ export const seedPaymentGateways = async (dataSource: DataSource, logger: Logger
const paymentGatewayRepo = dataSource.getRepository(PaymentGateway); const paymentGatewayRepo = dataSource.getRepository(PaymentGateway);
for (const paymentGateway of paymentGateways) { for (const paymentGateway of paymentGateways) {
const existingPg = await paymentGatewayRepo.findOne({ where: { name: paymentGateway.name } });
if (existingPg) {
logger.log(`${paymentGateway.name} already exists`);
continue;
}
const pg = paymentGatewayRepo.create(paymentGateway); const pg = paymentGatewayRepo.create(paymentGateway);
await paymentGatewayRepo.save(pg); await paymentGatewayRepo.save(pg);
} }
+2
View File
@@ -61,6 +61,7 @@
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"fastify": "^5.3.2", "fastify": "^5.3.2",
"handlebars": "^4.7.8", "handlebars": "^4.7.8",
"nestjs-soap": "^3.0.4",
"nestjs-telegraf": "^2.8.1", "nestjs-telegraf": "^2.8.1",
"nodemailer": "^6.10.1", "nodemailer": "^6.10.1",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
@@ -68,6 +69,7 @@
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2", "rxjs": "^7.8.2",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"soap": "^1.1.12",
"telegraf": "^4.16.3", "telegraf": "^4.16.3",
"typeorm": "^0.3.22" "typeorm": "^0.3.22"
}, },
+150 -2
View File
@@ -101,6 +101,9 @@ importers:
handlebars: handlebars:
specifier: ^4.7.8 specifier: ^4.7.8
version: 4.7.8 version: 4.7.8
nestjs-soap:
specifier: ^3.0.4
version: 3.0.4(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))
nestjs-telegraf: nestjs-telegraf:
specifier: ^2.8.1 specifier: ^2.8.1
version: 2.8.1(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.0.20(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.8.3) version: 2.8.1(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.0.20(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.8.3)
@@ -122,6 +125,9 @@ importers:
slugify: slugify:
specifier: ^1.6.6 specifier: ^1.6.6
version: 1.6.6 version: 1.6.6
soap:
specifier: ^1.1.12
version: 1.1.12
telegraf: telegraf:
specifier: ^4.16.3 specifier: ^4.16.3
version: 4.16.3 version: 4.16.3
@@ -1939,6 +1945,14 @@ packages:
'@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 '@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
prom-client: ^15.0.0 prom-client: ^15.0.0
'@xmldom/is-dom-node@1.0.1':
resolution: {integrity: sha512-CJDxIgE5I0FH+ttq/Fxy6nRpxP70+e2O048EPe85J2use3XKdatVM7dDVvFNjQudd9B49NPoZ+8PG49zj4Er8Q==}
engines: {node: '>= 16'}
'@xmldom/xmldom@0.8.10':
resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==}
engines: {node: '>=10.0.0'}
'@xtuc/ieee754@1.2.0': '@xtuc/ieee754@1.2.0':
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
@@ -2147,9 +2161,15 @@ packages:
resolution: {integrity: sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==} resolution: {integrity: sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
axios-ntlm@1.4.4:
resolution: {integrity: sha512-kpCRdzMfL8gi0Z0o96P3QPAK4XuC8iciGgxGXe+PeQ4oyjI2LZN8WSOKbu0Y9Jo3T/A7pB81n6jYVPIpglEuRA==}
axios@1.8.4: axios@1.8.4:
resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==}
axios@1.9.0:
resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
babel-jest@29.7.0: babel-jest@29.7.0:
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -2578,6 +2598,15 @@ packages:
supports-color: supports-color:
optional: true optional: true
debug@4.4.1:
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
decimal.js@10.5.0: decimal.js@10.5.0:
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
@@ -2630,6 +2659,9 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
des.js@1.1.0:
resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==}
detect-indent@6.1.0: detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -2645,6 +2677,9 @@ packages:
detect-node@2.1.0: detect-node@2.1.0:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
dev-null@0.1.1:
resolution: {integrity: sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ==}
dezalgo@1.0.4: dezalgo@1.0.4:
resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==}
@@ -3147,6 +3182,10 @@ packages:
formidable@3.5.3: formidable@3.5.3:
resolution: {integrity: sha512-pQEHGLZjLRyfLCe6r6n8IQGqHEceKfYR5tIf/iUDn5SabaitfVR/pIskxnyvSSl122J63rFY17i68hrfK0BVOA==} resolution: {integrity: sha512-pQEHGLZjLRyfLCe6r6n8IQGqHEceKfYR5tIf/iUDn5SabaitfVR/pIskxnyvSSl122J63rFY17i68hrfK0BVOA==}
formidable@3.5.4:
resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==}
engines: {node: '>=14.0.0'}
fs-extra@10.1.0: fs-extra@10.1.0:
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -3813,6 +3852,9 @@ packages:
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
engines: {node: '>=14'} engines: {node: '>=14'}
js-md4@0.3.2:
resolution: {integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==}
js-stringify@1.0.2: js-stringify@1.0.2:
resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==}
@@ -4136,6 +4178,9 @@ packages:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'} engines: {node: '>=18'}
minimalistic-assert@1.0.1:
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
minimatch@10.0.1: minimatch@10.0.1:
resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
@@ -4307,6 +4352,12 @@ packages:
neo-async@2.6.2: neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
nestjs-soap@3.0.4:
resolution: {integrity: sha512-/iPyBmHcQzJDSttQ5HeQ7ln9QDmxb27eKg+l8Jj0eO4sk/OmX9M4DUthEPjVZ3Gh11WVvzT5NuZIXEBSR/Im5A==}
engines: {node: '>=12.0.0'}
peerDependencies:
'@nestjs/common': ^8.4.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
nestjs-telegraf@2.8.1: nestjs-telegraf@2.8.1:
resolution: {integrity: sha512-7H3r6Yl4YNnJn/YSPcP26O2ESAKLJTgjKP6XuBkKw5OrYBXguGWmeUdNHYISCZTjKegHxfq8/9bjmfMrWrGIIA==} resolution: {integrity: sha512-7H3r6Yl4YNnJn/YSPcP26O2ESAKLJTgjKP6XuBkKw5OrYBXguGWmeUdNHYISCZTjKegHxfq8/9bjmfMrWrGIIA==}
peerDependencies: peerDependencies:
@@ -4961,6 +5012,9 @@ packages:
sax@1.2.1: sax@1.2.1:
resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==}
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
schema-utils@3.3.0: schema-utils@3.3.0:
resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==}
engines: {node: '>= 10.13.0'} engines: {node: '>= 10.13.0'}
@@ -5077,6 +5131,10 @@ packages:
resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
soap@1.1.12:
resolution: {integrity: sha512-bfgy09VAA2Pnv8I/qDpMvPFPV//eIGr/DOeaLx3uexpMrI+gq8Xuvp3KlTZYMhKFwjwgcLd+YpabFbOv82R5gQ==}
engines: {node: '>=14.17.0'}
sonic-boom@4.2.0: sonic-boom@4.2.0:
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
@@ -5631,6 +5689,10 @@ packages:
webpack-cli: webpack-cli:
optional: true optional: true
whatwg-mimetype@4.0.0:
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
engines: {node: '>=18'}
whatwg-url@5.0.0: whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
@@ -5696,6 +5758,10 @@ packages:
resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
xml-crypto@6.1.2:
resolution: {integrity: sha512-leBOVQdVi8FvPJrMYoum7Ici9qyxfE4kVi+AkpUoYCSXaQF4IlBm1cneTK9oAxR61LpYxTx7lNcsnBIeRpGW2w==}
engines: {node: '>=16'}
xml2js@0.6.2: xml2js@0.6.2:
resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==}
engines: {node: '>=4.0.0'} engines: {node: '>=4.0.0'}
@@ -5704,6 +5770,10 @@ packages:
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
xpath@0.0.33:
resolution: {integrity: sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA==}
engines: {node: '>=0.6.0'}
xtend@4.0.2: xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'} engines: {node: '>=0.4'}
@@ -8172,6 +8242,10 @@ snapshots:
'@nestjs/common': 11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/common': 11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
prom-client: 15.1.3 prom-client: 15.1.3
'@xmldom/is-dom-node@1.0.1': {}
'@xmldom/xmldom@0.8.10': {}
'@xtuc/ieee754@1.2.0': {} '@xtuc/ieee754@1.2.0': {}
'@xtuc/long@4.2.2': {} '@xtuc/long@4.2.2': {}
@@ -8383,9 +8457,26 @@ snapshots:
uuid: 8.0.0 uuid: 8.0.0
xml2js: 0.6.2 xml2js: 0.6.2
axios-ntlm@1.4.4(debug@4.4.1):
dependencies:
axios: 1.9.0(debug@4.4.1)
des.js: 1.1.0
dev-null: 0.1.1
js-md4: 0.3.2
transitivePeerDependencies:
- debug
axios@1.8.4: axios@1.8.4:
dependencies: dependencies:
follow-redirects: 1.15.9 follow-redirects: 1.15.9(debug@4.4.1)
form-data: 4.0.2
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
axios@1.9.0(debug@4.4.1):
dependencies:
follow-redirects: 1.15.9(debug@4.4.1)
form-data: 4.0.2 form-data: 4.0.2
proxy-from-env: 1.1.0 proxy-from-env: 1.1.0
transitivePeerDependencies: transitivePeerDependencies:
@@ -8897,6 +8988,10 @@ snapshots:
dependencies: dependencies:
ms: 2.1.3 ms: 2.1.3
debug@4.4.1:
dependencies:
ms: 2.1.3
decimal.js@10.5.0: {} decimal.js@10.5.0: {}
dedent@1.5.3: {} dedent@1.5.3: {}
@@ -8934,6 +9029,11 @@ snapshots:
dequal@2.0.3: {} dequal@2.0.3: {}
des.js@1.1.0:
dependencies:
inherits: 2.0.4
minimalistic-assert: 1.0.1
detect-indent@6.1.0: detect-indent@6.1.0:
optional: true optional: true
@@ -8944,6 +9044,8 @@ snapshots:
detect-node@2.1.0: detect-node@2.1.0:
optional: true optional: true
dev-null@0.1.1: {}
dezalgo@1.0.4: dezalgo@1.0.4:
dependencies: dependencies:
asap: 2.0.6 asap: 2.0.6
@@ -9568,7 +9670,9 @@ snapshots:
flatted@3.3.3: {} flatted@3.3.3: {}
follow-redirects@1.15.9: {} follow-redirects@1.15.9(debug@4.4.1):
optionalDependencies:
debug: 4.4.1
for-each@0.3.5: for-each@0.3.5:
dependencies: dependencies:
@@ -9609,6 +9713,12 @@ snapshots:
dezalgo: 1.0.4 dezalgo: 1.0.4
once: 1.4.0 once: 1.4.0
formidable@3.5.4:
dependencies:
'@paralleldrive/cuid2': 2.2.2
dezalgo: 1.0.4
once: 1.4.0
fs-extra@10.1.0: fs-extra@10.1.0:
dependencies: dependencies:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
@@ -10507,6 +10617,8 @@ snapshots:
js-cookie@3.0.5: js-cookie@3.0.5:
optional: true optional: true
js-md4@0.3.2: {}
js-stringify@1.0.2: js-stringify@1.0.2:
optional: true optional: true
@@ -10833,6 +10945,8 @@ snapshots:
mimic-function@5.0.1: {} mimic-function@5.0.1: {}
minimalistic-assert@1.0.1: {}
minimatch@10.0.1: minimatch@10.0.1:
dependencies: dependencies:
brace-expansion: 2.0.1 brace-expansion: 2.0.1
@@ -11228,6 +11342,13 @@ snapshots:
neo-async@2.6.2: {} neo-async@2.6.2: {}
nestjs-soap@3.0.4(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)):
dependencies:
'@nestjs/common': 11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
soap: 1.1.12
transitivePeerDependencies:
- supports-color
nestjs-telegraf@2.8.1(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.0.20(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.8.3): nestjs-telegraf@2.8.1(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.0.20(@nestjs/common@11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.8.3):
dependencies: dependencies:
'@nestjs/common': 11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/common': 11.0.20(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -11933,6 +12054,8 @@ snapshots:
sax@1.2.1: {} sax@1.2.1: {}
sax@1.4.1: {}
schema-utils@3.3.0: schema-utils@3.3.0:
dependencies: dependencies:
'@types/json-schema': 7.0.15 '@types/json-schema': 7.0.15
@@ -12062,6 +12185,21 @@ snapshots:
slugify@1.6.6: {} slugify@1.6.6: {}
soap@1.1.12:
dependencies:
axios: 1.9.0(debug@4.4.1)
axios-ntlm: 1.4.4(debug@4.4.1)
debug: 4.4.1
formidable: 3.5.4
get-stream: 6.0.1
lodash: 4.17.21
sax: 1.4.1
strip-bom: 3.0.0
whatwg-mimetype: 4.0.0
xml-crypto: 6.1.2
transitivePeerDependencies:
- supports-color
sonic-boom@4.2.0: sonic-boom@4.2.0:
dependencies: dependencies:
atomic-sleep: 1.0.0 atomic-sleep: 1.0.0
@@ -12639,6 +12777,8 @@ snapshots:
- esbuild - esbuild
- uglify-js - uglify-js
whatwg-mimetype@4.0.0: {}
whatwg-url@5.0.0: whatwg-url@5.0.0:
dependencies: dependencies:
tr46: 0.0.3 tr46: 0.0.3
@@ -12741,6 +12881,12 @@ snapshots:
imurmurhash: 0.1.4 imurmurhash: 0.1.4
signal-exit: 3.0.7 signal-exit: 3.0.7
xml-crypto@6.1.2:
dependencies:
'@xmldom/is-dom-node': 1.0.1
'@xmldom/xmldom': 0.8.10
xpath: 0.0.33
xml2js@0.6.2: xml2js@0.6.2:
dependencies: dependencies:
sax: 1.2.1 sax: 1.2.1
@@ -12748,6 +12894,8 @@ snapshots:
xmlbuilder@11.0.1: {} xmlbuilder@11.0.1: {}
xpath@0.0.33: {}
xtend@4.0.2: {} xtend@4.0.2: {}
y18n@5.0.8: {} y18n@5.0.8: {}
+22
View File
@@ -0,0 +1,22 @@
import { ConfigService } from "@nestjs/config";
export function parsianConfig() {
return {
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
loginAccount: configService.getOrThrow<string>("PARSIAN_LOGIN_ACCOUNT"),
callBackUrl: configService.getOrThrow<string>("CALLBACK_URL"),
}),
};
}
export interface IParsianConfig {
loginAccount: string;
callBackUrl: string;
}
export const ParsianConfiguration = {
Address: "https://pec.shaparak.ir/NewIPG/?token=",
WsdlInitial: "https://pec.shaparak.ir/NewIPGServices/Sale/SaleService.asmx?wsdl",
WsdlConfirm: "https://pec.shaparak.ir/NewIPGServices/Confirm/ConfirmService.asmx?wsdl",
};
@@ -1,5 +1,5 @@
import { ApiProperty } from "@nestjs/swagger"; import { ApiProperty } from "@nestjs/swagger";
import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsUUID, IsUrl, Min } from "class-validator"; import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsUUID, IsUrl } from "class-validator";
import { WalletMessage } from "../../../common/enums/message.enum"; import { WalletMessage } from "../../../common/enums/message.enum";
import { TransferType } from "../enums/payment-type.enum"; import { TransferType } from "../enums/payment-type.enum";
@@ -7,7 +7,7 @@ import { TransferType } from "../enums/payment-type.enum";
export class DepositDto { export class DepositDto {
@IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED }) @IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED })
@IsInt({ message: WalletMessage.AMOUNT_MUST_BE_INTEGER }) @IsInt({ message: WalletMessage.AMOUNT_MUST_BE_INTEGER })
@Min(100_000, { message: WalletMessage.AMOUNT_MINIMUM }) // @Min(100_000, { message: WalletMessage.AMOUNT_MINIMUM })
@ApiProperty({ description: "Amount to charge", example: 100_000 }) @ApiProperty({ description: "Amount to charge", example: 100_000 })
amount: number; amount: number;
} }
+6
View File
@@ -1,4 +1,10 @@
export const ZARINPAL_CONFIG = "ZARINPAL_CONFIG"; export const ZARINPAL_CONFIG = "ZARINPAL_CONFIG";
export const PARSIAN_CONFIG = "PARSIAN_CONFIG";
// SOAP Client Names
export const PARSIAN_SALE_CLIENT = "PARSIAN_SALE_CLIENT";
export const PARSIAN_CONFIRM_CLIENT = "PARSIAN_CONFIRM_CLIENT";
//=============================================== //===============================================
export const PAYMENT = Object.freeze({ export const PAYMENT = Object.freeze({
@@ -1,3 +1,4 @@
export enum GatewayEnum { export enum GatewayEnum {
ZARINPAL = "zarinpal", ZARINPAL = "zarinpal",
PARSIAN = "parsian",
} }
@@ -2,6 +2,7 @@ import { BadGatewayException, Injectable } from "@nestjs/common";
import { PaymentMessage } from "../../../common/enums/message.enum"; import { PaymentMessage } from "../../../common/enums/message.enum";
import { GatewayEnum } from "../enums/gateway.enum"; import { GatewayEnum } from "../enums/gateway.enum";
import { ParsianGateway } from "../gateways/parsian.gateway";
import { ZarinpalGateway } from "../gateways/zarinpal.gateway"; import { ZarinpalGateway } from "../gateways/zarinpal.gateway";
import { IPaymentGateway, IPaymentGatewayFactory } from "../interfaces/IPayment"; import { IPaymentGateway, IPaymentGatewayFactory } from "../interfaces/IPayment";
import { GatewayType } from "../types/gateway.type"; import { GatewayType } from "../types/gateway.type";
@@ -10,13 +11,17 @@ import { GatewayType } from "../types/gateway.type";
export class PaymentGatewayFactory implements IPaymentGatewayFactory { export class PaymentGatewayFactory implements IPaymentGatewayFactory {
private readonly gateways: Map<GatewayType, IPaymentGateway>; private readonly gateways: Map<GatewayType, IPaymentGateway>;
constructor(private readonly zarinpalGateway: ZarinpalGateway) { constructor(
private readonly zarinpalGateway: ZarinpalGateway,
private readonly parsianGateway: ParsianGateway,
) {
this.gateways = new Map<GatewayType, IPaymentGateway>(); this.gateways = new Map<GatewayType, IPaymentGateway>();
this.initializeGateways(); this.initializeGateways();
} }
private initializeGateways(): void { private initializeGateways(): void {
this.gateways.set(GatewayEnum.ZARINPAL, this.zarinpalGateway); this.gateways.set(GatewayEnum.ZARINPAL, this.zarinpalGateway);
this.gateways.set(GatewayEnum.PARSIAN, this.parsianGateway);
} }
getPaymentGateway(provider: GatewayType): IPaymentGateway { getPaymentGateway(provider: GatewayType): IPaymentGateway {
@@ -0,0 +1,165 @@
import { Inject, Injectable, InternalServerErrorException, Logger } from "@nestjs/common";
import { Client } from "nestjs-soap";
import { PaymentMessage } from "../../../common/enums/message.enum";
import { IParsianConfig, ParsianConfiguration } from "../../../configs/parsian.config";
import { PARSIAN_CONFIG, PARSIAN_CONFIRM_CLIENT, PARSIAN_SALE_CLIENT } from "../constants";
import { GatewayEnum } from "../enums/gateway.enum";
import {
IPaymentGateway,
IPaymentVerifyParams,
IProcessPaymentParams,
ParsianCallbackData,
ParsianConfirmPaymentResponse,
ParsianSalePaymentResponse,
} from "../interfaces/IPayment";
@Injectable()
export class ParsianGateway implements IPaymentGateway {
private readonly logger = new Logger(ParsianGateway.name);
constructor(
@Inject(PARSIAN_CONFIG) private readonly config: IParsianConfig,
@Inject(PARSIAN_SALE_CLIENT) private readonly saleClient: Client,
@Inject(PARSIAN_CONFIRM_CLIENT) private readonly confirmClient: Client,
) {
// Log the initialization status
this.logger.log(`ParsianGateway initialized - Sale client: ${!!this.saleClient}, Confirm client: ${!!this.confirmClient}`);
}
async processPayment(processParams: IProcessPaymentParams) {
try {
// Check if SOAP client is available
if (!this.saleClient) {
this.logger.error("SOAP sale client is not initialized");
throw new InternalServerErrorException({
message: "Payment service temporarily unavailable. Please try again later.",
code: "SOAP_CLIENT_NOT_INITIALIZED",
});
}
const requestData = {
requestData: {
LoginAccount: this.config.loginAccount,
OrderId: processParams.invoiceId || Date.now().toString(),
Amount: processParams.amount,
CallBackUrl: `${this.config.callBackUrl}/${GatewayEnum.PARSIAN}`,
Originator: processParams.mobile,
AdditionalData: processParams.description,
},
};
this.logger.log(`Processing payment request:`, {
LoginAccount: this.config.loginAccount,
OrderId: requestData.requestData.OrderId,
Amount: processParams.amount,
CallBackUrl: `${this.config.callBackUrl}/${GatewayEnum.PARSIAN}`,
});
const result = (await this.saleClient.SalePaymentRequestAsync(requestData))[0] as ParsianSalePaymentResponse;
if (!result || !result.SalePaymentRequestResult) {
this.logger.error("SalePaymentRequestResult not found in response");
throw new InternalServerErrorException({ message: PaymentMessage.ERROR_IN_PROCESS_PAYMENT, result });
}
const saleResult = result.SalePaymentRequestResult;
if (!saleResult.Token || Number(saleResult.Token) === 0) {
this.logger.error(`Parsian payment request failed: ${saleResult.Message}`);
throw new InternalServerErrorException({ message: PaymentMessage.ERROR_IN_PROCESS_PAYMENT, result });
}
this.logger.log(`Payment request successful - Token: ${saleResult.Token}`);
return {
redirectUrl: ParsianConfiguration.Address + saleResult.Token,
message: saleResult.Message || "Payment initialized successfully",
reference: saleResult.Token,
};
} catch (error) {
this.logger.error(`Payment processing error:`, error);
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_PROCESS_PAYMENT);
}
}
async verifyPayment(verifyParams: IPaymentVerifyParams) {
try {
// Check if SOAP client is available
if (!this.confirmClient) {
this.logger.error("SOAP confirm client is not initialized");
throw new InternalServerErrorException({
message: "Payment verification service temporarily unavailable. Please try again later.",
code: "SOAP_CLIENT_NOT_INITIALIZED",
});
}
// For Parsian, the verification should happen in the callback
// This method might be called with callback data
const callbackData = verifyParams as unknown as ParsianCallbackData;
// Check if this is a successful callback
if (Number(callbackData.RRN) < 0 || Number(callbackData.status) !== 0) {
this.logger.warn(`Payment failed in callback - RRN: ${callbackData.RRN}, Status: ${callbackData.status}`);
return {
code: Number(callbackData.status) || -1,
message: "Payment failed",
ref_id: 0,
card_hash: "",
card_pan: "",
fee_type: "",
fee: 0,
};
}
// Confirm the payment with Parsian
const requestData = {
requestData: {
LoginAccount: this.config.loginAccount,
Token: callbackData.Token,
},
};
this.logger.log(`Confirming payment:`, {
LoginAccount: this.config.loginAccount,
Token: callbackData.Token,
});
const result = (await this.confirmClient.ConfirmPaymentAsync(requestData)) as ParsianConfirmPaymentResponse;
if (!result || !result.ConfirmPaymentResult) {
this.logger.error("ConfirmPaymentResult not found in response");
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
}
const confirmResult = result.ConfirmPaymentResult;
if (confirmResult.Status === 0) {
this.logger.log(`Payment confirmed successfully - RRN: ${confirmResult.RRN}`);
return {
code: 100, // Success code
message: confirmResult.Message || "Payment confirmed successfully",
ref_id: Number(confirmResult.RRN) || 0,
card_hash: confirmResult.CardNumberMasked || "",
card_pan: confirmResult.CardNumberMasked || "",
fee_type: "",
fee: 0,
};
} else {
this.logger.warn(`Payment confirmation failed - Status: ${confirmResult.Status}, Message: ${confirmResult.Message}`);
return {
code: confirmResult.Status,
message: confirmResult.Message || "Payment confirmation failed",
ref_id: 0,
card_hash: confirmResult.CardNumberMasked || "",
card_pan: confirmResult.CardNumberMasked || "",
fee_type: "",
fee: 0,
};
}
} catch (error) {
this.logger.error(`Payment verification error:`, error);
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
}
}
}
@@ -68,6 +68,7 @@ interface IZarinPalPGRequestData {
interface ZarinpalError { interface ZarinpalError {
code: number; code: number;
message: string; message: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validations?: any[]; validations?: any[];
} }
@@ -91,6 +92,50 @@ export interface ZarinPalPGVerifyData {
errors: ZarinpalError[]; errors: ZarinpalError[];
} }
//--------------------- Parsian --------------------------------
export interface ParsianSalePaymentRequest {
LoginAccount: string;
OrderId: string;
Amount: number;
CallBackUrl: string;
Originator?: string;
AdditionalData?: string;
}
export interface ParsianSalePaymentResponse {
SalePaymentRequestResult: {
Token: string;
Status: number;
Message: string;
};
}
export interface ParsianConfirmPaymentRequest {
LoginAccount: string;
Token: string;
}
export interface ParsianConfirmPaymentResponse {
ConfirmPaymentResult: {
Status: number;
Token: string;
RRN: string;
Message: string;
CardNumberMasked: string;
};
}
export interface ParsianCallbackData {
Token: string;
OrderId: string;
TerminalNo: string;
RRN: string;
status: string;
Amount: string;
STraceNo: string;
}
export interface PaymentVerificationResult { export interface PaymentVerificationResult {
status: PaymentStatus; status: PaymentStatus;
payment: Payment; payment: Payment;
+26 -5
View File
@@ -1,23 +1,26 @@
import { BullModule } from "@nestjs/bullmq"; import { BullModule } from "@nestjs/bullmq";
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm"; import { TypeOrmModule } from "@nestjs/typeorm";
import { SoapModule } from "nestjs-soap";
import { PAYMENT, ZARINPAL_CONFIG } from "./constants"; import { PARSIAN_CONFIG, PARSIAN_CONFIRM_CLIENT, PARSIAN_SALE_CLIENT, PAYMENT, ZARINPAL_CONFIG } from "./constants";
import { BankAccount } from "./entities/bank-account.entity"; import { BankAccount } from "./entities/bank-account.entity";
import { DepositRequest } from "./entities/deposit-request.entity";
import { PaymentGateway } from "./entities/payment-gateway.entity";
import { Payment } from "./entities/payment.entity"; import { Payment } from "./entities/payment.entity";
import { PaymentGatewayFactory } from "./factories/payment.factory"; import { PaymentGatewayFactory } from "./factories/payment.factory";
import { ParsianGateway } from "./gateways/parsian.gateway";
import { ZarinpalGateway } from "./gateways/zarinpal.gateway"; import { ZarinpalGateway } from "./gateways/zarinpal.gateway";
import { PaymentsController } from "./payments.controller"; import { PaymentsController } from "./payments.controller";
import { PaymentsService } from "./providers/payments.service"; import { PaymentsService } from "./providers/payments.service";
import { PaymentProcessor } from "./queue/payment.processor"; import { PaymentProcessor } from "./queue/payment.processor";
import { BankAccountsRepository } from "./repositories/bank-accounts.repository"; import { BankAccountsRepository } from "./repositories/bank-accounts.repository";
import { PaymentsRepository } from "./repositories/payments.repository";
import { zarinpalConfig } from "../../configs/zarinpal.config";
import { WalletsModule } from "../wallets/wallets.module"; import { WalletsModule } from "../wallets/wallets.module";
import { DepositRequest } from "./entities/deposit-request.entity";
import { PaymentGateway } from "./entities/payment-gateway.entity";
import { DepositRequestsRepository } from "./repositories/deposit-requests.repository"; import { DepositRequestsRepository } from "./repositories/deposit-requests.repository";
import { PaymentGatewaysRepository } from "./repositories/payment-gateway.repository"; import { PaymentGatewaysRepository } from "./repositories/payment-gateway.repository";
import { PaymentsRepository } from "./repositories/payments.repository";
import { ParsianConfiguration, parsianConfig } from "../../configs/parsian.config";
import { zarinpalConfig } from "../../configs/zarinpal.config";
import { NotificationModule } from "../notifications/notifications.module"; import { NotificationModule } from "../notifications/notifications.module";
import { ReferralsModule } from "../referrals/referrals.module"; import { ReferralsModule } from "../referrals/referrals.module";
@@ -31,6 +34,18 @@ import { ReferralsModule } from "../referrals/referrals.module";
removeOnFail: false, removeOnFail: false,
}, },
}), }),
SoapModule.registerAsync({
clientName: PARSIAN_SALE_CLIENT,
useFactory: () => ({
uri: ParsianConfiguration.WsdlInitial,
}),
}),
SoapModule.registerAsync({
clientName: PARSIAN_CONFIRM_CLIENT,
useFactory: () => ({
uri: ParsianConfiguration.WsdlConfirm,
}),
}),
WalletsModule, WalletsModule,
NotificationModule, NotificationModule,
ReferralsModule, ReferralsModule,
@@ -40,6 +55,7 @@ import { ReferralsModule } from "../referrals/referrals.module";
PaymentsService, PaymentsService,
PaymentGatewayFactory, PaymentGatewayFactory,
ZarinpalGateway, ZarinpalGateway,
ParsianGateway,
PaymentsRepository, PaymentsRepository,
BankAccountsRepository, BankAccountsRepository,
PaymentGatewaysRepository, PaymentGatewaysRepository,
@@ -50,6 +66,11 @@ import { ReferralsModule } from "../referrals/referrals.module";
useFactory: zarinpalConfig().useFactory, useFactory: zarinpalConfig().useFactory,
inject: zarinpalConfig().inject, inject: zarinpalConfig().inject,
}, },
{
provide: PARSIAN_CONFIG,
useFactory: parsianConfig().useFactory,
inject: parsianConfig().inject,
},
], ],
exports: [PaymentsService], exports: [PaymentsService],
}) })
+1 -1
View File
@@ -1 +1 @@
export type GatewayType = "zarinpal"; export type GatewayType = "zarinpal" | "parsian";