@raaamie/pay 1.0.0 → 1.0.1

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.
@@ -22,6 +22,7 @@ function validateConfig(config) {
22
22
  }
23
23
  function buildCheckoutUrl(config, reference) {
24
24
  var _a, _b, _c, _d;
25
+ const baseUrl = config.gatewayUrl || GATEWAY_URL;
25
26
  const params = new URLSearchParams({
26
27
  key: config.key,
27
28
  amount: String(config.amount),
@@ -44,7 +45,7 @@ function buildCheckoutUrl(config, reference) {
44
45
  params.set('metadata', btoa(JSON.stringify(config.metadata)));
45
46
  if (config.redirectUrl)
46
47
  params.set('redirect_url', config.redirectUrl);
47
- return `${GATEWAY_URL}/pay/${reference}?${params.toString()}`;
48
+ return `${baseUrl}/pay/${reference}?${params.toString()}`;
48
49
  }
49
50
  function createIframeStyles() {
50
51
  return [
@@ -96,6 +97,22 @@ class RaaaamiePayPopup {
96
97
  this.backdrop.setAttribute('style', createBackdropStyles());
97
98
  this.backdrop.addEventListener('click', () => this.close());
98
99
  document.body.appendChild(this.backdrop);
100
+ // Create loader
101
+ const loader = document.createElement('div');
102
+ loader.setAttribute('id', 'raamiepay-loader');
103
+ loader.setAttribute('style', [
104
+ 'position:fixed',
105
+ 'top:0',
106
+ 'left:0',
107
+ 'width:100%',
108
+ 'height:100%',
109
+ 'z-index:2147483648',
110
+ 'display:flex',
111
+ 'align-items:center',
112
+ 'justify-content:center',
113
+ ].join(';'));
114
+ loader.innerHTML = '<div style="width:40px;height:40px;border:3px solid rgba(255,255,255,0.2);border-top-color:#fff;border-radius:50%;animation:raamiepay-spin .6s linear infinite"></div><style>@keyframes raamiepay-spin{to{transform:rotate(360deg)}}</style>';
115
+ document.body.appendChild(loader);
99
116
  // Create iframe
100
117
  const url = buildCheckoutUrl(this.config, this.reference);
101
118
  this.iframe = document.createElement('iframe');
@@ -103,17 +120,24 @@ class RaaaamiePayPopup {
103
120
  this.iframe.setAttribute('src', url);
104
121
  this.iframe.setAttribute('style', createIframeStyles());
105
122
  this.iframe.setAttribute('allow', 'payment');
123
+ this.iframe.setAttribute('allowTransparency', 'true');
106
124
  this.iframe.setAttribute('sandbox', 'allow-forms allow-scripts allow-same-origin allow-popups allow-top-navigation');
107
125
  this.iframe.setAttribute('title', 'RaaamiePay Secure Checkout');
108
126
  this.iframe.setAttribute('aria-label', 'Payment checkout');
109
127
  document.body.appendChild(this.iframe);
110
- // Fade in
128
+ // Fade in backdrop
111
129
  requestAnimationFrame(() => {
112
130
  if (this.backdrop)
113
131
  this.backdrop.style.opacity = '1';
132
+ });
133
+ // Show iframe once loaded, remove loader
134
+ this.iframe.onload = () => {
114
135
  if (this.iframe)
115
136
  this.iframe.style.opacity = '1';
116
- });
137
+ const l = document.getElementById('raamiepay-loader');
138
+ if (l)
139
+ l.remove();
140
+ };
117
141
  // Listen for messages from gateway
118
142
  this.messageHandler = (event) => this.handleMessage(event);
119
143
  window.addEventListener('message', this.messageHandler);
@@ -137,6 +161,9 @@ class RaaaamiePayPopup {
137
161
  this.backdrop.remove();
138
162
  this.backdrop = null;
139
163
  }
164
+ const l = document.getElementById('raamiepay-loader');
165
+ if (l)
166
+ l.remove();
140
167
  document.body.style.overflow = '';
141
168
  }, 300);
142
169
  // Clean up listener
@@ -18,6 +18,7 @@ function validateConfig(config) {
18
18
  }
19
19
  function buildCheckoutUrl(config, reference) {
20
20
  var _a, _b, _c, _d;
21
+ const baseUrl = config.gatewayUrl || GATEWAY_URL;
21
22
  const params = new URLSearchParams({
22
23
  key: config.key,
23
24
  amount: String(config.amount),
@@ -40,7 +41,7 @@ function buildCheckoutUrl(config, reference) {
40
41
  params.set('metadata', btoa(JSON.stringify(config.metadata)));
41
42
  if (config.redirectUrl)
42
43
  params.set('redirect_url', config.redirectUrl);
43
- return `${GATEWAY_URL}/pay/${reference}?${params.toString()}`;
44
+ return `${baseUrl}/pay/${reference}?${params.toString()}`;
44
45
  }
45
46
  function createIframeStyles() {
46
47
  return [
@@ -92,6 +93,22 @@ class RaaaamiePayPopup {
92
93
  this.backdrop.setAttribute('style', createBackdropStyles());
93
94
  this.backdrop.addEventListener('click', () => this.close());
94
95
  document.body.appendChild(this.backdrop);
96
+ // Create loader
97
+ const loader = document.createElement('div');
98
+ loader.setAttribute('id', 'raamiepay-loader');
99
+ loader.setAttribute('style', [
100
+ 'position:fixed',
101
+ 'top:0',
102
+ 'left:0',
103
+ 'width:100%',
104
+ 'height:100%',
105
+ 'z-index:2147483648',
106
+ 'display:flex',
107
+ 'align-items:center',
108
+ 'justify-content:center',
109
+ ].join(';'));
110
+ loader.innerHTML = '<div style="width:40px;height:40px;border:3px solid rgba(255,255,255,0.2);border-top-color:#fff;border-radius:50%;animation:raamiepay-spin .6s linear infinite"></div><style>@keyframes raamiepay-spin{to{transform:rotate(360deg)}}</style>';
111
+ document.body.appendChild(loader);
95
112
  // Create iframe
96
113
  const url = buildCheckoutUrl(this.config, this.reference);
97
114
  this.iframe = document.createElement('iframe');
@@ -99,17 +116,24 @@ class RaaaamiePayPopup {
99
116
  this.iframe.setAttribute('src', url);
100
117
  this.iframe.setAttribute('style', createIframeStyles());
101
118
  this.iframe.setAttribute('allow', 'payment');
119
+ this.iframe.setAttribute('allowTransparency', 'true');
102
120
  this.iframe.setAttribute('sandbox', 'allow-forms allow-scripts allow-same-origin allow-popups allow-top-navigation');
103
121
  this.iframe.setAttribute('title', 'RaaamiePay Secure Checkout');
104
122
  this.iframe.setAttribute('aria-label', 'Payment checkout');
105
123
  document.body.appendChild(this.iframe);
106
- // Fade in
124
+ // Fade in backdrop
107
125
  requestAnimationFrame(() => {
108
126
  if (this.backdrop)
109
127
  this.backdrop.style.opacity = '1';
128
+ });
129
+ // Show iframe once loaded, remove loader
130
+ this.iframe.onload = () => {
110
131
  if (this.iframe)
111
132
  this.iframe.style.opacity = '1';
112
- });
133
+ const l = document.getElementById('raamiepay-loader');
134
+ if (l)
135
+ l.remove();
136
+ };
113
137
  // Listen for messages from gateway
114
138
  this.messageHandler = (event) => this.handleMessage(event);
115
139
  window.addEventListener('message', this.messageHandler);
@@ -133,6 +157,9 @@ class RaaaamiePayPopup {
133
157
  this.backdrop.remove();
134
158
  this.backdrop = null;
135
159
  }
160
+ const l = document.getElementById('raamiepay-loader');
161
+ if (l)
162
+ l.remove();
136
163
  document.body.style.overflow = '';
137
164
  }, 300);
138
165
  // Clean up listener
@@ -1 +1 @@
1
- var RaaamiePay=function(e){"use strict";function t(){return`RPY-${Date.now().toString(36)}-${Math.random().toString(36).substring(2,10)}`.toUpperCase()}function i(e){if(!e.key)throw new Error('[RaaamiePay] "key" is required');if(!e.key.startsWith("pk_"))throw new Error('[RaaamiePay] Invalid public key. Must start with "pk_"');if(!e.amount||e.amount<=0)throw new Error('[RaaamiePay] "amount" must be greater than 0');if(e.customer&&!e.customer.email&&!e.customer.phone)throw new Error('[RaaamiePay] Customer must have at least "email" or "phone"')}function a(e,t){var i,a,r,s;const o=new URLSearchParams({key:e.key,amount:String(e.amount),currency:e.currency||"GHS",reference:t,sdk_version:"1.0.0",mode:"popup"});return(null===(i=e.customer)||void 0===i?void 0:i.email)&&o.set("email",e.customer.email),(null===(a=e.customer)||void 0===a?void 0:a.phone)&&o.set("phone",e.customer.phone),(null===(r=e.customer)||void 0===r?void 0:r.name)&&o.set("name",e.customer.name),e.description&&o.set("description",e.description),(null===(s=e.channels)||void 0===s?void 0:s.length)&&o.set("channels",e.channels.join(",")),e.metadata&&o.set("metadata",btoa(JSON.stringify(e.metadata))),e.redirectUrl&&o.set("redirect_url",e.redirectUrl),`https://pay.raaami.com/pay/${t}?${o.toString()}`}class r{constructor(e){this.iframe=null,this.backdrop=null,this.messageHandler=null,this.isOpen=!1,i(e),this.config=e,this.reference=e.reference||t()}open(){if(this.isOpen)return;this.isOpen=!0,document.body.style.overflow="hidden",this.backdrop=document.createElement("div"),this.backdrop.setAttribute("id","raamiepay-backdrop"),this.backdrop.setAttribute("style",["position:fixed","top:0","left:0","width:100%","height:100%","z-index:2147483646","background:rgba(0,0,0,0.6)","backdrop-filter:blur(4px)","-webkit-backdrop-filter:blur(4px)","opacity:0","transition:opacity 0.3s ease"].join(";")),this.backdrop.addEventListener("click",()=>this.close()),document.body.appendChild(this.backdrop);const e=a(this.config,this.reference);this.iframe=document.createElement("iframe"),this.iframe.setAttribute("id","raamiepay-checkout"),this.iframe.setAttribute("src",e),this.iframe.setAttribute("style",["position:fixed","top:0","left:0","width:100%","height:100%","z-index:2147483647","border:none","opacity:0","transition:opacity 0.3s ease"].join(";")),this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups allow-top-navigation"),this.iframe.setAttribute("title","RaaamiePay Secure Checkout"),this.iframe.setAttribute("aria-label","Payment checkout"),document.body.appendChild(this.iframe),requestAnimationFrame(()=>{this.backdrop&&(this.backdrop.style.opacity="1"),this.iframe&&(this.iframe.style.opacity="1")}),this.messageHandler=e=>this.handleMessage(e),window.addEventListener("message",this.messageHandler)}close(){var e,t;this.isOpen&&(this.isOpen=!1,this.backdrop&&(this.backdrop.style.opacity="0"),this.iframe&&(this.iframe.style.opacity="0"),setTimeout(()=>{this.iframe&&(this.iframe.remove(),this.iframe=null),this.backdrop&&(this.backdrop.remove(),this.backdrop=null),document.body.style.overflow=""},300),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),null===(t=(e=this.config).onClose)||void 0===t||t.call(e))}handleMessage(e){var t,i,a,r,s,o;if(!e.origin.includes("raaami.com")&&!e.origin.includes("localhost"))return;const n=e.data;if(null==n?void 0:n.type)switch(n.type){case"payment.success":null===(i=(t=this.config).onSuccess)||void 0===i||i.call(t,n.data),this.close();break;case"payment.failed":null===(r=(a=this.config).onError)||void 0===r||r.call(a,n.data),this.close();break;case"payment.close":this.close();break;case"payment.loaded":null===(o=(s=this.config).onLoad)||void 0===o||o.call(s)}}getReference(){return this.reference}}function s(e){i(e);const r=a(e,e.reference||t());window.location.href=r.replace("mode=popup","mode=redirect")}const o={popup(e){const t=new r(e);return t.open(),t},redirect(e){s(e)},create:e=>new r(e)};return e.RaaaamiePayPopup=r,e.RaaamiePay=o,e.default=o,e.redirect=s,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
1
+ var RaaamiePay=function(e){"use strict";function t(){return`RPY-${Date.now().toString(36)}-${Math.random().toString(36).substring(2,10)}`.toUpperCase()}function i(e){if(!e.key)throw new Error('[RaaamiePay] "key" is required');if(!e.key.startsWith("pk_"))throw new Error('[RaaamiePay] Invalid public key. Must start with "pk_"');if(!e.amount||e.amount<=0)throw new Error('[RaaamiePay] "amount" must be greater than 0');if(e.customer&&!e.customer.email&&!e.customer.phone)throw new Error('[RaaamiePay] Customer must have at least "email" or "phone"')}function a(e,t){var i,a,r,o;const s=e.gatewayUrl||"https://pay.raaami.com",n=new URLSearchParams({key:e.key,amount:String(e.amount),currency:e.currency||"GHS",reference:t,sdk_version:"1.0.0",mode:"popup"});return(null===(i=e.customer)||void 0===i?void 0:i.email)&&n.set("email",e.customer.email),(null===(a=e.customer)||void 0===a?void 0:a.phone)&&n.set("phone",e.customer.phone),(null===(r=e.customer)||void 0===r?void 0:r.name)&&n.set("name",e.customer.name),e.description&&n.set("description",e.description),(null===(o=e.channels)||void 0===o?void 0:o.length)&&n.set("channels",e.channels.join(",")),e.metadata&&n.set("metadata",btoa(JSON.stringify(e.metadata))),e.redirectUrl&&n.set("redirect_url",e.redirectUrl),`${s}/pay/${t}?${n.toString()}`}class r{constructor(e){this.iframe=null,this.backdrop=null,this.messageHandler=null,this.isOpen=!1,i(e),this.config=e,this.reference=e.reference||t()}open(){if(this.isOpen)return;this.isOpen=!0,document.body.style.overflow="hidden",this.backdrop=document.createElement("div"),this.backdrop.setAttribute("id","raamiepay-backdrop"),this.backdrop.setAttribute("style",["position:fixed","top:0","left:0","width:100%","height:100%","z-index:2147483646","background:rgba(0,0,0,0.6)","backdrop-filter:blur(4px)","-webkit-backdrop-filter:blur(4px)","opacity:0","transition:opacity 0.3s ease"].join(";")),this.backdrop.addEventListener("click",()=>this.close()),document.body.appendChild(this.backdrop);const e=document.createElement("div");e.setAttribute("id","raamiepay-loader"),e.setAttribute("style",["position:fixed","top:0","left:0","width:100%","height:100%","z-index:2147483648","display:flex","align-items:center","justify-content:center"].join(";")),e.innerHTML='<div style="width:40px;height:40px;border:3px solid rgba(255,255,255,0.2);border-top-color:#fff;border-radius:50%;animation:raamiepay-spin .6s linear infinite"></div><style>@keyframes raamiepay-spin{to{transform:rotate(360deg)}}</style>',document.body.appendChild(e);const t=a(this.config,this.reference);this.iframe=document.createElement("iframe"),this.iframe.setAttribute("id","raamiepay-checkout"),this.iframe.setAttribute("src",t),this.iframe.setAttribute("style",["position:fixed","top:0","left:0","width:100%","height:100%","z-index:2147483647","border:none","opacity:0","transition:opacity 0.3s ease"].join(";")),this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("allowTransparency","true"),this.iframe.setAttribute("sandbox","allow-forms allow-scripts allow-same-origin allow-popups allow-top-navigation"),this.iframe.setAttribute("title","RaaamiePay Secure Checkout"),this.iframe.setAttribute("aria-label","Payment checkout"),document.body.appendChild(this.iframe),requestAnimationFrame(()=>{this.backdrop&&(this.backdrop.style.opacity="1")}),this.iframe.onload=()=>{this.iframe&&(this.iframe.style.opacity="1");const e=document.getElementById("raamiepay-loader");e&&e.remove()},this.messageHandler=e=>this.handleMessage(e),window.addEventListener("message",this.messageHandler)}close(){var e,t;this.isOpen&&(this.isOpen=!1,this.backdrop&&(this.backdrop.style.opacity="0"),this.iframe&&(this.iframe.style.opacity="0"),setTimeout(()=>{this.iframe&&(this.iframe.remove(),this.iframe=null),this.backdrop&&(this.backdrop.remove(),this.backdrop=null);const e=document.getElementById("raamiepay-loader");e&&e.remove(),document.body.style.overflow=""},300),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),null===(t=(e=this.config).onClose)||void 0===t||t.call(e))}handleMessage(e){var t,i,a,r,o,s;if(!e.origin.includes("raaami.com")&&!e.origin.includes("localhost"))return;const n=e.data;if(null==n?void 0:n.type)switch(n.type){case"payment.success":null===(i=(t=this.config).onSuccess)||void 0===i||i.call(t,n.data),this.close();break;case"payment.failed":null===(r=(a=this.config).onError)||void 0===r||r.call(a,n.data),this.close();break;case"payment.close":this.close();break;case"payment.loaded":null===(s=(o=this.config).onLoad)||void 0===s||s.call(o)}}getReference(){return this.reference}}function o(e){i(e);const r=a(e,e.reference||t());window.location.href=r.replace("mode=popup","mode=redirect")}const s={popup(e){const t=new r(e);return t.open(),t},redirect(e){o(e)},create:e=>new r(e)};return e.RaaaamiePayPopup=r,e.RaaamiePay=s,e.default=s,e.redirect=o,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
package/dist/types.d.ts CHANGED
@@ -23,6 +23,8 @@ export interface RaaaamiePayConfig {
23
23
  metadata?: Record<string, unknown>;
24
24
  /** Override the default success redirect URL */
25
25
  redirectUrl?: string;
26
+ /** Override the gateway base URL (for local development) */
27
+ gatewayUrl?: string;
26
28
  /** Callback when payment is successful */
27
29
  onSuccess?: (response: RaaaamiePayResponse) => void;
28
30
  /** Callback when customer closes the popup */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raaamie/pay",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "RaaamiePay JavaScript SDK — Accept payments via popup or redirect",
5
5
  "author": "RaaamiePay",
6
6
  "license": "MIT",
@@ -10,7 +10,9 @@
10
10
  "unpkg": "dist/raamiepay.min.js",
11
11
  "jsdelivr": "dist/raamiepay.min.js",
12
12
  "types": "dist/index.d.ts",
13
- "files": ["dist"],
13
+ "files": [
14
+ "dist"
15
+ ],
14
16
  "exports": {
15
17
  ".": {
16
18
  "import": "./dist/raamiepay.esm.js",
@@ -31,5 +33,13 @@
31
33
  "tslib": "^2.6.3",
32
34
  "typescript": "^5.6.3"
33
35
  },
34
- "keywords": ["payment", "fintech", "checkout", "mobile-money", "ghana", "africa", "sdk"]
36
+ "keywords": [
37
+ "payment",
38
+ "fintech",
39
+ "checkout",
40
+ "mobile-money",
41
+ "ghana",
42
+ "africa",
43
+ "sdk"
44
+ ]
35
45
  }