npm package: @roadsync/roadsync-js
Description: RoadSync JavaScript SDK
Author: RoadSync
Latest version: 0.0.12

# RoadSync JavaScript SDK

## Awailable payment types 

| Tag                         | Payment type |
| --------------------------- | ------------ |
| `roadsync-efs-form`         | EFS Check    |
| `roadsync-comchek-form`     | Comcheck     |
| `roadsync-tchek-form`       | Tchek        |
| `roadsync-credit-card-form` | Credit Card  |

## Website Integration

You'll need a `locationId` and `apiKey` for configuration. Once you have those, and have loaded the appropriate polyfills for
your target browsers (if they are required), it's simple to add the RoadSync payment form to your page. Replace the `XXXXXXXXXX` in the example below
with your actual values for those fields.

Also, note the `amount` property. This is the value, in `USD`, for the transaction.

```html
<script type="module" src="https://unpkg.com/@roadsync/roadsync-js@0.0.11/dist/roadsync.bundled.js"></script>
<body>
    <roadsync-comchek-form id="roadsyncComcheck" location-id="XXXXXXXXXX" api-key="XXXXXXXXXX" amount="12.34"></roadsync-comchek-form>
</body>
```

Each component has `paymentSuccessful` and `paymentFailed` events that you could use:

```js
const paymentComponent = document.getElementById("roadsyncComcheck");

paymentComponent.addEventListener("paymentSuccessful", (event) => console.log(event))
paymentComponent.addEventListener("paymentFailed", (event) => console.log(event))
```

For using different environment, you could use `environment` property.
This adds part of path to existing Roadsync URL. For testing purposes you could use `dev` value for that property.

## Using in Frameworks

### Angular

In your angular module, add `CUSTOM_ELEMENTS_SCHEMA` to `schemas` parameter, so Angular will know about web components:
```typescript
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
```

In module that you want to use, simply import package and use tags as default HTML tags.
Notice that you could use Angular event syntax to use callbacks in your component.

```html
  <roadsync-efs-form
    api-key="XXXXXXXXXX"
    location-id="XXXXXXXXXX"
    amount="30.0"
    (paymentFailed)="onPaymentEventFired($event)"
    (paymentSuccessful)="onPaymentEventFired($event)"
  >
  </roadsync-efs-form>
```

```typescript
import '@roadsync/roadsync-js';
import { PaymentFailedEvent } from '@roadsync/roadsync-js/dist/models';

export class AppComponent {
  onPaymentEventFired(e: Event) {
    console.log(e);
    console.log((e as CustomEvent<PaymentFailedEvent>).detail.message);
  }
}
```

### React
React integration sligtly difficult because of events. React doc says that "Events emitted by a Web Component may not properly propagate through a React render tree".
So for that we need to add event listeners manually.

```js
import '@roadsync/roadsync-js';

function App() {
  const efsFormRef = useRef(null);

  useEffect(() => {
    // subscribe for event
    const efsForm = efsFormRef.current;
    if(!efsForm)
      return;

    efsForm.addEventListener("paymentFailed", paymentErrorCallback);
    efsForm.addEventListener("paymentSuccessful", paymentSuccessfulCallback);
    return () => {
      // unsubscribe for event
      efsForm.removeEventListener("paymentFailed", paymentErrorCallback);
      efsForm.removeEventListener("paymentSuccessful", paymentSuccessfulCallback);
    };
  }, []);

  // Error callback
  function paymentErrorCallback(rawEvent) {
    console.log(rawEvent)
  }

  // Success callback
  function paymentSuccessfulCallback(rawEvent) {
    console.log(rawEvent)
  }
  return (
    <div className="App">
      <h1>Hello world!</h1>
      <roadsync-efs-form 
          ref={efsFormRef} 
          location-id={'XXXXXXXXXX'} 
          api-key={'XXXXXXXXXX'}
          amount={'30.0'}>
        </roadsync-efs-form>
    </div>
  );
}
```

### React with Typescript
For major part you could use example provided above as good reference.
Unfortunately, Typescript in this scenario would not recognize custom web components.
To give compiler understanding what he is dealing with, add this code before your component

```typescript
import { RoadSyncEFSForm } from '@roadsync/roadsync-js';

type CustomElement<T> = Partial<T & DOMAttributes<T> & { children: any }> & ClassAttributes<HTMLElement>;

type RoadSyncEFSFormComponent = CustomElement<RoadSyncEFSForm>;

declare global {
  namespace JSX {
    interface IntrinsicElements {
      ['roadsync-efs-form']: RoadSyncEFSFormComponent;
    }
  }
}
```

This code will tell Typescript compiler that our components are inherited from default ones, and you could use any default React property, except for events.

We're working on proper React Typescript wrapper.

### Polyfills

RoadSync.js uses modern web techologies, and might need polyfills depending on
what browser support you target and how you plan on integrating it.

We use:

- fetch [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) [polyfill](https://github.com/github/fetch) [caniuse](https://caniuse.com/fetch)
- Web components [MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components) [polyfill](https://www.webcomponents.org/polyfills) [caniuse](https://caniuse.com/?search=web%20components)

There's a good chance you'll want to include these polyfills for widest browser support:

```html
<body>
  <!-- start polyfills -->
  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@2.6.0/webcomponents-loader.js"></script>
  <script src="https://unpkg.com/lit@2.2.0/polyfill-support.js"></script>

  <!-- start RoadSync.js -->
  <script type="module" src="https://unpkg.com/@roadsync/roadsync-js@0.0.11/dist/roadsync.js"></script>
  <body>
    <roadsync-checkout location-id="XXXXXXXXXX" api-key="XXXXXXXXXX"></roadsync-checkout>
  </body>
```

### Using an iframe

In the near future, we'll also support an iframe integration.
<!-- 
## Advanced Usage

### `window` events

When a payment is complete, we'll post the transaction details via a `CustomEvent` attached to the window.

```javascript
window.addEventListener('roadsync.transaction.complete', (ev) {
    console.log('RoadSync transaction complete', ev.detail);
});
```

When a payment fails, we'll post the transaction details via a `CustomEvent` attached to the window.

```javascript
window.addEventListener('roadsync.transaction.failed', (ev) {
    console.log('RoadSync transaction failed', ev.detail);
});
``` -->

### Verifying the transaction status

**IMPORTANT: Do not rely solely on the JavaScript events to verify transaction completion.**
You'll need to use your server to verify that the transaction is actually finished by contacting the RoadSync
API directly **before** shipping a product or considering a transaction to be complete.