Skip to content

Commit

Permalink
Merge pull request #2 from ashinzekene/paystack-embed
Browse files Browse the repository at this point in the history
Added paystack embed
  • Loading branch information
ashinzekene authored Dec 2, 2017
2 parents 5e07a41 + d7caec9 commit 231ffce
Show file tree
Hide file tree
Showing 20 changed files with 478 additions and 88 deletions.
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ All notable changes to `angular4-paystack` will be documented in this file
### Changed
- Updated ReadMe and
### Removed
- removed unecessary packaged file
- removed unecessary packaged file
### Fixed
- Some minor bugs

Expand All @@ -22,4 +22,13 @@ All notable changes to `angular4-paystack` will be documented in this file
## 1.2.1 - 2017-10-04
### Changed
- updated readme to show that a callback is compulsory
- corrected `@angular/core` version in peerDependency
- corrected `@angular/core` version in peerDependency

## 2.0.0 - 2017-12-02
### Added
- You can now use the paystack inline embed in your angular application
- Added tests
### Changed
- updated README to show how to use the paystack inline embed and little fixes
### Removed
- Text input (`(text)`) is no longer suypported for the `angular4-paystack` component. Check README for details
65 changes: 42 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ANGULAR4-PAYSTACK

> This is an angular module that abstracts the complexity of making paystack payments with Angular.
> This is an angular module that abstracts the complexity of making paystack payments with Angular2+.
## USAGE

### 1. Install the module
Expand All @@ -15,17 +15,16 @@
```

### 3. Import the module
In your `app.module.ts` or any preferred module, import the module like so:
In your `app.module.ts` or your working module like so:

```js
```ts
import { NgModule } from '@angular/core';

import { Angular4PaystackModule } from 'angular4-paystack';
...

@NgModule({
imports: [
...
Angular4PaystackModule,
]
})
Expand All @@ -34,39 +33,59 @@
```

### 4. Use the component in your code
There are two available options

* Paystack Inline - Loads the credit card form in an iframe that appears as a popup
```html
<angular4-paystack
[key]="'pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'"
[email]="'mailexample@mail.com'"
[amount]="5000000"
[ref]="'2637458697'"
[class]="'btn btn-primary'"
(close)="paymentCancel()"
(callback)="paymentDone($event)"
>Pay with Paystack</angular4-paystack>
```

* Paystack Inline Embed - Paystack Inline Embed is the latest addition to the stack, it offers a stylish Inline that loads the credit card form in a set container like it sits in your page.
```html
<angular4-paystack-embed
[key]="'pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'"
[email]="'mailexample@mail.com'"
[amount]="5000000"
[ref]="'2637458697'"
[class]="'btn btn-primary'"
(close)="paymentCancel()"
(callback)="paymentDone($event)"
></angular4-paystack-embed>
```
**NOTE**
- The payment form will be 100% of the width of wherever you put it.
- To maintain a uniform design, your page's background color should be white

```html
<angular4-paystack
[key]="'pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'"
[email]="'mailexample@mail.com'"
[amount]="5000000"
[ref]="'2637458697'"
[class]="'btn btn-primary'"
(close)="paymentCancel()"
(callback)="paymentDone($event)"
>Pay with Paystack</angular4-paystack>
```

## OPTIONS

