Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(loadLibrary): fix loadLibrary domain validation #325

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: E2E Tests
name: Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
test-e2e:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
Expand All @@ -30,3 +30,15 @@ jobs:
name: playwright-report
path: playwright-report/
retention-days: 30
test-unit:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit
82 changes: 45 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- BACK TO TOP LINK -->
<a id="readme-top"></a>

<a id="readme-top"></a>

<!-- PROJECT SHIELDS -->
<div align="center">
Expand Down Expand Up @@ -37,21 +37,20 @@
</p>
</div>


![SmartForm](./assets/smartform.png)

## About the project

Any payment form must comply with PCI-DSS requirements. A classical integration will be displayed
on the banks page using a redirection. In that case, PCI-DSS requirements are done by your bank.

By using this package Lyra allows to integrate a payment form using standard HTML elements on your
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
By using this package Lyra allows to integrate a payment form using standard HTML elements on your
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
all regulations.

The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
Ionic, etc.

## Getting Started
Expand All @@ -77,15 +76,17 @@ First, define the theme files to load in the head section of your HTML page:
```html
<head>
(...)
<link rel="stylesheet"
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css">
<link
rel="stylesheet"
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css"
/>
<script src="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon.js"></script>
(...)
</head>
```

> **Note**
>
>
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.

For more information about theming, please see [Lyra theming documentation][doc-themes]
Expand All @@ -101,45 +102,44 @@ After that, define the location where the payment form will be generated in your
```

> **Note**
>
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
>
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
> kind of payment method).

### Javascript

Import the library in your javascript file or component with:

```javascript
import KRGlue from "@lyracom/embedded-form-glue";
import KRGlue from '@lyracom/embedded-form-glue'
```

And finally, you can generate the payment form with the following code:

```javascript
/* Integration public key */
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~';
/* Endpoint. Must include the protocol (https://) */
const endPoint = '~~CHANGE_ME_ENDPOINT~~';
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~'
/* Endpoint. Base domain with its protocol (e.g. https://domain.name, do not include any path after the domain) */
const endPoint = '~~CHANGE_ME_ENDPOINT~~'

/* Load the remote library and get the KR object */
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
/* Setting configuration */
await KR.setFormConfig({ 'kr-language': 'en-US' })
/* Attach a payment form to a given DOM selector */
const { result } = await KR.attachForm('#myPaymentForm')
/* Show the payment form */
await KR.showForm(result.formId);
/* Render the payment form into a given DOM selector */
await KR.renderElements('#myPaymentForm')
```

> **Note**
>
>
> Replace **`~~CHANGE_ME_PUBLIC_KEY~~`** with your configuration public key.
>
>
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.

> **Warning**
>
> KR methods use Promises. You should always use the **await** keyword or **then method** when
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
>
> KR methods use Promises. You should always use the **await** keyword or **then method** when
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
> for more information.

## First transaction
Expand All @@ -148,8 +148,8 @@ Once the payment form is set up, you will see the skeleton animation. This is be
using the default demo token. To make a real transaction, you need to get a real **formToken**.

To get a proper test **formToken**, make a request to the Charge/CreatePayment web service. To not
expose your credentials, it is mandatory to do that from a server. Please see the
[NodeJS server example](examples/server/README.md), or visit the following links for more
expose your credentials, it is mandatory to do that from a server. Please see the
[NodeJS server example](examples/server/README.md), or visit the following links for more
information:

- [Embedded form quick start][doc-quick-start]
Expand All @@ -160,10 +160,14 @@ Once you have a **formToken**, you can set it in the payment form with the follo

```javascript
// Use the loadLibrary to set the form token
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey, '~~CHANGE_ME_FORM_TOKEN~~')
const { KR } = await KRGlue.loadLibrary(
endPoint,
publicKey,
'~~CHANGE_ME_FORM_TOKEN~~'
)

