{"id":9002,"date":"2024-06-10T08:53:22","date_gmt":"2024-06-10T08:53:22","guid":{"rendered":"https:\/\/ccbill.com\/doc\/?post_type=tjspw&#038;p=9002"},"modified":"2024-10-04T13:30:16","modified_gmt":"2024-10-04T13:30:16","slug":"typescript-node-js","status":"publish","type":"tjspw","link":"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js","title":{"rendered":"TypeScript\/Node.js"},"content":{"rendered":"\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"content\">\n<h2>TypeScript\/Node.js<\/h2>\n\t<p>The code example is written in TypeScript. It describes the steps required to perform authentication with the CCBill API and the payment token obtained using the CCBill API Payment Widget to perform the charge by payment token action (non-3DSecure and 3DSecure versions). This script covers the backend portion of the integration with the CCBill's RESTful Transaction API.<\/p>\n\t<article>\n\t\t<h3><span class=\"dropcap\">1.<\/span> Install Dependencies<\/h3>\n\t\t<p>The backend code uses the Axios dependency to make HTTP requests. Install it with:<\/p>\n<p>NPM:<\/p>\n<code class=\"snippet-small\">npm install axios<\/code>\n<p>Yarn:<\/p>\n<code class=\"snippet-small\">yarn add axios<\/code>\n<p class=\"highlight\" data-target=\"importing-axios\">Begin by importing the <strong><code>axios<\/code><\/strong> library.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">2.<\/span> Define Endpoints<\/h3>\n\t\t<p>The endpoints section defines the API endpoints you will use throughout the process.<\/p>\n\t\t<p>The example uses three endpoints to demonstrate the charge flow:<\/p>\n\t\t<p class=\"highlight\" data-target=\"tokenEndpoint\">1.&nbsp;<strong><code>tokenEndpoint<\/code><\/strong>&nbsp;allows requesting the CCBill Auth (Bearer) token required for authentication in subsequent operations.<\/p>\n\t\t<p class=\"highlight\" data-target=\"nonThreedsTransactionEndpoint\">2.&nbsp;<strong><code>nonThreedsTransactionEndpoint<\/code><\/strong>&nbsp;allows performing a non-3DSecured charge transaction using the payment token.<\/p>\n\t\t<p class=\"highlight\" data-target=\"threedsTransactionEndpoint\" data-highlight=\"section4\">3.&nbsp;<strong><code>threedsTransactionEndpoint<\/code><\/strong>&nbsp;allows performing a 3DSecured charge transaction using the payment token and previously obtained SCA parameters.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">3.<\/span> Provide Client Credentials<\/h3>\n\t\t<p class=\"highlight\" data-target=\"merchant-application-id\">Set your <strong>Merchant Application ID<\/strong> as the value of <strong><code>clientId<\/code><\/strong>, and the <strong>Merchant Secret<\/strong> as the value of <strong><code>clientSecret<\/code><\/strong>.<\/p>\n\t\t<p class=\"highlight\" data-target=\"accessToken\">The example code will set the <strong><code>accessToken<\/code><\/strong> value when the script executes.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">4.<\/span> Add Data<\/h3>\n\t\t<p>Provide the appropriate data for the request. To create a charge, the following parameters are obtained using the payment widget:<\/p>\n\t\t<p class=\"highlight\" data-target=\"paymentToken\">1. The <strong><code>paymentToken<\/code><\/strong> previously obtained using the widget.<\/p><p class=\"has-text-align-left\">Ensure the client's IP address is added as a payload <code>ipAddress<\/code> or header <code>X-Origin-IP<\/code>) parameter.<\/p>\n\t\t<p class=\"highlight\" data-target=\"TransactionData\">2.&nbsp;<strong><code>TransactionData<\/code><\/strong>, including the client account number, subaccount, the initial price, and period.<\/p>\n\t\t<p class=\"highlight\" data-target=\"ThreedsParameters\">3. If using 3DS, provide the <strong><code>ThreedsParameters<\/code><\/strong> previously obtained using the payment widget.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">5.<\/span> Generate Token<\/h3>\n\t\t<p class=\"highlight\" data-target=\"getOAuthToken\">Create a function to fetch the OAuth token (<strong><code>getOAuthToken<\/code><\/strong>). The function requires the client ID, client secret, and token endpoint to request the token.<\/p>\n\t\t<p>The token helps authenticate the payment requests.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">6.<\/span> Charge Transaction and Handle Response<\/h3>\n\t\t<p class=\"highlight\" data-target=\"chargeTransaction\">The<strong><code>chargeTransaction<\/code><\/strong>function performs the charge based on the provided endpoint, data, payment token, and generated access token.<\/p>\n\t\t<p class=\"highlight\" data-target=\"handleResponse\">If calling the function throws no errors, the response is passed to the <strong><code>handleResponse<\/code><\/strong> function.<\/p>\n\t\t<p>In this case, it only logs the response data. In a realistic scenario, it would allow you to continue processing the transaction and return the response to your client.<\/p>\n\t<\/article>\n\t<article>\n\t\t<h3><span class=\"dropcap\">7.<\/span> Test Transaction<\/h3>\n\t\t<p class=\"highlight\" data-target=\"fetch-oauth\">The code fetches the OAuth token based on the previously provided data.<\/p>\n\t\t<p class=\"highlight\" data-target=\"transaction-success\">If the access token is generated successfully, the code performs a non-3DS transaction and then a 3DSecure transaction, using the previously obtained SCA and other transaction data.<\/p>\n\t<\/article>\t\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"examples\">\n\t<div class=\"navigation\">\n        <span class=\"nav-item selected\">backend.ts<\/span>\n    <\/div>\n\t<div class=\"files\">\n        <div class=\"file file-1 active\">\n\t\t<pre class=\"language-js line-numbers\" data-start=\"1\">\n\t\t<div title=\"importing-axios\">\n\t\t\t<code class=\"language-js code-block\">import axios from &#039;axios&#039;;<\/code>\n\t\t<\/div>\n\t\t<div title=\"TransactionData\">\n\t\t<code class=\"language-js code-block\" >interface TransactionData {\n\t\t\tclientAccnum: number;\n\t\t\tclientSubacc: number;\n\t\t\tinitialPrice: number;\n\t\t\tinitialPeriod: number;\n\t\t}<\/code>\n\t\t<\/div>\n<code class=\"language-js\">interface ThreedsParameters {\n    threedsEci: string;\n    threedsError: string;\n    threedsStatus: string;\n    threedsClientTransactionId: string;\n    threedsAcsTransId: string;\n    threedsDsTransId: string;\n    threedsCurrency: string;\n    threedsAmount: string;\n    threedsCardToken: string;\n    threedsVersion: string;\n    threedsCavv: string;\n    threedsXid: string;\n    threedsSuccess: string;\n    threedsAuthenticationType: string;\n    threedsAuthenticationValue: string;\n}\n\ninterface TransactionResponse {\n    declineCode: number | undefined;\n    declineText: string | undefined;\n    denialId: number | undefined;\n    approved: boolean;\n    paymentUniqueId: string | undefined;\n    sessionId: number | undefined;\n    subscriptionId: number | undefined;\n    newPaymentTokenId: number | undefined;\n}\n\ninterface ApiResponse {\n    status: number;\n    data: TransactionResponse;\n}\n\ntype ThreedsTransactionData = TransactionData &amp; ThreedsParameters;\n\n\/\/ Endpoints\nconst baseUrl = &#039;https:\/\/api.ccbill.com&#039;;\n<\/code>\n<div title=\"tokenEndpoint\">\n\t<code class=\"language-js code-block\">const tokenEndpoint = `${baseUrl}\/ccbill-auth\/oauth\/token?grant_type=client_credentials`;\n\t<\/code>\n<\/div>\n<div title=\"nonThreedsTransactionEndpoint\">\n\t<code class=\"language-js code-block\">const nonThreedsTransactionEndpoint = `${baseUrl}\/transactions\/payment-tokens\/`;\n\t<\/code>\n<\/div>\n<div title=\"threedsTransactionEndpoint\">\n\t<code class=\"language-js code-block\">const threedsTransactionEndpoint = `${nonThreedsTransactionEndpoint}threeds\/`;\n\t<\/code>\n<\/div>\n\t<code class=\"language-js\">\n\n\t\/\/ Client credentials\n\t<\/code>\n<div title=\"merchant-application-id\">\n\t<code class=\"language-js code-block\">const clientId = &#039;YOUR-CLIENT-ID&#039;;\n\tconst clientSecret = &#039;YOUR-CLIENT-SECRET&#039;;\n\t<\/code>\n<\/div>\n<div title=\"accessToken\">\n\t<code class=\"language-js code-block\">let accessToken: string | null = &#039;&#039;; \/\/ the access token will be obtained during script execution\n\t<\/code>\n<\/div>\n\t<code class=\"language-js\">\/\/ Requests data\n\t<\/code>\n<div title=\"paymentToken\">\n\t<code class=\"language-js code-block\">const paymentToken = &#039;YOUR-PAYMENT-TOKEN&#039;;\n\t<\/code>\n<\/div>\n<div title=\"TransactionData\">\n\t<code class=\"language-js code-block\">const transactionData = {\n\t\tclientAccnum: 900684,\n\t\tclientSubacc: 0,\n\t\tinitialPrice: 10,\n\t\tinitialPeriod: 10,\n\t};\n\t<\/code>\n<\/div>\n<div title=\"ThreedsParameters\">\n\t<code class=\"language-js code-block\">const threedsParameters = {\n\t\tthreedsEci: &#039;05&#039;,\n\t\tthreedsError: &#039;&#039;,\n\t\tthreedsStatus: &#039;Y&#039;,\n\t\tthreedsClientTransactionId: &#039;mcn-id-h76oy394utw&#039;,\n\t\tthreedsAcsTransId: &#039;d6f15aae-2c9d-4333-a920-954be07c0c76&#039;,\n\t\tthreedsDsTransId: &#039;d65e93c3-35ab-41ba-b307-767bfc19eae3&#039;,\n\t\tthreedsCurrency: &#039;978&#039;,\n\t\tthreedsAmount: &#039;10&#039;,\n\t\tthreedsCardToken: &#039;01ae5d142g7efb4b&#039;,\n\t\tthreedsVersion: &#039;2.2.0&#039;,\n\t\tthreedsCavv: &#039;&#039;,\n\t\tthreedsXid: &#039;&#039;,\n\t\tthreedsSuccess: &#039;true&#039;,\n\t\tthreedsAuthenticationType: &#039;01&#039;,\n\t\tthreedsAuthenticationValue: &#039;5VdhGOTXBJw9+kEBOTtaJiLUAr8=&#039;,\n\t};\n\t<\/code>\n<\/div>\n<div title=\"getOAuthToken\">\n\t<code class=\"language-js code-block\">async function getOAuthToken(tokenEndpoint: string, clientId: string, clientSecret: string): Promise&lt;string | null&gt; {\n\n\t\ttry {\n\t\t\tconst response = await axios.post(tokenEndpoint, null, {\n\t\t\t\tauth: {\n\t\t\t\t\tusername: clientId,\n\t\t\t\t\tpassword: clientSecret,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (response.status === 200) {\n\t\t\t\treturn response.data.access_token;\n\t\t\t} else {\n\t\t\t\tconsole.log(&#039;Token request failed with status code:&#039;, response.status);\n\t\t\t\tconsole.log(&#039;Response content:&#039;, response.data);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(&#039;Error while getting the OAuth token:&#039;, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\t<\/code>\n<\/div>\n<div title=\"chargeTransaction\">\n<code class=\"language-js code-block\">async function chargeTransaction(endpoint: string, accessToken: string, paymentToken: string, transactionData: TransactionData | ThreedsTransactionData): Promise&lt;void&gt; {\n    const headers = {\n        authorization: `Bearer ${accessToken}`,\n    };\n\n    try {\n        const response = await axios.post(`${endpoint}${paymentToken}`, transactionData, {\n            headers,\n        });\n        handleResponse(response);\n    } catch (error) {\n        console.error(&#039;Error while charging the transaction:&#039;, error);\n    }\n}<\/code>\n<\/div>\n<div title=\"handleResponse\">\n<code class=\"language-js code-block\">function handleResponse(response: ApiResponse): void {\n    if (response.status === 200) {\n        console.log(&#039;Response:&#039;, response.data);\n    } else {\n        console.error(&#039;Error:&#039;, response.data);\n    }\n}<\/code>\n<\/div>\n<div title=\"fetch-oauth\">\n <code class=\"language-js code-block\">\n\t(async () =&gt; {\n\t\/\/ Get access token\n    accessToken = await getOAuthToken(tokenEndpoint, clientId, clientSecret);\n<\/code>\n<\/div>\n<div title=\"transaction-success\">\n<code class=\"language-js code-block\">if (accessToken) {\n        \/\/ Charge regular transaction\n        await chargeTransaction(nonThreedsTransactionEndpoint, accessToken, paymentToken, transactionData);\n\n        \/\/ Charge threeds verified transaction\n        await chargeTransaction(threedsTransactionEndpoint, accessToken, paymentToken, {\n            ...transactionData,\n            ...threedsParameters,\n        });\n    }\n})();<\/code>\n<\/div>\n<\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":4,"featured_media":0,"template":"","meta":{"_acf_changed":false,"kk_blocks_editor_width":"","_kiokenblocks_attr":"","_kiokenblocks_dimensions":""},"backend":[69],"frontend":[],"class_list":["post-9002","tjspw","type-tjspw","status-publish","hentry","backend-typescript-node-js"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>TypeScript\/Node.js - CCBill Doc<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TypeScript\/Node.js - CCBill Doc\" \/>\n<meta property=\"og:description\" content=\"TypeScript\/Node.js The code example is written in TypeScript. It describes the steps required to perform...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js\" \/>\n<meta property=\"og:site_name\" content=\"CCBill Doc\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-04T13:30:16+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js\",\"url\":\"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js\",\"name\":\"TypeScript\/Node.js - CCBill Doc\",\"isPartOf\":{\"@id\":\"https:\/\/ccbill.com\/doc\/#website\"},\"datePublished\":\"2024-06-10T08:53:22+00:00\",\"dateModified\":\"2024-10-04T13:30:16+00:00\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js\"]}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ccbill.com\/doc\/#website\",\"url\":\"https:\/\/ccbill.com\/doc\/\",\"name\":\"CCBill Doc\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ccbill.com\/doc\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"TypeScript\/Node.js - CCBill Doc","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js","og_locale":"en_US","og_type":"article","og_title":"TypeScript\/Node.js - CCBill Doc","og_description":"TypeScript\/Node.js The code example is written in TypeScript. It describes the steps required to perform...","og_url":"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js","og_site_name":"CCBill Doc","article_modified_time":"2024-10-04T13:30:16+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js","url":"https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js","name":"TypeScript\/Node.js - CCBill Doc","isPartOf":{"@id":"https:\/\/ccbill.com\/doc\/#website"},"datePublished":"2024-06-10T08:53:22+00:00","dateModified":"2024-10-04T13:30:16+00:00","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ccbill.com\/doc\/tjspw\/typescript-node-js"]}]},{"@type":"WebSite","@id":"https:\/\/ccbill.com\/doc\/#website","url":"https:\/\/ccbill.com\/doc\/","name":"CCBill Doc","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ccbill.com\/doc\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/tjspw\/9002"}],"collection":[{"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/tjspw"}],"about":[{"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/types\/tjspw"}],"author":[{"embeddable":true,"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/users\/4"}],"wp:attachment":[{"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/media?parent=9002"}],"wp:term":[{"taxonomy":"backend","embeddable":true,"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/backend?post=9002"},{"taxonomy":"frontend","embeddable":true,"href":"https:\/\/ccbill.com\/doc\/wp-json\/wp\/v2\/frontend?post=9002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}