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 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
- > This is an angular module that abstracts the complexity of making klasha payments.
3
+ > Angular component, directive and service for accepting [Klasha](https://klasha.com) payments.
4
4
 
5
- ## Demo
5
+ [![npm](https://img.shields.io/npm/v/angular-klasha.svg)](https://www.npmjs.com/package/angular-klasha)
6
+ [![license](https://img.shields.io/npm/l/angular-klasha.svg)](LICENSE.md)
6
7
 
7
- ![Demo](App.png?raw=true "Demo Image")
8
+ ---
8
9
 
9
- ## USAGE
10
+ ## ⚠️ Upgrade from 0.0.x immediately — 0.0.x is completely non-functional
10
11
 
11
- ### 1. Install the module
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
- ### 2. Import the module
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
- In your `app.module.ts` or any module where the component or directive would be used like so:
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('merchantKey','businessId',false),
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
- ### 3. Implement in your project
108
+ > `isTestMode` here is what gets forwarded to `KlashaClient` as its 9th
109
+ > argument. Leaving it out means **live payments**.
37
110
 
38
- There are two available options
111
+ ## 2. Use the component or the directive
39
112
 
40
- - **AngularKlashaComponent**: Renders a button which when clicked loads klasha Inline in an iframe
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
- ```html
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
- - **AngularKlashaDirective**: A directive that loads klasha inline in an iframe when clicked
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, OnInit } from "@angular/core";
121
+ import { Component } from '@angular/core';
122
+ import { AngularKlashaComponent, KlashaOptions } from 'angular-klasha';
84
123
 
85
124
  @Component({
86
- selector: "app-root",
87
- templateUrl: "./app.component.html",
88
- styleUrls: ["./app.component.css"],
125
+ selector: 'app-checkout',
126
+ standalone: true,
127
+ imports: [AngularKlashaComponent],
128
+ templateUrl: './checkout.component.html',
89
129
  })
90
- export class AppComponent implements OnInit {
91
- tx_ref = '' + Math.floor((Math.random() * 1000000000) + 1);
92
- constructor() {}
130
+ export class CheckoutComponent {
131
+ options: KlashaOptions = this.buildOptions();
93
132
 
94
- paymentInit() {
95
- console.log("Payment initialized");
133
+ paymentInit(): void {
134
+ console.log('Payment initialised');
96
135
  }
97
136
 
98
- paymentDone(info: any) {
99
- this.title = "Payment Done";
100
- console.log(this.title, info);
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
- ngOnInit() {
104
- this.tx_ref ='' + Math.floor((Math.random() * 1000000000) + 1);
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
- <button
113
- angular-klasha
163
+ <angular-klasha
114
164
  [klashaOptions]="options"
115
- (paymentInit)="paymentCancel()"
165
+ [class]="'btn btn-primary'"
166
+ (paymentInit)="paymentInit()"
116
167
  (callBack)="paymentDone($event)"
117
168
  >
118
169
  Pay with Klasha
119
- </button>
170
+ </angular-klasha>
120
171
  ```
121
172
 
122
- And then in your `component.ts`
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 "@angular/core";
126
- import { KlashaOptions } from "angular-klasha";
179
+ import { Component } from '@angular/core';
180
+ import { AngularKlashaDirective } from 'angular-klasha';
127
181
 
128
182
  @Component({
129
- selector: "app-root",
130
- templateUrl: "./app.component.html",
131
- styleUrls: ["./app.component.css"],
183
+ selector: 'app-checkout',
184
+ standalone: true,
185
+ imports: [AngularKlashaDirective],
186
+ templateUrl: './checkout.component.html',
132
187
  })
133
- export class AppComponent {
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
- Also, you can pass in a merchantKey and businessId in the component and the directive, in such situation, this merchantKey and businessId is given a higher ptx_ref over the global `forRoot` merchantKey and businessId. For example, if you have this is your file
169
-
170
- ```ts
171
- @NgModule({
172
- imports: [
173
- AngularKlashaModule.forRoot('merchantKey','businessId',false),
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
- and this in your component
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
- [fullname]="'some-random-str'"
184
- [phone_number]="'some-random-str'"
185
- [paymentDescription]="'some-random-str'"
186
- [email]="'mailexample@mail.com'"
187
- [amount]="'1000000'"
188
- [merchantKey]="'merchantKey2'"
189
- [businessId]="'businessId2'"
190
- [tx_ref]="'some-random-str'"
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
- Then `merchantKey2` and `businessId2` would be used instead
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
- ## OPTIONS
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
- >The function accepts some parameters necessary for processing payment, and they include the following:
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
- | Parameters | Description |
204
- | --------------- | --------------------------------------------------------------------------------------------------------------------------- |
205
- | merchantKey | The key generated by the merchant after creating a business in the merchant dashboard. It can be the public or private key. |
206
- | amount | The amount that is paid by the customer to the merchant. |
207
- | Container id | The id of an empty container div in your code. by default it is generated |
208
- | callbackUrl | The url your customers are being redirected to after processing payment. |
209
- | destinationCurrency | The country code e.g NGN (Nigeria). |
210
- | sourceCurrency | The currency set by the merchant in which the price of goods is displayed. |
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
- > Kit can further be broken down into:
338
+ Also exported: `KLASHA_SCRIPT_URL`, `nextKlashaContainerId()`, and the
339
+ `MERCHANT_KEY`, `BUSINESS_ID` and `IS_TEST_MODE` injection tokens.
218
340
 
219
- | Parameters | Description |
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
- > For more information checkout [klasha's documentation](https://documenter.getpostman.com/view/8963555/TzJoFgHh)
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
- Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities.
379
+ Fork the repository and open a pull request contributions are welcome.
233
380
 
234
381
  ## How can I thank you?
235
382
 
236
- Why not star the github repo? I'd love the attention! Why not share the link for this repository on Twitter or anywhere? Spread the word!
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 information.
391
+ The MIT License (MIT). Please see the [License File](LICENSE.md) for more
392
+ information.