angular-klasha 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/LICENSE.md +21 -0
- package/README.md +307 -160
- package/fesm2022/angular-klasha.mjs +545 -0
- package/fesm2022/angular-klasha.mjs.map +1 -0
- package/index.d.ts +422 -0
- package/package.json +28 -26
- package/angular-klasha.d.ts +0 -6
- package/angular-klasha.metadata.json +0 -1
- package/bundles/angular-klasha.umd.js +0 -744
- package/bundles/angular-klasha.umd.js.map +0 -1
- package/esm2015/angular-klasha.js +0 -7
- package/esm2015/lib/angular-klasha.component.js +0 -89
- package/esm2015/lib/angular-klasha.directive.js +0 -89
- package/esm2015/lib/angular-klasha.module.js +0 -34
- package/esm2015/lib/angular-klasha.service.js +0 -133
- package/esm2015/lib/klasha-keys.js +0 -5
- package/esm2015/model/klasha-options.js +0 -2
- package/esm2015/public_api.js +0 -7
- package/fesm2015/angular-klasha.js +0 -342
- package/fesm2015/angular-klasha.js.map +0 -1
- package/lib/angular-klasha.component.d.ts +0 -29
- package/lib/angular-klasha.directive.d.ts +0 -30
- package/lib/angular-klasha.module.d.ts +0 -4
- package/lib/angular-klasha.service.d.ts +0 -12
- package/lib/klasha-keys.d.ts +0 -4
- package/model/klasha-options.d.ts +0 -121
- package/public_api.d.ts +0 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `angular-klasha` are documented here.
|
|
4
|
+
|
|
5
|
+
## 1.0.0
|
|
6
|
+
|
|
7
|
+
This release makes the library work at all. Everything published before it is
|
|
8
|
+
non-functional — see the warning at the top of the README.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The checkout script URL.** 0.0.x loaded
|
|
13
|
+
`https://klastatic.fra1.digitaloceanspaces.com/{test,prod}/js/klasha-integration.js`.
|
|
14
|
+
That bucket has been deleted and returns `NoSuchBucket` for both the test and
|
|
15
|
+
the production path, so `window.KlashaClient` was never defined and no
|
|
16
|
+
payment could ever start. The library now loads
|
|
17
|
+
`https://js.klasha.com/pay.js`, the single script Klasha currently ships.
|
|
18
|
+
- **`isTestMode` is now forwarded to `KlashaClient`.** It is the 9th
|
|
19
|
+
constructor argument and the only thing that selects the sandbox over the
|
|
20
|
+
live gateway. 0.0.x passed eight arguments, so `isTestMode` was `undefined`
|
|
21
|
+
inside the Klasha script and **every sandbox payment was routed to the live
|
|
22
|
+
gateway**, the live redirect URL and the live iframe. The flag is coerced
|
|
23
|
+
with `Boolean()` so a stray string such as `'false'` cannot silently select
|
|
24
|
+
production.
|
|
25
|
+
- **`kit.phone` is now populated.** The Klasha script reads `kit.phone`;
|
|
26
|
+
0.0.x only set `kit.phone_number`, which is never read, so the customer's
|
|
27
|
+
phone number was silently dropped from the exchange-rate request. Both fields
|
|
28
|
+
are now set, and `phone` is accepted as a top-level option.
|
|
29
|
+
- **Duplicate container elements.** 0.0.x appended a `<div id="ktest">` from
|
|
30
|
+
the service constructor, on every injection, and hardcoded `'ktest'` as the
|
|
31
|
+
container id for every instance. Each component/directive instance now owns a
|
|
32
|
+
unique container id, the element is created lazily on the first payment,
|
|
33
|
+
reused afterwards, and removed on destroy.
|
|
34
|
+
- **jQuery is no longer loaded.** 0.0.x pulled jQuery 3.5.1 from the Google CDN
|
|
35
|
+
(twice) even though the Klasha script does not use it.
|
|
36
|
+
- **Removed `console.log` noise** from the service constructor and script
|
|
37
|
+
loader.
|
|
38
|
+
- Removed the vendored, dead copy of `klasha-integration.js` that was shipped
|
|
39
|
+
inside the published package.
|
|
40
|
+
- The service no longer performs DOM work in its constructor, so merely
|
|
41
|
+
injecting it has no side effects.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **Standalone support.** `AngularKlashaComponent` and `AngularKlashaDirective`
|
|
46
|
+
are standalone and can be imported directly. `provideKlasha({ merchantKey,
|
|
47
|
+
businessId, isTestMode })` configures a standalone application.
|
|
48
|
+
- `AngularKlashaModule.forRoot()` also accepts a config object.
|
|
49
|
+
- `AngularKlashaService.launch()`, `ensureContainer()`, `removeContainer()` and
|
|
50
|
+
the exported `KLASHA_SCRIPT_URL` / `nextKlashaContainerId()` for programmatic
|
|
51
|
+
use.
|
|
52
|
+
- `phone` as a top-level option and as an input, alongside the deprecated
|
|
53
|
+
`phone_number`.
|
|
54
|
+
- `tx_ref` is generated when the merchant does not supply one.
|
|
55
|
+
- Regression tests covering the 9th argument, `kit.phone`, the script URL and
|
|
56
|
+
single-container behaviour.
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- **Angular 16, 17, 18, 19 and 20 are supported.** `peerDependencies` were
|
|
61
|
+
pinned to `~12.0.1`.
|
|
62
|
+
- **`ng-packagr` is no longer a `peerDependency`.** Consumers were being forced
|
|
63
|
+
to install a build tool to use a runtime library.
|
|
64
|
+
- The package now ships modern Ivy partial-compilation output (`fesm2022` +
|
|
65
|
+
`exports` map). The hand-written View-Engine-era `main`/`module`/`esm5`/
|
|
66
|
+
`fesm5`/`metadata` entry points have been removed — Angular 13 dropped
|
|
67
|
+
support for all of them.
|
|
68
|
+
- Most `KlashaOptions` fields are now optional; only `merchantKey`,
|
|
69
|
+
`businessId`, `amount` and `email` are required.
|
|
70
|
+
- `PrivateKlashaOptions` is renamed `ResolvedKlashaOptions`; the old name
|
|
71
|
+
remains as a deprecated alias.
|
|
72
|
+
- `tx_ref` is no longer a validation error when omitted.
|
|
73
|
+
|
|
74
|
+
### Removed
|
|
75
|
+
|
|
76
|
+
- `TestComponent`, test scaffolding that was being compiled into the library
|
|
77
|
+
source tree.
|
|
78
|
+
|
|
79
|
+
## 0.0.1
|
|
80
|
+
|
|
81
|
+
Initial release. Non-functional — see above.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Dansteve Adekanbi <danstevea@gmail.com>
|
|
4
|
+
|
|
5
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
> of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
> in the Software without restriction, including without limitation the rights
|
|
8
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
> copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
> furnished to do so, subject to the following conditions:
|
|
11
|
+
>
|
|
12
|
+
> The above copyright notice and this permission notice shall be included in
|
|
13
|
+
> all copies or substantial portions of the Software.
|
|
14
|
+
>
|
|
15
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
> THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,245 +1,392 @@
|
|
|
1
1
|
# angular-klasha
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Angular component, directive and service for accepting [Klasha](https://klasha.com) payments.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/angular-klasha)
|
|
6
|
+
[](LICENSE.md)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
---
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## ⚠️ Upgrade from 0.0.x immediately — 0.0.x is completely non-functional
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
**`angular-klasha@0.0.1` cannot process a payment at all, and never warns you.**
|
|
13
|
+
|
|
14
|
+
1. **Its checkout script no longer exists.** 0.0.x loaded
|
|
15
|
+
`https://klastatic.fra1.digitaloceanspaces.com/{test,prod}/js/klasha-integration.js`.
|
|
16
|
+
That DigitalOcean Spaces bucket has been deleted and both URLs now return
|
|
17
|
+
`NoSuchBucket`. `window.KlashaClient` is therefore never defined and the
|
|
18
|
+
checkout silently never opens.
|
|
19
|
+
2. **The 9th `isTestMode` argument is missing.** `KlashaClient` takes
|
|
20
|
+
`isTestMode` as its 9th constructor argument, and on the current `pay.js`
|
|
21
|
+
it is the *only* thing that selects the sandbox. 0.0.x passes **eight**.
|
|
22
|
+
That matters now, because the current script serves one URL for both
|
|
23
|
+
environments — repointing without adding the argument would send sandbox
|
|
24
|
+
traffic to production. 1.0.0 passes it, coerced to a real boolean.
|
|
25
|
+
|
|
26
|
+
For the avoidance of doubt about the past: while the old CDN existed, 0.0.x
|
|
27
|
+
selected `/test/js/` or `/prod/js/` correctly from `isTestMode`, and that
|
|
28
|
+
script was environment-specific by URL. There is no evidence historical
|
|
29
|
+
sandbox payments reached production.
|
|
30
|
+
3. **The customer phone number was dropped.** 0.0.x set `kit.phone_number`;
|
|
31
|
+
the Klasha script only ever reads `kit.phone`.
|
|
32
|
+
4. **Duplicate DOM ids.** 0.0.x appended a `<div id="ktest">` from the service
|
|
33
|
+
constructor on every injection, so more than one payment button meant more
|
|
34
|
+
than one element with the same id.
|
|
35
|
+
5. **It loaded jQuery** from the Google CDN for no reason — the Klasha script
|
|
36
|
+
does not use jQuery.
|
|
37
|
+
6. It also `console.log`'d on construction and shipped a stale vendored copy of
|
|
38
|
+
the dead integration script inside the published package.
|
|
39
|
+
|
|
40
|
+
`1.0.0` fixes all of the above: it loads the current script
|
|
41
|
+
`https://js.klasha.com/pay.js`, forwards `isTestMode` as a real boolean 9th
|
|
42
|
+
argument, sets `kit.phone`, gives every instance its own container element, and
|
|
43
|
+
loads no jQuery.
|
|
44
|
+
|
|
45
|
+
**There is no safe way to stay on 0.0.x. Upgrade.**
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
| | |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| Angular | **16, 17, 18, 19 or 20** (`@angular/common` and `@angular/core`) |
|
|
54
|
+
| Environment | Browser. The checkout script cannot run during server-side rendering; call `pay()` from a browser-only code path. |
|
|
55
|
+
|
|
56
|
+
Published as Ivy partial-compilation output, so it works with both
|
|
57
|
+
NgModule-based and standalone applications.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
12
60
|
|
|
13
61
|
```sh
|
|
14
62
|
npm install --save angular-klasha
|
|
15
63
|
```
|
|
16
64
|
|
|
17
|
-
|
|
65
|
+
No script tag, no jQuery and no extra setup: `https://js.klasha.com/pay.js` is
|
|
66
|
+
injected lazily the first time a payment is started.
|
|
67
|
+
|
|
68
|
+
## 1. Configure your merchant credentials
|
|
69
|
+
|
|
70
|
+
### Standalone applications
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
74
|
+
import { provideKlasha } from 'angular-klasha';
|
|
75
|
+
|
|
76
|
+
import { AppComponent } from './app/app.component';
|
|
77
|
+
|
|
78
|
+
bootstrapApplication(AppComponent, {
|
|
79
|
+
providers: [
|
|
80
|
+
provideKlasha({
|
|
81
|
+
merchantKey: 'YOUR_MERCHANT_KEY',
|
|
82
|
+
businessId: '1',
|
|
83
|
+
isTestMode: true, // false (or omitted) targets the LIVE gateway
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### NgModule applications
|
|
18
90
|
|
|
19
|
-
|
|
91
|
+
`forRoot()` still works exactly as it did in 0.0.x, so existing code does not
|
|
92
|
+
have to change:
|
|
20
93
|
|
|
21
94
|
```ts
|
|
22
95
|
import { NgModule } from '@angular/core';
|
|
23
|
-
|
|
24
96
|
import { AngularKlashaModule } from 'angular-klasha';
|
|
25
|
-
...
|
|
26
97
|
|
|
27
98
|
@NgModule({
|
|
28
99
|
imports: [
|
|
29
|
-
AngularKlashaModule.forRoot('
|
|
30
|
-
|
|
100
|
+
AngularKlashaModule.forRoot('YOUR_MERCHANT_KEY', '1', true),
|
|
101
|
+
// a config object also works:
|
|
102
|
+
// AngularKlashaModule.forRoot({ merchantKey: 'YOUR_MERCHANT_KEY', businessId: '1', isTestMode: true }),
|
|
103
|
+
],
|
|
31
104
|
})
|
|
32
|
-
|
|
33
105
|
export class AppModule {}
|
|
34
106
|
```
|
|
35
107
|
|
|
36
|
-
|
|
108
|
+
> `isTestMode` here is what gets forwarded to `KlashaClient` as its 9th
|
|
109
|
+
> argument. Leaving it out means **live payments**.
|
|
37
110
|
|
|
38
|
-
|
|
111
|
+
## 2. Use the component or the directive
|
|
39
112
|
|
|
40
|
-
|
|
113
|
+
Both are **standalone**, so you can import either one directly into a
|
|
114
|
+
standalone component — or get both by importing `AngularKlashaModule`.
|
|
41
115
|
|
|
42
|
-
|
|
43
|
-
<angular-klasha
|
|
44
|
-
[fullname]="'some-random-str'"
|
|
45
|
-
[phone_number]="'some-random-str'"
|
|
46
|
-
[paymentDescription]="'some-random-str'"
|
|
47
|
-
[email]="'mailexample@mail.com'"
|
|
48
|
-
[amount]="'1000000'"
|
|
49
|
-
[merchantKey]="'some-random-str'"
|
|
50
|
-
[businessId]="'some-random-str'"
|
|
51
|
-
[tx_ref]="'some-random-str'"
|
|
52
|
-
(paymentInit)="paymentInit()"
|
|
53
|
-
(callBack)="paymentDone($event)"
|
|
54
|
-
>
|
|
55
|
-
Pay with Klasha
|
|
56
|
-
</angular-klasha>
|
|
57
|
-
```
|
|
116
|
+
### `AngularKlashaComponent`
|
|
58
117
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```html
|
|
62
|
-
<button
|
|
63
|
-
angular-klasha
|
|
64
|
-
[fullname]="'some-random-str'"
|
|
65
|
-
[phone_number]="'some-random-str'"
|
|
66
|
-
[paymentDescription]="'some-random-str'"
|
|
67
|
-
[email]="'mailexample@mail.com'"
|
|
68
|
-
[amount]="'1000000'"
|
|
69
|
-
[merchantKey]="'some-random-str'"
|
|
70
|
-
[businessId]="'some-random-str'"
|
|
71
|
-
[tx_ref]="'some-random-str'"
|
|
72
|
-
(paymentInit)="paymentInit()"
|
|
73
|
-
[class]="'btn btn-primary'"
|
|
74
|
-
(callBack)="paymentDone($event)"
|
|
75
|
-
>
|
|
76
|
-
Pay with Klasha
|
|
77
|
-
</button>
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
And then in your `component.ts`
|
|
118
|
+
Renders a `<button>` that opens the Klasha checkout when clicked.
|
|
81
119
|
|
|
82
120
|
```ts
|
|
83
|
-
import { Component
|
|
121
|
+
import { Component } from '@angular/core';
|
|
122
|
+
import { AngularKlashaComponent, KlashaOptions } from 'angular-klasha';
|
|
84
123
|
|
|
85
124
|
@Component({
|
|
86
|
-
selector:
|
|
87
|
-
|
|
88
|
-
|
|
125
|
+
selector: 'app-checkout',
|
|
126
|
+
standalone: true,
|
|
127
|
+
imports: [AngularKlashaComponent],
|
|
128
|
+
templateUrl: './checkout.component.html',
|
|
89
129
|
})
|
|
90
|
-
export class
|
|
91
|
-
|
|
92
|
-
constructor() {}
|
|
130
|
+
export class CheckoutComponent {
|
|
131
|
+
options: KlashaOptions = this.buildOptions();
|
|
93
132
|
|
|
94
|
-
paymentInit() {
|
|
95
|
-
console.log(
|
|
133
|
+
paymentInit(): void {
|
|
134
|
+
console.log('Payment initialised');
|
|
96
135
|
}
|
|
97
136
|
|
|
98
|
-
paymentDone(
|
|
99
|
-
|
|
100
|
-
|
|
137
|
+
paymentDone(response: unknown): void {
|
|
138
|
+
console.log('Payment done', response);
|
|
139
|
+
// Build a fresh options object for the next payment: `tx_ref` must be
|
|
140
|
+
// unique and the Klasha script mutates the `kit` object it is given.
|
|
141
|
+
this.options = this.buildOptions();
|
|
101
142
|
}
|
|
102
143
|
|
|
103
|
-
|
|
104
|
-
|
|
144
|
+
private buildOptions(): KlashaOptions {
|
|
145
|
+
return {
|
|
146
|
+
merchantKey: 'YOUR_MERCHANT_KEY',
|
|
147
|
+
businessId: '1',
|
|
148
|
+
amount: 10000,
|
|
149
|
+
email: 'customer@example.com',
|
|
150
|
+
fullname: 'Some Customer',
|
|
151
|
+
phone: '+2348000000000',
|
|
152
|
+
sourceCurrency: 'NGN',
|
|
153
|
+
destinationCurrency: 'NGN',
|
|
154
|
+
tx_ref: `klasha-${Date.now()}`,
|
|
155
|
+
paymentDescription: 'Order #1234',
|
|
156
|
+
isTestMode: true,
|
|
157
|
+
};
|
|
105
158
|
}
|
|
106
159
|
}
|
|
107
160
|
```
|
|
108
161
|
|
|
109
|
-
Also you can use the `klashaOptions` object like so:
|
|
110
|
-
|
|
111
162
|
```html
|
|
112
|
-
<
|
|
113
|
-
angular-klasha
|
|
163
|
+
<angular-klasha
|
|
114
164
|
[klashaOptions]="options"
|
|
115
|
-
|
|
165
|
+
[class]="'btn btn-primary'"
|
|
166
|
+
(paymentInit)="paymentInit()"
|
|
116
167
|
(callBack)="paymentDone($event)"
|
|
117
168
|
>
|
|
118
169
|
Pay with Klasha
|
|
119
|
-
</
|
|
170
|
+
</angular-klasha>
|
|
120
171
|
```
|
|
121
172
|
|
|
122
|
-
|
|
173
|
+
### `AngularKlashaDirective`
|
|
174
|
+
|
|
175
|
+
Same behaviour, applied to your own element so you keep full control of the
|
|
176
|
+
markup:
|
|
123
177
|
|
|
124
178
|
```ts
|
|
125
|
-
import { Component } from
|
|
126
|
-
import {
|
|
179
|
+
import { Component } from '@angular/core';
|
|
180
|
+
import { AngularKlashaDirective } from 'angular-klasha';
|
|
127
181
|
|
|
128
182
|
@Component({
|
|
129
|
-
selector:
|
|
130
|
-
|
|
131
|
-
|
|
183
|
+
selector: 'app-checkout',
|
|
184
|
+
standalone: true,
|
|
185
|
+
imports: [AngularKlashaDirective],
|
|
186
|
+
templateUrl: './checkout.component.html',
|
|
132
187
|
})
|
|
133
|
-
export class
|
|
134
|
-
options: KlashaOptions = {
|
|
135
|
-
email: 'some-random-str',
|
|
136
|
-
phone_number: 'some-random-str',
|
|
137
|
-
merchantKey: 'some-random-str',
|
|
138
|
-
amount: 1000,
|
|
139
|
-
sourceCurrency: '',
|
|
140
|
-
destinationCurrency: '',
|
|
141
|
-
tx_ref: '' + Math.floor((Math.random() * 1000000000) + 1),
|
|
142
|
-
businessId: '1',
|
|
143
|
-
fullname: 'some-random-str',
|
|
144
|
-
paymentDescription: '',
|
|
145
|
-
kit: {
|
|
146
|
-
currency: '',
|
|
147
|
-
phone_number: 'some-random-str',
|
|
148
|
-
email: 'some-random-str',
|
|
149
|
-
fullname: 'some-random-str',
|
|
150
|
-
tx_ref: '',
|
|
151
|
-
paymentType: '',
|
|
152
|
-
}
|
|
153
|
-
;
|
|
154
|
-
constructor() {}
|
|
155
|
-
|
|
156
|
-
paymentInit() {
|
|
157
|
-
console.log("Payment initialized");
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
paymentDone(info: any) {
|
|
161
|
-
this.title = "Payment Done";
|
|
162
|
-
console.log(this.title, info);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
}
|
|
188
|
+
export class CheckoutComponent { /* … same class body as above … */ }
|
|
166
189
|
```
|
|
167
190
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
```html
|
|
192
|
+
<button
|
|
193
|
+
type="button"
|
|
194
|
+
angular-klasha
|
|
195
|
+
[klashaOptions]="options"
|
|
196
|
+
(paymentInit)="paymentInit()"
|
|
197
|
+
(callBack)="paymentDone($event)"
|
|
198
|
+
>
|
|
199
|
+
Pay with Klasha
|
|
200
|
+
</button>
|
|
176
201
|
```
|
|
177
202
|
|
|
178
|
-
|
|
203
|
+
### Individual inputs instead of `klashaOptions`
|
|
204
|
+
|
|
205
|
+
Every field of `KlashaOptions` is also available as its own input:
|
|
179
206
|
|
|
180
207
|
```html
|
|
181
208
|
<button
|
|
209
|
+
type="button"
|
|
182
210
|
angular-klasha
|
|
183
|
-
[
|
|
184
|
-
[
|
|
185
|
-
[
|
|
186
|
-
[email]="'
|
|
187
|
-
[
|
|
188
|
-
[
|
|
189
|
-
[
|
|
190
|
-
[
|
|
211
|
+
[merchantKey]="'YOUR_MERCHANT_KEY'"
|
|
212
|
+
[businessId]="'1'"
|
|
213
|
+
[amount]="10000"
|
|
214
|
+
[email]="'customer@example.com'"
|
|
215
|
+
[fullname]="'Some Customer'"
|
|
216
|
+
[phone]="'+2348000000000'"
|
|
217
|
+
[tx_ref]="txRef"
|
|
218
|
+
[isTestMode]="true"
|
|
219
|
+
(paymentInit)="paymentInit()"
|
|
191
220
|
(callBack)="paymentDone($event)"
|
|
192
221
|
>
|
|
193
222
|
Pay with Klasha
|
|
194
223
|
</button>
|
|
195
224
|
```
|
|
196
225
|
|
|
197
|
-
|
|
226
|
+
`merchantKey`, `businessId` and `isTestMode` set on the component/directive
|
|
227
|
+
take priority over the values given to `provideKlasha()` / `forRoot()`.
|
|
228
|
+
|
|
229
|
+
> **`(callBack)` is required.** Without a subscriber, `pay()` refuses to open
|
|
230
|
+
> the checkout and returns
|
|
231
|
+
> `angular-klasha: Insert a callBack output like so (callBack)='PaymentComplete($event)' to check payment status`.
|
|
232
|
+
|
|
233
|
+
## Options
|
|
234
|
+
|
|
235
|
+
`KlashaOptions` — `merchantKey`, `businessId`, `amount` and `email` are
|
|
236
|
+
required; everything else is optional.
|
|
237
|
+
|
|
238
|
+
| Option | Type | Description |
|
|
239
|
+
| --- | --- | --- |
|
|
240
|
+
| `merchantKey` | `string` | Your Klasha merchant key. Falls back to the globally provided one. |
|
|
241
|
+
| `businessId` | `string` | Your Klasha business id. Falls back to the globally provided one. |
|
|
242
|
+
| `amount` | `number` | Amount to charge. |
|
|
243
|
+
| `email` | `string` | Customer email address. |
|
|
244
|
+
| `fullname` | `string` | Customer full name. |
|
|
245
|
+
| `phone` | `string` | Customer phone number. **This is the field the Klasha script reads.** |
|
|
246
|
+
| `phone_number` | `string` | *Deprecated* alias of `phone`, still accepted. |
|
|
247
|
+
| `sourceCurrency` | `string` | Currency you price in. Defaults to `NGN`. |
|
|
248
|
+
| `destinationCurrency` | `string` | Currency the customer is charged in. Defaults to `NGN`. |
|
|
249
|
+
| `tx_ref` | `string` | Unique transaction reference. Generated for you when omitted. |
|
|
250
|
+
| `callbackUrl` | `string` | URL the customer is redirected to after paying. |
|
|
251
|
+
| `paymentDescription` | `string` | Human readable description of the payment. |
|
|
252
|
+
| `isTestMode` | `boolean` | `true` = Klasha sandbox, `false`/omitted = **live gateway**. |
|
|
253
|
+
| `metadata` | `unknown` | Free-form data kept on the instance; not sent to Klasha. |
|
|
254
|
+
| `kit` | `KlashaKitOptions` | Advanced: extra fields merged into the payload handed to the Klasha script. |
|
|
255
|
+
|
|
256
|
+
### `kit`
|
|
257
|
+
|
|
258
|
+
You rarely need to set `kit` yourself — the service builds it from the options
|
|
259
|
+
above. It ends up containing:
|
|
260
|
+
|
|
261
|
+
| Field | Source |
|
|
262
|
+
| --- | --- |
|
|
263
|
+
| `currency` | `sourceCurrency` |
|
|
264
|
+
| `phone` | `phone` (or the deprecated `phone_number`) |
|
|
265
|
+
| `phone_number` | the same value, kept only for backwards compatibility |
|
|
266
|
+
| `email` | `email` |
|
|
267
|
+
| `fullname` | `fullname` |
|
|
268
|
+
| `tx_ref` | `tx_ref`, generated when omitted |
|
|
269
|
+
| `productType` | `kit.productType` (or the deprecated `kit.paymentType`) |
|
|
270
|
+
| `amount` | `kit.amount`, defaulting to `amount` |
|
|
271
|
+
| `sourceAmount` | `kit.sourceAmount`, when you supply one |
|
|
272
|
+
| `callBack` | wired to the `(callBack)` output for you |
|
|
273
|
+
|
|
274
|
+
> The Klasha script **mutates** the `kit` object it is given (it assigns
|
|
275
|
+
> `businessId`, `currency` and `redirect_url` onto it). `angular-klasha` builds
|
|
276
|
+
> a brand new `kit` for every payment, so never share one between payments.
|
|
277
|
+
|
|
278
|
+
## Outputs
|
|
279
|
+
|
|
280
|
+
| Output | Fires |
|
|
281
|
+
| --- | --- |
|
|
282
|
+
| `(paymentInit)` | Immediately before the Klasha checkout is opened. |
|
|
283
|
+
| `(callBack)` | With the Klasha response once the payment flow finishes. **Required.** |
|
|
284
|
+
|
|
285
|
+
## The checkout container
|
|
286
|
+
|
|
287
|
+
The Klasha script renders into a container element looked up by id. Each
|
|
288
|
+
component/directive instance gets its own id (`klasha-container-1`,
|
|
289
|
+
`klasha-container-2`, …): the element is created on the first payment, reused
|
|
290
|
+
on every subsequent one, and removed on destroy. 0.0.x hardcoded `ktest` for
|
|
291
|
+
every instance and appended a new element each time.
|
|
292
|
+
|
|
293
|
+
If you need the id — for styling, say — read it off the instance:
|
|
198
294
|
|
|
199
|
-
|
|
295
|
+
```ts
|
|
296
|
+
@ViewChild(AngularKlashaDirective) klasha!: AngularKlashaDirective;
|
|
297
|
+
// this.klasha.containerId
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Programmatic use
|
|
301
|
+
|
|
302
|
+
`AngularKlashaService` is `providedIn: 'root'` and can be used without the
|
|
303
|
+
component or the directive:
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
import { inject } from '@angular/core';
|
|
307
|
+
import { AngularKlashaService } from 'angular-klasha';
|
|
308
|
+
|
|
309
|
+
const klasha = inject(AngularKlashaService);
|
|
200
310
|
|
|
201
|
-
|
|
311
|
+
async function pay(): Promise<void> {
|
|
312
|
+
const options = klasha.getKlashaOptions({
|
|
313
|
+
merchantKey: 'YOUR_MERCHANT_KEY',
|
|
314
|
+
businessId: '1',
|
|
315
|
+
amount: 10000,
|
|
316
|
+
email: 'customer@example.com',
|
|
317
|
+
fullname: 'Some Customer',
|
|
318
|
+
phone: '+2348000000000',
|
|
319
|
+
isTestMode: true,
|
|
320
|
+
});
|
|
321
|
+
options.kit.callBack = (response) => console.log('done', response);
|
|
322
|
+
|
|
323
|
+
const containerId = 'my-klasha-container';
|
|
324
|
+
await klasha.loadScript();
|
|
325
|
+
klasha.launch(options, containerId); // creates the container if needed
|
|
326
|
+
}
|
|
327
|
+
```
|
|
202
328
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
|
210
|
-
|
|
|
211
|
-
| phone_number | The customer’s phone number. |
|
|
212
|
-
| email | The customer’s email address. |
|
|
213
|
-
| fullname | The customer’s full name. |
|
|
214
|
-
| tx_ref | The transaction reference number. It calls a javascript function `makeid(8)` where 8 is the length of the id. The length can be any number you desire and an example format is; klasha-8 to 12 digits-datetime (klasha-0123456789-01022021). |
|
|
215
|
-
| Kit | A JSONArray containing the customer’s info as well as the transaction reference.|
|
|
329
|
+
| Member | Description |
|
|
330
|
+
| --- | --- |
|
|
331
|
+
| `loadScript()` | Injects `https://js.klasha.com/pay.js` once and resolves when `window.KlashaClient` is available. |
|
|
332
|
+
| `getKlashaOptions(options)` | Resolves defaults and builds a fresh `kit`. |
|
|
333
|
+
| `checkInput(options)` | Returns `''` when the options are usable, otherwise an error message. |
|
|
334
|
+
| `launch(resolvedOptions, containerId)` | Constructs `KlashaClient` (with all **nine** arguments) and calls `init()`. |
|
|
335
|
+
| `ensureContainer(id)` / `removeContainer(id)` | Container lifecycle. |
|
|
336
|
+
| `makeId(length?)` | Random transaction reference generator. |
|
|
216
337
|
|
|
217
|
-
|
|
338
|
+
Also exported: `KLASHA_SCRIPT_URL`, `nextKlashaContainerId()`, and the
|
|
339
|
+
`MERCHANT_KEY`, `BUSINESS_ID` and `IS_TEST_MODE` injection tokens.
|
|
218
340
|
|
|
219
|
-
|
|
220
|
-
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
221
|
-
| currency | The currency in which payment is made. |
|
|
222
|
-
| phone_number | The customer’s phone number. |
|
|
223
|
-
| email | The customer’s email address. |
|
|
224
|
-
| fullname | The customer’s full name. |
|
|
225
|
-
| tx_ref | The transaction reference number. It calls a javascript function `makeid(8)` where 8 is the length of the id. The length can be any number you desire and an example format is; klasha-8 to 12 digits-datetime (klasha-0123456789-01022021). |
|
|
226
|
-
| Call back | A javascript function that is called after the payment has been made. It can return a successful or failed message depending on the status of the transaction. |
|
|
341
|
+
## Migrating from 0.0.x
|
|
227
342
|
|
|
228
|
-
|
|
343
|
+
| 0.0.x | 1.0.0 |
|
|
344
|
+
| --- | --- |
|
|
345
|
+
| `AngularKlashaModule.forRoot(key, biz, isTest)` | Unchanged — still works. |
|
|
346
|
+
| `<angular-klasha>` / `[angular-klasha]` | Unchanged; now standalone as well. |
|
|
347
|
+
| `(callBack)`, `(paymentInit)` | Unchanged. |
|
|
348
|
+
| `phone_number` | Still accepted; prefer `phone`. |
|
|
349
|
+
| `KlashaOptions` required almost every field | Only `merchantKey`, `businessId`, `amount` and `email` are required. |
|
|
350
|
+
| `tx_ref` had to be supplied | Generated when omitted. |
|
|
351
|
+
| Container was always `ktest` | Per-instance id, available as `.containerId`. |
|
|
352
|
+
| `isTestMode` was ignored by the Klasha script | Forwarded as the 9th constructor argument. |
|
|
353
|
+
| `PrivateKlashaOptions` | Renamed `ResolvedKlashaOptions` (old name kept as a deprecated alias). |
|
|
354
|
+
|
|
355
|
+
Nothing that worked before has been removed.
|
|
356
|
+
|
|
357
|
+
## Testing your integration
|
|
358
|
+
|
|
359
|
+
You cannot complete a real payment without live merchant credentials. Mock
|
|
360
|
+
`window.KlashaClient` and assert on the constructor arguments — argument index
|
|
361
|
+
8 is `isTestMode`:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
const calls: unknown[][] = [];
|
|
365
|
+
(window as any).KlashaClient = function (this: any, ...args: unknown[]) {
|
|
366
|
+
calls.push(args);
|
|
367
|
+
this.init = () => undefined;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// … trigger a payment …
|
|
371
|
+
|
|
372
|
+
expect(calls[0].length).toBe(9);
|
|
373
|
+
expect(calls[0][8]).toBe(true); // isTestMode
|
|
374
|
+
expect((calls[0][7] as any).phone).toBe('+2348000000000');
|
|
375
|
+
```
|
|
229
376
|
|
|
230
377
|
## Contributing
|
|
231
378
|
|
|
232
|
-
|
|
379
|
+
Fork the repository and open a pull request — contributions are welcome.
|
|
233
380
|
|
|
234
381
|
## How can I thank you?
|
|
235
382
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
Don't forget to [follow me on twitter](https://twitter.com/dansteveade)!
|
|
383
|
+
Star the GitHub repository, and share it. Don't forget to
|
|
384
|
+
[follow me on twitter](https://twitter.com/dansteveade)!
|
|
239
385
|
|
|
240
386
|
Thanks!
|
|
241
387
|
Dansteve Adekanbi.
|
|
242
388
|
|
|
243
389
|
## License
|
|
244
390
|
|
|
245
|
-
The MIT License (MIT). Please see [License File](LICENSE.md) for more
|
|
391
|
+
The MIT License (MIT). Please see the [License File](LICENSE.md) for more
|
|
392
|
+
information.
|