|Name | Type | Required | Default Value | Description |
|-----------------------|----------------|---------------------|---------------------|---------------------|
| `amount ` | `number` | true | undefined | Amount to withdraw (in kobo for NGN)
| `email ` | `string` | true | undefined | Email of subscriber/client
| `email ` | `string` | true | undefined | The customer's email address.
| `key` | `string` | true | undefined | Your pubic Key from Paystack. Use test key for test mode and live key for live mode
| `ref` | `string` | true | undefined | Unique reference
| `callback` | `function` | true | undefined | A function called when transaction is successful. Returns a parameter containing unique reference
| `transaction_charge` | `number` | false | 0 | A flat fee to charge the subaccount for this transaction, in kobo.
| `ref` | `string` | true | undefined | Unique case sensitive transaction reference. Only -,., = and alphanumeric characters allowed.
| `callback` | `function` | true | undefined | A function called when transaction is successful. Returns an object containing unique reference
| `metadata` | `object` | false | {} | custom details
| `class` | `string` | false | undefined | A string of classes to add to the component
| `style` | `object` | false | undefined | CSS stylings, eg ```{fontColor: 'red'}```
| `class` | `string` | false | undefined | A string of classes to add to the component (not available for **inline embed**)
| `style` | `object` | false | undefined | CSS stylings, eg ```{fontColor: 'red'}``` (not available for **inline embed**)
| `text` | `object` | false | undefined | Text output of the component
| `currency` | `string` | false | "NGN" | Transaction currency
| `plan` | `string` | false | "" | If transaction is to create a subscription to a predefined plan, provide plan code here.
| `quantity` | `string` | false | "" | Used to apply a multiple to the amount returned by the plan code above.
| `onClose` | `function` | false | undefined | A function called if the customer closes the payment window
**For Split Payments** |
| `subaccount` | `string` | false | "" | The code for the subaccount that owns the payment.
| `transaction_charge` | `number` | false | 0 | A flat fee to charge the subaccount for this transaction, in kobo.
| `bearer` | `string` | false | "" | Who bears Paystack charges? account or subaccount
| `onClose` | `function` | false | undefined | A function called when transaction is cancelled

> For more information checkout [paystack's documentation](https://developers.paystack.co/docs/paystack-inline#section-working-with-paystack-inline)

Expand Down
74 changes: 74 additions & 0 deletions examples/src/app/angular4-paystack/angular-paystack.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { async, TestBed } from "@angular/core/testing";
import { Angular4PaystackComponent } from "./angular4-paystack.component";

let comp
describe("Angular4-Paystack Popup", ()=> {
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [ Angular4PaystackComponent ],
})
.compileComponents()
})

beforeEach(() => {
let fixture = TestBed.createComponent(Angular4PaystackComponent);
comp = fixture.componentInstance
})

it("Should fail validation if key is not supplied", () => {
comp.amount = 1235678
comp.email = "ashinzekene@gmail.com"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if amount is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if amount is not a number", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.ref = "jfdi9urrktkkgkd"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if ref is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail valiation if callback is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.ref = "950gjvkjbk"
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail valiation if style is not an object", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.ref = "950gjvkjbk"
comp.style = "invalid style"
expect(comp.checkInput()).toBeFalsy()
})

it("Should pass valiation if ref, amount, email and key and callback is supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.ref = "950gjvkjbk"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeTruthy()
})

})
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Component, OnInit, Input, Output,EventEmitter } from '@angular/core';
import { PaystackOptions } from "./paystack-options";

interface myWindow extends Window {
PaystackPop: any
}
declare var window: Partial<myWindow>

@Component({
selector: 'angular4-paystack-embed',
template: `<div id="paystackEmbedContainer"></div>`
})

