{"_id":"expresscheckout-nodejs","name":"expresscheckout-nodejs","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"expresscheckout-nodejs","version":"1.0.0","description":"Juspay's official expresscheckout-nodejs sdk","homepage":"https://docs.juspay.in/api-reference/docs/express-checkout/introduction","scripts":{"prepublishOnly":"npm test","build":"npm run build:cjs && npm run build:esm && npm run build:types","build:cjs":"node tools/cleanup cjs && tsc -p config/tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json","build:esm":"node tools/cleanup esm && tsc -p config/tsconfig.esm.json && echo '{\"type\":\"module\"}' > ./dist/esm/package.json","build:types":"node tools/cleanup types && tsc -p config/tsconfig.types.json","clean":"node tools/cleanup","package":"npm run build && npm pack .","test":"env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' & mocha  --require ts-node/register ./tests/**/*.spec.ts --timeout 50000","examples":"npm test -- -g Compatibility"},"repository":{"url":"https://bitbucket.juspay.net/projects/CL/repos/expresscheckout-nodejs-sdk/browse"},"engines":{"node":">=12.*"},"publishConfig":{"access":"public"},"keywords":["payments","juspay","expresscheckout","nodejs","sdk","expresscheckout-nodejs-sdk"],"main":"./dist/cjs/index.cjs.js","module":"./dist/esm/index.js","types":"./dist/types/index.d.ts","exports":{".":{"import":{"types":"./dist/types/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/types/index.d.ts","default":"./dist/cjs/index.cjs.js"}}},"author":{"name":"Juspay Technologies"},"license":"MIT","dependencies":{"winston":"^3.11.0"},"devDependencies":{"@commitlint/cli":"^13.1.0","@commitlint/config-conventional":"^13.1.0","@types/chai":"^4.3.5","@types/mocha":"^10.0.1","@types/node":"^20.6.3","@types/node-jose":"^1.1.10","@typescript-eslint/eslint-plugin":"^4.31.1","@typescript-eslint/parser":"^4.31.1","chai":"^4.3.7","dotenv":"^16.3.1","eslint":"^7.32.0","eslint-config-prettier":"^8.3.0","eslint-plugin-import":"^2.27.5","eslint-plugin-prettier":"^4.0.0","mocha":"^10.2.0","prettier":"^2.4.0","ts-loader":"^9.2.5","ts-node":"^10.9.1","typescript":"^4.9.5"},"gitHead":"1447d50306ba1a4fa0f08f21ff685fc2d3725eaa","_id":"expresscheckout-nodejs@1.0.0","_nodeVersion":"14.17.6","_npmVersion":"6.14.15","dist":{"integrity":"sha512-+QT499qo879I8yYuEdbeC2L0vtztp9txpvhAReqFF2uQSlHsFCh4u3dQ/sYgMJrhPHYoHKzhm8yTS8ZorKN16w==","shasum":"553fd22daca95fd27f8a98af4adb5d80041f6cb6","tarball":"https://registry.npmjs.org/expresscheckout-nodejs/-/expresscheckout-nodejs-1.0.0.tgz","fileCount":137,"unpackedSize":305862,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC2ZKByBqZbhwHaf6OpCtAxq3NBAIMGqkSxbqhhjb93uAiEA4FFcLQ18q23+Di1w01odg0BdSCjdt2WobXq+t6Z7xyY="}]},"_npmUser":{"name":"krupal.panchasara.juspay","email":"krupal.panchasara@juspay.in"},"directories":{},"maintainers":[{"name":"krupal.panchasara.juspay","email":"krupal.panchasara@juspay.in"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/expresscheckout-nodejs_1.0.0_1705496768638_0.7447855683368096"},"_hasShrinkwrap":false}},"time":{"created":"2024-01-17T13:06:08.514Z","1.0.0":"2024-01-17T13:06:08.798Z","modified":"2024-01-17T13:06:09.135Z"},"maintainers":[{"name":"krupal.panchasara.juspay","email":"krupal.panchasara@juspay.in"}],"description":"Juspay's official expresscheckout-nodejs sdk","homepage":"https://docs.juspay.in/api-reference/docs/express-checkout/introduction","keywords":["payments","juspay","expresscheckout","nodejs","sdk","expresscheckout-nodejs-sdk"],"repository":{"url":"https://bitbucket.juspay.net/projects/CL/repos/expresscheckout-nodejs-sdk/browse"},"author":{"name":"Juspay Technologies"},"license":"MIT","readme":"<p>\n<a href=\"https://www.gnu.org/licenses/agpl-3.0\"><img src=\"https://img.shields.io/badge/License-AGPL_v3-purple.svg\" alt=\"MIT License\"></a>\n<a href=\"https://bitbucket.juspay.net/projects/CL/repos/expresscheckout-nodejs-sdk/browse\"><img src=\"https://img.shields.io/badge/Version-v1.0.0-blue.svg\" alt=\"v1.0.0\"></a>\n</p>\n\n\n# Juspay's Expresscheckout NodeJs SDK\nPlease go through the documentation for Juspay API [here](https://docs.juspay.in/api-reference/docs/express-checkout/introduction)\n\n\n## Contents\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [Identify Endpoints](#identify-endpoints)\n  - [Rest endpoints for Juspay](#rest-endpoints-for-juspay)\n  - [Rest endpoints for HDFC tenant](#rest-endpoints-for-hdfc-tenant)\n- [Authentication and Access](#authentication-and-access)\n  - [Basic Authentication method](#basic-authentication-method)\n  - [JWE+JWS encryption](#jwejws-encryption)\n    - [JWE components](#jwe-components)\n    - [JWS components](#jws-components)\n- [Importing SDKs](#importing-sdks)\n  - [CommonJS](#commonjs)\n  - [Using Typescript/ES Module](#using-typescriptes-module)\n- [SDK Resources](#sdk-resources)\n  - [Using try/catch blocks](#using-trycatch-blocks)\n  - [Using Promises](#using-promises)\n  - [Response http object](#response-http-object)\n  - [Override default configs for single resource](#override-default-configs-for-single-resource)\n- [Error Handling And Examples](#error-handling-and-examples)\n  - [APIError to refund unknown order id](#apierror-to-refund-unknown-order-id)\n  - [JuspayError in case of failed signature verification](#juspayerror-in-case-of-failed-signature-verification)\n- [Logging](#logging)\n  - [Disable logs](#disable-logs)\n  - [Custom pino or buyan logger](#custom-pino-or-buyan-logger)\n  - [Custom logging framework](#custom-logging-framework)\n- [ Resources List](#resources-list)\n- [Questions?](#questions)\n\n## Installation\nInstallation using npm\n\n```bash\nnpm i expresscheckout-nodejs\n```\n\n## Getting Started\nTo access the apis you will need merchantId and authentication methods, juspay supports Basic authentication with apikey for most of the routes. This SDK also supports JWT authentication for routes that currently support it. It'll be prioritized over Basic authentication in case of multiple authentication options.\n\n## Identify Endpoints\n### Rest endpoints for Juspay\n\n| Environment       | Endpoint                         |\n| ------------------| ---------------------------------|\n| Sandbox           | https://sandbox.juspay.in        |\n| Production        | https://api.juspay.in            |\n\n### Rest endpoints for HDFC tenant\n\n| Environment       | Endpoint                                 |\n| ------------------| -----------------------------------------|\n| Sandbox           | https://smartgatewayuat.hdfcbank.com     |\n| Production        |\thttps://smartgateway.hdfcbank.com        |\n\n> Default endpoint is https://sandbox.juspay.in\n\n## Authentication and Access\nCurrent version of expresscheckout-nodejs supports JWE+JWS and Basic authentication method using apiKey.\nBasic info on each methods\n\n> Make sure to pass **_merchantId_** in Juspay initialization\n\n### Basic Authentication method\nTo use this method use **apiKey** generated from your dashboard under sidebar **_Payments > Settings > Security > API Keys_**\n\n```js\nconst juspay = new Juspay({\n  apiKey: \"your apiKey\",\n  merchantId: \"your merchantId\"\n})\n```\n\n### JWE+JWS encryption\nThis method is more secure authentication method that encrypts the signed payload using **_AES-256-GCM_** algorithm,\npayload is signed using **_RSA-SHA256_** algorithm of actual data. Hence, we'll use 2 pairs for keys, one for JWE and one for JWS.\n\nJWT and JWE+JWS will be used interchangeably here.\n\n```js\nconst juspay = new Juspay.Juspay({\n  merchantId: \"your merchantId\",\n  jweAuth: {\n    keyId: \"your keyId\",\n    privateKey: \"your privateKey\",\n    publicKey: \"your publicKey\",\n  },\n})\n```\n\nTo get the keys go to sidebar then **_Payments > Settings > Security > JWT Keys > Upload New JWT > (I don't have the JWT Keys, I want to auto generate the keys <OR> I have the JWT Keys already, I want to manually upload the Public Key)_**. Keys will be downloaded as per your selection.\n\n> Keys should not be hard coded and should be saved securely either on server file system, env or KMS services.\n\n#### JWE components (as json)\n\n| Component         | Function                                                                                                          |\n| ------------------| ------------------------------------------------------------------------------------------------------------------|\n| encryptedKey      | A random key created during runtime and shared after encrypting (alg RSA-OAEP-256) it using publicKey             |\n| encryptedPayload  | Actual cipher text is encrypted using AES-GCM-256 data, for JWE+JWS use case it will be JWS see below in [JWS components section](#json-components)                                                            |\n| iv                | It adds randomness to encryption, ensuring varied ciphertext for the same plaintext                               |\n| tag               | It ensures the integrity and authenticity of the ciphertext, detecting any unauthorized modifications             |\n| header            | metadata information containing keyId(for rotation mainly), alg, enc, cty                                         |\n\n\n#### JWS components (as stringified json)\n| Component         | Function                                                          |\n| ------------------| ------------------------------------------------------------------|\n| payload           | request data                                                      |\n| header            | Contains algorithm to sign, key-id (for rotation mainly)          |\n| signature         | The generated signature which will be verified on Juspay’s end    |\n\nYou don't have to worry about encrypting and decrypting the data as it'll be handled by sdk itself. If JWE configuration is present and api supports it, it'll prioritize that over apiKey. For cases where api only supports basic auth and apikey is not given, it'll throw appropriate errors.\n\n## Importing SDKs\n### CommonJS\n```js\nconst { Juspay, APIError } = require('expresscheckout-nodejs')\n```\nOR\n```js\nconst expresscheckout = require('expresscheckout-nodejs')\n// usage expresscheckout.Juspay, expresscheckout.APIError\n```\n\n### Using Typescript/ES Module\n```js\nimport Juspay, { APIError } from 'expresscheckout-nodejs'\n```\nOR\n```js\nimport * as expresscheckout from 'expresscheckout-nodejs'\n// usage expresscheckout. Juspay, expresscheckout.APIError, expresscheckout.CreateCustomerRequest\n```\n\n## SDK Resources\nNow that we have setup authentication and have access to call juspay apis we'll see an example of [orderSession](https://docs.juspay.in/hyper-checkout/web/base-sdk-integration/session) api using promise and try/catch blocks whichever suits your programming style.\n\n### Using try/catch blocks\n```js\ntry {\n  const juspay = new Juspay.Juspay({\n    merchantId: 'merchantId',\n    apiKey: 'apiKey',\n  })\n  const orderSessionResponse = await juspay.orderSession.create({\n    amount: 1,\n    order_id: 'order_' + Date.now(),\n    payment_page_client_id: 'your payment page client id',\n  })\n  console.log(orderSessionResponse)\n} catch (error) {\n  console.log(error)\n}\n```\n\n### Using Promises\n```js\nconst juspay = new Juspay({\n  merchantId: 'merchantId',\n  apiKey: 'apiKey',\n})\nconst orderId = 'ORD_' + Date.now()\njuspay.order\n  .create({\n    amount: 100,\n    order_id: orderId,\n    // optional fields below\n    currency: 'INR',\n    customer_id: 'juspay_test_1',\n    customer_email: 'test@juspay.in',\n    customer_phone: '9988776655',\n    product_id: '123456',\n    return_url: 'https://abc.xyz.com/123456',\n    description: 'Sample Description',\n    billing_address_first_name: 'Juspay',\n    billing_address_last_name: 'Technologies',\n    billing_address_line1: 'Girija Building',\n    billing_address_line2: 'Ganapati Temple Road',\n    billing_address_line3: '8th Block, Koramangala',\n    billing_address_city: 'Bengaluru',\n    billing_address_state: 'Karnataka',\n    billing_address_country: 'India',\n    billing_address_postal_code: '560095',\n    billing_address_phone: '9988776655',\n    billing_address_country_code_iso: 'IND',\n    shipping_address_first_name: 'Juspay',\n    shipping_address_last_name: 'Technologies',\n    shipping_address_line1: 'Girija Building',\n    shipping_address_line2: 'Ganapathi Temple Road',\n    shipping_address_line3: '8th Block, Koramangala',\n    shipping_address_city: 'Bengaluru',\n    shipping_address_state: 'Karnataka',\n    shipping_address_country: 'India',\n    shipping_address_postal_code: '560095',\n    shipping_address_phone: '9988776655',\n    shipping_address_country_code_iso: 'IND',\n    'options.get_client_auth_token': true,\n    basket:\n      '[{\"id\":\"PID1\",\"quantity\":1,\"unitPrice\":25123.25}, {\"id\":\"PID2\",\"quantity\":1,\"unitPrice\":25123.25}]',\n  })\n  .then((res) => console.log(res))\n  .catch((err) => console.error(res))\n```\n\n### Override default configs for single resource\nLet's say you want to increase a timeout for payments api other than default **80,000ms**. Do Not modify juspay instance directly, as it's shared and can cause troubles with other apis. Use optional juspayConfig params inside resource function calls to override configs.\n\n```js\ntry {\n  const juspay = new Juspay({\n    jweAuth: {\n      keyId: process.env.KEY_ID,\n      privateKey: prepareKey(process.env.PRIVATE_KEY),\n      publicKey: prepareKey(process.env.PUBLIC_KEY),\n    },\n    merchantId: 'merchantId',\n  })\n  // uses default timeout\n  const order = await juspay.order.create({\n    amount: 100,\n    order_id: 'ORD_' + Date.now(),\n  })\n  const paymentResponse = await juspay.payments.create(\n    {\n      order_id: order.order_id,\n      payment_method_type: 'CARD',\n      redirect_after_payment: true,\n      payment_method: 'MASTERCARD',\n      card_exp_month: '04',\n      card_exp_year: '24',\n      card_security_code: '424',\n      save_to_locker: false,\n      card_number: '4242424242424242',\n    },\n    // resource specific timeout\n    {\n      timeout: 100000,\n    }\n  )\n  console.log(paymentResponse)\n} catch (error) {\n  throw error\n}\n```\n\nyou can override all the juspay environment specific config using resource function parameter as shown below\n\n> PCI compliant merchants can use order+txns call inside payments resource itself, read more [here](https://docs.juspay.in/api-reference/docs/express-checkout/create-order-with-payments).\n\nIn some cases you will need to pass customer id to use juspay's active-active features. Here's how you can add resources specific headers.\n\n```js\nconst orderStatus = await juspay.order.status(\n  order.order_id,\n  {\n    'options.add_full_gateway_response': true,\n  },\n  {\n    timeout: 10000,\n    version: '2024-01-03'\n    headers: {\n      'x-customerid': customerId,\n    },\n  }\n)\n```\n\n### Response http object\nSDK attaches ```http``` key in response object for the user if it's of any use.\n\n## Error Handling And Examples\nSDK errors are categorized in three parts **_APIError_**, **_JuspayError_** and **_Error_**. **_APIError_** is api errors coming from servers like **_AuthenticationError_**, **_InvalidRequestError_**, **_InternalServerError_**. Here **_JuspayError_** is thrown by sdk for cases like **_IllegalPrivateKey_**, **_IllegalPublicKey_**, **_DecryptionFailed_**, **_SignatureValidationFailed_** etc. **_Error_** is usually user error for setting up authentication configurations or some unkown cases. Also **_APIError_** extends **_JuspayError_**.\n\n### APIError to refund unknown order id\n```js\n// unknown order id\nconst orderId = 'order_' + Date.now()\njuspay.order\n  .refund(orderId, {\n    unique_request_id: 'refund_test_' + Date.now(),\n    order_id: orderId,\n    amount: 1,\n  })\n  .catch((res) => {\n    // prints true\n    console.log(err instanceof APIError)\n    // prints true\n    console.log(err instanceof JuspayError)\n    console.error(res)\n  })\n```\n\n### JuspayError in case of failed signature verification\n```js\nconst order_id = 'ORD_' + Date.now()\njuspay.order\n  .status('order_id', {\n    order_id,\n    'options.add_full_gateway_response': true,\n  })\n  .then((res) => {\n    console.log(res)\n  })\n  .catch((err) => {\n    // prints true\n    console.log(err instanceof JuspayError)\n    console.error(err)\n  })\n```\n\n**_APIError_** will be false in this case as decryption and verification is done by sdk and error is raised by sdk.\nIf you want to raise flags in your system for such tampering cases please use error names such as **_SignatureValidationFailed_** or **_DecryptionFailed_**.\n\n## Logging\nLogging sdk events like request, response and resource url becomes important for debugging in large and complicated systems. Hence, sdk comes with ```winston``` logger and has minimal logging configuration with it. It is enabled by default.\n\nIf you want to customize logging in accordance with your project, please go through this section. Because nodejs does not have standardized logging framework support like Java SDK has exposed a basic logging interface to customize it for your own system.\n\n> ```Juspay.customLogger``` of type ```(resource: string) => IJuspayLogger``` takes a function with one string parameter i.e. ```resource``` (which is the name of the class from which it's printed, used for debugging purposes) and returns the instance of the class which implements ```IJuspayLogger``` interface. interface definition [below](#custom-logging-framework)\n\n### Disable Logs\n```js\nimport Juspay from 'expresscheckout-nodejs'\n\nJuspay.customLogger = (resource) => Juspay.silentLogger\n```\n\n### Custom winston logger\n```js\nimport Juspay from 'expresscheckout-nodejs'\nimport winston from 'winston'\n\nJuspay.customLogger = (resource) => winston.createLogger({\n    transports: new winston.transports.Console(),\n})\n```\n\n### Custom pino or buyan logger\n```js\nimport Juspay from 'expresscheckout-nodejs'\nimport pino from 'pino'\nimport bunyan from 'bunyan'\n\n// pino\nJuspay.customLogger = (resource) => new pino()\n\n// buyan\nJuspay.customLogger = (resource) => bunyan.createLogger({name: 'expresscheckout-nodejs-sampleProject'})\n```\n\n### Custom logging framework\n\nIf you have your custom logging framework, the instance should look like ```IJuspayLogger``` interface, it's a basic interface as shown below.\n```js\ninterface IJuspayLogger {\n  info: (message: any) => IJuspayLogger | unknown\n  error: (message: any) => IJuspayLogger | unknown\n}\n```\n\n```js\n// making a custom logger, it has to implement IJuspayLogger interface\nclass CustomLogger {\n  constructor(defaultJuspayLogs) {}\n\n  info(message) {\n    console.log(message)\n    return this\n  }\n\n  error(message) {\n    console.log(message)\n    return this\n  }\n}\nJuspay.customLogger = (resource) => new CustomLogger(resource)\n```\n\nbecause of a common interface of logger and SDK's logging usage is not chained we can do something like\n\n```js\nimport Juspay from 'expresscheckout-nodejs'\n\nJuspay.customLogger = (resource) => console\n```\n\nto print it directly on the console for quick tests. But as it's printing to console it will not print nested deep objects.\n\n## Resources List\nHere's the list of supported apis in this sdk under current version\n\n| Resource                        | Endpoint                                                   | Authentication Methods               | Documentation                                                                                                               |\n| --------------------------------| -----------------------------------------------------------|--------------------------------------| ----------------------------------------------------------------------------------------------------------------------------|\n| customers.create                | POST:   /customers                                         | Basic                                | [here](https://docs.juspay.in/api-reference/docs/express-checkout/createcustomer)                                           |\n| customers.get                   | GET:    /customers/:customer_id                            | Basic                                | [here](https://docs.juspay.in/api-reference/docs/express-checkout/getcustomer)                                              |\n| customers.update                | POST:   /customers/:customer_id                            | Basic                                | [here](https://docs.juspay.in/api-reference/docs/express-checkout/updatecustomer)                                           |\n| payments.create                 | POST:   /txns                                              | Basic, JWE+JWS                       | [here](https://docs.juspay.in/api-reference/docs/express-checkout/credit--debit-card-transaction)                           |\n| order.create                    | POST:   /orders                                            | Basic                                | [here](https://docs.juspay.in/api-reference/docs/express-checkout/create-order-api)                                         |\n| order.status                    | GET:    /orders/:order_id                                  | Basic, JWE+JWS                       | [here](https://docs.juspay.in/api-reference/docs/express-checkout/order-status-api)                                         |\n| order.update                    | POST:   /orders/:order_id                                  | Basic                                | [here](https://docs.juspay.in/api-reference/docs/express-checkout/update-order-api)                                         |\n| order.refund                    | POST:   /orders/:order_id/refunds                          | Basic, JWE+JWS                       | [here](https://docs.juspay.in/api-reference/docs/express-checkout/refund-order-api)                                         |\n| orderSession.create             | POST:   /session                                           | Basic, JWE+JWS                       | [here](https://docs.juspay.in/hyper-checkout/android/base-sdk-integration/session)                                          |\n\nPlease note that JWE+JWS or JWT if supported has different route than normal, general nomenclature has **_/v4/_** prefixed, with few exceptions with order.status has **_/v4/order-status_** and refund has **_/v4/orders/${order_id}/refunds_**\n\n## Questions?\nStill have any questions? Feel free to mail us here - support@juspay.in.\n\n","readmeFilename":"README.md"}