├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── package-lock.json ├── package.json ├── paytm ├── config.js ├── lib │ ├── checksum.js │ └── crypt.js └── services │ └── index.js ├── server.js └── views ├── paytmRedirect.ejs └── response.ejs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '20 15 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # parcel-bundler cache (https://parceljs.org/) 61 | .cache 62 | 63 | # next.js build output 64 | .next 65 | 66 | # nuxt.js build output 67 | .nuxt 68 | 69 | # vuepress build output 70 | .vuepress/dist 71 | 72 | # Serverless directories 73 | .serverless 74 | 75 | #webstorm 76 | .idea/ 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Aditya Raval 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paytm Payment Gateway Integration With NodeJS & Express 2 | 3 | 4 | Simple explanatory way to use Paytm Payment Integration with NodeJS with Express with minimal dependancies. 5 | 6 | ### Node Packages Used 7 | * [ejs] - HTML Templating Engine! 8 | * [express] - Http web server! 9 | * [CORS] - CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.. 10 | * [dotenv] - Environment config! 11 | * [shortid] - generate unique short IDs 12 | * [body-parser] - Express Middleware.. 13 | 14 | ### ENV Setup 15 | Create .env file as below. 16 | 17 | ```sh 18 | MID=**MID Given By Paytm Staging Credentials** 19 | PAYTM_MERCHANT_KEY=**PAYTM_MERCHANT_KEY Given By Paytm Staging Credentials** 20 | WEBSITE=WEBSTAGING 21 | CHANNEL_ID=WEB 22 | INDUSTRY_TYPE_ID=Retail 23 | PAYTM_FINAL_URL=https://securegw-stage.paytm.in/theia/processTransaction 24 | CALLBACK_URL=http://localhost:4000/paywithpaytmresponse 25 | PORT=4000 26 | ``` 27 | 28 | 29 | 30 | ### Installation 31 | Install the dependencies and devDependencies and start the server. 32 | 33 | ```sh 34 | $ cd paytm-integration-nodejs-express 35 | $ npm install 36 | $ npm start 37 | ``` 38 | 39 | ### STEPS 40 | * Open below url in browser! 41 | http://localhost:4000/paywithpaytm?amount=10 42 | 43 | * You will be redirected to the payment page of paytm,use this staging credentials to login 44 | Mobile no=7777777777, 45 | OTP=489871 46 | 47 | * After you login with the staging credentials you will be logged in and once you will click Pay Now button,you will be redirected to below response page with proper payment summary. 48 | http://localhost:4000/paywithpaytmresponse 49 | 50 | License 51 | ---- 52 | 53 | MIT 54 | 55 | 56 | **Free Software, Hell Yeah!** 57 | 58 | 59 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paytm-integration", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.5", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 11 | "requires": { 12 | "mime-types": "~2.1.18", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "ansi-styles": { 17 | "version": "4.3.0", 18 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 19 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 20 | "requires": { 21 | "color-convert": "^2.0.1" 22 | } 23 | }, 24 | "array-flatten": { 25 | "version": "1.1.1", 26 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 27 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 28 | }, 29 | "async": { 30 | "version": "3.2.4", 31 | "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", 32 | "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" 33 | }, 34 | "balanced-match": { 35 | "version": "1.0.2", 36 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 37 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 38 | }, 39 | "body-parser": { 40 | "version": "1.18.3", 41 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 42 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 43 | "requires": { 44 | "bytes": "3.0.0", 45 | "content-type": "~1.0.4", 46 | "debug": "2.6.9", 47 | "depd": "~1.1.2", 48 | "http-errors": "~1.6.3", 49 | "iconv-lite": "0.4.23", 50 | "on-finished": "~2.3.0", 51 | "qs": "6.5.2", 52 | "raw-body": "2.3.3", 53 | "type-is": "~1.6.16" 54 | }, 55 | "dependencies": { 56 | "qs": { 57 | "version": "6.5.2", 58 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 59 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 60 | } 61 | } 62 | }, 63 | "brace-expansion": { 64 | "version": "2.0.1", 65 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 66 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 67 | "requires": { 68 | "balanced-match": "^1.0.0" 69 | } 70 | }, 71 | "bytes": { 72 | "version": "3.0.0", 73 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 74 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 75 | }, 76 | "chalk": { 77 | "version": "4.1.2", 78 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 79 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 80 | "requires": { 81 | "ansi-styles": "^4.1.0", 82 | "supports-color": "^7.1.0" 83 | } 84 | }, 85 | "color-convert": { 86 | "version": "2.0.1", 87 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 88 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 89 | "requires": { 90 | "color-name": "~1.1.4" 91 | } 92 | }, 93 | "color-name": { 94 | "version": "1.1.4", 95 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 96 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 97 | }, 98 | "concat-map": { 99 | "version": "0.0.1", 100 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 101 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 102 | }, 103 | "content-disposition": { 104 | "version": "0.5.2", 105 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 106 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 107 | }, 108 | "content-type": { 109 | "version": "1.0.4", 110 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 111 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 112 | }, 113 | "cookie": { 114 | "version": "0.3.1", 115 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 116 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 117 | }, 118 | "cookie-signature": { 119 | "version": "1.0.6", 120 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 121 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 122 | }, 123 | "cors": { 124 | "version": "2.8.4", 125 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", 126 | "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", 127 | "requires": { 128 | "object-assign": "^4", 129 | "vary": "^1" 130 | } 131 | }, 132 | "debug": { 133 | "version": "2.6.9", 134 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 135 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 136 | "requires": { 137 | "ms": "2.0.0" 138 | } 139 | }, 140 | "depd": { 141 | "version": "1.1.2", 142 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 143 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 144 | }, 145 | "destroy": { 146 | "version": "1.0.4", 147 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 148 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 149 | }, 150 | "dotenv": { 151 | "version": "6.0.0", 152 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.0.0.tgz", 153 | "integrity": "sha512-FlWbnhgjtwD+uNLUGHbMykMOYQaTivdHEmYwAKFjn6GKe/CqY0fNae93ZHTd20snh9ZLr8mTzIL9m0APQ1pjQg==" 154 | }, 155 | "ee-first": { 156 | "version": "1.1.1", 157 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 158 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 159 | }, 160 | "ejs": { 161 | "version": "3.1.7", 162 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", 163 | "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", 164 | "requires": { 165 | "jake": "^10.8.5" 166 | } 167 | }, 168 | "encodeurl": { 169 | "version": "1.0.2", 170 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 171 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 172 | }, 173 | "escape-html": { 174 | "version": "1.0.3", 175 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 176 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 177 | }, 178 | "etag": { 179 | "version": "1.8.1", 180 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 181 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 182 | }, 183 | "express": { 184 | "version": "4.16.3", 185 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", 186 | "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", 187 | "requires": { 188 | "accepts": "~1.3.5", 189 | "array-flatten": "1.1.1", 190 | "body-parser": "1.18.2", 191 | "content-disposition": "0.5.2", 192 | "content-type": "~1.0.4", 193 | "cookie": "0.3.1", 194 | "cookie-signature": "1.0.6", 195 | "debug": "2.6.9", 196 | "depd": "~1.1.2", 197 | "encodeurl": "~1.0.2", 198 | "escape-html": "~1.0.3", 199 | "etag": "~1.8.1", 200 | "finalhandler": "1.1.1", 201 | "fresh": "0.5.2", 202 | "merge-descriptors": "1.0.1", 203 | "methods": "~1.1.2", 204 | "on-finished": "~2.3.0", 205 | "parseurl": "~1.3.2", 206 | "path-to-regexp": "0.1.7", 207 | "proxy-addr": "~2.0.3", 208 | "qs": "6.5.1", 209 | "range-parser": "~1.2.0", 210 | "safe-buffer": "5.1.1", 211 | "send": "0.16.2", 212 | "serve-static": "1.13.2", 213 | "setprototypeof": "1.1.0", 214 | "statuses": "~1.4.0", 215 | "type-is": "~1.6.16", 216 | "utils-merge": "1.0.1", 217 | "vary": "~1.1.2" 218 | }, 219 | "dependencies": { 220 | "body-parser": { 221 | "version": "1.18.2", 222 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 223 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 224 | "requires": { 225 | "bytes": "3.0.0", 226 | "content-type": "~1.0.4", 227 | "debug": "2.6.9", 228 | "depd": "~1.1.1", 229 | "http-errors": "~1.6.2", 230 | "iconv-lite": "0.4.19", 231 | "on-finished": "~2.3.0", 232 | "qs": "6.5.1", 233 | "raw-body": "2.3.2", 234 | "type-is": "~1.6.15" 235 | } 236 | }, 237 | "iconv-lite": { 238 | "version": "0.4.19", 239 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 240 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 241 | }, 242 | "raw-body": { 243 | "version": "2.3.2", 244 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 245 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 246 | "requires": { 247 | "bytes": "3.0.0", 248 | "http-errors": "1.6.2", 249 | "iconv-lite": "0.4.19", 250 | "unpipe": "1.0.0" 251 | }, 252 | "dependencies": { 253 | "depd": { 254 | "version": "1.1.1", 255 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 256 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 257 | }, 258 | "http-errors": { 259 | "version": "1.6.2", 260 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 261 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 262 | "requires": { 263 | "depd": "1.1.1", 264 | "inherits": "2.0.3", 265 | "setprototypeof": "1.0.3", 266 | "statuses": ">= 1.3.1 < 2" 267 | } 268 | }, 269 | "setprototypeof": { 270 | "version": "1.0.3", 271 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 272 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 273 | } 274 | } 275 | } 276 | } 277 | }, 278 | "filelist": { 279 | "version": "1.0.4", 280 | "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", 281 | "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", 282 | "requires": { 283 | "minimatch": "^5.0.1" 284 | }, 285 | "dependencies": { 286 | "minimatch": { 287 | "version": "5.1.0", 288 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", 289 | "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", 290 | "requires": { 291 | "brace-expansion": "^2.0.1" 292 | } 293 | } 294 | } 295 | }, 296 | "finalhandler": { 297 | "version": "1.1.1", 298 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 299 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "encodeurl": "~1.0.2", 303 | "escape-html": "~1.0.3", 304 | "on-finished": "~2.3.0", 305 | "parseurl": "~1.3.2", 306 | "statuses": "~1.4.0", 307 | "unpipe": "~1.0.0" 308 | } 309 | }, 310 | "forwarded": { 311 | "version": "0.1.2", 312 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 313 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 314 | }, 315 | "fresh": { 316 | "version": "0.5.2", 317 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 318 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 319 | }, 320 | "has-flag": { 321 | "version": "4.0.0", 322 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 323 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 324 | }, 325 | "http-errors": { 326 | "version": "1.6.3", 327 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 328 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 329 | "requires": { 330 | "depd": "~1.1.2", 331 | "inherits": "2.0.3", 332 | "setprototypeof": "1.1.0", 333 | "statuses": ">= 1.4.0 < 2" 334 | } 335 | }, 336 | "iconv-lite": { 337 | "version": "0.4.23", 338 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 339 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 340 | "requires": { 341 | "safer-buffer": ">= 2.1.2 < 3" 342 | } 343 | }, 344 | "inherits": { 345 | "version": "2.0.3", 346 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 347 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 348 | }, 349 | "ipaddr.js": { 350 | "version": "1.6.0", 351 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", 352 | "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" 353 | }, 354 | "jake": { 355 | "version": "10.8.5", 356 | "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", 357 | "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", 358 | "requires": { 359 | "async": "^3.2.3", 360 | "chalk": "^4.0.2", 361 | "filelist": "^1.0.1", 362 | "minimatch": "^3.0.4" 363 | } 364 | }, 365 | "media-typer": { 366 | "version": "0.3.0", 367 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 368 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 369 | }, 370 | "merge-descriptors": { 371 | "version": "1.0.1", 372 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 373 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 374 | }, 375 | "methods": { 376 | "version": "1.1.2", 377 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 378 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 379 | }, 380 | "mime": { 381 | "version": "1.4.1", 382 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 383 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 384 | }, 385 | "mime-db": { 386 | "version": "1.33.0", 387 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", 388 | "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" 389 | }, 390 | "mime-types": { 391 | "version": "2.1.18", 392 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", 393 | "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", 394 | "requires": { 395 | "mime-db": "~1.33.0" 396 | } 397 | }, 398 | "minimatch": { 399 | "version": "3.1.2", 400 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 401 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 402 | "requires": { 403 | "brace-expansion": "^1.1.7" 404 | }, 405 | "dependencies": { 406 | "brace-expansion": { 407 | "version": "1.1.11", 408 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 409 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 410 | "requires": { 411 | "balanced-match": "^1.0.0", 412 | "concat-map": "0.0.1" 413 | } 414 | } 415 | } 416 | }, 417 | "ms": { 418 | "version": "2.0.0", 419 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 420 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 421 | }, 422 | "nanoid": { 423 | "version": "1.0.7", 424 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.0.7.tgz", 425 | "integrity": "sha512-DCTnU68QAckm8vgPbFhM1XcK3/zX8LWL4/kEXzPH5w2qy2ibBWHig+685aF8ff8rd5lUXkhVB3W60pb4mbRcDA==" 426 | }, 427 | "negotiator": { 428 | "version": "0.6.1", 429 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 430 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 431 | }, 432 | "object-assign": { 433 | "version": "4.1.1", 434 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 435 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 436 | }, 437 | "on-finished": { 438 | "version": "2.3.0", 439 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 440 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 441 | "requires": { 442 | "ee-first": "1.1.1" 443 | } 444 | }, 445 | "parseurl": { 446 | "version": "1.3.2", 447 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 448 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 449 | }, 450 | "path-to-regexp": { 451 | "version": "0.1.7", 452 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 453 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 454 | }, 455 | "proxy-addr": { 456 | "version": "2.0.3", 457 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", 458 | "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", 459 | "requires": { 460 | "forwarded": "~0.1.2", 461 | "ipaddr.js": "1.6.0" 462 | } 463 | }, 464 | "qs": { 465 | "version": "6.5.1", 466 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 467 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 468 | }, 469 | "range-parser": { 470 | "version": "1.2.0", 471 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 472 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 473 | }, 474 | "raw-body": { 475 | "version": "2.3.3", 476 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 477 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 478 | "requires": { 479 | "bytes": "3.0.0", 480 | "http-errors": "1.6.3", 481 | "iconv-lite": "0.4.23", 482 | "unpipe": "1.0.0" 483 | } 484 | }, 485 | "safe-buffer": { 486 | "version": "5.1.1", 487 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 488 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 489 | }, 490 | "safer-buffer": { 491 | "version": "2.1.2", 492 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 493 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 494 | }, 495 | "send": { 496 | "version": "0.16.2", 497 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 498 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 499 | "requires": { 500 | "debug": "2.6.9", 501 | "depd": "~1.1.2", 502 | "destroy": "~1.0.4", 503 | "encodeurl": "~1.0.2", 504 | "escape-html": "~1.0.3", 505 | "etag": "~1.8.1", 506 | "fresh": "0.5.2", 507 | "http-errors": "~1.6.2", 508 | "mime": "1.4.1", 509 | "ms": "2.0.0", 510 | "on-finished": "~2.3.0", 511 | "range-parser": "~1.2.0", 512 | "statuses": "~1.4.0" 513 | } 514 | }, 515 | "serve-static": { 516 | "version": "1.13.2", 517 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 518 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 519 | "requires": { 520 | "encodeurl": "~1.0.2", 521 | "escape-html": "~1.0.3", 522 | "parseurl": "~1.3.2", 523 | "send": "0.16.2" 524 | } 525 | }, 526 | "setprototypeof": { 527 | "version": "1.1.0", 528 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 529 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 530 | }, 531 | "shortid": { 532 | "version": "2.2.10", 533 | "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.10.tgz", 534 | "integrity": "sha512-eeiSfCwMWCBvKO19ToZQyqjGgKOEI9Plu676Sx8lrhNc/zCg7U6JzSYPt9wwnQDsbf400sAowenPNBC4dQ1KBA==", 535 | "requires": { 536 | "nanoid": "^1.0.7" 537 | } 538 | }, 539 | "statuses": { 540 | "version": "1.4.0", 541 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 542 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 543 | }, 544 | "supports-color": { 545 | "version": "7.2.0", 546 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 547 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 548 | "requires": { 549 | "has-flag": "^4.0.0" 550 | } 551 | }, 552 | "type-is": { 553 | "version": "1.6.16", 554 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 555 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 556 | "requires": { 557 | "media-typer": "0.3.0", 558 | "mime-types": "~2.1.18" 559 | } 560 | }, 561 | "unpipe": { 562 | "version": "1.0.0", 563 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 564 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 565 | }, 566 | "utils-merge": { 567 | "version": "1.0.1", 568 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 569 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 570 | }, 571 | "vary": { 572 | "version": "1.1.2", 573 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 574 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 575 | } 576 | } 577 | } 578 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paytm-integration", 3 | "version": "1.0.0", 4 | "description": "Paytm Integration", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "test", 8 | "start": "node server.js" 9 | }, 10 | "author": "Aditya Raval", 11 | "homepage": "https://github.com/adityaraval/paytm-integration-nodejs-express#readme", 12 | "license": "MIT", 13 | "dependencies": { 14 | "body-parser": "^1.18.3", 15 | "cors": "^2.8.4", 16 | "dotenv": "^6.0.0", 17 | "ejs": "^3.1.7", 18 | "express": "^4.16.3", 19 | "shortid": "^2.2.10" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /paytm/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MID: process.env.MID, 3 | PAYTM_MERCHANT_KEY: process.env.PAYTM_MERCHANT_KEY, 4 | PAYTM_FINAL_URL: process.env.PAYTM_FINAL_URL, 5 | WEBSITE: process.env.WEBSITE, 6 | CHANNEL_ID: process.env.CHANNEL_ID, 7 | INDUSTRY_TYPE_ID: process.env.INDUSTRY_TYPE_ID, 8 | CALLBACK_URL: process.env.CALLBACK_URL 9 | }; 10 | -------------------------------------------------------------------------------- /paytm/lib/checksum.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var crypt = require("./crypt"); 4 | var util = require("util"); 5 | var crypto = require("crypto"); 6 | 7 | //mandatory flag: when it set, only mandatory parameters are added to checksum 8 | 9 | function paramsToString(params, mandatoryflag) { 10 | var data = ""; 11 | var tempKeys = Object.keys(params); 12 | tempKeys.sort(); 13 | tempKeys.forEach(function(key) { 14 | var n = params[key].includes("REFUND"); 15 | var m = params[key].includes("|"); 16 | if (n == true) { 17 | params[key] = ""; 18 | } 19 | if (m == true) { 20 | params[key] = ""; 21 | } 22 | if (key !== "CHECKSUMHASH") { 23 | if (params[key] === "null") params[key] = ""; 24 | if (!mandatoryflag || mandatoryParams.indexOf(key) !== -1) { 25 | data += params[key] + "|"; 26 | } 27 | } 28 | }); 29 | return data; 30 | } 31 | 32 | function genchecksum(params, key, cb) { 33 | var data = paramsToString(params); 34 | crypt.gen_salt(4, function(err, salt) { 35 | var sha256 = crypto 36 | .createHash("sha256") 37 | .update(data + salt) 38 | .digest("hex"); 39 | var check_sum = sha256 + salt; 40 | var encrypted = crypt.encrypt(check_sum, key); 41 | cb(undefined, encrypted); 42 | }); 43 | } 44 | function genchecksumbystring(params, key, cb) { 45 | crypt.gen_salt(4, function(err, salt) { 46 | var sha256 = crypto 47 | .createHash("sha256") 48 | .update(params + "|" + salt) 49 | .digest("hex"); 50 | var check_sum = sha256 + salt; 51 | var encrypted = crypt.encrypt(check_sum, key); 52 | 53 | var CHECKSUMHASH = encodeURIComponent(encrypted); 54 | CHECKSUMHASH = encrypted; 55 | cb(undefined, CHECKSUMHASH); 56 | }); 57 | } 58 | 59 | function verifychecksum(params, key, checksumhash) { 60 | var data = paramsToString(params, false); 61 | 62 | //TODO: after PG fix on thier side remove below two lines 63 | if (typeof checksumhash !== "undefined") { 64 | checksumhash = checksumhash.replace("\n", ""); 65 | checksumhash = checksumhash.replace("\r", ""); 66 | var temp = decodeURIComponent(checksumhash); 67 | var checksum = crypt.decrypt(temp, key); 68 | var salt = checksum.substr(checksum.length - 4); 69 | var sha256 = checksum.substr(0, checksum.length - 4); 70 | var hash = crypto 71 | .createHash("sha256") 72 | .update(data + salt) 73 | .digest("hex"); 74 | if (hash === sha256) { 75 | return true; 76 | } else { 77 | util.log("checksum is wrong"); 78 | return false; 79 | } 80 | } else { 81 | util.log("checksum not found"); 82 | return false; 83 | } 84 | } 85 | 86 | function verifychecksumbystring(params, key, checksumhash) { 87 | var checksum = crypt.decrypt(checksumhash, key); 88 | var salt = checksum.substr(checksum.length - 4); 89 | var sha256 = checksum.substr(0, checksum.length - 4); 90 | var hash = crypto 91 | .createHash("sha256") 92 | .update(params + "|" + salt) 93 | .digest("hex"); 94 | if (hash === sha256) { 95 | return true; 96 | } else { 97 | util.log("checksum is wrong"); 98 | return false; 99 | } 100 | } 101 | 102 | function genchecksumforrefund(params, key, cb) { 103 | var data = paramsToStringrefund(params); 104 | crypt.gen_salt(4, function(err, salt) { 105 | var sha256 = crypto 106 | .createHash("sha256") 107 | .update(data + salt) 108 | .digest("hex"); 109 | var check_sum = sha256 + salt; 110 | var encrypted = crypt.encrypt(check_sum, key); 111 | params.CHECKSUM = encodeURIComponent(encrypted); 112 | cb(undefined, params); 113 | }); 114 | } 115 | 116 | function paramsToStringrefund(params, mandatoryflag) { 117 | var data = ""; 118 | var tempKeys = Object.keys(params); 119 | tempKeys.sort(); 120 | tempKeys.forEach(function(key) { 121 | var m = params[key].includes("|"); 122 | if (m == true) { 123 | params[key] = ""; 124 | } 125 | if (key !== "CHECKSUMHASH") { 126 | if (params[key] === "null") params[key] = ""; 127 | if (!mandatoryflag || mandatoryParams.indexOf(key) !== -1) { 128 | data += params[key] + "|"; 129 | } 130 | } 131 | }); 132 | return data; 133 | } 134 | 135 | module.exports.genchecksum = genchecksum; 136 | module.exports.verifychecksum = verifychecksum; 137 | module.exports.verifychecksumbystring = verifychecksumbystring; 138 | module.exports.genchecksumbystring = genchecksumbystring; 139 | module.exports.genchecksumforrefund = genchecksumforrefund; 140 | -------------------------------------------------------------------------------- /paytm/lib/crypt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var crypto = require('crypto'); 4 | var util = require('util'); 5 | 6 | var crypt = { 7 | iv: '@@@@&&&###$$$$', 8 | 9 | encrypt: function (data,custom_key) { 10 | var iv = this.iv; 11 | var key = custom_key; 12 | var algo = '256'; 13 | switch (key.length) { 14 | case 16: 15 | algo = '128'; 16 | break; 17 | case 24: 18 | algo = '192'; 19 | break; 20 | case 32: 21 | algo = '256'; 22 | break; 23 | 24 | } 25 | var cipher = crypto.createCipheriv('AES-' + algo + '-CBC', key, iv); 26 | //var cipher = crypto.createCipher('aes256',key); 27 | var encrypted = cipher.update(data, 'binary', 'base64'); 28 | encrypted += cipher.final('base64'); 29 | return encrypted; 30 | }, 31 | 32 | decrypt: function (data,custom_key) { 33 | var iv = this.iv; 34 | var key = custom_key; 35 | var algo = '256'; 36 | switch (key.length) { 37 | case 16: 38 | algo = '128'; 39 | break; 40 | case 24: 41 | algo = '192'; 42 | break; 43 | case 32: 44 | algo = '256'; 45 | break; 46 | } 47 | var decipher = crypto.createDecipheriv('AES-' + algo + '-CBC', key, iv); 48 | var decrypted = decipher.update(data, 'base64', 'binary'); 49 | try { 50 | decrypted += decipher.final('binary'); 51 | } catch (e) { 52 | util.log(util.inspect(e)); 53 | } 54 | return decrypted; 55 | }, 56 | 57 | gen_salt: function (length, cb) { 58 | crypto.randomBytes((length * 3.0) / 4.0, function (err, buf) { 59 | var salt; 60 | if (!err) { 61 | salt = buf.toString("base64"); 62 | } 63 | //salt=Math.floor(Math.random()*8999)+1000; 64 | cb(err, salt); 65 | }); 66 | }, 67 | 68 | /* one way md5 hash with salt */ 69 | md5sum: function (salt, data) { 70 | return crypto.createHash('md5').update(salt + data).digest('hex'); 71 | }, 72 | sha256sum: function (salt, data) { 73 | return crypto.createHash('sha256').update(data + salt).digest('hex'); 74 | } 75 | }; 76 | 77 | module.exports = crypt; 78 | 79 | (function () { 80 | var i; 81 | 82 | function logsalt(err, salt) { 83 | if (!err) { 84 | console.log('salt is ' + salt); 85 | } 86 | } 87 | 88 | if (require.main === module) { 89 | var enc = crypt.encrypt('One97'); 90 | console.log('encrypted - ' + enc); 91 | console.log('decrypted - ' + crypt.decrypt(enc)); 92 | 93 | for (i = 0; i < 5; i++) { 94 | crypt.gen_salt(4, logsalt); 95 | } 96 | } 97 | 98 | }()); 99 | -------------------------------------------------------------------------------- /paytm/services/index.js: -------------------------------------------------------------------------------- 1 | const checksum = require('../lib/checksum'); 2 | const config = require('../config'); 3 | const shortid = require('shortid'); 4 | 5 | const initPayment = function(amount) { 6 | return new Promise((resolve, reject) => { 7 | let paymentObj = { 8 | ORDER_ID: shortid.generate(), 9 | CUST_ID: shortid.generate(), 10 | INDUSTRY_TYPE_ID: config.INDUSTRY_TYPE_ID, 11 | CHANNEL_ID: config.CHANNEL_ID, 12 | TXN_AMOUNT: amount.toString(), 13 | MID: config.MID, 14 | WEBSITE: config.WEBSITE, 15 | CALLBACK_URL: config.CALLBACK_URL 16 | }; 17 | 18 | checksum.genchecksum( 19 | paymentObj, 20 | config.PAYTM_MERCHANT_KEY, 21 | (err, result) => { 22 | if (err) { 23 | return reject('Error while generating checksum'); 24 | } else { 25 | paymentObj.CHECKSUMHASH = result; 26 | return resolve(paymentObj); 27 | } 28 | } 29 | ); 30 | }); 31 | }; 32 | 33 | const responsePayment = function(paymentObject) { 34 | return new Promise((resolve, reject) => { 35 | if ( 36 | checksum.verifychecksum( 37 | paymentObject, 38 | config.PAYTM_MERCHANT_KEY, 39 | paymentObject.CHECKSUMHASH 40 | ) 41 | ) { 42 | resolve(paymentObject); 43 | } else { 44 | return reject('Error while verifying checksum'); 45 | } 46 | }); 47 | }; 48 | 49 | module.exports = { 50 | initPayment: initPayment, 51 | responsePayment: responsePayment 52 | }; 53 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const bodyParser = require("body-parser"); 3 | const cors = require("cors"); 4 | const ejs = require("ejs"); 5 | const app = express(); 6 | require("dotenv").config(); 7 | 8 | const PORT = process.env.PORT || 4000; 9 | 10 | const {initPayment, responsePayment} = require("./paytm/services/index"); 11 | 12 | app.use(cors()); 13 | 14 | app.use(bodyParser.json()); 15 | app.use(bodyParser.urlencoded({extended: true})); 16 | 17 | app.use(express.static(__dirname + "/views")); 18 | app.set("view engine", "ejs"); 19 | 20 | app.get("/paywithpaytm", (req, res) => { 21 | initPayment(req.query.amount).then( 22 | success => { 23 | res.render("paytmRedirect.ejs", { 24 | resultData: success, 25 | paytmFinalUrl: process.env.PAYTM_FINAL_URL 26 | }); 27 | }, 28 | error => { 29 | res.send(error); 30 | } 31 | ); 32 | }); 33 | 34 | app.post("/paywithpaytmresponse", (req, res) => { 35 | responsePayment(req.body).then( 36 | success => { 37 | res.render("response.ejs", {resultData: "true", responseData: success}); 38 | }, 39 | error => { 40 | res.send(error); 41 | } 42 | ); 43 | }); 44 | 45 | app.listen(PORT, () => { 46 | console.log("Running on " + PORT); 47 | }); 48 | -------------------------------------------------------------------------------- /views/paytmRedirect.ejs: -------------------------------------------------------------------------------- 1 | 2 |
3 |PAYMENT RECEIPT 75 | | 76 ||
---|---|
<%= name %> | 84 |<%= responseData[name] %> | 85 |
Thank you!. 91 | | 92 |