export class Angular4PaystackEmbed implements OnInit {
@Input() text: string
@Input() key: string
@Input() email: string
@Input() amount: number
@Input() metadata: {}
@Input() ref: string
@Input() currency: string
@Input() plan: string
@Input() quantity: string
@Input() subaccount: string
@Input() transaction_charge: number
@Input() bearer: string
@Output() close: EventEmitter<string> = new EventEmitter<string>()
@Output() callback: EventEmitter<string> = new EventEmitter<string>()
private paystackOptions: Partial<PaystackOptions>;
constructor() {}

pay() {
this.setUp()
console.log("OK payment will begin")
if(!this.checkInput()) return
window.PaystackPop.setup(this.paystackOptions)
}
checkInput(){
if(!this.key) return console.error("Paystack key cannot be empty")
if(!this.email) return console.error("Paystack email cannot be empty")
if(!this.amount) return console.error("Paystack amount cannot be empty")
if(!this.ref) return console.error("Paystack ref cannot be empty")
if (!this.callback.observers.length) return console.error(`Insert a callback output like so (callback)='PaymentComplete($event)' to check payment status`)
return true
}

setUp() {
this.paystackOptions = {
container: "paystackEmbedContainer",
key: this.key ,
email: this.email ,
amount: this.amount ,
ref: this.ref ,
metadata: this.metadata || {},
currency: this.currency || "NGN" ,
plan: this.plan || "" ,
quantity: this.quantity || "" ,
subaccount: this.subaccount || "" ,
transaction_charge: this.transaction_charge || 0 ,
bearer: this.bearer || "" ,
callback: (res) => this.callback.emit(res),
onClose: () => this.close.emit(),
}
}
ngOnInit() {
if(this.text) {
console.error("Paystack Text input is deprecated. Add text into textnode like so <angular4-paystack>Pay With Paystack</angular4-paystack>")
}
this.pay()
}

}
73 changes: 73 additions & 0 deletions examples/src/app/angular4-paystack/angular4-paystack-embed.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { async, TestBed } from "@angular/core/testing";
import { Angular4PaystackEmbed } from "./angular4-paystack-embed.component";

let comp
describe("Angular4-Paystack Embed", ()=> {
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [ Angular4PaystackEmbed ],
})
.compileComponents()
})

beforeEach(() => {
let fixture = TestBed.createComponent(Angular4PaystackEmbed);
comp = fixture.componentInstance
})

it("Should fail validation if key is not supplied", () => {
comp.amount = 1235678
comp.email = "ashinzekene@gmail.com"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if amount is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if amount is not a number", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.ref = "jfdi9urrktkkgkd"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail validation if ref is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail valiation if callback is not supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.ref = "950gjvkjbk"
expect(comp.checkInput()).toBeFalsy()
})

it("Should fail valiation if style is supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.style = { color: "rred" }
expect(comp.checkInput()).toBeFalsy()
})

it("Should pass valiation if ref, amount, email and key and callback is supplied", () => {
comp.key = "pk_test_*************"
comp.email = "ashinzekene@gmail.com"
comp.amount = 5000000
comp.ref = "950gjvkjbk"
comp.callback.subscribe((res) => {})
expect(comp.checkInput()).toBeTruthy()
})

})
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { NgModule } from '@angular/core';
import { CommonModule } from "@angular/common";

import { Angular4PaystackComponent } from './angular4-paystack.component';
import { Angular4PaystackEmbed } from "./angular4-paystack-embed.component";

@NgModule({
imports: [CommonModule],
exports: [Angular4PaystackComponent],
declarations: [Angular4PaystackComponent],
exports: [Angular4PaystackComponent, Angular4PaystackEmbed],
declarations: [Angular4PaystackComponent, Angular4PaystackEmbed],
providers: [],
})
export class Angular4PaystackModule { }
1 change: 1 addition & 0 deletions examples/src/app/angular4-paystack/paystack-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface PaystackOptions {
bearer: string;
callback: (reference: string) => void ;
onClose: () => void;
container?: string
}
7 changes: 4 additions & 3 deletions examples/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ <h1>
<img width="300" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
</div>
<h2>Here are some links to help you start: </h2>
<angular4-paystack
[key]="'pk_test_*************************'"
<angular4-paystack-embed
[key]="'pk_test_c613fc7d428a64fd1e5daea22f8380551b28c78e'"
[email]="'mailexample@mail.com'"
[amount]="'5000000'"
[ref]="'26374586297'"
(close)="paymentCancel()"
[style]="{border: 'none', backgroundColor: '#11FF55', padding: '5px 15px'}" >Pay With Paystack</angular4-paystack>
(callback)="paymentDone($event)"
>Pay With Paystack</angular4-paystack-embed>
<ul>
<li>
<h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
Expand Down
Loading

0 comments on commit 231ffce

Please sign in to comment.