diff --git a/config/default.yml b/config/default.yml index 41b3e46..36dd6aa 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1,5 +1,5 @@ server: - port: 3500 + port: 3200 db: type: 'postgres' port: '5432' @@ -50,7 +50,7 @@ smsPhoneNumberArgName: message: 'text' url: - url: "https://rest.nexmo.com/sms/json" + url: "http://localhost:4200/#" bodyWay2SMS: apikey: "CKDG9HL5KYFLLILRMX3QX1CPKOIP8QF1" @@ -71,8 +71,8 @@ sms-headers: headers: { "content-type": "application/json" } payment-gateway: - successRedirectUrl: "/transaction/issue-application" - failureRedirectUrl: "/transaction/issue-application/status=failure" + successRedirectUrl: "/tender-view" + failureRedirectUrl: "/tender-view" successRedirectUrlStudent: "/student/payment-redirection" failureRedirectUrlStudent: "/student/payment-redirection" successRedirectUrlStudentInternal: "/transaction/student-fee" @@ -81,10 +81,10 @@ payment-gateway: failureRedirectUrlAcceptance: "/student/application" successRedirectUrlAcceptancePublic: "/auth/public/admission-form" failureRedirectUrlAcceptancePublic: "auth/public/admission-form" - furl: "http://192.168.1.24:3100/api/v1/payment-gateway/failure" - surl: "http://192.168.1.24:3100/api/v1/payment-gateway/success" - key : "" - salt : "" + furl: "https://tenderapi.accuratesoftware.online/api/v1/payment-gateway/failure" + surl: "https://tenderapi.accuratesoftware.online/api/v1/payment-gateway/success" + key : "MY3BX1lo" + salt : "9BISuuPeit" testing : true sms-merabt: diff --git a/package-lock.json b/package-lock.json index 69cde4f..431c15b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "config": "^3.3.3", "crypto-js": "^4.0.0", "ifsc": "^2.0.11", + "js-sha512": "^0.8.0", "jwt-payload": "^1.0.7", "node-oracledb": "^1.0.2", "oracledb": "^5.1.0", @@ -33,11 +34,13 @@ "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.0", + "payumoney_nodejs": "^2.0.4", "pg": "^8.5.1", "reflect-metadata": "^0.1.13", "request": "^2.88.2", "rimraf": "^3.0.2", "rxjs": "^6.6.6", + "sha512-crypt-ts": "^0.1.27", "typeorm": "^0.2.31" }, "devDependencies": { @@ -8576,6 +8579,11 @@ "node": ">= 10.13.0" } }, + "node_modules/js-sha512": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==" + }, "node_modules/js-stringify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", @@ -10292,6 +10300,15 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/payumoney_nodejs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/payumoney_nodejs/-/payumoney_nodejs-2.0.4.tgz", + "integrity": "sha512-CcTFSORMG3o2MqhBgAoNTJySqsQ4w7G/Hv2wWunla7Mxz27xgYvfJF30GlR2S+K9Vht9cWWs43Sk5YtYKCShBw==", + "dependencies": { + "request": "^2.87.0", + "sha512": "0.0.1" + } + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -11914,6 +11931,16 @@ "sha.js": "bin.js" } }, + "node_modules/sha512": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/sha512/-/sha512-0.0.1.tgz", + "integrity": "sha512-2t5rZu72ebMg2/OK44S/48UKxgBl7Kc3w/I0DkIzNld8NzDUxFBL2pOYAWEVknnuOqO62a3W+3x/xD7LrosGBg==" + }, + "node_modules/sha512-crypt-ts": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/sha512-crypt-ts/-/sha512-crypt-ts-0.1.27.tgz", + "integrity": "sha512-S/7vb0rJ3ZM6Y1oILqFXM+MGusE3f9SXlEB47qhkVZc2KneF1n6aHd0L1Grl3EKU8nJ44GXY69yRlWfbJXppZg==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -21291,6 +21318,11 @@ "supports-color": "^7.0.0" } }, + "js-sha512": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==" + }, "js-stringify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", @@ -22675,6 +22707,15 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "payumoney_nodejs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/payumoney_nodejs/-/payumoney_nodejs-2.0.4.tgz", + "integrity": "sha512-CcTFSORMG3o2MqhBgAoNTJySqsQ4w7G/Hv2wWunla7Mxz27xgYvfJF30GlR2S+K9Vht9cWWs43Sk5YtYKCShBw==", + "requires": { + "request": "^2.87.0", + "sha512": "0.0.1" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -23963,6 +24004,16 @@ "safe-buffer": "^5.0.1" } }, + "sha512": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/sha512/-/sha512-0.0.1.tgz", + "integrity": "sha512-2t5rZu72ebMg2/OK44S/48UKxgBl7Kc3w/I0DkIzNld8NzDUxFBL2pOYAWEVknnuOqO62a3W+3x/xD7LrosGBg==" + }, + "sha512-crypt-ts": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/sha512-crypt-ts/-/sha512-crypt-ts-0.1.27.tgz", + "integrity": "sha512-S/7vb0rJ3ZM6Y1oILqFXM+MGusE3f9SXlEB47qhkVZc2KneF1n6aHd0L1Grl3EKU8nJ44GXY69yRlWfbJXppZg==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index 1374db2..20afd7d 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "config": "^3.3.3", "crypto-js": "^4.0.0", "ifsc": "^2.0.11", + "js-sha512": "^0.8.0", "jwt-payload": "^1.0.7", "node-oracledb": "^1.0.2", "oracledb": "^5.1.0", @@ -45,11 +46,13 @@ "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.0", + "payumoney_nodejs": "^2.0.4", "pg": "^8.5.1", "reflect-metadata": "^0.1.13", "request": "^2.88.2", "rimraf": "^3.0.2", "rxjs": "^6.6.6", + "sha512-crypt-ts": "^0.1.27", "typeorm": "^0.2.31" }, "devDependencies": { diff --git a/src/app.module.ts b/src/app.module.ts index 43d7f77..c59526b 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -17,6 +17,10 @@ import { DocumentTypeModule } from './tables/document-type/document-type.module' import { CoversLovModule } from './tables/covers-lov/covers-lov.module'; import { FileFormatLovModule } from './tables/file-format-lov/file-format-lov.module'; import { CoversMasterModule } from './tables/covers-master/covers-master.module'; +import { PaymentGatewayModule } from './payment-gateway/payment-gateway.module'; +import { PayuTransactionListModule } from './tables/payu-transaction-list/payu-transaction-list.module'; +import { PaymentStatusModule } from './tables/payment-status/payment-status.module'; +import { PaymentMasterModule } from './tables/payment-master/payment-master.module'; @Module({ @@ -37,7 +41,12 @@ import { CoversMasterModule } from './tables/covers-master/covers-master.module' DocumentTypeModule, CoversLovModule, FileFormatLovModule, - CoversMasterModule + CoversMasterModule, + PaymentGatewayModule, + PayuTransactionListModule, + PaymentStatusModule, + PaymentMasterModule + ], }) export class AppModule { } diff --git a/src/auth/pcduser.entity.ts b/src/auth/pcduser.entity.ts index b4d1efa..6f69c7d 100644 --- a/src/auth/pcduser.entity.ts +++ b/src/auth/pcduser.entity.ts @@ -2,6 +2,8 @@ import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom"; import { Column, Entity, OneToMany, PrimaryColumn } from "typeorm"; import * as bcrypt from 'bcrypt'; import { BadRequestException } from "@nestjs/common"; +import { TenderDoc } from "src/tables/tender-documents/tender-doc.entity"; +import { PaymentMaster } from "src/tables/payment-master/payment-master.entity"; @Entity('pcduser') export class Pcduser extends PcdBaseEntity { @@ -148,6 +150,13 @@ export class Pcduser extends PcdBaseEntity { length: 50 }) tSalt: string | null; + + @OneToMany(() => PaymentMaster, (paymentMaster) => paymentMaster.pcduserD) + paymentMaster : PaymentMaster[] + + + @OneToMany(() => TenderDoc, (tenderDoc) => tenderDoc.userD ) + tenderDoc:TenderDoc[] async validatePassword(password: string,user ): Promise { const hash = await bcrypt.hash(password, this.salt); return hash === this.pass; diff --git a/src/dto/payment-master.dto.ts b/src/dto/payment-master.dto.ts new file mode 100644 index 0000000..fa2e7b9 --- /dev/null +++ b/src/dto/payment-master.dto.ts @@ -0,0 +1,12 @@ +export class PaymentMasterDto { + + userId:string + + tenderId:number + + transId:number + + status?:string + + finalBidAmt?:number +} \ No newline at end of file diff --git a/src/dto/payu-transaction-list.dto.ts b/src/dto/payu-transaction-list.dto.ts new file mode 100644 index 0000000..c17f9af --- /dev/null +++ b/src/dto/payu-transaction-list.dto.ts @@ -0,0 +1,102 @@ +export class PayuTransactionListDto { + + id: string + + status: string + + key: string + + merchantname: string + + firstname: string + + lastname: string + + addedon: Date + + bank_name: string + + payment_gateway: string + + phone: number | any + + email: string + + transaction_fee: number + + amount: number | any + + discount: number | any + + additional_charges: number | any + + productinfo: string + + error_code: string + + bank_ref_no: number | any + + ibibo_code: string + + mode: string + + ip: string + + card_no: number | any + + cardtype: string + + offer_key: string + + field0: string + + field1: string + + field2: string + + field3: string + + field4: string + + field5: string + + field6: string + + field7: string + + field8: string + + field9: string + + udf1: string + + udf2: string + + udf3: string + + udf4: string + + udf5: string + + address2: string + + city: string + + zipcode: string + + pg_mid: string + + issuing_bank: string + + offer_type: string + + failure_reason: string + + mer_service_fee: string + + mer_service_tax: string + + txnid: string; + + gateway: string; +} \ No newline at end of file diff --git a/src/dto/purchase.dto.ts b/src/dto/purchase.dto.ts new file mode 100644 index 0000000..5adb0f7 --- /dev/null +++ b/src/dto/purchase.dto.ts @@ -0,0 +1,17 @@ + +export class PurchaseDto { + + amount: number; + + application: string; + + mobile: string; + + email: string; + + type: string; + + menuId?: string; + + +} \ No newline at end of file diff --git a/src/dto/tender-document.dto.ts b/src/dto/tender-document.dto.ts index c62bb2f..2f5cd8c 100644 --- a/src/dto/tender-document.dto.ts +++ b/src/dto/tender-document.dto.ts @@ -1,6 +1,6 @@ export class TenderDocumentDto{ - tenderId:string; + tenderId:number; docName:string; @@ -11,4 +11,6 @@ export class TenderDocumentDto{ documentSize:number; documentCategory:string; + + userId?:string } \ No newline at end of file diff --git a/src/file-upload/file-upload.controller.ts b/src/file-upload/file-upload.controller.ts index c445a41..54448bc 100644 --- a/src/file-upload/file-upload.controller.ts +++ b/src/file-upload/file-upload.controller.ts @@ -10,6 +10,9 @@ import * as fs from 'fs'; import * as archiver from 'archiver'; import * as path from 'path'; import { join, extname } from 'path'; +import { tenderDocRepository } from 'src/tables/tender-documents/tender-doc.repository'; +import { TenderDocumentDto } from 'src/dto/tender-document.dto'; +import { InjectRepository } from '@nestjs/typeorm'; export function createFolders(filePath: string) { @@ -36,11 +39,14 @@ export function createFolders(filePath: string) { @Controller('file-upload') export class FileUploadController { constructor( - private iservice: FileUploadService + @InjectRepository(tenderDocRepository) + private tenderDocRepository:tenderDocRepository, + + private iservice: FileUploadService, ) { } - @UseGuards(AuthGuard()) + @Post('user-documents/:id/:userId') @UseInterceptors(FileInterceptor('file', { storage: diskStorage({ @@ -49,7 +55,6 @@ export class FileUploadController { createFolders(parentFolder); const childFolder: string = parentFolder + '/' + req.params.userId; createFolders(childFolder); - return cb(null, childFolder); }, filename: (req, file, cb) => { @@ -60,7 +65,12 @@ export class FileUploadController { }) })) userDoc(@UploadedFile() file) { - return { fileName: file.filename, filePath: file.path }; + if (!file) { + return { error: 'No file uploaded.' }; + } + //To return the size of the document in kb + const fileSizeKB = Math.ceil(file.size / 1024); + return { fileName: file.filename, filePath: file.path, fileSizeKB }; } @@ -71,7 +81,7 @@ export class FileUploadController { storage: diskStorage({ // destination: './uploads/cars', destination: (req, res, cb) => { - console.log(req); + const filePath: string = './uploads/BankDocuments/' + req.params.id; createFolders(filePath); @@ -127,33 +137,73 @@ export class FileUploadController { @Param('filename') filename : string, @Param('id') id:string): Promise { const filePath = './uploads/Drawings/'+id+'/'+ filename; - console.log("filepath===",filePath); - try { - await fs.promises.unlink(filePath); - return { message: 'File deleted successfully.' }; - } catch (err) { - throw new NotFoundException('File not found.'); - } + console.log("deleted=====",id,filename); + + await fs.promises.unlink(filePath); + const filter = { docName: filename }; + const deletedEntry = await this.tenderDocRepository.findOne(filter); + if (deletedEntry) { + console.log('helloooooo'); + await this.tenderDocRepository.remove(deletedEntry); + console.log('Entry deleted successfully.'); + } + return { message: 'File and entry deleted successfully.' }; + } catch (err) { + throw new NotFoundException('File or entry not found.'); + } } + + @Delete('R-userDoc/:id/:userId/:filename') +async deleteUserDoc( + @Param('userId') userId: string, + @Param('filename') filename: string, + @Param('id') id: string, +): Promise { + const filePath = './uploads/userDocuments/' + id + '/' + userId + '/' + filename; + try { + console.log("deleted=====",userId,filename); + + await fs.promises.unlink(filePath); + const filter = { docName: filename }; + const deletedEntry = await this.tenderDocRepository.findOne(filter); + if (deletedEntry) { + console.log('helloooooo'); + await this.tenderDocRepository.remove(deletedEntry); + console.log('Entry deleted successfully.'); + } + return { message: 'File and entry deleted successfully.' }; + } catch (err) { + throw new NotFoundException('File or entry not found.'); + } +} + @UseGuards(AuthGuard()) - @Delete('R-userDoc/:id/:userId/:filename') - async deleteUserDoc( - @Param('userId') userId:string, - @Param('filename') filename : string, - @Param('id') id:string): Promise { - const filePath = './uploads/userDocuments/'+id+'/'+userId +'/'+ filename; - console.log("filepath===",filePath); + @Delete('R-bankDoc/:id/:filename') +async deleteBankDoc( + @Param('filename') filename : string, + @Param('id') id:string): Promise { + const filePath = './uploads/BankDocuments/'+id +'/'+ filename; + console.log("filepath===",filePath); + try { + console.log("deleted=====",id,filename); - try { - await fs.promises.unlink(filePath); - return { message: 'File deleted successfully.' }; - } catch (err) { - throw new NotFoundException('File not found.'); - } - } + await fs.promises.unlink(filePath); + const filter = { docName: filename }; + const deletedEntry = await this.tenderDocRepository.findOne(filter); + if (deletedEntry) { + console.log('helloooooo'); + await this.tenderDocRepository.remove(deletedEntry); + console.log('Entry deleted successfully.'); + } + return { message: 'File and entry deleted successfully.' }; + } catch (err) { + throw new NotFoundException('File or entry not found.'); + } +} + @UseGuards(AuthGuard()) @Delete('R-notice/:id/:filename') @@ -162,13 +212,21 @@ async deleteNotice( @Param('id') id:string): Promise { const filePath = './uploads/Notice/'+id +'/'+ filename; console.log("filepath===",filePath); - - try { - await fs.promises.unlink(filePath); - return { message: 'File deleted successfully.' }; - } catch (err) { - throw new NotFoundException('File not found.'); - } + try { + console.log("deleted=====",id,filename); + + await fs.promises.unlink(filePath); + const filter = { docName: filename }; + const deletedEntry = await this.tenderDocRepository.findOne(filter); + if (deletedEntry) { + console.log('helloooooo'); + await this.tenderDocRepository.remove(deletedEntry); + console.log('Entry deleted successfully.'); + } + return { message: 'File and entry deleted successfully.' }; + } catch (err) { + throw new NotFoundException('File or entry not found.'); + } } @@ -237,7 +295,7 @@ async deleteNotice( }) } - @UseGuards(AuthGuard()) + @Get('user-Documents/:id/:userId/:imgpath') getUserDocuments( @Param('imgpath') image: string, @@ -256,7 +314,7 @@ async deleteNotice( } - @UseGuards(AuthGuard()) + @Get('Bank-Documents-Arc/:id') async getBankDocumentsAsZip( @Param('id') id: string, @@ -314,7 +372,7 @@ async deleteNotice( } - @UseGuards(AuthGuard()) + @Get('Drawings-Arc/:id') async getDrawingsAsZip( @Param('id') id: string, @@ -371,14 +429,17 @@ async deleteNotice( } - @UseGuards(AuthGuard()) - @Get('user-doc-arc/:id') + + @Get('user-doc-arc/:id/:userId') async getUserDocsAsZip( @Param('id') id: string, + @Param('userId') userId:string, @Res() res, @Req() req, ) { - const folderPath = path.join('./uploads/userDocuments', id); + const folderPath = path.join('./uploads/userDocuments'+'/'+id+'/'+ userId); + + if (!fs.existsSync(folderPath)) { res.status(404).send({ error: 'File not found' }); return; diff --git a/src/file-upload/file-upload.module.ts b/src/file-upload/file-upload.module.ts index 82b5a65..684f576 100644 --- a/src/file-upload/file-upload.module.ts +++ b/src/file-upload/file-upload.module.ts @@ -3,15 +3,22 @@ import { FileUploadController } from './file-upload.controller'; import { FileUploadService } from './file-upload.service'; import { MulterModule } from '@nestjs/platform-express'; import { AuthModule } from 'src/auth/auth.module'; +import { tenderDocRepository } from 'src/tables/tender-documents/tender-doc.repository'; +import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ MulterModule.register({ dest: './uploads' }), + TypeOrmModule.forFeature([ + tenderDocRepository + ]), AuthModule, + tenderDocRepository ], controllers: [FileUploadController], - providers: [FileUploadService] + providers: [FileUploadService, + ] }) export class FileUploadModule { } diff --git a/src/payment-gateway/payment-gateway.controller.ts b/src/payment-gateway/payment-gateway.controller.ts new file mode 100644 index 0000000..ff36652 --- /dev/null +++ b/src/payment-gateway/payment-gateway.controller.ts @@ -0,0 +1,289 @@ +import { Body, Controller, Get, Param, Post, Query, Req, Res, UseGuards } from '@nestjs/common'; +import { FreeChargePaymentGatewayService, PaymentGatewayService } from './payment-gateway.service'; +import * as config from 'config'; +import { AuthGuard } from '@nestjs/passport'; +import { GetUser } from 'src/auth/dto/get-user.decorator'; +import { PcduserDto } from 'src/auth/dto/pcd-user.dto'; +import { PurchaseDto } from 'src/dto/purchase.dto'; +import { FindManyOptions } from 'typeorm'; +import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository'; + +@Controller('payment-gateway') +export class PaymentGatewayController { + constructor( + private paymentGatewayService: PaymentGatewayService, + private paymentMasterRepo : PaymentMasterRepository + ) { } + + @Post() + @UseGuards(AuthGuard()) + createPayment( + @Req() req, + @Res() res, + @GetUser() user: PcduserDto + ): void { + // console.log('=============',user); + + try { + const paymentBody: PurchaseDto = req.body; + paymentBody.amount = req.body.amount; + paymentBody.email = req.body.email; + paymentBody['user'] = user.userId; + paymentBody.mobile = req.body.mobile; + paymentBody.application = `${req.body.application}ESC${user.userId}`; + paymentBody.type = req.body.type; + this.paymentGatewayService.makePayment(req.body, (error, result) => { + if (error) { + res.status(error.code).send(error) + //res.send (error); + } else { + res.send(result); + } + }); + } catch (e) { + console.log("Exception in creating User Data . ", e); + } + } + + @Post('public') + createPaymentPublic( + @Req() req, + @Res() res, + ): void { + // console.log('=============',user); + + try { + const paymentBody: PurchaseDto = req.body; + paymentBody.amount = req.body.amount; + paymentBody.email = req.body.email; + paymentBody['user'] = 'system'; + paymentBody.mobile = req.body.mobile; + paymentBody.application = req.body.application; + paymentBody.type = req.body.type; + paymentBody.menuId = 'PUBLIC'; + this.paymentGatewayService.makePayment(req.body, (error, result) => { + if (error) { + res.status(error.code).send(error) + //res.send (error); + } else { + res.send(result); + } + }); + } catch (e) { + console.log("Exception in creating User Data . ", e); + } + } + + @Post('success') + async paymentSuccess( + @Req() req, + @Res() res, + ): Promise { + console.log("==req====", req.body); + try { + const paymentSuccessBody = req.body; + console.log(paymentSuccessBody); + const userId = paymentSuccessBody.lastname.split('ESC')[1]; + const tenderId = paymentSuccessBody.lastname.split('ESC')[0]; + let user = await this.paymentMasterRepo.findOne({ userId: userId , tenderId:tenderId}); + console.log(user); + + this.paymentGatewayService.paymentSuccess(paymentSuccessBody, (error, result) => { + const prodInfo = paymentSuccessBody.productinfo.split('ESC'); + console.log(prodInfo, '#####'); + console.log('*************', config.get('payment-gateway')); + + if (error) { + let redirectUrl + redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrl + `/${req.body.lastname.split('ESC')[0]}/f`; + user.status = 'F' + this.paymentMasterRepo.save(user); + console.log("==redirectUrl====", redirectUrl); + res.redirect(redirectUrl); + // res.send(error); + } else { + let redirectUrl + redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${req.body.lastname.split('ESC')[0]}/s`; + user.status = 'S' + this.paymentMasterRepo.save(user); + console.log("==redirectUrl====", redirectUrl); + res.redirect(redirectUrl); + } + }); + + } catch (e) { + console.log("Exception in creating User Data . ", e); + } + } + + @Post('failure') + async paymentFailure( + @Req() req, + @Res() res, + ): Promise { + console.log(req.body, 'request body'); + try { + const paymentFailureBody = req.body; + const userId = paymentFailureBody.lastname.split('ESC')[1]; + const tenderId = paymentFailureBody.lastname.split('ESC')[0]; + let user = await this.paymentMasterRepo.findOne({ userId: userId , tenderId:tenderId}); + console.log(user); + this.paymentGatewayService.paymentFailure(paymentFailureBody, (error, result) => { + console.log(paymentFailureBody); + console.log(config.get('payment-gateway')); + + + + if (error) { + res.send(error); + user.status = 'F' + this.paymentMasterRepo.save(user); + } else { + // Redirect to payment failure page + let redirectUrl + redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrl + `${req.body.lastname.split('ESC')[0]}/f`; + user.status = 'F' + this.paymentMasterRepo.save(user); + res.redirect(redirectUrl); + } + }); + } catch (e) { + console.log("Exception in creating User Data . ", e); + } + } +} + +// @Controller('payment-gateway-fc') +// export class FreeChargePaymentGatewayController { +// constructor( +// private freeChargePaymentGatewayService: FreeChargePaymentGatewayService +// ) { } + +// @Post('status') +// async checkPaymentStatus( +// @Body() body: any, +// @GetUser() user: PcduserDto +// ): Promise { +// console.log("===dd===", body); +// return await this.freeChargePaymentGatewayService.checkPaymentStatus(body, user); +// } + +// @Post('refund') +// async refundPayment( +// @Body() body: any, +// @GetUser() user: PcduserDto +// ): Promise { +// console.log("===dd===", body); +// return await this.freeChargePaymentGatewayService.refundPayment(body, user); +// } + + +// @Post() +// @UseGuards(AuthGuard()) +// createPayment( +// @Req() req, +// @Res() res, +// @GetUser() user: PcduserDto +// ): void { +// // console.log('=============',user); + +// try { +// const paymentBody: PurchaseDto = req.body; +// paymentBody.amount = req.body.amount; +// paymentBody.email = req.body.email; +// paymentBody['user'] = user.userId; +// paymentBody.mobile = req.body.mobile; +// paymentBody.application = req.body.application; +// paymentBody.type = req.body.type; +// this.freeChargePaymentGatewayService.makePayment(paymentBody, (error, result) => { +// if (error) { +// // console.log(error,'err here'); + +// res.status(error.status).send() +// //res.send (error); +// } else { +// res.send(result); +// } +// }); +// } catch (e) { +// console.log("Exception in creating User Data . ", e); +// } +// } + + +// @Post('success') +// paymentSuccess( +// @Req() req, +// @Res() res, +// ): void { +// console.log("==req====", req.body); +// try { + +// console.log(req.body); +// if (req.body.statusCode == "SPG-0000") { +// const paymentSuccessBody = req.body; +// this.freeChargePaymentGatewayService.paymentSuccess(paymentSuccessBody, (error, result) => { +// if (error) { +// console.log(error, 'error test'); + +// let redirectUrl +// if (paymentSuccessBody.productinfo == 'F') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentSuccessBody.lastname}?payment=Y`; +// } else if (paymentSuccessBody.productinfo == 'S') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudent + `?id=${paymentSuccessBody.lastname}&status=Y`; +// } else if (paymentSuccessBody.productinfo == 'A') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlAcceptance + `/${paymentSuccessBody.lastname}?status=N`; +// } else if (paymentSuccessBody.productinfo == 'I') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudentInternal + `?rollNo=${paymentSuccessBody.lastname}&status=N`; +// } + + +// res.redirect(redirectUrl); +// // res.send(error); +// } else { +// console.log('success test', paymentSuccessBody.productinfo); + +// let redirectUrl +// if (paymentSuccessBody.productinfo == 'F') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentSuccessBody.lastname}?payment=Y`; +// } else if (paymentSuccessBody.productinfo == 'S') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlStudent + `?id=${paymentSuccessBody.lastname}&status=Y`; +// } else if (paymentSuccessBody.productinfo == 'A') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlAcceptance + `/${paymentSuccessBody.lastname}?status=Y`; +// } else if (paymentSuccessBody.productinfo == 'I') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlStudentInternal + `?rollNo=${paymentSuccessBody.lastname}&studentId=${paymentSuccessBody.studentId}&status=Y`; +// } +// console.log(redirectUrl, 'red'); +// res.redirect(redirectUrl); +// } +// }); +// } +// else if (req.body.statusCode == "SPG-0001") { +// const paymentFailureBody = req.body; +// this.freeChargePaymentGatewayService.paymentFailure(paymentFailureBody, (error, result) => { +// if (error) { +// res.send(error); +// } else { +// // Redirect to payment failure page +// let redirectUrl +// if (paymentFailureBody.productinfo.split('ESC')[1] == 'F') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentFailureBody.lastname}?payment=N`; +// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'S') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudent + `?id=${paymentFailureBody.lastname}&status=N`; +// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'A') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlAcceptance + `/${paymentFailureBody.lastname}?status=N`; +// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'I') { +// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudentInternal + `?rollNo=${paymentFailureBody.lastname}&status=N`; +// } + +// res.redirect(redirectUrl); +// } +// }); +// } +// } catch (e) { +// console.log("Exception in creating User Data . ", e); +// } + // } + + +// } diff --git a/src/payment-gateway/payment-gateway.module.ts b/src/payment-gateway/payment-gateway.module.ts new file mode 100644 index 0000000..a3d4c30 --- /dev/null +++ b/src/payment-gateway/payment-gateway.module.ts @@ -0,0 +1,37 @@ +import { HttpModule, Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AuthModule } from 'src/auth/auth.module'; +import { AuthService } from 'src/auth/auth.service'; +import { CryptoService } from 'src/auth/crypto.service'; +import { PcduserRepository } from 'src/auth/pcduser.repository'; +import { EmailModule } from 'src/email/email.module'; +import { PaymentStatusRepository } from 'src/tables/payment-status/payment-status.repository'; + + + +import { PaymentGatewayController } from './payment-gateway.controller'; +import { PaymentGatewayService } from './payment-gateway.service'; +import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository'; + +@Module({ + imports: [ + + TypeOrmModule.forFeature([ + PaymentStatusRepository, + PaymentMasterRepository, + + + ]), AuthModule, + HttpModule.register({ + timeout: 5000, + maxRedirects: 5, + }), + + EmailModule, + ], + controllers: [PaymentGatewayController], + providers: [PaymentGatewayService, + CryptoService, + ] +}) +export class PaymentGatewayModule { } diff --git a/src/payment-gateway/payment-gateway.service.ts b/src/payment-gateway/payment-gateway.service.ts new file mode 100644 index 0000000..6e8b625 --- /dev/null +++ b/src/payment-gateway/payment-gateway.service.ts @@ -0,0 +1,554 @@ +import { BadRequestException, HttpException, HttpService, Injectable, InternalServerErrorException, Logger, MethodNotAllowedException } from '@nestjs/common'; +import { PaymentDto } from '../dto/payment.dto'; +import { AuthService } from 'src/auth/auth.service'; +import { Connection, FindManyOptions, getConnection } from 'typeorm'; +import { InjectRepository } from '@nestjs/typeorm'; +import * as bcrypt from 'bcrypt'; +//import { generate } from 'generate-password'; +import * as config from 'config'; +import { CryptoService } from 'src/auth/crypto.service'; +import { PcduserRepository } from 'src/auth/pcduser.repository'; +import { PaymentStatusRepository } from 'src/tables/payment-status/payment-status.repository'; +import { PurchaseDto } from 'src/dto/purchase.dto'; +import { PaymentStatusDto } from 'src/dto/payment-status.dto'; +import { convertDate } from 'src/pipe/pcd-date.pipe'; +var crypto = require('crypto') +import fetch from "node-fetch"; +import { PayuTransactionListDto } from 'src/dto/payu-transaction-list.dto'; +import { PayuTransactionListRepository } from 'src/tables/payu-transaction-list/payu-transaction-list.repository'; +import { PcduserDto } from 'src/auth/dto/pcd-user.dto'; +import { PaymentMasterDto } from 'src/dto/payment-master.dto'; +import { Console } from 'console'; +import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository'; + +var myHeaders = new fetch.Headers(); + +const payUMoney = require("payumoney_nodejs"); +const querystring = require('querystring'); + +const paymentGatewayConf = config.get('payment-gateway'); +const paymentGatewayMethod: "DHOFAR" | "PAYU" = paymentGatewayConf.method; + +@Injectable() +export class PaymentGatewayService { + + private logger = new Logger('PaymentGatewayService'); // for logging + + + constructor( + private readonly http: HttpService, + // private authService: AuthService, + private paymentStatusRepo: PaymentStatusRepository, + private paymentMasterRepo : PaymentMasterRepository, + + private crypto: CryptoService, + + ) { + // Set you MERCHANT_KEY, MERCHANT_SALT_KEY, PAYUMONEY_AUTHORIZATION_HEADER + // for both Production and Sandox Account + payUMoney.setProdKeys(paymentGatewayConf.key, paymentGatewayConf.salt, "ylb6+TCDC20wlyTooZbYM9wDw4abjaOVV9KiHFzGPgw="); + payUMoney.setSandboxKeys(paymentGatewayConf.key, paymentGatewayConf.salt, "ylb6+TCDC20wlyTooZbYM9wDw4abjaOVV9KiHFzGPgw="); + payUMoney.isProdMode(true); + } + + public async makePayment(paymentBody: PurchaseDto, callback: (error: any, response: any) => void) { + // let total = 0; + // let tax = 0; + // let totalAmount = 0; + // let minAmount = paymentBody.amount; + // key : "crvbe4" + // salt : "wIVuIkieIBBrSYtXP3aVw5uFH7eFe2nM" + + let date = new Date() + let paymentStatus = new PaymentStatusDto() + paymentStatus.createdBy = paymentBody["user"]; + paymentStatus.modifiedBy = paymentBody["user"]; + paymentStatus.email = paymentBody.email; + paymentStatus.type = paymentBody.type; + paymentStatus.status = 'U'; + paymentStatus.paymentOption = 'P'; //F - FreeCharge | P - PayU + + let paymentModel = new PaymentDto(); + paymentModel.txnid = Date.now(); + paymentStatus.txnid = paymentModel.txnid; + paymentModel.firstname = 'Admin'; + paymentModel.lastname = paymentBody.application.toString(); + paymentModel.email = paymentBody.email; + paymentModel.service_provider = 'payu_paisa'; + paymentModel.furl = config.get('payment-gateway').furl; + paymentModel.surl = config.get('payment-gateway').surl; + paymentModel.amount = 1; + + let paymentMaster = new PaymentMasterDto(); + paymentMaster.userId = paymentModel.lastname.split('ESC')[1]; + paymentMaster.tenderId =parseInt( paymentModel.lastname.split('ESC')[0]); + paymentMaster.transId = paymentStatus.txnid; + paymentMaster.status = 'P'; + console.log('paymentmasterDto======',paymentMaster); + + const paymentMas = this.paymentMasterRepo.save(paymentMaster); + + + // if (paymentBody.type == 'F') { + // let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application); + // if (!application) + // throw new BadRequestException('application not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = application.receiptAmount; + // paymentStatus.application = application.id; + // paymentModel.phone = parseInt(application.motherPhoneNo); + // if (paymentGatewayConf.testing == true) + // paymentModel.amount = 1; + // else + // paymentModel.amount = application.receiptAmount; + // } + // if (paymentBody.type == 'S') { + // let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application); + // if (!payment) + // throw new BadRequestException('payment not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = payment.paidAmount; + // paymentStatus.paymentId = payment.id; + // paymentModel.phone = payment.contactPhone; + // if (paymentGatewayConf.testing == true) + // paymentModel.amount = 1; + // else + // paymentModel.amount = payment.paidAmount; + + // } + // if (paymentBody.type == 'I') { + // let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application); + // if (!payment) + // throw new BadRequestException('payment not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = payment.paidAmount; + // paymentStatus.paymentId = payment.id; + // paymentModel.phone = payment.contactPhone; + // if (paymentGatewayConf.testing == true) + // paymentModel.amount = 1; + // else + // paymentModel.amount = payment.paidAmount; + + // } + // if (paymentBody.type == 'A') { + // let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application); + // let courseFee = await this.sisFeeRepository.findOne({ where: { id: application.acceptance } }) + // if (!application) + // throw new BadRequestException('payment not generated') + // let date = new Date() + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = parseInt(courseFee.feeCharge); + // paymentStatus.application = application.id; + // paymentStatus.identifier = 'A'; + // paymentModel.phone = parseInt(application.motherPhoneNo); + // if (paymentGatewayConf.testing == true) + // paymentModel.amount = 1; + // else + // paymentModel.amount = parseInt(courseFee.feeCharge); + + // } + const pay = await this.paymentStatusRepo.save(paymentStatus); + paymentModel.productinfo = `${pay.id}ESC${paymentBody.type}`; + console.log(paymentModel); + + { + payUMoney.pay(paymentModel, (error: any, response: any) => { + if (error) { + console.error("makePayment error : " + error); + callback(error, null); + } else { + console.log("Payment Redirection link " + response + '===' + error); + callback(error, { url: response }); + } + }); + } + } + + public async paymentSuccess(paymentBody: any, callback: (error: any, response: any) => void) { + // console.log("===payment body===", paymentBody); + let code; + let paymentSuccessBody; + let receiptNo; + let receiptNoPrefix; + + paymentSuccessBody = paymentBody; + code = paymentSuccessBody.txnid; + console.log(paymentSuccessBody, 'successbody'); + + let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "id": paymentSuccessBody.productinfo.split('ESC')[0] } }); + paymentStatus.status = 'S'; + await this.paymentStatusRepo.save(paymentStatus); + + // const queryRunner = getConnection().createQueryRunner(); + // await queryRunner.connect(); + // await queryRunner.startTransaction(); + // try { + // let productData + // // if (paymentStatus.type == 'F' || paymentStatus.type == 'A') { + // // productData = await this.sisAdmissionFormRepository.findOne({ where: { id: paymentStatus.application }, select: ['id', 'sessionId'] }) + // // } else { + // // productData = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'sessionId'] }) + // // } + + // // const session = await this.sisSessionRepository.findOne({ where: { id: productData.sessionId } }); + // // receiptNoPrefix = session.sessionCode; + // // receiptNo = parseInt(session.receiptSeq.toString()) + 1; + + // // await queryRunner.manager.query(`update sis_session set receipt_seq = ${receiptNo} where id = ${session.id}`); + // // if (paymentStatus.type == 'F') + // // await queryRunner.manager.query(`update sis_admission_form set payment_stat ='S',receipt_no_prefix='${receiptNoPrefix}',receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`) + // // if (paymentStatus.type == 'S') { + // // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`) + // // } + // // if (paymentStatus.type == 'I') { + // // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`) + // // const data = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'studentId'] }); + // // const student = await this.sisStudentRepository.findOne({ where: { id: data.studentId }, select: ['id', 'rollNo', 'sessionId'] }); + // // paymentBody.lastname = student.rollNo; + // // paymentBody['studentId'] = student.id; + // // paymentBody['sessionId'] = student.sessionId; + + // // } + // // if (paymentStatus.type == 'A') { + // // await queryRunner.manager.query(`update sis_admission_form set acceptance_fee_stat ='S',acceptance_receipt_no_prefix='${receiptNoPrefix}',acceptance_receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`) + // // } + // queryRunner.commitTransaction() + + + callback(null, { status: "Payment Success", id: code }); + // } catch (error) { + // queryRunner.rollbackTransaction() + // } finally { + // queryRunner.release() + // } + + } + + public async paymentFailure(paymentBody: any, callback: (error: any, response: any) => void) { + let paymentFailureBody; + let code; + console.log("Payment Failure"); + paymentFailureBody = paymentBody; + + + let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "txnid": paymentFailureBody.txnid } }); + paymentStatus.status = 'F'; + await this.paymentStatusRepo.save(paymentStatus); + + code = paymentFailureBody.txnid; + + // await this.authService.updateHeader(code, 2, paymentFailureBody); + callback(null, { status: "Payment Failed" }); + } + + async insertPaymentStatus() { + + } + + // PAYU SECTION END DONT ADD PAYU RELATED CODE BELOW + + + +} +@Injectable() +export class FreeChargePaymentGatewayService { + + constructor( + private readonly http: HttpService, + private paymentStatusRepo: PaymentStatusRepository, + private crypto: CryptoService, + private PayuTransactionListRepository: PayuTransactionListRepository + ) { } + + async getUrl() { + if (config.get('payment-gateway-freecharge').production) { + return config.get('payment-gateway-freecharge').prodUrl; + } else { + return config.get('payment-gateway-freecharge').sandUrl; + } + } + + async makePayment(paymentBody: PurchaseDto, callback: (error: any, response: any) => void) { + let date = new Date() + + let paymentStatus = new PaymentStatusDto() + paymentStatus.createdBy = paymentBody["user"]; + paymentStatus.modifiedBy = paymentBody["user"]; + paymentStatus.email = paymentBody.email; + paymentStatus.type = paymentBody.type; + paymentStatus.status = 'U'; + paymentStatus.paymentOption = 'F'; //F - FreeCharge | P - PayU + + + let paymentJson = { + merchantId: config.get('payment-gateway-freecharge').merchantId, + callbackUrl: config.get('payment-gateway-freecharge').callBackUrl, + merchantTxnId: null, + merchantTxnAmount: paymentBody.amount, + currency: config.get('payment-gateway-freecharge').currency, + customerEmailId: paymentBody.email, + customerMobileNo: paymentBody.mobile, + timestamp: date.getTime(), + udf1: null + } + paymentStatus.txnid = paymentJson.timestamp; + paymentJson.merchantTxnId = paymentJson.timestamp; + + // if (paymentBody.type == 'F') { + // let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application); + // if (!application) + // throw new BadRequestException('application not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = application.receiptAmount; + // paymentStatus.application = application.id; + // paymentJson.customerMobileNo = application.motherPhoneNo; + // if (paymentGatewayConf.testing == true) + // paymentJson.merchantTxnAmount = 1; + // else + // paymentJson.merchantTxnAmount = application.receiptAmount; + // } + // if (paymentBody.type == 'S') { + // let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application); + // if (!payment) + // throw new BadRequestException('payment not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = payment.paidAmount; + // paymentStatus.paymentId = payment.id; + // paymentJson.customerMobileNo = payment.contactPhone.toString(); + // if (paymentGatewayConf.testing == true) + // paymentJson.merchantTxnAmount = 1; + // else + // paymentJson.merchantTxnAmount = payment.paidAmount; + + // } + // if (paymentBody.type == 'I') { + // let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application); + // if (!payment) + // throw new BadRequestException('payment not generated') + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = payment.paidAmount; + // paymentStatus.paymentId = payment.id; + // paymentJson.merchantTxnAmount = payment.contactPhone; + // if (paymentGatewayConf.testing == true) + // paymentJson.merchantTxnAmount = 1; + // else + // paymentJson.merchantTxnAmount = payment.paidAmount; + + // } + // if (paymentBody.type == 'A') { + // let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application); + // let courseFee = await this.sisFeeRepository.findOne({ where: { id: application.acceptance } }) + // if (!application) + // throw new BadRequestException('payment not generated') + // let date = new Date() + // paymentStatus.paymentDate = new Date(); + // paymentStatus.amount = parseInt(courseFee.feeCharge); + // paymentStatus.application = application.id; + // paymentStatus.identifier = 'A'; + // paymentJson.customerMobileNo = application.motherPhoneNo; + // if (paymentGatewayConf.testing == true) + // paymentJson.merchantTxnAmount = 1; + // else + // paymentJson.merchantTxnAmount = parseInt(courseFee.feeCharge); + + // } + const pay = await this.paymentStatusRepo.save(paymentStatus); + paymentJson.udf1 = `${pay.id}ESC${paymentBody.type}`; + + const ordered = Object.keys(paymentJson).sort().reduce( + (obj, key) => { + obj[key] = paymentJson[key]; + return obj; + }, + {} + ); + + console.log(ordered) + + let string = '' + + for (const [key, value] of Object.entries(ordered)) { + if (value) + string = string + value + } + string = string + config.get('payment-gateway-freecharge').key + console.log(string); + + const hash = crypto.createHash('sha256').update(string).digest('hex'); + + console.log(hash); + paymentJson['signature'] = hash + callback(null, { paymentBody: paymentJson, url: `${await this.getUrl()}/payment/v1/checkout` }) + } + + public async paymentSuccess(paymentBody: any, callback: (error: any, response: any) => void) { + // console.log("===payment body===", paymentBody); + let code; + let paymentSuccessBody; + let receiptNo; + let receiptNoPrefix; + + paymentSuccessBody = paymentBody; + + console.log(paymentSuccessBody, 'successbody'); + + + let paymentStatus = await this.paymentStatusRepo.findOne({ where: { txnid: paymentBody.merchantTxnId } }); + await this.insertPaymentRecord(paymentStatus, paymentSuccessBody); + if (paymentStatus.application) { + paymentSuccessBody.lastname = paymentStatus.application; + } else if (paymentStatus.paymentId) { + paymentSuccessBody.lastname = paymentStatus.paymentId + } + code = paymentStatus.txnid; + paymentStatus.status = 'S'; + paymentStatus.txnrefid = paymentSuccessBody.txnReferenceId; + paymentSuccessBody.productinfo = paymentStatus.type; + await this.paymentStatusRepo.save(paymentStatus); + + const queryRunner = getConnection().createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + let productData + // if (paymentStatus.type == 'F' || paymentStatus.type == 'A') { + // productData = await this.sisAdmissionFormRepository.findOne({ where: { id: paymentStatus.application }, select: ['id', 'sessionId'] }) + // } else { + // productData = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'sessionId'] }) + // } + + // const session = await this.sisSessionRepository.findOne({ where: { id: productData.sessionId } }); + // receiptNoPrefix = session.sessionCode; + // receiptNo = parseInt(session.receiptSeq.toString()) + 1; + + // await queryRunner.manager.query(`update sis_session set receipt_seq = ${receiptNo} where id = ${session.id}`); + // if (paymentStatus.type == 'F') + // await queryRunner.manager.query(`update sis_admission_form set payment_stat ='S',receipt_no_prefix='${receiptNoPrefix}',receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`) + // if (paymentStatus.type == 'S') { + // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`) + // } + // if (paymentStatus.type == 'I') { + // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`) + // const data = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'studentId'] }); + // const student = await this.sisStudentRepository.findOne({ where: { id: data.studentId }, select: ['id', 'rollNo', 'sessionId'] }); + // paymentBody.lastname = student.rollNo; + // paymentBody['studentId'] = student.id; + // paymentBody['sessionId'] = student.sessionId; + + // } + if (paymentStatus.type == 'A') { + await queryRunner.manager.query(`update sis_admission_form set acceptance_fee_stat ='S',acceptance_receipt_no_prefix='${receiptNoPrefix}',acceptance_receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`) + } + queryRunner.commitTransaction() + + + callback(null, { status: "Payment Success", id: code }); + } catch (error) { + console.log(error); + + queryRunner.rollbackTransaction() + } finally { + queryRunner.release() + } + + } + + async insertPaymentRecord(paymentStatus: PaymentStatusDto, paymentSuccessBody: any) { + let PayuTransaction = new PayuTransactionListDto(); + PayuTransaction.addedon = paymentStatus.paymentDate; + PayuTransaction.amount = paymentSuccessBody.amount; + PayuTransaction.txnid = paymentSuccessBody.merchantTxnId; + PayuTransaction.status = 'success'; + PayuTransaction.gateway = 'FreeCharge'; + PayuTransaction.transaction_fee = paymentSuccessBody.amount; + PayuTransaction.mer_service_fee = paymentSuccessBody.handlingFee; + PayuTransaction.mer_service_tax = paymentSuccessBody.taxAmount; + PayuTransaction.id = paymentSuccessBody.txnReferenceId; + await this.PayuTransactionListRepository.save(PayuTransaction) + } + + + async checkPaymentStatus(body: any, user: PcduserDto) { + let paymentBody = { + "merchantId": `${config.get('payment-gateway-freecharge').merchantId}`, + "merchantTxnId": `${body.merchantTxnId}` + } + let string = '' + for (const [key, value] of Object.entries(paymentBody)) { + if (value) + string = string + value + } + string = string + config.get('payment-gateway-freecharge').key + console.log(string); + + const hash = crypto.createHash('sha256').update(string).digest('hex'); + paymentBody['signature'] = hash; + return this.http.post(`${await this.getUrl()}/payment/v1/txn/status`, paymentBody).toPromise().then((res) => { + console.log("===res====", res.data); + return res.data; + }, (err) => { + console.log("===errr====", err); + return err; + }); + } + + async refundPayment(body: any, user: PcduserDto) { + let date = new Date() + let paymentBody = { + "merchantId": `${config.get('payment-gateway-freecharge').merchantId}`, + "merchantRefundTxnId": date.getTime(), + "txnReferenceId": body.txnReferenceId, + "refundAmount": body.amount, + "currency": "INR" + } + const ordered = Object.keys(paymentBody).sort().reduce( + (obj, key) => { + obj[key] = paymentBody[key]; + return obj; + }, + {} + ); + let string = '' + for (const [key, value] of Object.entries(ordered)) { + if (value) + string = string + value + } + string = string + config.get('payment-gateway-freecharge').key; + const hash = crypto.createHash('sha256').update(string).digest('hex'); + paymentBody['signature'] = hash; + return this.http.post(`${await this.getUrl()}/payment/v1/refund`, paymentBody).toPromise().then((res) => { + console.log("===res====", res.data); + return res.data; + }, (err) => { + console.log("===errr====", err); + return err; + }); + } + + public async paymentFailure(paymentBody: any, callback: (error: any, response: any) => void) { + let paymentFailureBody; + let code; + + paymentFailureBody = paymentBody; + let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "txnid": paymentFailureBody.merchantTxnId } }); + paymentFailureBody.productinfo = paymentStatus.type; + if (paymentStatus.application) { + paymentFailureBody.lastname = paymentStatus.application; + } else if (paymentStatus.paymentId) { + paymentFailureBody.lastname = paymentStatus.paymentId + } + + paymentStatus.status = 'F'; + await this.paymentStatusRepo.save(paymentStatus); + + code = paymentFailureBody.merchantTxnId; + + // await this.authService.updateHeader(code, 2, paymentFailureBody); + callback(null, { status: "Payment Failed" }); + } + + +} + + + diff --git a/src/tables/payment-master/payment-master.controller.ts b/src/tables/payment-master/payment-master.controller.ts new file mode 100644 index 0000000..43ecf11 --- /dev/null +++ b/src/tables/payment-master/payment-master.controller.ts @@ -0,0 +1,44 @@ +import { Controller, Get, Param, Post,Body,UseGuards } from '@nestjs/common'; +import { PaymentMasterDto } from 'src/dto/payment-master.dto'; +import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller'; +import { PaymentMasterService } from './payment-master.service'; +import { AuthGuard } from '@nestjs/passport'; +@UseGuards(AuthGuard()) +@Controller('payment-master') +export class PaymentMasterController extends PcdFormGridController { + + constructor( + private paymentMasterService: PaymentMasterService + ) { + super(paymentMasterService); + } + + + @Get('bid-report/:id') + async bidReport( + @Param('id') tenderId: string + ):Promise{ + return this.paymentMasterService.bidReport(tenderId) + } + + + @Get('bid-payment-check/:userId/:tenderId') + async bidPaymentCheck( + @Param('userId') userId: string, + @Param('tenderId') tenderId : string + ){ + + + return this.paymentMasterService.bidPaymentCheck(tenderId ,userId) + } + + @Post('finalBidAmt/:userId/:tenderId') + async finalBidAmt( + @Body() body: { bidAmount : number }, + @Param('userId') userId: string, + @Param('tenderId') tenderId : string, + ){ + return this.paymentMasterService.finalBidAmt(tenderId ,userId , body) + } + +} diff --git a/src/tables/payment-master/payment-master.entity.ts b/src/tables/payment-master/payment-master.entity.ts new file mode 100644 index 0000000..6bcbda1 --- /dev/null +++ b/src/tables/payment-master/payment-master.entity.ts @@ -0,0 +1,58 @@ +import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom"; +import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { TenderMaster } from "../tender-master/tender-master.entity"; +import { Pcduser } from "src/auth/pcduser.entity"; + +@Entity('payment-master') +export class PaymentMaster extends PcdBaseEntity{ + @PrimaryGeneratedColumn({ + name:"id" + }) + id:number + + @Column({ + name:"user_id", + type:"varchar", + nullable:true, + }) + userId:string + + @Column({ + name:"tender_id", + type:"numeric", + nullable:true, + }) + tenderId:number + + @Column({ + name:"trans_id", + type:"numeric", + nullable:true, + }) + transId:number + + @Column({ + name:"status", + type:"varchar", + nullable:true, + length:2 + }) + status:string + + @Column({ + name:"final_bid_amt", + type:"numeric", + nullable:true, + }) + finalBidAmt:number + + + @ManyToOne(() => Pcduser, (pcduser) => pcduser.paymentMaster, { eager: true }) + @JoinColumn([{ name: "user_id", referencedColumnName: "userId" }]) + pcduserD: Pcduser + + @ManyToOne(() => TenderMaster, (tenderMaster) => tenderMaster.paymentMaster, ) + @JoinColumn([{ name: "tender_id", referencedColumnName: "id" }]) + tenderMasterD: TenderMaster + +} \ No newline at end of file diff --git a/src/tables/payment-master/payment-master.module.ts b/src/tables/payment-master/payment-master.module.ts new file mode 100644 index 0000000..d4977cc --- /dev/null +++ b/src/tables/payment-master/payment-master.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { PaymentMasterController } from './payment-master.controller'; +import { PaymentMasterService } from './payment-master.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AuthModule } from 'src/auth/auth.module'; +import { PaymentMasterRepository } from './payment-master.repository'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([PaymentMasterRepository]), + AuthModule + ], + controllers: [PaymentMasterController], + providers: [PaymentMasterService] +}) +export class PaymentMasterModule {} diff --git a/src/tables/payment-master/payment-master.repository.ts b/src/tables/payment-master/payment-master.repository.ts new file mode 100644 index 0000000..76a56a5 --- /dev/null +++ b/src/tables/payment-master/payment-master.repository.ts @@ -0,0 +1,7 @@ +import { EntityRepository, Repository } from "typeorm"; +import { PaymentMaster } from "./payment-master.entity"; + +@EntityRepository(PaymentMaster) +export class PaymentMasterRepository extends Repository{ + +} \ No newline at end of file diff --git a/src/tables/payment-master/payment-master.service.ts b/src/tables/payment-master/payment-master.service.ts new file mode 100644 index 0000000..f941224 --- /dev/null +++ b/src/tables/payment-master/payment-master.service.ts @@ -0,0 +1,66 @@ +import { Injectable ,BadRequestException} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { PaymentMasterDto } from 'src/dto/payment-master.dto'; +import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service'; +import { PaymentMasterRepository } from './payment-master.repository'; +import { log } from 'console'; + +@Injectable() +export class PaymentMasterService extends PcdFormGridService{ + + constructor( + @InjectRepository(PaymentMasterRepository) + private paymentMasterRepository: PaymentMasterRepository, + ) { + super(paymentMasterRepository); + } + +async bidReport(tenderId){ + let id = tenderId.toString() + console.log(id); + + let query= `SELECT "PaymentMaster"."id" AS "id", + "PaymentMaster"."user_id" AS "userId", "PaymentMaster"."tender_id" AS "tenderId", + "PaymentMaster"."trans_id" AS "transId", "PaymentMaster"."status" AS "status", + "PaymentMaster"."final_bid_amt" AS "finalBidAmt", + "PaymentMaster_pcduserD"."user_name" AS "userName", + "PaymentMaster_pcduserD"."email" AS "email", + "PaymentMaster_pcduserD"."mobile_number" AS "mobileNumber" FROM "payment-master" "PaymentMaster" LEFT JOIN "pcduser" "PaymentMaster_pcduserD" ON + "PaymentMaster_pcduserD"."user_id"="PaymentMaster"."user_id" WHERE "PaymentMaster"."tender_id"= ${id}` + let report =await this.paymentMasterRepository.query(query) + return report; + +} + +async bidPaymentCheck(tenderId,userId){ + let query= `SELECT "PaymentMaster"."id" AS "id", + "PaymentMaster"."user_id" AS "userId", "PaymentMaster"."tender_id" AS "tenderId", + "PaymentMaster"."trans_id" AS "transId", "PaymentMaster"."status" AS "status", + "PaymentMaster_pcduserD"."user_name" AS "userName", + "PaymentMaster_pcduserD"."email" AS "email", + "PaymentMaster_pcduserD"."mobile_number" AS "mobileNumber" FROM "payment-master" "PaymentMaster" LEFT JOIN "pcduser" "PaymentMaster_pcduserD" ON + "PaymentMaster_pcduserD"."user_id"="PaymentMaster"."user_id" WHERE "PaymentMaster"."tender_id"= ${tenderId} and "PaymentMaster"."user_id"= '${userId}' + and "PaymentMaster"."status"='S' ` + let report =await this.paymentMasterRepository.query(query) + return report; + +} + +async finalBidAmt(tenderId ,userId,body){ + let user = await this.paymentMasterRepository.findOne({ tenderId:tenderId , userId:userId }); + if(!user){ + throw new BadRequestException('User Details not found') + } + if(user.finalBidAmt == null){ + user.finalBidAmt = body.bidAmount; + this.paymentMasterRepository.save(user) + return {data : "Final Bid Amount Successfully Saved"} + }else{ + throw new BadRequestException('Bid Amount Already Exist') + } + + +} + +} + diff --git a/src/tables/payment-status/payment-status.controller.ts b/src/tables/payment-status/payment-status.controller.ts new file mode 100644 index 0000000..2ff254a --- /dev/null +++ b/src/tables/payment-status/payment-status.controller.ts @@ -0,0 +1,15 @@ +import { Controller, UseGuards } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { PaymentStatusDto } from 'src/dto/payment-status.dto'; +import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller'; +import { PaymentStatusService } from './payment-status.service'; + +@UseGuards(AuthGuard()) +@Controller('payment-status') +export class PaymentStatusController extends PcdFormGridController{ + constructor( + private iservice: PaymentStatusService + ) { + super(iservice); + } +} \ No newline at end of file diff --git a/src/tables/payment-status/payment-status.entity.ts b/src/tables/payment-status/payment-status.entity.ts new file mode 100644 index 0000000..0c4f037 --- /dev/null +++ b/src/tables/payment-status/payment-status.entity.ts @@ -0,0 +1,166 @@ +import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom"; +import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; + + +@Entity("payment_status") +export class PaymentStatus extends PcdBaseEntity { + @PrimaryGeneratedColumn({ + name: "id", + }) + id: number; + + @Column({ + name: "payment_date", + type: "date", + nullable: true + }) + paymentDate: Date; + + @Column({ + name: 'payment_option', + type: 'char', + length: 1, + nullable: true + }) + paymentOption: string; + + @Column({ + name: 'payment_card_details', + type: 'varchar', + length: 500, + nullable: true + }) + paymentCardDetails: string; + + @Column({ + name: 'status', + type: 'char', + length: 1, + nullable: true + }) + status: string; + + @Column({ + name: 'type', + type: 'char', + length: 1, + nullable: true + }) + type: string; + + @Column({ + name: 'email', + type: 'varchar', + length: 500, + nullable: true + }) + email: string; + + @Column({ + name: 'mobile', + type: 'varchar', + length: 100, + nullable: true + }) + mobile: string; + + @Column({ + name: 'application', + type: 'numeric', + nullable: true + }) + application: number; + + + // @ManyToOne(type => SisAdmissionForm, sisAdmissionForm => sisAdmissionForm.paymentStatus) + // @JoinColumn({ name: 'application', referencedColumnName: 'id' }) + // applicationD: SisAdmissionForm; + + @Column({ + name: 'payment_id', + type: 'numeric', + nullable: true + }) + paymentId: number; + + // @ManyToOne(type => SisFeePaymentOnline, sisFeePaymentOnline => sisFeePaymentOnline.paymentStatus) + // @JoinColumn({ name: 'payment_id', referencedColumnName: 'id' }) + // paymentIdD: SisFeePaymentOnline; + + @Column({ + name: 'billing_address_1', + type: 'varchar', + length: 100, + nullable: true + }) + billingAddress1: string; + + @Column({ + name: 'billing_address_2', + type: 'varchar', + length: 100, + nullable: true + }) + billingAddress2: string; + + @Column({ + name: 'billing_address_3', + type: 'varchar', + length: 100, + nullable: true + }) + billingAddress3: string; + + @Column({ + name: 'billing_address_4', + type: 'varchar', + length: 100, + nullable: true + }) + billingAddress4: string; + + @Column({ + name: 'amount', + type: 'numeric', + precision: 18, + scale: 3, + nullable: true + }) + amount: number; + + + @Column({ + name: 'remarks', + type: 'varchar', + length: 1000, + nullable: true + }) + remarks: string; + + + @Column({ + name: 'txnid', + type: 'numeric', + nullable: false + }) + txnid: number; + + @Column({ + name: 'txnrefid', + type: 'varchar', + nullable: true, + length: 100 + }) + txnrefid: string; + + @Column({ + name: 'retry_count', + type: 'numeric', + default: () => "(0)" + }) + retryCount: number; + + @Column("varchar", { name: "identifier", nullable: true, length: 1 }) + identifier: string; + +} \ No newline at end of file diff --git a/src/tables/payment-status/payment-status.module.ts b/src/tables/payment-status/payment-status.module.ts new file mode 100644 index 0000000..3e91fba --- /dev/null +++ b/src/tables/payment-status/payment-status.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AuthModule } from 'src/auth/auth.module'; +import { PaymentStatusController } from './payment-status.controller'; +import { PaymentStatusRepository } from './payment-status.repository'; +import { PaymentStatusService } from './payment-status.service'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([ + PaymentStatusRepository + ]), + AuthModule + ], + controllers: [PaymentStatusController], + providers: [PaymentStatusService] +}) +export class PaymentStatusModule { } diff --git a/src/tables/payment-status/payment-status.repository.ts b/src/tables/payment-status/payment-status.repository.ts new file mode 100644 index 0000000..edd6189 --- /dev/null +++ b/src/tables/payment-status/payment-status.repository.ts @@ -0,0 +1,7 @@ +import { EntityRepository, Repository } from "typeorm"; +import { PaymentStatus } from "./payment-status.entity"; + +@EntityRepository(PaymentStatus) +export class PaymentStatusRepository extends Repository{ + +} \ No newline at end of file diff --git a/src/tables/payment-status/payment-status.service.ts b/src/tables/payment-status/payment-status.service.ts new file mode 100644 index 0000000..963bc7b --- /dev/null +++ b/src/tables/payment-status/payment-status.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { PaymentStatusDto } from 'src/dto/payment-status.dto'; +import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service'; +import { PaymentStatusRepository } from './payment-status.repository'; + +@Injectable() +export class PaymentStatusService extends PcdFormGridService{ + MANDATORY_FEILDS: string[] = []; + DUPLICATE_CHK: string[] = []; + MAIN_KEY = 'id' + constructor( + @InjectRepository(PaymentStatusRepository) + private paymentStatusRepository: PaymentStatusRepository, + ) { + super(paymentStatusRepository); + } +} diff --git a/src/tables/payu-transaction-list/payu-transaction-list.controller.ts b/src/tables/payu-transaction-list/payu-transaction-list.controller.ts new file mode 100644 index 0000000..8e8532e --- /dev/null +++ b/src/tables/payu-transaction-list/payu-transaction-list.controller.ts @@ -0,0 +1,37 @@ +import { Body, Controller, Get, Post, Query, UseGuards } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { GetUser } from 'src/auth/dto/get-user.decorator'; +import { PcduserDto } from 'src/auth/dto/pcd-user.dto'; +import { PayuTransactionListDto } from 'src/dto/payu-transaction-list.dto'; +import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller'; +import { FindManyOptions } from 'typeorm'; +import { PayuTransactionListService } from './payu-transaction-list.service'; + +@UseGuards(AuthGuard()) +@Controller('payu-transaction-list') +export class PayuTransactionListController extends PcdFormGridController{ + constructor( + private PayuTransactionListservice: PayuTransactionListService + ) { + super(PayuTransactionListservice); + } + @Post('get-transaction') + getTransactionDetails( + @Body() body: PcduserDto, + @GetUser() user: PcduserDto): Promise { + + return this.PayuTransactionListservice.getTransactionDetails(body); + } + + @Get('date-filter') + dateFilter(@Query() filter: FindManyOptions) { + + return this.PayuTransactionListservice.dateFilter(filter) + } + + @Get('check-status') + checkPaymentStatus(): Promise { + + return this.PayuTransactionListservice.checkPaymentStatus(); + } +} diff --git a/src/tables/payu-transaction-list/payu-transaction-list.entity.ts b/src/tables/payu-transaction-list/payu-transaction-list.entity.ts new file mode 100644 index 0000000..7b0f6b1 --- /dev/null +++ b/src/tables/payu-transaction-list/payu-transaction-list.entity.ts @@ -0,0 +1,362 @@ +// import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom"; +import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm" + +@Entity('payu_transaction') +export class PayuTransactionListEntity extends BaseEntity { + + @PrimaryGeneratedColumn({ + name: 'id', + }) + sisId: string; + + @Column({ + type: 'varchar', + name: 'payu_id', + }) + id: string + + @Column({ + type: 'varchar', + name: 'status', + nullable: true, + + + }) + status: string; + + @Column({ + type: 'varchar', + name: 'key', + nullable: true + }) + key: string + + @Column({ + type: 'varchar', + name: 'merchantname', + nullable: true + }) + merchantname: string + + @Column({ + type: 'varchar', + name: 'firstName', + nullable: true + }) + firstname: string + + @Column({ + type: 'varchar', + name: 'lastname', + nullable: true + }) + lastname: string + + @Column({ + type: 'varchar', + name: 'addedon', + nullable: true + }) + addedon: Date + + @Column({ + type: 'varchar', + name: 'bank_name', + nullable: true + }) + bank_name: string + + @Column({ + type: 'varchar', + name: 'payment_gateway', + nullable: true + }) + payment_gateway: string + + @Column({ + type: 'varchar', + name: 'phone', + nullable: true + }) + phone: string + + @Column({ + type: 'varchar', + name: 'email', + nullable: true + }) + email: string + + @Column({ + type: 'varchar', + name: 'transaction_fee', + nullable: true + }) + transaction_fee: number + + @Column({ + type: 'varchar', + name: 'amount', + nullable: true + }) + amount: string + + @Column({ + type: 'varchar', + name: 'discount', + nullable: true + }) + discount: string + + @Column({ + type: 'varchar', + name: 'additional_charges', + nullable: true + }) + additional_charges: string + + @Column({ + type: 'varchar', + name: 'productinfo', + nullable: true + }) + productinfo: string + + @Column({ + type: 'varchar', + name: 'error_code', + nullable: true + }) + error_code: string + + @Column({ + type: 'varchar', + name: 'bank_ref_no', + nullable: true + }) + bank_ref_no: string + + @Column({ + type: 'varchar', + name: 'ibibo_code', + nullable: true + }) + ibibo_code: string + + @Column({ + type: 'varchar', + name: 'mode', + nullable: true + }) + mode: string + + @Column({ + type: 'varchar', + name: 'ip', + nullable: true + }) + ip: string + + @Column({ + type: 'varchar', + name: 'card_no', + nullable: true + }) + card_no: string + + @Column({ + type: 'varchar', + name: 'cardtype', + nullable: true + }) + cardtype: string + + @Column({ + type: 'varchar', + name: 'offer_key', + nullable: true + }) + offer_key: string + + @Column({ + type: 'varchar', + name: 'field0', + nullable: true + }) + field0: string + + @Column({ + type: 'varchar', + name: 'field1', + nullable: true + }) + field1: string + + @Column({ + type: 'varchar', + name: 'field2', + nullable: true + }) + field2: string + + @Column({ + type: 'varchar', + name: 'field3', + nullable: true + }) + field3: string + + @Column({ + type: 'varchar', + name: 'field4', + nullable: true + }) + field4: string + + @Column({ + type: 'varchar', + name: 'field5', + nullable: true + }) + field5: string + + @Column({ + type: 'varchar', + name: 'field6', + nullable: true + }) + field6: string + + @Column({ + type: 'varchar', + name: 'field7', + nullable: true + }) + field7: string + + @Column({ + type: 'varchar', + name: 'field8', + nullable: true + }) + field8: string + + @Column({ + type: 'varchar', + name: 'field9', + nullable: true + }) + field9: string + + @Column({ + type: 'varchar', + name: 'udf1', + nullable: true + }) + udf1: string + + @Column({ + type: 'varchar', + name: 'udf2', + nullable: true + }) + udf2: string + + @Column({ + type: 'varchar', + name: 'udf3', + nullable: true + }) + udf3: string + + @Column({ + type: 'varchar', + name: 'udf4', + nullable: true + }) + udf4: string + + @Column({ + type: 'varchar', + name: 'udf5', + nullable: true + }) + udf5: string + + @Column({ + type: 'varchar', + name: 'address2', + nullable: true + }) + address2: string + + @Column({ + type: 'varchar', + name: 'city', + nullable: true + }) + city: string + + @Column({ + type: 'varchar', + name: 'zipcode', + nullable: true + }) + zipcode: string + + @Column({ + type: 'varchar', + name: 'pg_mid', + nullable: true + }) + pg_mid: string + + @Column({ + type: 'varchar', + name: 'issuing_bank', + nullable: true + }) + issuing_bank: string + + @Column({ + type: 'varchar', + name: 'offer_type', + nullable: true + }) + offer_type: string + + @Column({ + type: 'varchar', + name: 'failure_reason', + nullable: true + }) + failure_reason: string + + @Column({ + type: 'varchar', + name: 'mer_service_fee', + nullable: true + }) + mer_service_fee: string + + @Column({ + type: 'varchar', + name: 'mer_service_tax', + nullable: true + }) + mer_service_tax: string + + @Column({ + type: 'varchar', + name: 'txnid', + nullable: true + }) + txnid: string + + @Column({ + type: 'varchar', + name: 'gateway', + nullable: true + }) + gateway: string; +} \ No newline at end of file diff --git a/src/tables/payu-transaction-list/payu-transaction-list.module.ts b/src/tables/payu-transaction-list/payu-transaction-list.module.ts new file mode 100644 index 0000000..3983606 --- /dev/null +++ b/src/tables/payu-transaction-list/payu-transaction-list.module.ts @@ -0,0 +1,21 @@ +import { HttpModule, Module } from '@nestjs/common'; +import { PayuTransactionListService } from './payu-transaction-list.service'; +import { PayuTransactionListController } from './payu-transaction-list.controller'; +import { PayuTransactionListRepository } from './payu-transaction-list.repository'; +import { PcduserRepository } from 'src/auth/pcduser.repository'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AuthModule } from 'src/auth/auth.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([ + PayuTransactionListRepository, + ]), + AuthModule, + HttpModule + ], + providers: [PayuTransactionListService], + controllers: [PayuTransactionListController], + exports: [PayuTransactionListService] +}) +export class PayuTransactionListModule { } diff --git a/src/tables/payu-transaction-list/payu-transaction-list.repository.ts b/src/tables/payu-transaction-list/payu-transaction-list.repository.ts new file mode 100644 index 0000000..b67bc88 --- /dev/null +++ b/src/tables/payu-transaction-list/payu-transaction-list.repository.ts @@ -0,0 +1,8 @@ +import { Logger } from "@nestjs/common"; +import { EntityRepository, Repository } from "typeorm"; +import { PayuTransactionListEntity } from "./payu-transaction-list.entity"; + +@EntityRepository(PayuTransactionListEntity) +export class PayuTransactionListRepository extends Repository{ + private logger = new Logger ("SisPayuTransactionListRepository"); +} \ No newline at end of file diff --git a/src/tables/payu-transaction-list/payu-transaction-list.service.ts b/src/tables/payu-transaction-list/payu-transaction-list.service.ts new file mode 100644 index 0000000..41b091f --- /dev/null +++ b/src/tables/payu-transaction-list/payu-transaction-list.service.ts @@ -0,0 +1,130 @@ +import { Body, HttpService, Injectable } from '@nestjs/common'; +import { Cron } from '@nestjs/schedule'; +import { InjectRepository } from '@nestjs/typeorm'; +import * as config from 'config'; +// import { sha512 } from 'js-sha512'; +import { of } from 'rxjs'; +import { PayuTransactionListDto } from 'src/dto/payu-transaction-list.dto'; +import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service'; +import { convertDateString } from 'src/pipe/pcd-date.pipe'; +import { FindManyOptions, In } from 'typeorm'; +import { PayuTransactionListRepository } from './payu-transaction-list.repository'; +import { sha512 } from 'js-sha512'; + + +@Injectable() +export class PayuTransactionListService extends PcdFormGridService{ + constructor( + @InjectRepository(PayuTransactionListRepository) + private PayuTransactionListRepository: PayuTransactionListRepository, + private readonly http: HttpService + ) { + super(PayuTransactionListRepository); + } + @Cron('* 55 23 * * *') + async handleCron() { + let date = new Date(); + const DateString = convertDateString(date, "yyyy-MM-dd"); + + await this.getTransactionDetails({ var1: DateString, var2: DateString, isSave: true }); + + } + async getTransactionDetails(body: any) { + const command = "get_Transaction_Details" + const key = config.get('payment-gateway').key + const salt = config.get('payment-gateway').salt + const var1 = body.var1 + const var2 = body.var2 + const sha = key + '|' + command + '|' + var1 + '|' + salt + const hash = sha512(sha); + const url = 'https://info.payu.in/merchant/postservice?form=2' + + let postData = { + "key": key, + "salt": salt, + "var1": var1, + "var2": var2, + "hash": hash, + "command": command + + } + console.log(postData); + + let Data = new URLSearchParams(postData).toString(); + const data: any = await this.http.post(url, Data).toPromise().then((res) => { + console.log("===res====", res.data); + return res.data; + }, (err) => { + console.log("===errr====", err); + return err; + }); + // console.log(data.Transaction_details); + + if (body.isSave && data?.Transaction_details) { + console.log('cron started'); + + for (let row of data.Transaction_details) { + let existing = await this.PayuTransactionListRepository.findOne({ where: { id: row.id } }) + if (!existing) { + row.gateway = 'PayU' + await this.PayuTransactionListRepository.save(row); + }else{ + row.gateway = 'PayU' + await this.PayuTransactionListRepository.update( { id: row.id },row); + } + } + this.PayuTransactionListRepository.query(`DELETE FROM + sis_payu_transaction a + USING sis_payu_transaction b + WHERE + a.id > b.id + AND a.payu_id = b.payu_id`) + console.log('completed'); + + } + return data; + + } + //fromDate and toDate filter + async dateFilter(filter: FindManyOptions) { + console.log("dateFilter", filter) + const date = await this.PayuTransactionListRepository.query(`select * from sis_payu_transaction spt where spt.addedon between '${filter.where['fromDate']}' and '${filter.where['toDate']}'`) + return date; + } + + @Cron('0 */2 * * *') + async checkPaymentStatus() { + + const payments = await this.PayuTransactionListRepository.find({ where: { status: In(['initiated', 'in progress']) } }) + for (let row of payments) { + const command = "verify_payment" + const key = config.get('payment-gateway').key + const salt = config.get('payment-gateway').salt + const var1 = row.txnid; + const sha = key + '|' + command + '|' + var1 + '|' + salt + const hash = sha512(sha); + const url = 'https://info.payu.in/merchant/postservice?form=2' + + let postData = { + "key": key, + "salt": salt, + "var1": var1, + "hash": hash, + "command": command + + } + let Data = new URLSearchParams(postData).toString(); + const data: any = await this.http.post(url, Data).toPromise().then(async (res) => { + if (res.data.status = 1) { + if (res.data.transaction_details[var1].status) { + row.status = res.data.transaction_details[var1].status + this.PayuTransactionListRepository.save(row) + } + } + }) + } + + } + + +} diff --git a/src/tables/tender-documents/tender-doc.entity.ts b/src/tables/tender-documents/tender-doc.entity.ts index 2b14b19..56737bc 100644 --- a/src/tables/tender-documents/tender-doc.entity.ts +++ b/src/tables/tender-documents/tender-doc.entity.ts @@ -2,6 +2,7 @@ import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom"; import { TenderMaster } from "src/tables/tender-master/tender-master.entity"; import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { DocumentType } from "../document-type/document-type.entity"; +import { Pcduser } from "src/auth/pcduser.entity"; @Entity("tender-doc") export class TenderDoc extends PcdBaseEntity{ @@ -49,6 +50,13 @@ export class TenderDoc extends PcdBaseEntity{ nullable:true }) documentCategory:string + + @Column({ + name:"user_id", + type:'varchar', + nullable:true + }) + userId:number; @ManyToOne(() => TenderMaster,(tenderMaster)=> tenderMaster.TenderDoc) @JoinColumn([{ name: "tender_id", referencedColumnName: "id" }]) @@ -58,5 +66,7 @@ export class TenderDoc extends PcdBaseEntity{ @JoinColumn([{ name: "doc_type", referencedColumnName: "id" }]) documentTypeD:DocumentType - + @ManyToOne(() => Pcduser,(Pcduser)=> Pcduser.tenderDoc,{eager:true}) + @JoinColumn([{ name: "user_id", referencedColumnName: "userId" }]) + userD:DocumentType } \ No newline at end of file diff --git a/src/tables/tender-master/tender-master.entity.ts b/src/tables/tender-master/tender-master.entity.ts index 77742b7..de3b927 100644 --- a/src/tables/tender-master/tender-master.entity.ts +++ b/src/tables/tender-master/tender-master.entity.ts @@ -9,6 +9,7 @@ import { TenderType } from "src/tables/tender-type/tender-type.entity"; import { TenderDoc } from "src/tables/tender-documents/tender-doc.entity"; import { Column, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { CoverDoc } from "../covers-master/covers-master.entity"; +import { PaymentMaster } from "../payment-master/payment-master.entity"; @Entity('tender_master') export class TenderMaster extends PcdBaseEntity { @@ -364,6 +365,10 @@ export class TenderMaster extends PcdBaseEntity { @OneToMany(() => paymentInstrument, (paymentInstrument) => paymentInstrument.tenderIdD) paymentInstrument: paymentInstrument[] + + @OneToMany(() => PaymentMaster, (paymentMaster) => paymentMaster.tenderMasterD) + paymentMaster: PaymentMaster[] + @OneToMany(() => TenderDoc, (TenderDoc) => TenderDoc.tenderIdD) TenderDoc: TenderDoc[]