@crosspay-lb/js 0.1.0 → 0.2.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/README.md +9 -9
- package/dist/crosspay.min.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +103 -136
- package/dist/index.d.ts +103 -136
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,17 +10,17 @@ npm install @crosspay-lb/js
|
|
|
10
10
|
```ts
|
|
11
11
|
import { init } from '@crosspay-lb/js'
|
|
12
12
|
|
|
13
|
-
const cp = init({ environment: 'production' })
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
description: 'Orden 1001',
|
|
19
|
-
customer: { firstName: 'Ana', lastName: 'Díaz', email: 'ana@correo.com' },
|
|
20
|
-
})
|
|
13
|
+
const cp = init({ environment: 'production', publishableKey: 'pk_live_…' })
|
|
14
|
+
|
|
15
|
+
// clientSecret: lo crea TU servidor con @crosspay-lb/node (sessions.create)
|
|
16
|
+
const fields = await cp.card.mount({ container: '#card', clientSecret })
|
|
17
|
+
const result = await fields.pay()
|
|
21
18
|
```
|
|
22
19
|
|
|
23
|
-
O por CDN: `<script src="https://cdn.jsdelivr.net/npm/@crosspay-lb/js@0/dist/crosspay.min.js"></script>` → `window.Crosspay`.
|
|
20
|
+
O por CDN: `<script src="https://cdn.jsdelivr.net/npm/@crosspay-lb/js@0.2/dist/crosspay.min.js"></script>` → `window.Crosspay`.
|
|
21
|
+
|
|
22
|
+
Requisitos: llave pública del comercio, sitio en sus **dominios autorizados** y
|
|
23
|
+
una sesión de pago creada en el servidor con la llave secreta.
|
|
24
24
|
|
|
25
25
|
Documentación completa: panel de Crosspay → **Documentación de la API** → *crosspay.js*.
|
|
26
26
|
|
package/dist/crosspay.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var Crosspay=(()=>{var
|
|
1
|
+
"use strict";var Crosspay=(()=>{var v=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var z=(e,t)=>{for(var n in t)v(e,n,{get:t[n],enumerable:!0})},K=(e,t,n,p)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of N(t))!H.call(e,r)&&r!==n&&v(e,r,{get:()=>t[r],enumerable:!(p=q(t,r))||p.enumerable});return e};var Y=e=>K(v({},"__esModule",{value:!0}),e);var ee={};z(ee,{API_BASE_URLS:()=>f,CrosspayError:()=>a,init:()=>b,version:()=>$});var a=class extends Error{constructor(n,p,r){super(n);this.code=p;this.details=r;this.name="CrosspayError"}};var w="crosspay-fields/2";function I(e,t){return typeof e=="object"&&e!==null&&e.protocol===w&&e.channel===t&&typeof e.kind=="string"}function T(e){return new URLSearchParams({channel:e.channel,origin:e.parentOrigin}).toString()}var V=3e4,W={position:"fixed",inset:"0",width:"100%",height:"100%",zIndex:"2147483647"};function O(e,t,n){let p=typeof n.container=="string"?document.querySelector(n.container):n.container;if(!p)return Promise.reject(new a(`No existe el contenedor ${String(n.container)}.`,"INVALID_CONTAINER"));let r=new URL(e).origin,o=R(),i=document.createElement("div");i.style.position="relative";let s=document.createElement("iframe");s.src=`${e}#${T({channel:o,parentOrigin:window.location.origin})}`,s.title="Formulario seguro de tarjeta",s.setAttribute("scrolling","no"),s.setAttribute("allow","payment"),Object.assign(s.style,{display:"block",width:"100%",height:"0px",border:"0",background:"transparent",colorScheme:"normal"}),i.appendChild(s),p.replaceChildren(i);let l=0,d=new Map,u=m=>{s.contentWindow?.postMessage({...m,protocol:w,channel:o},r)},D=m=>{m?(i.style.height=`${l}px`,Object.assign(s.style,W)):(i.style.height="",Object.assign(s.style,{position:"",inset:"",width:"100%",height:`${l}px`,zIndex:""}))},h=!1,x=()=>{if(!h){h=!0,window.removeEventListener("message",k);for(let m of d.values())m.reject(new a("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));d.clear(),i.remove()}},y=null;function k(m){if(m.source!==s.contentWindow||m.origin!==r||!I(m.data,o))return;let c=m.data;switch(c.kind){case"ready":u({kind:"init",options:{publishableKey:t,clientSecret:n.clientSecret,installments:n.installments,labels:n.labels,styles:n.styles}});break;case"mounted":y?.(c.session);break;case"mount-error":y?.(new a(c.message,c.code));break;case"resize":l=Math.max(0,Math.ceil(c.height)),s.style.position!=="fixed"?s.style.height=`${l}px`:i.style.height=`${l}px`;break;case"validity":n.onValidityChange?.(c.valid);break;case"overlay":D(c.active);break;case"paid":{let g=d.get(c.requestId);d.delete(c.requestId),g?.resolve(c.result);break}case"pay-error":{let g=d.get(c.requestId);d.delete(c.requestId),g?.reject(new a(c.message,c.code));break}}}return window.addEventListener("message",k),new Promise((m,c)=>{let g=setTimeout(()=>{y?.(new a("No se pudo cargar el formulario de tarjeta.","FIELDS_TIMEOUT"))},V);y=S=>{if(y=null,clearTimeout(g),S instanceof a){x(),c(S);return}m({session:S,pay(){if(h)return Promise.reject(new a("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));let P=R();return new Promise((j,B)=>{d.set(P,{resolve:j,reject:B}),u({kind:"pay",requestId:P})})},destroy:x})}})}function R(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}var f={development:"https://api-dev.crosspaysolutions.financial",production:"https://api.crosspaysolutions.financial"};function F(e){let t=f[e];if(!t)throw new TypeError(`Ambiente de Crosspay no valido: "${String(e)}". Usa "development" o "production".`);return t}var C={development:"https://fields-dev.crosspaysolutions.financial/",production:"https://fields.crosspaysolutions.financial/"};function U(e){let t=(r,o)=>(e.fetch??globalThis.fetch)(r,o);async function n(r,o,i){let s={Accept:"application/json"};i!==void 0&&(s["Content-Type"]="application/json"),e.locale&&(s["Accept-Language"]=e.locale);let l;try{l=await t(`${e.baseUrl}${o}`,{method:r,headers:s,body:i===void 0?void 0:JSON.stringify(i),credentials:"omit"})}catch(u){throw new a("No se pudo conectar con Crosspay.","NETWORK_ERROR",u)}let d=await l.json().catch(()=>null);if(!l.ok||d?.success===!1){let u=d?.message||d?.error||`Crosspay respondio ${l.status}.`;throw new a(u,`HTTP_${l.status}`,d)}return d}async function p(r,o,i){let s=await n(r,o,i);return s&&typeof s=="object"&&"data"in s?s.data:s}return{get:r=>p("GET",r),post:(r,o)=>p("POST",r,o),postRaw:(r,o)=>n("POST",r,o)}}var _="cp_device_id";function G(){try{let e=localStorage.getItem(_);return e||(e=typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`,localStorage.setItem(_,e)),e}catch{return""}}function J(){return typeof navigator>"u"?"":[navigator.userAgent,navigator.language,typeof screen<"u"?`${screen.width}x${screen.height}`:"",E()].join("|")}function Q(e){let t=5381;for(let n=0;n<e.length;n+=1)t=(t<<5)+t+e.charCodeAt(n)|0;return(t>>>0).toString(16)}function E(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch{return""}}function L(){let e=G(),t=Q(J());return e?`${e}.${t}`:t}function X(){let e=typeof navigator<"u"?navigator.language?.split("-")[0]:void 0;return{fingerprint:L(),timezone:E(),...e?{language:e}:{}}}function M(e){return{status(t){return e.get(`/payments/status/${encodeURIComponent(t)}`)}}}function A(e,t){return{async listBanks(n="COP"){return(await e.get(`/payments/pse/banks?currency=${encodeURIComponent(n)}`)??[]).filter(r=>{let o=String(r.code??"").trim(),i=String(r.name??"").normalize("NFD").replace(/\p{Diacritic}/gu,"").toLowerCase();return o!==""&&o!=="0"&&!i.includes("seleccione su banco")})},async pay(n){let{clientSecret:p,...r}=n,o=await e.postRaw("/payments/sessions/pay",{publishableKey:t,clientSecret:p,parentOrigin:window.location.origin,method:"pse",pse:r,meta:X()}),{data:i,...s}=o??{},l=i?.sessionId;return{...s,...l?{sessionId:l}:{}}}}}var Z={development:"pk_test_",production:"pk_live_"};function b(e){let t=F(e.environment),n=String(e.publishableKey??"").trim(),p=Z[e.environment];if(!n.startsWith(p))throw new TypeError(`\`publishableKey\` debe empezar por "${p}" en el ambiente "${e.environment}".`);if(e.fieldsUrl&&e.environment!=="development")throw new TypeError('`fieldsUrl` solo se admite en el ambiente "development".');let r=e.fieldsUrl??C[e.environment],o=U({baseUrl:t,locale:e.locale,fetch:e.fetch});return{environment:e.environment,card:{async mount(i){if(!String(i.clientSecret??"").trim())throw new a("Falta `clientSecret`: crea la sesion de pago en tu servidor con @crosspay-lb/node.","INVALID_REQUEST");return O(r,n,i)}},payments:M(o),pse:A(o,n)}}var $="0.2.0";return Y(ee);})();
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var S=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var n in t)S(e,n,{get:t[n],enumerable:!0})},z=(e,t,n,p)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of q(t))!N.call(e,r)&&r!==n&&S(e,r,{get:()=>t[r],enumerable:!(p=B(t,r))||p.enumerable});return e};var K=e=>z(S({},"__esModule",{value:!0}),e);var ee={};H(ee,{API_BASE_URLS:()=>C,CrosspayError:()=>a,FIELDS_URLS:()=>f,init:()=>$,version:()=>Z});module.exports=K(ee);var a=class extends Error{constructor(n,p,r){super(n);this.code=p;this.details=r;this.name="CrosspayError"}};var w="crosspay-fields/2";function P(e,t){return typeof e=="object"&&e!==null&&e.protocol===w&&e.channel===t&&typeof e.kind=="string"}function T(e){return new URLSearchParams({channel:e.channel,origin:e.parentOrigin}).toString()}var Y=3e4,V={position:"fixed",inset:"0",width:"100%",height:"100%",zIndex:"2147483647"};function R(e,t,n){let p=typeof n.container=="string"?document.querySelector(n.container):n.container;if(!p)return Promise.reject(new a(`No existe el contenedor ${String(n.container)}.`,"INVALID_CONTAINER"));let r=new URL(e).origin,o=I(),i=document.createElement("div");i.style.position="relative";let s=document.createElement("iframe");s.src=`${e}#${T({channel:o,parentOrigin:window.location.origin})}`,s.title="Formulario seguro de tarjeta",s.setAttribute("scrolling","no"),s.setAttribute("allow","payment"),Object.assign(s.style,{display:"block",width:"100%",height:"0px",border:"0",background:"transparent",colorScheme:"normal"}),i.appendChild(s),p.replaceChildren(i);let l=0,d=new Map,u=m=>{s.contentWindow?.postMessage({...m,protocol:w,channel:o},r)},A=m=>{m?(i.style.height=`${l}px`,Object.assign(s.style,V)):(i.style.height="",Object.assign(s.style,{position:"",inset:"",width:"100%",height:`${l}px`,zIndex:""}))},h=!1,b=()=>{if(!h){h=!0,window.removeEventListener("message",x);for(let m of d.values())m.reject(new a("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));d.clear(),i.remove()}},y=null;function x(m){if(m.source!==s.contentWindow||m.origin!==r||!P(m.data,o))return;let c=m.data;switch(c.kind){case"ready":u({kind:"init",options:{publishableKey:t,clientSecret:n.clientSecret,installments:n.installments,labels:n.labels,styles:n.styles}});break;case"mounted":y?.(c.session);break;case"mount-error":y?.(new a(c.message,c.code));break;case"resize":l=Math.max(0,Math.ceil(c.height)),s.style.position!=="fixed"?s.style.height=`${l}px`:i.style.height=`${l}px`;break;case"validity":n.onValidityChange?.(c.valid);break;case"overlay":A(c.active);break;case"paid":{let g=d.get(c.requestId);d.delete(c.requestId),g?.resolve(c.result);break}case"pay-error":{let g=d.get(c.requestId);d.delete(c.requestId),g?.reject(new a(c.message,c.code));break}}}return window.addEventListener("message",x),new Promise((m,c)=>{let g=setTimeout(()=>{y?.(new a("No se pudo cargar el formulario de tarjeta.","FIELDS_TIMEOUT"))},Y);y=v=>{if(y=null,clearTimeout(g),v instanceof a){b(),c(v);return}m({session:v,pay(){if(h)return Promise.reject(new a("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));let k=I();return new Promise((D,j)=>{d.set(k,{resolve:D,reject:j}),u({kind:"pay",requestId:k})})},destroy:b})}})}function I(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}var C={development:"https://api-dev.crosspaysolutions.financial",production:"https://api.crosspaysolutions.financial"};function O(e){let t=C[e];if(!t)throw new TypeError(`Ambiente de Crosspay no valido: "${String(e)}". Usa "development" o "production".`);return t}var f={development:"https://fields-dev.crosspaysolutions.financial/",production:"https://fields.crosspaysolutions.financial/"};function F(e){let t=(r,o)=>(e.fetch??globalThis.fetch)(r,o);async function n(r,o,i){let s={Accept:"application/json"};i!==void 0&&(s["Content-Type"]="application/json"),e.locale&&(s["Accept-Language"]=e.locale);let l;try{l=await t(`${e.baseUrl}${o}`,{method:r,headers:s,body:i===void 0?void 0:JSON.stringify(i),credentials:"omit"})}catch(u){throw new a("No se pudo conectar con Crosspay.","NETWORK_ERROR",u)}let d=await l.json().catch(()=>null);if(!l.ok||d?.success===!1){let u=d?.message||d?.error||`Crosspay respondio ${l.status}.`;throw new a(u,`HTTP_${l.status}`,d)}return d}async function p(r,o,i){let s=await n(r,o,i);return s&&typeof s=="object"&&"data"in s?s.data:s}return{get:r=>p("GET",r),post:(r,o)=>p("POST",r,o),postRaw:(r,o)=>n("POST",r,o)}}var U="cp_device_id";function W(){try{let e=localStorage.getItem(U);return e||(e=typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`,localStorage.setItem(U,e)),e}catch{return""}}function G(){return typeof navigator>"u"?"":[navigator.userAgent,navigator.language,typeof screen<"u"?`${screen.width}x${screen.height}`:"",E()].join("|")}function J(e){let t=5381;for(let n=0;n<e.length;n+=1)t=(t<<5)+t+e.charCodeAt(n)|0;return(t>>>0).toString(16)}function E(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch{return""}}function L(){let e=W(),t=J(G());return e?`${e}.${t}`:t}function Q(){let e=typeof navigator<"u"?navigator.language?.split("-")[0]:void 0;return{fingerprint:L(),timezone:E(),...e?{language:e}:{}}}function M(e){return{status(t){return e.get(`/payments/status/${encodeURIComponent(t)}`)}}}function _(e,t){return{async listBanks(n="COP"){return(await e.get(`/payments/pse/banks?currency=${encodeURIComponent(n)}`)??[]).filter(r=>{let o=String(r.code??"").trim(),i=String(r.name??"").normalize("NFD").replace(/\p{Diacritic}/gu,"").toLowerCase();return o!==""&&o!=="0"&&!i.includes("seleccione su banco")})},async pay(n){let{clientSecret:p,...r}=n,o=await e.postRaw("/payments/sessions/pay",{publishableKey:t,clientSecret:p,parentOrigin:window.location.origin,method:"pse",pse:r,meta:Q()}),{data:i,...s}=o??{},l=i?.sessionId;return{...s,...l?{sessionId:l}:{}}}}}var X={development:"pk_test_",production:"pk_live_"};function $(e){let t=O(e.environment),n=String(e.publishableKey??"").trim(),p=X[e.environment];if(!n.startsWith(p))throw new TypeError(`\`publishableKey\` debe empezar por "${p}" en el ambiente "${e.environment}".`);if(e.fieldsUrl&&e.environment!=="development")throw new TypeError('`fieldsUrl` solo se admite en el ambiente "development".');let r=e.fieldsUrl??f[e.environment],o=F({baseUrl:t,locale:e.locale,fetch:e.fetch});return{environment:e.environment,card:{async mount(i){if(!String(i.clientSecret??"").trim())throw new a("Falta `clientSecret`: crea la sesion de pago en tu servidor con @crosspay-lb/node.","INVALID_REQUEST");return R(r,n,i)}},payments:M(o),pse:_(o,n)}}var Z="0.2.0";0&&(module.exports={API_BASE_URLS,CrosspayError,FIELDS_URLS,init,version});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,84 @@
|
|
|
1
|
+
interface HttpClientOptions {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
locale?: string;
|
|
4
|
+
fetch?: typeof fetch;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Cliente HTTP minimo sobre `fetch`.
|
|
8
|
+
*
|
|
9
|
+
* Desde el navegador NO se manda la llave secreta: el backend reconoce al
|
|
10
|
+
* comercio por su llave publica, el `Origin` de su dominio autorizado y la
|
|
11
|
+
* sesion que creo su servidor. La llave secreta solo va en `@crosspay-lb/node`.
|
|
12
|
+
*
|
|
13
|
+
* El backend responde `{ success, data }`; aqui se desenvuelve `data` y un
|
|
14
|
+
* `success: false` se convierte en `CrosspayError`.
|
|
15
|
+
*/
|
|
16
|
+
declare function createHttpClient(options: HttpClientOptions): {
|
|
17
|
+
get: <T>(path: string) => Promise<T>;
|
|
18
|
+
post: <T>(path: string, body: unknown) => Promise<T>;
|
|
19
|
+
/** Sin desenvolver: para respuestas planas como la del cobro. */
|
|
20
|
+
postRaw: (path: string, body: unknown) => Promise<{
|
|
21
|
+
success?: boolean;
|
|
22
|
+
data?: unknown;
|
|
23
|
+
message?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
} | null>;
|
|
26
|
+
};
|
|
27
|
+
type HttpClient = ReturnType<typeof createHttpClient>;
|
|
28
|
+
|
|
29
|
+
type PaymentStatus = 'approved' | 'pending' | 'declined' | 'failed' | 'cancelled' | 'refunded' | (string & {});
|
|
30
|
+
interface PaymentResult {
|
|
31
|
+
success: boolean;
|
|
32
|
+
status: PaymentStatus;
|
|
33
|
+
message?: string;
|
|
34
|
+
transactionId: string | null;
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
/** PSE: URL del banco a la que hay que llevar al pagador. */
|
|
37
|
+
redirectUrl?: string;
|
|
38
|
+
declineReason?: string | null;
|
|
39
|
+
amount?: number;
|
|
40
|
+
currency?: string;
|
|
41
|
+
reference?: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
interface Bank {
|
|
45
|
+
code: string;
|
|
46
|
+
name: string;
|
|
47
|
+
}
|
|
48
|
+
interface PsePayInput {
|
|
49
|
+
/** `clientSecret` de la sesion creada por el servidor del comercio. */
|
|
50
|
+
clientSecret: string;
|
|
51
|
+
/** Codigo del banco, de `pse.listBanks()`. */
|
|
52
|
+
bank: string;
|
|
53
|
+
documentType: string;
|
|
54
|
+
documentNumber: string;
|
|
55
|
+
/** `natural` o `juridica`. */
|
|
56
|
+
personType: string;
|
|
57
|
+
/** Direccion del pagador. Obligatoria para PSE. */
|
|
58
|
+
address?: string;
|
|
59
|
+
}
|
|
60
|
+
declare function createPaymentsApi(http: HttpClient): {
|
|
61
|
+
/** Estado publico de una transaccion (el mismo recurso del comprobante). */
|
|
62
|
+
status(transactionId: string): Promise<PaymentResult>;
|
|
63
|
+
};
|
|
64
|
+
declare function createPseApi(http: HttpClient, publishableKey: string): {
|
|
65
|
+
/** Bancos PSE (Colombia). Se quita la entrada guia "seleccione su banco". */
|
|
66
|
+
listBanks(currency?: string): Promise<Bank[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Inicia el pago PSE de la sesion. Devuelve `redirectUrl`: hay que llevar
|
|
69
|
+
* al pagador al banco. Monto y cliente salen de la sesion.
|
|
70
|
+
*/
|
|
71
|
+
pay(input: PsePayInput): Promise<PaymentResult>;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** Lo que la pagina de campos confirma de la sesion al montar. */
|
|
75
|
+
interface SessionSummary {
|
|
76
|
+
sessionId: string;
|
|
77
|
+
amount: number;
|
|
78
|
+
currency: string;
|
|
79
|
+
description: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
1
82
|
interface CardFieldLabels {
|
|
2
83
|
cardholderName?: string;
|
|
3
84
|
cardNumber?: string;
|
|
@@ -8,12 +89,12 @@ interface CardFieldLabels {
|
|
|
8
89
|
interface CardFieldsOptions {
|
|
9
90
|
/** Donde se inserta el formulario: un selector CSS o el elemento. */
|
|
10
91
|
container: string | HTMLElement;
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
92
|
+
/**
|
|
93
|
+
* `clientSecret` de la sesion de pago que creo el SERVIDOR del comercio con
|
|
94
|
+
* su llave secreta (`sessions.create` de @crosspay-lb/node). Monto, moneda y
|
|
95
|
+
* cliente salen de la sesion: el navegador no puede cambiarlos.
|
|
96
|
+
*/
|
|
97
|
+
clientSecret: string;
|
|
17
98
|
/** Muestra el selector de cuotas. */
|
|
18
99
|
installments?: boolean;
|
|
19
100
|
labels?: CardFieldLabels;
|
|
@@ -26,25 +107,15 @@ interface CardFieldsOptions {
|
|
|
26
107
|
/** Se dispara cada vez que cambia la validez del formulario. */
|
|
27
108
|
onValidityChange?: (isValid: boolean) => void;
|
|
28
109
|
}
|
|
29
|
-
/** Token de un solo uso. Nunca contiene el numero de tarjeta. */
|
|
30
|
-
interface CardToken {
|
|
31
|
-
token: string;
|
|
32
|
-
deferred?: {
|
|
33
|
-
months?: number;
|
|
34
|
-
creditType?: string;
|
|
35
|
-
graceMonths?: number;
|
|
36
|
-
};
|
|
37
|
-
bin?: string;
|
|
38
|
-
lastFourDigits?: string;
|
|
39
|
-
brand?: string;
|
|
40
|
-
}
|
|
41
110
|
interface MountedCardFields {
|
|
111
|
+
/** Monto, moneda y descripcion de la sesion que se va a pagar. */
|
|
112
|
+
readonly session: SessionSummary;
|
|
42
113
|
/**
|
|
43
|
-
*
|
|
44
|
-
* completa, asi que puede tardar. Lanza `CrosspayError` si la
|
|
45
|
-
* rechaza.
|
|
114
|
+
* Tokeniza y cobra la sesion. Puede abrir la verificacion 3DS del banco a
|
|
115
|
+
* pantalla completa, asi que puede tardar. Lanza `CrosspayError` si la
|
|
116
|
+
* tarjeta se rechaza o la sesion ya no se puede pagar.
|
|
46
117
|
*/
|
|
47
|
-
|
|
118
|
+
pay(): Promise<PaymentResult>;
|
|
48
119
|
/** Retira el formulario. */
|
|
49
120
|
destroy(): void;
|
|
50
121
|
}
|
|
@@ -66,115 +137,16 @@ declare const API_BASE_URLS: Record<CrosspayEnvironment, string>;
|
|
|
66
137
|
*/
|
|
67
138
|
declare const FIELDS_URLS: Record<CrosspayEnvironment, string>;
|
|
68
139
|
|
|
69
|
-
interface HttpClientOptions {
|
|
70
|
-
baseUrl: string;
|
|
71
|
-
/** Id publico de la empresa (20 digitos). Viaja como `X-Company-Id`. */
|
|
72
|
-
companyId?: string;
|
|
73
|
-
locale?: string;
|
|
74
|
-
fetch?: typeof fetch;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Cliente HTTP minimo sobre `fetch`.
|
|
78
|
-
*
|
|
79
|
-
* Desde el navegador NO se manda API key: el backend autentica por el `Origin`
|
|
80
|
-
* del sitio del comercio, que debe estar registrado en el CORS de su empresa.
|
|
81
|
-
* La API key de integracion es secreta y solo va en `@crosspay-lb/node`.
|
|
82
|
-
*
|
|
83
|
-
* El backend responde `{ success, data }`; aqui se desenvuelve `data` y un
|
|
84
|
-
* `success: false` se convierte en `CrosspayError`.
|
|
85
|
-
*/
|
|
86
|
-
declare function createHttpClient(options: HttpClientOptions): {
|
|
87
|
-
get: <T>(path: string) => Promise<T>;
|
|
88
|
-
post: <T>(path: string, body: unknown) => Promise<T>;
|
|
89
|
-
};
|
|
90
|
-
type HttpClient = ReturnType<typeof createHttpClient>;
|
|
91
|
-
|
|
92
|
-
interface Customer {
|
|
93
|
-
firstName: string;
|
|
94
|
-
lastName: string;
|
|
95
|
-
email: string;
|
|
96
|
-
phone?: string;
|
|
97
|
-
documentType?: string;
|
|
98
|
-
documentNumber?: string;
|
|
99
|
-
}
|
|
100
|
-
interface PseData {
|
|
101
|
-
/** Codigo del banco, de `pse.listBanks()`. */
|
|
102
|
-
bank: string;
|
|
103
|
-
documentType: string;
|
|
104
|
-
documentNumber: string;
|
|
105
|
-
/** `natural` o `juridica`. */
|
|
106
|
-
personType: string;
|
|
107
|
-
/** Direccion del pagador. Obligatoria para PSE. */
|
|
108
|
-
address?: string;
|
|
109
|
-
}
|
|
110
|
-
interface BasePaymentInput {
|
|
111
|
-
amount: number;
|
|
112
|
-
currency: string;
|
|
113
|
-
description: string;
|
|
114
|
-
/** Referencia del comercio (numero de orden, factura…). */
|
|
115
|
-
reference?: string;
|
|
116
|
-
customer: Customer;
|
|
117
|
-
/** A donde vuelve el pagador cuando el medio lo saca de la pagina (PSE, 3DS). */
|
|
118
|
-
returnUrl?: string;
|
|
119
|
-
/** Datos libres del comercio. Viajan en `meta`. */
|
|
120
|
-
metadata?: Record<string, unknown>;
|
|
121
|
-
}
|
|
122
|
-
interface CardPaymentInput extends BasePaymentInput {
|
|
123
|
-
method: 'card';
|
|
124
|
-
cardToken: CardToken;
|
|
125
|
-
}
|
|
126
|
-
interface PsePaymentInput extends BasePaymentInput {
|
|
127
|
-
method: 'pse';
|
|
128
|
-
pse: PseData;
|
|
129
|
-
}
|
|
130
|
-
type PaymentInput = CardPaymentInput | PsePaymentInput;
|
|
131
|
-
type PaymentStatus = 'approved' | 'pending' | 'declined' | 'failed' | 'cancelled' | 'refunded' | (string & {});
|
|
132
|
-
interface PaymentResult {
|
|
133
|
-
success: boolean;
|
|
134
|
-
status: PaymentStatus;
|
|
135
|
-
message?: string;
|
|
136
|
-
transactionId: string | null;
|
|
137
|
-
gatewayTransactionId?: string | null;
|
|
138
|
-
/** PSE: URL del banco a la que hay que llevar al pagador. */
|
|
139
|
-
redirectUrl?: string;
|
|
140
|
-
declineReason?: string | null;
|
|
141
|
-
amount?: number;
|
|
142
|
-
currency?: string;
|
|
143
|
-
reference?: string;
|
|
144
|
-
[key: string]: unknown;
|
|
145
|
-
}
|
|
146
|
-
interface Bank {
|
|
147
|
-
code: string;
|
|
148
|
-
name: string;
|
|
149
|
-
}
|
|
150
|
-
declare function createPaymentsApi(http: HttpClient): {
|
|
151
|
-
/** Crea el cobro. Para tarjeta, el `cardToken` sale de `card.tokenize()`. */
|
|
152
|
-
create(input: PaymentInput): Promise<PaymentResult>;
|
|
153
|
-
/**
|
|
154
|
-
* Registra un rechazo en la tokenizacion como transaccion declinada, para
|
|
155
|
-
* trazabilidad. No cobra nada ni lleva datos de tarjeta.
|
|
156
|
-
*/
|
|
157
|
-
reportTokenizationDecline(input: Omit<CardPaymentInput, "cardToken">, decline: {
|
|
158
|
-
code?: string;
|
|
159
|
-
message?: string;
|
|
160
|
-
}): Promise<PaymentResult>;
|
|
161
|
-
/** Estado publico de una transaccion (el mismo recurso del comprobante). */
|
|
162
|
-
status(transactionId: string): Promise<PaymentResult>;
|
|
163
|
-
};
|
|
164
|
-
declare function createPseApi(http: HttpClient): {
|
|
165
|
-
/** Bancos PSE (Colombia). Se quita la entrada guia "seleccione su banco". */
|
|
166
|
-
listBanks(currency?: string): Promise<Bank[]>;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
140
|
interface CrosspayOptions {
|
|
170
141
|
/** `development` → api-dev.crosspaysolutions.financial · `production` → api.crosspaysolutions.financial */
|
|
171
142
|
environment: CrosspayEnvironment;
|
|
172
143
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* del
|
|
144
|
+
* Llave publica del comercio (panel → Integracion). `pk_test_…` en
|
|
145
|
+
* development, `pk_live_…` en production. Es publica por diseno: solo
|
|
146
|
+
* funciona desde los dominios autorizados del comercio y con una sesion
|
|
147
|
+
* creada por su servidor.
|
|
176
148
|
*/
|
|
177
|
-
|
|
149
|
+
publishableKey: string;
|
|
178
150
|
/** Idioma de los correos al pagador (`es`, `en`…). */
|
|
179
151
|
locale?: string;
|
|
180
152
|
/** Para pruebas. Por defecto, el `fetch` del navegador. */
|
|
@@ -190,18 +162,13 @@ interface Crosspay {
|
|
|
190
162
|
readonly environment: CrosspayEnvironment;
|
|
191
163
|
card: {
|
|
192
164
|
/**
|
|
193
|
-
* Monta el formulario seguro de tarjeta en `options.container
|
|
194
|
-
* con `
|
|
165
|
+
* Monta el formulario seguro de tarjeta en `options.container` para la
|
|
166
|
+
* sesion `options.clientSecret`. Rechaza con `CrosspayError` si la llave,
|
|
167
|
+
* la sesion o el dominio no son validos.
|
|
195
168
|
*/
|
|
196
169
|
mount(options: CardFieldsOptions): Promise<MountedCardFields>;
|
|
197
170
|
};
|
|
198
|
-
payments: ReturnType<typeof createPaymentsApi
|
|
199
|
-
/**
|
|
200
|
-
* Atajo: tokeniza y cobra. Si la tarjeta se rechaza al tokenizar, deja
|
|
201
|
-
* registrada la transaccion declinada y relanza el `CrosspayError`.
|
|
202
|
-
*/
|
|
203
|
-
payWithCard(fields: MountedCardFields, input: Omit<CardPaymentInput, 'cardToken' | 'method'>): Promise<PaymentResult>;
|
|
204
|
-
};
|
|
171
|
+
payments: ReturnType<typeof createPaymentsApi>;
|
|
205
172
|
pse: ReturnType<typeof createPseApi>;
|
|
206
173
|
}
|
|
207
174
|
declare function init(options: CrosspayOptions): Crosspay;
|
|
@@ -222,4 +189,4 @@ declare class CrosspayError extends Error {
|
|
|
222
189
|
/** Version de la libreria, inyectada en el build. */
|
|
223
190
|
declare const version: string;
|
|
224
191
|
|
|
225
|
-
export { API_BASE_URLS, type Bank, type CardFieldLabels, type CardFieldsOptions, type
|
|
192
|
+
export { API_BASE_URLS, type Bank, type CardFieldLabels, type CardFieldsOptions, type Crosspay, type CrosspayEnvironment, CrosspayError, type CrosspayOptions, FIELDS_URLS, type MountedCardFields, type PaymentResult, type PaymentStatus, type PsePayInput, type SessionSummary, init, version };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,84 @@
|
|
|
1
|
+
interface HttpClientOptions {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
locale?: string;
|
|
4
|
+
fetch?: typeof fetch;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Cliente HTTP minimo sobre `fetch`.
|
|
8
|
+
*
|
|
9
|
+
* Desde el navegador NO se manda la llave secreta: el backend reconoce al
|
|
10
|
+
* comercio por su llave publica, el `Origin` de su dominio autorizado y la
|
|
11
|
+
* sesion que creo su servidor. La llave secreta solo va en `@crosspay-lb/node`.
|
|
12
|
+
*
|
|
13
|
+
* El backend responde `{ success, data }`; aqui se desenvuelve `data` y un
|
|
14
|
+
* `success: false` se convierte en `CrosspayError`.
|
|
15
|
+
*/
|
|
16
|
+
declare function createHttpClient(options: HttpClientOptions): {
|
|
17
|
+
get: <T>(path: string) => Promise<T>;
|
|
18
|
+
post: <T>(path: string, body: unknown) => Promise<T>;
|
|
19
|
+
/** Sin desenvolver: para respuestas planas como la del cobro. */
|
|
20
|
+
postRaw: (path: string, body: unknown) => Promise<{
|
|
21
|
+
success?: boolean;
|
|
22
|
+
data?: unknown;
|
|
23
|
+
message?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
} | null>;
|
|
26
|
+
};
|
|
27
|
+
type HttpClient = ReturnType<typeof createHttpClient>;
|
|
28
|
+
|
|
29
|
+
type PaymentStatus = 'approved' | 'pending' | 'declined' | 'failed' | 'cancelled' | 'refunded' | (string & {});
|
|
30
|
+
interface PaymentResult {
|
|
31
|
+
success: boolean;
|
|
32
|
+
status: PaymentStatus;
|
|
33
|
+
message?: string;
|
|
34
|
+
transactionId: string | null;
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
/** PSE: URL del banco a la que hay que llevar al pagador. */
|
|
37
|
+
redirectUrl?: string;
|
|
38
|
+
declineReason?: string | null;
|
|
39
|
+
amount?: number;
|
|
40
|
+
currency?: string;
|
|
41
|
+
reference?: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
interface Bank {
|
|
45
|
+
code: string;
|
|
46
|
+
name: string;
|
|
47
|
+
}
|
|
48
|
+
interface PsePayInput {
|
|
49
|
+
/** `clientSecret` de la sesion creada por el servidor del comercio. */
|
|
50
|
+
clientSecret: string;
|
|
51
|
+
/** Codigo del banco, de `pse.listBanks()`. */
|
|
52
|
+
bank: string;
|
|
53
|
+
documentType: string;
|
|
54
|
+
documentNumber: string;
|
|
55
|
+
/** `natural` o `juridica`. */
|
|
56
|
+
personType: string;
|
|
57
|
+
/** Direccion del pagador. Obligatoria para PSE. */
|
|
58
|
+
address?: string;
|
|
59
|
+
}
|
|
60
|
+
declare function createPaymentsApi(http: HttpClient): {
|
|
61
|
+
/** Estado publico de una transaccion (el mismo recurso del comprobante). */
|
|
62
|
+
status(transactionId: string): Promise<PaymentResult>;
|
|
63
|
+
};
|
|
64
|
+
declare function createPseApi(http: HttpClient, publishableKey: string): {
|
|
65
|
+
/** Bancos PSE (Colombia). Se quita la entrada guia "seleccione su banco". */
|
|
66
|
+
listBanks(currency?: string): Promise<Bank[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Inicia el pago PSE de la sesion. Devuelve `redirectUrl`: hay que llevar
|
|
69
|
+
* al pagador al banco. Monto y cliente salen de la sesion.
|
|
70
|
+
*/
|
|
71
|
+
pay(input: PsePayInput): Promise<PaymentResult>;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** Lo que la pagina de campos confirma de la sesion al montar. */
|
|
75
|
+
interface SessionSummary {
|
|
76
|
+
sessionId: string;
|
|
77
|
+
amount: number;
|
|
78
|
+
currency: string;
|
|
79
|
+
description: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
1
82
|
interface CardFieldLabels {
|
|
2
83
|
cardholderName?: string;
|
|
3
84
|
cardNumber?: string;
|
|
@@ -8,12 +89,12 @@ interface CardFieldLabels {
|
|
|
8
89
|
interface CardFieldsOptions {
|
|
9
90
|
/** Donde se inserta el formulario: un selector CSS o el elemento. */
|
|
10
91
|
container: string | HTMLElement;
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
92
|
+
/**
|
|
93
|
+
* `clientSecret` de la sesion de pago que creo el SERVIDOR del comercio con
|
|
94
|
+
* su llave secreta (`sessions.create` de @crosspay-lb/node). Monto, moneda y
|
|
95
|
+
* cliente salen de la sesion: el navegador no puede cambiarlos.
|
|
96
|
+
*/
|
|
97
|
+
clientSecret: string;
|
|
17
98
|
/** Muestra el selector de cuotas. */
|
|
18
99
|
installments?: boolean;
|
|
19
100
|
labels?: CardFieldLabels;
|
|
@@ -26,25 +107,15 @@ interface CardFieldsOptions {
|
|
|
26
107
|
/** Se dispara cada vez que cambia la validez del formulario. */
|
|
27
108
|
onValidityChange?: (isValid: boolean) => void;
|
|
28
109
|
}
|
|
29
|
-
/** Token de un solo uso. Nunca contiene el numero de tarjeta. */
|
|
30
|
-
interface CardToken {
|
|
31
|
-
token: string;
|
|
32
|
-
deferred?: {
|
|
33
|
-
months?: number;
|
|
34
|
-
creditType?: string;
|
|
35
|
-
graceMonths?: number;
|
|
36
|
-
};
|
|
37
|
-
bin?: string;
|
|
38
|
-
lastFourDigits?: string;
|
|
39
|
-
brand?: string;
|
|
40
|
-
}
|
|
41
110
|
interface MountedCardFields {
|
|
111
|
+
/** Monto, moneda y descripcion de la sesion que se va a pagar. */
|
|
112
|
+
readonly session: SessionSummary;
|
|
42
113
|
/**
|
|
43
|
-
*
|
|
44
|
-
* completa, asi que puede tardar. Lanza `CrosspayError` si la
|
|
45
|
-
* rechaza.
|
|
114
|
+
* Tokeniza y cobra la sesion. Puede abrir la verificacion 3DS del banco a
|
|
115
|
+
* pantalla completa, asi que puede tardar. Lanza `CrosspayError` si la
|
|
116
|
+
* tarjeta se rechaza o la sesion ya no se puede pagar.
|
|
46
117
|
*/
|
|
47
|
-
|
|
118
|
+
pay(): Promise<PaymentResult>;
|
|
48
119
|
/** Retira el formulario. */
|
|
49
120
|
destroy(): void;
|
|
50
121
|
}
|
|
@@ -66,115 +137,16 @@ declare const API_BASE_URLS: Record<CrosspayEnvironment, string>;
|
|
|
66
137
|
*/
|
|
67
138
|
declare const FIELDS_URLS: Record<CrosspayEnvironment, string>;
|
|
68
139
|
|
|
69
|
-
interface HttpClientOptions {
|
|
70
|
-
baseUrl: string;
|
|
71
|
-
/** Id publico de la empresa (20 digitos). Viaja como `X-Company-Id`. */
|
|
72
|
-
companyId?: string;
|
|
73
|
-
locale?: string;
|
|
74
|
-
fetch?: typeof fetch;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Cliente HTTP minimo sobre `fetch`.
|
|
78
|
-
*
|
|
79
|
-
* Desde el navegador NO se manda API key: el backend autentica por el `Origin`
|
|
80
|
-
* del sitio del comercio, que debe estar registrado en el CORS de su empresa.
|
|
81
|
-
* La API key de integracion es secreta y solo va en `@crosspay-lb/node`.
|
|
82
|
-
*
|
|
83
|
-
* El backend responde `{ success, data }`; aqui se desenvuelve `data` y un
|
|
84
|
-
* `success: false` se convierte en `CrosspayError`.
|
|
85
|
-
*/
|
|
86
|
-
declare function createHttpClient(options: HttpClientOptions): {
|
|
87
|
-
get: <T>(path: string) => Promise<T>;
|
|
88
|
-
post: <T>(path: string, body: unknown) => Promise<T>;
|
|
89
|
-
};
|
|
90
|
-
type HttpClient = ReturnType<typeof createHttpClient>;
|
|
91
|
-
|
|
92
|
-
interface Customer {
|
|
93
|
-
firstName: string;
|
|
94
|
-
lastName: string;
|
|
95
|
-
email: string;
|
|
96
|
-
phone?: string;
|
|
97
|
-
documentType?: string;
|
|
98
|
-
documentNumber?: string;
|
|
99
|
-
}
|
|
100
|
-
interface PseData {
|
|
101
|
-
/** Codigo del banco, de `pse.listBanks()`. */
|
|
102
|
-
bank: string;
|
|
103
|
-
documentType: string;
|
|
104
|
-
documentNumber: string;
|
|
105
|
-
/** `natural` o `juridica`. */
|
|
106
|
-
personType: string;
|
|
107
|
-
/** Direccion del pagador. Obligatoria para PSE. */
|
|
108
|
-
address?: string;
|
|
109
|
-
}
|
|
110
|
-
interface BasePaymentInput {
|
|
111
|
-
amount: number;
|
|
112
|
-
currency: string;
|
|
113
|
-
description: string;
|
|
114
|
-
/** Referencia del comercio (numero de orden, factura…). */
|
|
115
|
-
reference?: string;
|
|
116
|
-
customer: Customer;
|
|
117
|
-
/** A donde vuelve el pagador cuando el medio lo saca de la pagina (PSE, 3DS). */
|
|
118
|
-
returnUrl?: string;
|
|
119
|
-
/** Datos libres del comercio. Viajan en `meta`. */
|
|
120
|
-
metadata?: Record<string, unknown>;
|
|
121
|
-
}
|
|
122
|
-
interface CardPaymentInput extends BasePaymentInput {
|
|
123
|
-
method: 'card';
|
|
124
|
-
cardToken: CardToken;
|
|
125
|
-
}
|
|
126
|
-
interface PsePaymentInput extends BasePaymentInput {
|
|
127
|
-
method: 'pse';
|
|
128
|
-
pse: PseData;
|
|
129
|
-
}
|
|
130
|
-
type PaymentInput = CardPaymentInput | PsePaymentInput;
|
|
131
|
-
type PaymentStatus = 'approved' | 'pending' | 'declined' | 'failed' | 'cancelled' | 'refunded' | (string & {});
|
|
132
|
-
interface PaymentResult {
|
|
133
|
-
success: boolean;
|
|
134
|
-
status: PaymentStatus;
|
|
135
|
-
message?: string;
|
|
136
|
-
transactionId: string | null;
|
|
137
|
-
gatewayTransactionId?: string | null;
|
|
138
|
-
/** PSE: URL del banco a la que hay que llevar al pagador. */
|
|
139
|
-
redirectUrl?: string;
|
|
140
|
-
declineReason?: string | null;
|
|
141
|
-
amount?: number;
|
|
142
|
-
currency?: string;
|
|
143
|
-
reference?: string;
|
|
144
|
-
[key: string]: unknown;
|
|
145
|
-
}
|
|
146
|
-
interface Bank {
|
|
147
|
-
code: string;
|
|
148
|
-
name: string;
|
|
149
|
-
}
|
|
150
|
-
declare function createPaymentsApi(http: HttpClient): {
|
|
151
|
-
/** Crea el cobro. Para tarjeta, el `cardToken` sale de `card.tokenize()`. */
|
|
152
|
-
create(input: PaymentInput): Promise<PaymentResult>;
|
|
153
|
-
/**
|
|
154
|
-
* Registra un rechazo en la tokenizacion como transaccion declinada, para
|
|
155
|
-
* trazabilidad. No cobra nada ni lleva datos de tarjeta.
|
|
156
|
-
*/
|
|
157
|
-
reportTokenizationDecline(input: Omit<CardPaymentInput, "cardToken">, decline: {
|
|
158
|
-
code?: string;
|
|
159
|
-
message?: string;
|
|
160
|
-
}): Promise<PaymentResult>;
|
|
161
|
-
/** Estado publico de una transaccion (el mismo recurso del comprobante). */
|
|
162
|
-
status(transactionId: string): Promise<PaymentResult>;
|
|
163
|
-
};
|
|
164
|
-
declare function createPseApi(http: HttpClient): {
|
|
165
|
-
/** Bancos PSE (Colombia). Se quita la entrada guia "seleccione su banco". */
|
|
166
|
-
listBanks(currency?: string): Promise<Bank[]>;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
140
|
interface CrosspayOptions {
|
|
170
141
|
/** `development` → api-dev.crosspaysolutions.financial · `production` → api.crosspaysolutions.financial */
|
|
171
142
|
environment: CrosspayEnvironment;
|
|
172
143
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* del
|
|
144
|
+
* Llave publica del comercio (panel → Integracion). `pk_test_…` en
|
|
145
|
+
* development, `pk_live_…` en production. Es publica por diseno: solo
|
|
146
|
+
* funciona desde los dominios autorizados del comercio y con una sesion
|
|
147
|
+
* creada por su servidor.
|
|
176
148
|
*/
|
|
177
|
-
|
|
149
|
+
publishableKey: string;
|
|
178
150
|
/** Idioma de los correos al pagador (`es`, `en`…). */
|
|
179
151
|
locale?: string;
|
|
180
152
|
/** Para pruebas. Por defecto, el `fetch` del navegador. */
|
|
@@ -190,18 +162,13 @@ interface Crosspay {
|
|
|
190
162
|
readonly environment: CrosspayEnvironment;
|
|
191
163
|
card: {
|
|
192
164
|
/**
|
|
193
|
-
* Monta el formulario seguro de tarjeta en `options.container
|
|
194
|
-
* con `
|
|
165
|
+
* Monta el formulario seguro de tarjeta en `options.container` para la
|
|
166
|
+
* sesion `options.clientSecret`. Rechaza con `CrosspayError` si la llave,
|
|
167
|
+
* la sesion o el dominio no son validos.
|
|
195
168
|
*/
|
|
196
169
|
mount(options: CardFieldsOptions): Promise<MountedCardFields>;
|
|
197
170
|
};
|
|
198
|
-
payments: ReturnType<typeof createPaymentsApi
|
|
199
|
-
/**
|
|
200
|
-
* Atajo: tokeniza y cobra. Si la tarjeta se rechaza al tokenizar, deja
|
|
201
|
-
* registrada la transaccion declinada y relanza el `CrosspayError`.
|
|
202
|
-
*/
|
|
203
|
-
payWithCard(fields: MountedCardFields, input: Omit<CardPaymentInput, 'cardToken' | 'method'>): Promise<PaymentResult>;
|
|
204
|
-
};
|
|
171
|
+
payments: ReturnType<typeof createPaymentsApi>;
|
|
205
172
|
pse: ReturnType<typeof createPseApi>;
|
|
206
173
|
}
|
|
207
174
|
declare function init(options: CrosspayOptions): Crosspay;
|
|
@@ -222,4 +189,4 @@ declare class CrosspayError extends Error {
|
|
|
222
189
|
/** Version de la libreria, inyectada en el build. */
|
|
223
190
|
declare const version: string;
|
|
224
191
|
|
|
225
|
-
export { API_BASE_URLS, type Bank, type CardFieldLabels, type CardFieldsOptions, type
|
|
192
|
+
export { API_BASE_URLS, type Bank, type CardFieldLabels, type CardFieldsOptions, type Crosspay, type CrosspayEnvironment, CrosspayError, type CrosspayOptions, FIELDS_URLS, type MountedCardFields, type PaymentResult, type PaymentStatus, type PsePayInput, type SessionSummary, init, version };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var c=class extends Error{constructor(t,d,s){super(t);this.code=d;this.details=s;this.name="CrosspayError"}};var v="crosspay-fields/2";function x(e,r){return typeof e=="object"&&e!==null&&e.protocol===v&&e.channel===r&&typeof e.kind=="string"}function k(e){return new URLSearchParams({channel:e.channel,origin:e.parentOrigin}).toString()}var D=3e4,j={position:"fixed",inset:"0",width:"100%",height:"100%",zIndex:"2147483647"};function T(e,r,t){let d=typeof t.container=="string"?document.querySelector(t.container):t.container;if(!d)return Promise.reject(new c(`No existe el contenedor ${String(t.container)}.`,"INVALID_CONTAINER"));let s=new URL(e).origin,o=P(),i=document.createElement("div");i.style.position="relative";let n=document.createElement("iframe");n.src=`${e}#${k({channel:o,parentOrigin:window.location.origin})}`,n.title="Formulario seguro de tarjeta",n.setAttribute("scrolling","no"),n.setAttribute("allow","payment"),Object.assign(n.style,{display:"block",width:"100%",height:"0px",border:"0",background:"transparent",colorScheme:"normal"}),i.appendChild(n),d.replaceChildren(i);let p=0,l=new Map,u=m=>{n.contentWindow?.postMessage({...m,protocol:v,channel:o},s)},_=m=>{m?(i.style.height=`${p}px`,Object.assign(n.style,j)):(i.style.height="",Object.assign(n.style,{position:"",inset:"",width:"100%",height:`${p}px`,zIndex:""}))},f=!1,C=()=>{if(!f){f=!0,window.removeEventListener("message",E);for(let m of l.values())m.reject(new c("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));l.clear(),i.remove()}},y=null;function E(m){if(m.source!==n.contentWindow||m.origin!==s||!x(m.data,o))return;let a=m.data;switch(a.kind){case"ready":u({kind:"init",options:{publishableKey:r,clientSecret:t.clientSecret,installments:t.installments,labels:t.labels,styles:t.styles}});break;case"mounted":y?.(a.session);break;case"mount-error":y?.(new c(a.message,a.code));break;case"resize":p=Math.max(0,Math.ceil(a.height)),n.style.position!=="fixed"?n.style.height=`${p}px`:i.style.height=`${p}px`;break;case"validity":t.onValidityChange?.(a.valid);break;case"overlay":_(a.active);break;case"paid":{let g=l.get(a.requestId);l.delete(a.requestId),g?.resolve(a.result);break}case"pay-error":{let g=l.get(a.requestId);l.delete(a.requestId),g?.reject(new c(a.message,a.code));break}}}return window.addEventListener("message",E),new Promise((m,a)=>{let g=setTimeout(()=>{y?.(new c("No se pudo cargar el formulario de tarjeta.","FIELDS_TIMEOUT"))},D);y=h=>{if(y=null,clearTimeout(g),h instanceof c){C(),a(h);return}m({session:h,pay(){if(f)return Promise.reject(new c("El formulario de tarjeta se retiro.","FIELDS_DESTROYED"));let b=P();return new Promise(($,A)=>{l.set(b,{resolve:$,reject:A}),u({kind:"pay",requestId:b})})},destroy:C})}})}function P(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}var I={development:"https://api-dev.crosspaysolutions.financial",production:"https://api.crosspaysolutions.financial"};function R(e){let r=I[e];if(!r)throw new TypeError(`Ambiente de Crosspay no valido: "${String(e)}". Usa "development" o "production".`);return r}var S={development:"https://fields-dev.crosspaysolutions.financial/",production:"https://fields.crosspaysolutions.financial/"};function O(e){let r=(s,o)=>(e.fetch??globalThis.fetch)(s,o);async function t(s,o,i){let n={Accept:"application/json"};i!==void 0&&(n["Content-Type"]="application/json"),e.locale&&(n["Accept-Language"]=e.locale);let p;try{p=await r(`${e.baseUrl}${o}`,{method:s,headers:n,body:i===void 0?void 0:JSON.stringify(i),credentials:"omit"})}catch(u){throw new c("No se pudo conectar con Crosspay.","NETWORK_ERROR",u)}let l=await p.json().catch(()=>null);if(!p.ok||l?.success===!1){let u=l?.message||l?.error||`Crosspay respondio ${p.status}.`;throw new c(u,`HTTP_${p.status}`,l)}return l}async function d(s,o,i){let n=await t(s,o,i);return n&&typeof n=="object"&&"data"in n?n.data:n}return{get:s=>d("GET",s),post:(s,o)=>d("POST",s,o),postRaw:(s,o)=>t("POST",s,o)}}var F="cp_device_id";function B(){try{let e=localStorage.getItem(F);return e||(e=typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`,localStorage.setItem(F,e)),e}catch{return""}}function q(){return typeof navigator>"u"?"":[navigator.userAgent,navigator.language,typeof screen<"u"?`${screen.width}x${screen.height}`:"",w()].join("|")}function N(e){let r=5381;for(let t=0;t<e.length;t+=1)r=(r<<5)+r+e.charCodeAt(t)|0;return(r>>>0).toString(16)}function w(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch{return""}}function U(){let e=B(),r=N(q());return e?`${e}.${r}`:r}function H(){let e=typeof navigator<"u"?navigator.language?.split("-")[0]:void 0;return{fingerprint:U(),timezone:w(),...e?{language:e}:{}}}function L(e){return{status(r){return e.get(`/payments/status/${encodeURIComponent(r)}`)}}}function M(e,r){return{async listBanks(t="COP"){return(await e.get(`/payments/pse/banks?currency=${encodeURIComponent(t)}`)??[]).filter(s=>{let o=String(s.code??"").trim(),i=String(s.name??"").normalize("NFD").replace(/\p{Diacritic}/gu,"").toLowerCase();return o!==""&&o!=="0"&&!i.includes("seleccione su banco")})},async pay(t){let{clientSecret:d,...s}=t,o=await e.postRaw("/payments/sessions/pay",{publishableKey:r,clientSecret:d,parentOrigin:window.location.origin,method:"pse",pse:s,meta:H()}),{data:i,...n}=o??{},p=i?.sessionId;return{...n,...p?{sessionId:p}:{}}}}}var z={development:"pk_test_",production:"pk_live_"};function K(e){let r=R(e.environment),t=String(e.publishableKey??"").trim(),d=z[e.environment];if(!t.startsWith(d))throw new TypeError(`\`publishableKey\` debe empezar por "${d}" en el ambiente "${e.environment}".`);if(e.fieldsUrl&&e.environment!=="development")throw new TypeError('`fieldsUrl` solo se admite en el ambiente "development".');let s=e.fieldsUrl??S[e.environment],o=O({baseUrl:r,locale:e.locale,fetch:e.fetch});return{environment:e.environment,card:{async mount(i){if(!String(i.clientSecret??"").trim())throw new c("Falta `clientSecret`: crea la sesion de pago en tu servidor con @crosspay-lb/node.","INVALID_REQUEST");return T(s,t,i)}},payments:L(o),pse:M(o,t)}}var pe="0.2.0";export{I as API_BASE_URLS,c as CrosspayError,S as FIELDS_URLS,K as init,pe as version};
|
package/package.json
CHANGED