// Or set the form token once the library is loaded
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
await KR.setFormConfig({ formToken: '~~CHANGE_ME_FORM_TOKEN~~' })
```

Expand All @@ -178,11 +182,11 @@ methods.

### loadLibrary

Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
the `KR` object.

```javascript
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
```

## KR object
Expand All @@ -195,7 +199,7 @@ The available methods and callbacks are described in the following sections.
- [KR callbacks](./docs/kr_callbacks.md)

> **Note**
>
>
> See Lyra [Javascript library reference][doc-reference] for the complete reference guide.

## JavaScript frameworks integration
Expand All @@ -221,14 +225,15 @@ The payment form can be customized in many ways. Some of them in the following e
- [Add additional fields](./docs/customization#add-additional-fields)
- [Use a different HTML structure](./docs/customization#use-a-different-html-structure)

Any of these customizations can be done using the same method **KR.attachForm()**.
Any of these customizations can be done using the same method **KR.renderElements()**.

> **Note**
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.

<!-- CONTRIBUTING -->

## Contributing

Contributions are welcome and pull requests will be reviewed and taken into account.
Expand Down Expand Up @@ -260,17 +265,19 @@ npm run examples:serve
Execute the tests with the command:

```bash
npm run test
npm run test:e2e
```

<!-- LICENSE -->

## License

Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for more information.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- MARKDOWN LINKS & IMAGES -->

[build-shield]: https://img.shields.io/circleci/build/github/lyra/embedded-form-glue?style=for-the-badge&logo=github
[build-url]: https://circleci.com/gh/lyra/embedded-form-glue
[npm-shield]: https://img.shields.io/npm/v/@lyracom/embedded-form-glue?style=for-the-badge&logo=npm
Expand All @@ -285,6 +292,7 @@ Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for mor
[license-url]: https://github.com/lyra/embedded-form-glue/blob/master/LICENSE.txt

<!-- DOC LINKS -->

[doc-home]: https://docs.lyra.com/en/rest/V4.0/javascript/
[doc-quick-start]: https://docs.lyra.com/en/rest/V4.0/javascript/quick_start_js.html
[doc-reference]: https://docs.lyra.com/en/rest/V4.0/javascript/features/reference.html
Expand Down
14 changes: 11 additions & 3 deletions app/KryptonGlue.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ class Glue {
}

loadLibrary(domain, publicKey, formToken = null) {
const domainRegex =
/^(?:http(s)?:\/\/)[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/g
const pubKeyRegex = /^\d{2,8}:(|test)publickey_.+$/g

if (this.loaded) return this.getKrypton(publicKey)
if (!domain) return Promise.reject('Domain not defined')
if (!publicKey) return Promise.reject('Public key not defined')

if (!domainRegex.test(domain)) {
// Domain validation
try {
const domainUrl = new URL(domain)

if (!['http:', 'https:'].includes(domainUrl.protocol))
throw new Error('Invalid protocol')

if (domainUrl.port) throw new Error('No port allowed')
if (domainUrl.search !== '') throw new Error('No query params allowed')
if (domainUrl.pathname !== '/') throw new Error('Invalid path')
} catch (err) {
console.error('Domain format should be https://domain.name')
return Promise.reject(`[${domain}] is not a valid endpoint domain`)
}
Expand Down
14 changes: 7 additions & 7 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The payment form can be customized in many ways like:
<div class="kr-pan"></div>
<div class="kr-expiry"></div>
</div>
</div>
</div>
</div>
```

Expand All @@ -23,7 +23,7 @@ The payment form can be customized in many ways like:
<div class="kr-smart-form">
<div class="kr-embedded">
<div class="kr-pan"></div>
<input
<input
class="kr-theme my-custom-email-field"
type="text"
name="email"
Expand Down Expand Up @@ -57,13 +57,13 @@ The payment form can be customized in many ways like:
</div>
<div class="kr-expiry"></div>
</div>
</div>
</div>
</div>
```

Any of these customizations can be done using the same method **KR.attachForm()**.
Any of these customizations can be done using the same method **KR.renderElements()**.

> **Note**
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.
25 changes: 18 additions & 7 deletions docs/kr_methods.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@

# KR object methods

These are the current available methods to manipulate the payment form:

## attachForm
## renderElements

Render a payment form into a given DOM selector: return a `promise` with the `KR` object and result.

```javascript
const selector = `#myPaymentForm` // DOM selector
const { KR, result } = await KR.renderElements(selector)
```

> **_NOTE:_** if nothing is provided renderElements will search the complete DOM for the supported HTML elements
## attachForm (DEPRECATED use renderElements instead)

Attach a payment form to a given DOM selector: return a `promise` with the `KR` object and result.

Expand All @@ -20,8 +30,9 @@ Add a payment form to a given DOM selector: return a `promise` with the `KR` obj
const selector = `#myPaymentForm` // DOM selector
const { KR, result } = await KR.addForm(selector)
```

> **Warning**
>
>
> Only for cards payment method
## showForm
Expand All @@ -42,7 +53,6 @@ const { result } = await KR.addForm(selector)
const { KR } = await KR.hideForm(result.formId)
```


## setFormConfig

Set the configuration of the payment form on runtime: return a `promise` with the `KR` object.
Expand All @@ -53,8 +63,9 @@ const { KR } = await KR.setFormConfig({
language: `en-US`
})
```

> **Note**
>
>
> Please see the [type definition](../index.d.ts) file for the list of available configuration options.
## validateForm
Expand Down Expand Up @@ -87,7 +98,6 @@ available in the payment form.
const { KR } = await KR.openPaymentMethod('cards')
```


## openPopin

On popin mode, open the payment form in a popin: return a `promise` with the `KR` object.
Expand Down Expand Up @@ -159,10 +169,11 @@ Remove all generated payment forms: return a `promise` with the `KR` object.
```javascript
const { KR } = await KR.removeForms()
```

## removeEventCallbacks

Remove all event callbacks: return a `promise` with the `KR` object.

```javascript
const { KR } = await KR.removeEventCallbacks()
```
```
Loading