diff --git a/docs/guides/share/index.mdx b/docs/guides/share/index.mdx index 5e47c77e..fdfa38af 100644 --- a/docs/guides/share/index.mdx +++ b/docs/guides/share/index.mdx @@ -39,12 +39,22 @@ import { Card } from "@site/src/components/shared/Card"; > Use custom masks to securely display sensitive information. - } href="/docs/guides/share/reveal-tokenized-data" heading="Reveal Tokenized Data" > - Use Basis Theory Elements to reveal sensitive data back to customers without touching it. + Use Basis Theory Elements to reveal tokenized data back to customers without touching it. + + + } + href="/docs/guides/share/reveal-data-from-third-party" + heading="Reveal Data From 3rd Party" + > + Use Basis Theory Elements to reveal sensitive data from a third party back to customers without touching it. diff --git a/docs/guides/share/reveal-data-from-third-party.mdx b/docs/guides/share/reveal-data-from-third-party.mdx new file mode 100644 index 00000000..9dbc0f4c --- /dev/null +++ b/docs/guides/share/reveal-data-from-third-party.mdx @@ -0,0 +1,1025 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import useBaseUrl from "@docusaurus/useBaseUrl"; + +import { Alert, Alerts } from "@site/src/components/shared/Alert"; +import { AuthButtons } from "@site/src/components/docs/AuthButtons"; +import { Card } from "@site/src/components/shared/Card" + +import styles from "@site/src/pages/index.module.css"; +import ThemedImage from "@theme/ThemedImage"; + +import Android from "@site/static/img/sdk/logos/android.svg"; +import JavaScript from "@site/static/img/sdk/logos/javascript.svg"; +import ReactSvg from "@site/static/img/sdk/logos/react.svg"; + + +# Reveal Data from 3rd Party + +This guide will show you how to reveal sensitive data from a third party back to a customer without your frontend or backend code ever needing to touch the actual raw data. + +Key concepts in this guide: + +- [Applications](/docs/api/applications) +- [Sessions](/docs/api/applications/sessions) +- [Proxies](/docs/api/proxies/) + +## Getting Started + +To get started, you will need a Basis Theory account. + + + +### Creating a Public Application +Next you will need a [Public Application](/docs/api/applications#application-types) in order to create tokens, sessions and initialize our Elements libraries. + +[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Public%20App) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings: + +- Name - Public App +- Application Type - Public +- Permissions - `token:create` + + + Save the API Key from the created Public Application as it will be used later in this guide. + + + +## Configuring Basis Theory Elements + +[Basis Theory Elements](/docs/concepts/elements) is available for the following technologies. Click below for detailed instructions on how to install and configure it. + +
+} +className={styles.sdk} +openInNewWindow={true} +> +Javascript + + +} +className={styles.sdk} +openInNewWindow={true} +> +React + + + + +
+} +className={styles.sdk} +openInNewWindow={true} +> +iOS + + +} +className={styles.sdk} +openInNewWindow={true} +> +Android + + + +## Creating a Text Element + +To safely reveal data back to a customer, we must create an Element that will hold and display the data. +In this example we'll create a Text Element, which can hold any `string` value. + + + + +```javascript showLineNumbers +import { BasisTheory } from '@basis-theory/basis-theory-js'; + +let bt; +//highlight-start +let textElement; +//highlight-end + +(async () => { + bt = await new BasisTheory().init('test_1234567890', { elements: true }); + + //highlight-start + textElement = bt.createElement('text', { + targetId: 'exampleTextElement', + }); + + // here #exampleTextElement is a DOM selector + // example:
+ await textElement.mount('#exampleTextElement'); + //highlight-end +})(); +``` +
+ + +```tsx showLineNumbers +// highlight-next-line +import { useRef } from 'react'; + +import { + BasisTheoryProvider, + // highlight-next-line + TextElement, + useBasisTheory, +} from '@basis-theory/basis-theory-react'; + +function App() { + const { bt } = useBasisTheory('test_1234567890', { elements: true }); + // highlight-next-line + const textRef = useRef(null); + + return ( + + // highlight-start + + // highlight-end + + ); +} + +export default App; +``` + + + +```text +To add a Text Element to your iOS app, you just have to follow these three steps: + +1. Drop a UITextField onto your Main.storyboard file and select it. +2. Select TextElementUITextField as the class for the UITextField. +3. Add an outlet for your text field to your ViewController. +``` + +```swift showLineNumbers title="ViewController.swift" +import UIKit +import BasisTheoryElements + +class ViewController: UIViewController { + // highlight-next-line + @IBOutlet weak var exampleTextElement: TextElementUITextField! + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } +} +``` + + + +```text +To add a Text Element to your Android app, you just have to follow these two steps: + +1. Add the XML below to your MainActivity layout. +2. Reference your XML element in the MainActivity class. +```` + +```xml title="res/layout/activity_main.xml" + +``` + +```kotlin showLineNumbers title="MainActivity.kt" +import com.basistheory.android.view.TextElement + +class MainActivity : AppCompatActivity() { + // highlight-next-line + private lateinit var exampleTextElement: TextElement + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + // highlight-next-line + exampleTextElement = findViewById(R.id.exampleTextElement) + } +} +``` + + +
+ + + Be sure to replace test_1234567890 with the Public API Key you + created in Getting Started. + + +## Creating a Session + +Next, we'll create a [Session](/docs/api/applications/sessions). Sessions provide temporary elevated access to your public applications, +and we'll will use it to safely authenticate the request to the third party. Add the following code to create a session: + + + + + +```javascript showLineNumbers +import { BasisTheory } from '@basis-theory/basis-theory-js'; + +let bt; +let textElement; + +(async () => { + bt = await new BasisTheory().init('test_1234567890', { elements: true }); + + textElement = bt.createElement('text', { + targetId: 'exampleTextElement', + }); + + // here #exampleTextElement is a DOM selector + // example:
+ await textElement.mount('#exampleTextElement'); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + // highlight-next-line + const session = await bt.sessions.create(); + } + +})(); +``` +
+ + +```tsx showLineNumbers + +import { useRef } from 'react'; + +import { + BasisTheoryProvider, + TextElement, + useBasisTheory, +} from '@basis-theory/basis-theory-react'; + +function App() { + const { bt } = useBasisTheory('test_1234567890', { elements: true }); + const textRef = useRef(null); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + // highlight-next-line + const session = await bt.sessions.create(); + } + + return ( + + + + ); +} + +export default App; +``` + + + +```swift showLineNumbers +import UIKit +import BasisTheoryElements + +class ViewController: UIViewController { + @IBOutlet weak var exampleTextElement: TextElementUITextField! + + // this is just an example method that'll have the full lifecycle for revealing + func reveal() { + //highlight-start + BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in + let sessionKey = data!.sessionKey! + let nonce = data!.nonce! + + } + //highlight-end + } + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } +} +``` + + + +```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +//highlight-next-line +import com.basistheory.android.service.BasisTheoryElements + +class MainActivity : AppCompatActivity() { + + private lateinit var exampleTextElement: TextElement + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + exampleTextElement = findViewById(R.id.example_text_element) + } + + // this is just an example method that'll have the full lifecycle for revealing + private fun reveal() { + //highlight-start + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + //highlight-end + + // highlight-next-line + val session = bt.createSession() + } +} +``` + +
+ +## Creating a Pre-Configured Proxy + +To retrieve data from a third party URL without touching it, we will create a [Pre-Configured Proxy](/docs/api/proxies/pre-configured-proxies) + +### Creating a Management Application + +To create a proxy, you will need a [Management Application](docs/api/applications#application-types). + +[Click here](https://portal.basistheory.com/applications/create?permissions=proxy%3Acreate&type=management&name=Management%20App) to create a Management Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings: + +- Name - Create Proxy +- Application Type - Management +- Permissions: `proxy: create` + + +### Creating the Proxy in the Backend + +In this guide, we'll use [Express.js](https://expressjs.com/) as our backend but [docs](docs/api/) are available for different technologies. +We'll create a `backend.js` file and add the following code to start the Express.js backend and create a proxy to the third party: + +```javascript showLineNumbers title="backend.js" +const express = require("express"); +const { BasisTheory } = require("@basis-theory/basis-theory-js"); + +const app = express(); +const port = 4242; + +let bt = await new BasisTheory().init(); + +app.post("/create-proxy", async (request, response) => { + const proxy = await bt.proxies.create( + { + name: "Proxy to Third Party", + destinationUrl: "http://third_party_url.com", + requestTransform: { + code: `module.exports = async function (req) { + let { args: { body, headers }, bt } = req; + + return { + body, + headers: { + ...headers, + "Authorization": req.configuration.Credentials + }, + } + };`, + }, + configuration: { + Credentials: "credential_1234567890" + }, + requireAuth: true, + }, + { apiKey: "test_mgmt_1234567890" } // management application + ); + + response.send(proxy); +}); + +app.listen(port, () => { + console.log(`Example app listening on port ${port}`); +}); +``` + +Notice that we are using a [request transform](/docs/api/proxies/pre-configured-proxies#request-transforms) to add the third party credentials to the `Authorization` header before making the request to the third party. +These kind of values can be safely stored in the `configuration` object and re-use them for every proxy execution. + + +Start the server with the following command (from the same directory as `backend.js`). + +``` bash +node backend.js +``` + +You can now use your favorite API client or just run the following `curl` command from your terminal: + +```shell +curl -X POST http://localhost:4242/create-proxy +``` + + + Be sure to replace test_mgmt_1234567890 with the Management API Key you + created in Creating a Management Application, http://third_party_url.com with the third party URL and credential_1234567890 with the third party credentials (optionally). + + + + Write down the key value returned from the proxy as its going to be used in the next steps. + + + +## Authorizing a Session + +In order to use the session to securely invoke our proxy, we need to authorize it with a Private Application. + +### Creating a Private Application + +First, lets create the [Private Application](docs/api/applications#application-types). To do so [Click here](https://portal.basistheory.com/applications/create?permissions=token%3Ause&type=private&name=Invoke%20Proxy) or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings: + +- Name - Invoke Proxy +- Application Type - Private +- Permissions - `token:use` + + + The Private Application must be in the same Tenant as Public Application used to create the Session. + + + + Save the API Key from the created Private Application as it will be used later in this guide. + + +### Authorizing In the Backend + +Using the Private Application API Key and the `nonce` from our session we can grant temporary authorization to invoke the proxy. + + +The only way to ensure your private API keys are not publically accessible is for this step to execute in your backend service. + + +```javascript showLineNumbers title="backend.js" +const express = require("express"); +const { BasisTheory } = require("@basis-theory/basis-theory-js"); + +const app = express(); +const port = 4242; + +let bt = await new BasisTheory().init(); + +app.post("/create-proxy", async (request, response) => { + const proxy = await bt.proxies.create( + { + name: "Proxy to Third Party", + destinationUrl: "http://third_party_url.com", + requestTransform: { + code: `module.exports = async function (req) { + let { args: { body, headers }, bt } = req; + + return { + body, + headers: { + ...headers, + "Authorization": req.configuration.Credentials + }, + } + };`, + }, + configuration: { + Credentials: "credential_1234567890" + }, + requireAuth: true, + }, + { apiKey: "test_mgmt_1234567890" } // management application + ); + + response.send(proxy); +}); + +//highlight-start +app.post("/authorize", async (request, response) => { + const { nonce } = request.body; + + // authorizing a session returns an empty 200 response + await bt.sessions.authorize({ + nonce: nonce, + permissions: ['token:use'] + }, { apiKey: "test_priv_1234567890" }); // private application + + // this response is arbitrary and not required + response.json({ + result: "success", + }); +}); +//highlight-end + +app.listen(port, () => { + console.log(`Example app listening on port ${port}`); +}); +``` + + + Be sure to replace test_priv_1234567890 with the Private API Key you + created in the Creating a Private Application step. + + + + In a real world scenario, make sure to include your own form of authentication between your frontend and backend for this request. + + +### Calling the Authorization Endpoint + +Next, from our client application, we'll call the authorization endpoint created on the [Authorizing in the Backend](docs/guides/share/reveal-data-from-third-party#authorizing-in-the-backend) step, passing our created session `nonce`: + + + + + +```javascript showLineNumbers +import { BasisTheory } from '@basis-theory/basis-theory-js'; + +let bt; +let textElement; + +(async () => { + bt = await new BasisTheory().init('test_1234567890', { elements: true }); + + textElement = bt.createElement('text', { + targetId: 'exampleTextElement', + }); + + // here #exampleTextElement is a DOM selector + // example:
+ await textElement.mount('#exampleTextElement'); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + const session = await bt.sessions.create(); + + // highlight-start + await fetch('http://localhost:4242/authorize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ nonce: session.nonce }), + }); + // highlight-end + } +})(); +``` +
+ + +```tsx showLineNumbers + +import { useRef } from 'react'; + +import { + BasisTheoryProvider, + TextElement, + useBasisTheory, +} from '@basis-theory/basis-theory-react'; + +function App() { + const { bt } = useBasisTheory('test_1234567890', { elements: true }); + const textRef = useRef(null); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + const session = await bt.sessions.create(); + + // highlight-start + await fetch('http://localhost:4242/authorize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ nonce: session.nonce }), + }); + // highlight-end + } + + return ( + + + + ); +} + +export default App; +``` + + + +```swift showLineNumbers +import UIKit +import BasisTheoryElements + +class ViewController: UIViewController { + @IBOutlet weak var exampleTextElement: TextElementUITextField! + + // this is just an example method that'll have the full lifecycle for revealing + func reveal() { + BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in + let sessionKey = data!.sessionKey! + let nonce = data!.nonce! + + //highlight-start + self.authorizeSession(nonce: nonce) { result, error in + // + } + //highlight-end + } + } + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + //highlight-start + func authorizeSession(nonce: String, completion: @escaping ([String: Any]?, Error?) -> Void) { + let parameters = ["nonce": nonce] + + let url = URL(string: "http://localhost:4242/authorize")! + let session = URLSession.shared + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + do { + request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) + } catch let error { + completion(nil, error) + } + + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + request.addValue("application/json", forHTTPHeaderField: "Accept") + + let task = session.dataTask(with: request, completionHandler: { data, response, error in + guard error == nil else { + completion(nil, error) + return + } + + do { + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] + completion(json, nil) + } catch let error { + completion(nil, error) + } + }) + + task.resume() + } + //highlight-end +} +``` + + + +```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +import com.basistheory.android.service.BasisTheoryElements +//highlight-start +import java.net.HttpURLConnection +import java.net.URL +//highlight-end + +class MainActivity : AppCompatActivity() { + + private lateinit var exampleTextElement: TextElement + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + exampleTextElement = findViewById(R.id.example_text_element) + } + + // this is just an example method that'll have the full lifecycle for revealing + private fun reveal() { + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + + val session = bt.createSession() + + //highlight-next-line + authorizeSession(session.sessionKey) + } + + //highlight-start + private fun authorizeSession(nonce: String) { + val url = URL("http://localhost:4242/authorize") + val con = url.openConnection() as HttpURLConnection + + con.requestMethod = "POST" + con.doOutput = true + con.setRequestProperty("Content-Type", "application/json") + con.setRequestProperty("Accept", "application/json"); + + val body = String.format("{\"nonce\": \"%s\"}", nonce) + + con.outputStream.use { os -> + val input: ByteArray = body.toByteArray(Charsets.UTF_8) + os.write(input, 0, input.size) + } + + if (con.responseCode == 200) { + return + } + } + //highlight-end +} +``` + +
+ +## Invoking the Proxy and Revealing the Data + +With the authorized session, we can now use the `sessionKey` to invoke our created proxy. +We'll add the following code to retrieve the data and set its value to the text element. + + + + + +```javascript showLineNumbers +import { BasisTheory } from "@basis-theory/basis-theory-js"; + +let bt; +let textElement; + +(async () => { + bt = await new BasisTheory().init("test_1234567890", { elements: true }); + + textElement = bt.createElement("text", { + targetId: "exampleTextElement", + }); + + // here #exampleTextElement is a DOM selector + // example:
+ await textElement.mount("#exampleTextElement"); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + const session = await bt.sessions.create(); + + await fetch("http://localhost:4242/authorize", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ nonce: session.nonce }), + }); + + // highlight-start + const data = await bt.proxy.get({ + headers: { + "BT-PROXY-KEY": "proxy_key_1234567890" + }, + apiKey: session.sessionKey, + }); + // highlight-end + + //highlight-next-line + textElement.setValue(data); + }; +})(); +``` +
+ + +```tsx showLineNumbers + +import { useRef } from 'react'; + +import { + BasisTheoryProvider, + TextElement, + useBasisTheory, +} from '@basis-theory/basis-theory-react'; + +function App() { + const { bt } = useBasisTheory('test_1234567890', { elements: true }); + const textRef = useRef(null); + + // this is just an example method that'll have the full lifecycle for revealing + const reveal = async () => { + const session = await bt.sessions.create(); + + await fetch('http://localhost:4242/authorize', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ nonce: session.nonce }), + }); + + // highlight-start + const data = await bt.proxy.get({ + headers: { + "BT-PROXY-KEY": "proxy_key_1234567890" + }, + apiKey: session.sessionKey, + }); + // highlight-end + + //highlight-next-line + textElement.setValue(data); + } + + return ( + + + + ); +} + +export default App; +``` + + + +```swift showLineNumbers +import UIKit +import BasisTheoryElements + +class ViewController: UIViewController { + @IBOutlet weak var exampleTextElement: TextElementUITextField! + + // this is just an example method that'll have the full lifecycle for revealing + func reveal() { + BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in + let sessionKey = data!.sessionKey! + let nonce = data!.nonce! + + + self.authorizeSession(nonce: nonce) { result, error in + //highlight-start + let proxyHttpRequest = ProxyHttpRequest(method: .get, path: String("/" + issuerCardId)) + BasisTheoryElements.proxy(apiKey: sessionKey, proxyKey: "proxy_key_1234567890", proxyHttpRequest: proxyHttpRequest) + { response, data, error in + DispatchQueue.main.async { + self.cardVerificationCodeElement.setValue(elementValueReference: data!.cvv!.elementValueReference) + } + } + //highlight-end + } + } + } + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + func authorizeSession(nonce: String, completion: @escaping ([String: Any]?, Error?) -> Void) { + let parameters = ["nonce": nonce] + + let url = URL(string: "http://localhost:4242/authorize")! + let session = URLSession.shared + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + do { + request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) + } catch let error { + completion(nil, error) + } + + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + request.addValue("application/json", forHTTPHeaderField: "Accept") + + let task = session.dataTask(with: request, completionHandler: { data, response, error in + guard error == nil else { + completion(nil, error) + return + } + + do { + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] + completion(json, nil) + } catch let error { + completion(nil, error) + } + }) + + task.resume() + } +} +``` + + + +```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +import com.basistheory.android.service.BasisTheoryElements +import java.net.HttpURLConnection +import java.net.URL +//highlight-next-line +import com.basistheory.android.service.ProxyRequest + +class MainActivity : AppCompatActivity() { + + private lateinit var exampleTextElement: TextElement + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + exampleTextElement = findViewById(R.id.example_text_element) + } + + // this is just an example method that'll have the full lifecycle for revealing + private fun reveal() { + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + + val session = bt.createSession() + + authorizeSession(session.nonce) + + //highlight-start + val proxyRequest: ProxyRequest = ProxyRequest().apply { + headers = mapOf( + "BT-PROXY-KEY" to "proxy_key_1234567890", + "Content-Type" to "application/json" + ) + } + val data = bt.proxy.get(proxyRequest, session.sessionKey) + //highlight-end + + //highlight-next-line + exampleTextElement.setValueRef(data) + } + + private fun authorizeSession(nonce: String) { + val url = URL("http://localhost:4242/authorize") + val con = url.openConnection() as HttpURLConnection + + con.requestMethod = "POST" + con.doOutput = true + con.setRequestProperty("Content-Type", "application/json") + con.setRequestProperty("Accept", "application/json"); + + val body = String.format("{\"nonce\": \"%s\"}", nonce) + + con.outputStream.use { os -> + val input: ByteArray = body.toByteArray(Charsets.UTF_8) + os.write(input, 0, input.size) + } + + if (con.responseCode == 200) { + return + } + } +} +``` + +
+ +🎉 The code above is the last bit that we need to reveal data from a third party! + + + + The data you receive as response from the proxy is not the raw data, but a synthetic reference to it that can only be used with setValue to display it. + + +## Conclusion + +You can now reveal any data to a customer without your application accessing the underlying value, reducing compliance and regulatory scope. +Just execute the `reveal` method in whichever way you desire (like with the click of a button) and watch the response value from the proxy appear on your Text Element. + +## Learn More + +- [Customize your web form](/docs/guides/collect/customize-web-form) +- [Access data using sessions](/docs/guides/govern/sessions) +- [Reveal tokenized data](/docs/guides/share/reveal-tokenized-data) diff --git a/docs/guides/share/reveal-tokenized-data.mdx b/docs/guides/share/reveal-tokenized-data.mdx index 76401b31..efdb83ed 100644 --- a/docs/guides/share/reveal-tokenized-data.mdx +++ b/docs/guides/share/reveal-tokenized-data.mdx @@ -33,7 +33,7 @@ To get started, you will need a Basis Theory account. ### Creating a Public Application Next you will need a [Public Application](/docs/api/applications#application-types) in order to create tokens, sessions and initialize our Elements libraries. -[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Collect%20Data%20from%20Web%20Guide) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings: +[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Public%20App) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings: - Name - Public App - Application Type - Public @@ -203,6 +203,8 @@ To add a Text Element to your Android app, you just have to follow these two ste ``` ```kotlin showLineNumbers title="MainActivity.kt" +import com.basistheory.android.view.TextElement + class MainActivity : AppCompatActivity() { // highlight-next-line private lateinit var exampleTextElement: TextElement @@ -325,6 +327,9 @@ class ViewController: UIViewController { ```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +//highlight-next-line +import com.basistheory.android.service.BasisTheoryElements class MainActivity : AppCompatActivity() { private lateinit var exampleTextElement: TextElement @@ -338,6 +343,12 @@ class MainActivity : AppCompatActivity() { // this is just an example method that'll have the full lifecycle for revealing private fun reveal() { + //highlight-start + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + //highlight-end + // highlight-next-line val session = bt.createSession() } @@ -591,6 +602,8 @@ class ViewController: UIViewController { ```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +import com.basistheory.android.service.BasisTheoryElements //highlight-start import java.net.HttpURLConnection import java.net.URL @@ -609,6 +622,10 @@ class MainActivity : AppCompatActivity() { // this is just an example method that'll have the full lifecycle for revealing private fun reveal() { + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + val session = bt.createSession() //highlight-next-line @@ -816,6 +833,8 @@ class ViewController: UIViewController { ```kotlin showLineNumbers +import com.basistheory.android.view.TextElement +import com.basistheory.android.service.BasisTheoryElements import java.net.HttpURLConnection import java.net.URL @@ -832,6 +851,10 @@ class MainActivity : AppCompatActivity() { // this is just an example method that'll have the full lifecycle for revealing private fun reveal() { + val bt = BasisTheoryElements.builder() + .apiKey("test_1234567890") + .build() + val session = bt.createSession() authorizeSession(session.nonce) @@ -874,6 +897,7 @@ class MainActivity : AppCompatActivity() { You can now reveal any data to a customer without your application accessing the underlying value, reducing compliance and regulatory scope. Just execute the `reveal` method in whichever way you desire (like with the click of a button) and watch the token value appear on your Text Element. +If you need to reveal data stored outside of Basis Theory in a similar manner, check our [Reveal Data from 3rd Party](/docs/guides/share/reveal-data-from-third-party) guide. ## Learn More diff --git a/sidebars.js b/sidebars.js index d03ac6e3..4e53f5d0 100644 --- a/sidebars.js +++ b/sidebars.js @@ -62,7 +62,8 @@ const sidebars = { items: [ "guides/share/send-data-to-third-party", "guides/share/display-masked-data", - "guides/share/reveal-tokenized-data" + "guides/share/reveal-tokenized-data", + "guides/share/reveal-data-from-third-party" ], }, { diff --git a/src/components/shared/Card.tsx b/src/components/shared/Card.tsx index 22ade09e..8f0afb23 100644 --- a/src/components/shared/Card.tsx +++ b/src/components/shared/Card.tsx @@ -30,6 +30,7 @@ interface Card { hoverable?: boolean; cta?: React.ReactNode; column?: boolean; + openInNewWindow: boolean; } const Card = ({ @@ -42,6 +43,7 @@ const Card = ({ cta, hoverable = true, column = false, + openInNewWindow = false, ...otherProps }: PropsWithChildren< DetailedHTMLProps, HTMLDivElement> & Card @@ -53,7 +55,7 @@ const Card = ({ ? (e) => { e.preventDefault(); - if (href.startsWith("https")) { + if (href.startsWith("https") || openInNewWindow) { window.open(href, "_blank"); } else { history.push(href);