pi-spi-sdk 0.1.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.
Files changed (208) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +22 -0
  3. package/README.md +300 -0
  4. package/dist/config.d.ts +35 -0
  5. package/dist/config.js +4 -0
  6. package/dist/error-handler.d.ts +7 -0
  7. package/dist/error-handler.js +52 -0
  8. package/dist/errors.d.ts +25 -0
  9. package/dist/errors.js +40 -0
  10. package/dist/examples.d.ts +8 -0
  11. package/dist/examples.js +91 -0
  12. package/dist/generated/core/ApiError.d.ts +10 -0
  13. package/dist/generated/core/ApiError.js +11 -0
  14. package/dist/generated/core/ApiRequestOptions.d.ts +13 -0
  15. package/dist/generated/core/ApiRequestOptions.js +1 -0
  16. package/dist/generated/core/ApiResult.d.ts +7 -0
  17. package/dist/generated/core/ApiResult.js +1 -0
  18. package/dist/generated/core/CancelablePromise.d.ts +20 -0
  19. package/dist/generated/core/CancelablePromise.js +111 -0
  20. package/dist/generated/core/OpenAPI.d.ts +16 -0
  21. package/dist/generated/core/OpenAPI.js +11 -0
  22. package/dist/generated/core/request.d.ts +34 -0
  23. package/dist/generated/core/request.js +269 -0
  24. package/dist/generated/index.d.ts +78 -0
  25. package/dist/generated/index.js +43 -0
  26. package/dist/generated/models/AliasCreationReponse.d.ts +22 -0
  27. package/dist/generated/models/AliasCreationReponse.js +1 -0
  28. package/dist/generated/models/AliasCreationRequest.d.ts +11 -0
  29. package/dist/generated/models/AliasCreationRequest.js +1 -0
  30. package/dist/generated/models/AliasReponseListe.d.ts +26 -0
  31. package/dist/generated/models/AliasReponseListe.js +1 -0
  32. package/dist/generated/models/AnnulationStatut.d.ts +13 -0
  33. package/dist/generated/models/AnnulationStatut.js +18 -0
  34. package/dist/generated/models/Champs.d.ts +1 -0
  35. package/dist/generated/models/Champs.js +1 -0
  36. package/dist/generated/models/CompteOperation.d.ts +72 -0
  37. package/dist/generated/models/CompteOperation.js +24 -0
  38. package/dist/generated/models/CompteOperationListe.d.ts +18 -0
  39. package/dist/generated/models/CompteOperationListe.js +1 -0
  40. package/dist/generated/models/CompteSolde.d.ts +129 -0
  41. package/dist/generated/models/CompteSolde.js +71 -0
  42. package/dist/generated/models/CompteTransfertIntraReponse.d.ts +33 -0
  43. package/dist/generated/models/CompteTransfertIntraReponse.js +12 -0
  44. package/dist/generated/models/CompteTransfertIntraRequest.d.ts +9 -0
  45. package/dist/generated/models/CompteTransfertIntraRequest.js +1 -0
  46. package/dist/generated/models/DemandePaiementConfirmationAnnulationRaison.d.ts +14 -0
  47. package/dist/generated/models/DemandePaiementConfirmationAnnulationRaison.js +19 -0
  48. package/dist/generated/models/DemandePaiementConfirmationReponse.d.ts +41 -0
  49. package/dist/generated/models/DemandePaiementConfirmationReponse.js +13 -0
  50. package/dist/generated/models/DemandePaiementConfirmationRequest.d.ts +3 -0
  51. package/dist/generated/models/DemandePaiementConfirmationRequest.js +1 -0
  52. package/dist/generated/models/DemandePaiementConfirmationRequestAccepter.d.ts +9 -0
  53. package/dist/generated/models/DemandePaiementConfirmationRequestAccepter.js +1 -0
  54. package/dist/generated/models/DemandePaiementConfirmationRequestRejeter.d.ts +9 -0
  55. package/dist/generated/models/DemandePaiementConfirmationRequestRejeter.js +1 -0
  56. package/dist/generated/models/DemandePaiementConsultationReponse.d.ts +151 -0
  57. package/dist/generated/models/DemandePaiementConsultationReponse.js +27 -0
  58. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequest.d.ts +3 -0
  59. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequest.js +1 -0
  60. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequestAccepter.d.ts +9 -0
  61. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequestAccepter.js +1 -0
  62. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequestRejeter.d.ts +9 -0
  63. package/dist/generated/models/DemandePaiementEnMasseConfirmationRequestRejeter.js +1 -0
  64. package/dist/generated/models/DemandePaiementEnMasseRequest.d.ts +74 -0
  65. package/dist/generated/models/DemandePaiementEnMasseRequest.js +1 -0
  66. package/dist/generated/models/DemandePaiementEnMasseStatutReponse.d.ts +98 -0
  67. package/dist/generated/models/DemandePaiementEnMasseStatutReponse.js +20 -0
  68. package/dist/generated/models/DemandePaiementListe.d.ts +26 -0
  69. package/dist/generated/models/DemandePaiementListe.js +1 -0
  70. package/dist/generated/models/DemandePaiementListeItem.d.ts +163 -0
  71. package/dist/generated/models/DemandePaiementListeItem.js +27 -0
  72. package/dist/generated/models/DemandePaiementReponse.d.ts +129 -0
  73. package/dist/generated/models/DemandePaiementReponse.js +1 -0
  74. package/dist/generated/models/DemandePaiementReponseRequest.d.ts +21 -0
  75. package/dist/generated/models/DemandePaiementReponseRequest.js +11 -0
  76. package/dist/generated/models/DemandePaiementRequest.d.ts +98 -0
  77. package/dist/generated/models/DemandePaiementRequest.js +7 -0
  78. package/dist/generated/models/DemandePaiementRequestBase.d.ts +42 -0
  79. package/dist/generated/models/DemandePaiementRequestBase.js +1 -0
  80. package/dist/generated/models/DemandePaiementRequestCategorie.d.ts +12 -0
  81. package/dist/generated/models/DemandePaiementRequestCategorie.js +17 -0
  82. package/dist/generated/models/DemandePaiementStatut.d.ts +13 -0
  83. package/dist/generated/models/DemandePaiementStatut.js +18 -0
  84. package/dist/generated/models/DemandePaiementStatutRaison.d.ts +46 -0
  85. package/dist/generated/models/DemandePaiementStatutRaison.js +51 -0
  86. package/dist/generated/models/ListeMeta.d.ts +14 -0
  87. package/dist/generated/models/ListeMeta.js +1 -0
  88. package/dist/generated/models/Paiement.d.ts +156 -0
  89. package/dist/generated/models/Paiement.js +28 -0
  90. package/dist/generated/models/PaiementAnnulationMotif.d.ts +17 -0
  91. package/dist/generated/models/PaiementAnnulationMotif.js +22 -0
  92. package/dist/generated/models/PaiementAnnulationReponseRequest.d.ts +11 -0
  93. package/dist/generated/models/PaiementAnnulationReponseRequest.js +1 -0
  94. package/dist/generated/models/PaiementAnnulationReponseRequestAccepter.d.ts +9 -0
  95. package/dist/generated/models/PaiementAnnulationReponseRequestAccepter.js +1 -0
  96. package/dist/generated/models/PaiementAnnulationReponseRequestRejeter.d.ts +9 -0
  97. package/dist/generated/models/PaiementAnnulationReponseRequestRejeter.js +1 -0
  98. package/dist/generated/models/PaiementAnnulationRequest.d.ts +4 -0
  99. package/dist/generated/models/PaiementAnnulationRequest.js +1 -0
  100. package/dist/generated/models/PaiementAnnulationStatutRaison.d.ts +21 -0
  101. package/dist/generated/models/PaiementAnnulationStatutRaison.js +26 -0
  102. package/dist/generated/models/PaiementEnMasseConfirmationRequest.d.ts +3 -0
  103. package/dist/generated/models/PaiementEnMasseConfirmationRequest.js +1 -0
  104. package/dist/generated/models/PaiementEnMasseConfirmationRequestAccepter.d.ts +9 -0
  105. package/dist/generated/models/PaiementEnMasseConfirmationRequestAccepter.js +1 -0
  106. package/dist/generated/models/PaiementEnMasseConfirmationRequestRejeter.d.ts +9 -0
  107. package/dist/generated/models/PaiementEnMasseConfirmationRequestRejeter.js +1 -0
  108. package/dist/generated/models/PaiementEnMasseReponseStatut.d.ts +97 -0
  109. package/dist/generated/models/PaiementEnMasseReponseStatut.js +20 -0
  110. package/dist/generated/models/PaiementEnMasseRequest.d.ts +54 -0
  111. package/dist/generated/models/PaiementEnMasseRequest.js +1 -0
  112. package/dist/generated/models/PaiementImmediatConfirmationReponse.d.ts +31 -0
  113. package/dist/generated/models/PaiementImmediatConfirmationReponse.js +7 -0
  114. package/dist/generated/models/PaiementImmediatConfirmationRequest.d.ts +3 -0
  115. package/dist/generated/models/PaiementImmediatConfirmationRequest.js +1 -0
  116. package/dist/generated/models/PaiementImmediatConfirmationRequestAccepter.d.ts +9 -0
  117. package/dist/generated/models/PaiementImmediatConfirmationRequestAccepter.js +1 -0
  118. package/dist/generated/models/PaiementImmediatConfirmationRequestRejeter.d.ts +9 -0
  119. package/dist/generated/models/PaiementImmediatConfirmationRequestRejeter.js +1 -0
  120. package/dist/generated/models/PaiementImmediatReponse.d.ts +98 -0
  121. package/dist/generated/models/PaiementImmediatReponse.js +7 -0
  122. package/dist/generated/models/PaiementImmediatRequest.d.ts +13 -0
  123. package/dist/generated/models/PaiementImmediatRequest.js +1 -0
  124. package/dist/generated/models/PaiementListe.d.ts +6 -0
  125. package/dist/generated/models/PaiementListe.js +1 -0
  126. package/dist/generated/models/PaiementRequest.d.ts +33 -0
  127. package/dist/generated/models/PaiementRequest.js +1 -0
  128. package/dist/generated/models/PaiementStatut.d.ts +13 -0
  129. package/dist/generated/models/PaiementStatut.js +18 -0
  130. package/dist/generated/models/PaiementStatutRaison.d.ts +56 -0
  131. package/dist/generated/models/PaiementStatutRaison.js +61 -0
  132. package/dist/generated/models/Problem7807.d.ts +31 -0
  133. package/dist/generated/models/Problem7807.js +1 -0
  134. package/dist/generated/models/RefDocType.d.ts +38 -0
  135. package/dist/generated/models/RefDocType.js +43 -0
  136. package/dist/generated/models/RetourStatut.d.ts +13 -0
  137. package/dist/generated/models/RetourStatut.js +18 -0
  138. package/dist/generated/models/RetourStatutRaison.d.ts +25 -0
  139. package/dist/generated/models/RetourStatutRaison.js +30 -0
  140. package/dist/generated/models/WebhookCreationRequest.d.ts +14 -0
  141. package/dist/generated/models/WebhookCreationRequest.js +1 -0
  142. package/dist/generated/models/WebhookCreationResponse.d.ts +12 -0
  143. package/dist/generated/models/WebhookCreationResponse.js +1 -0
  144. package/dist/generated/models/WebhookData.d.ts +8 -0
  145. package/dist/generated/models/WebhookData.js +1 -0
  146. package/dist/generated/models/WebhookEvent.d.ts +191 -0
  147. package/dist/generated/models/WebhookEvent.js +42 -0
  148. package/dist/generated/models/WebhookEventsList.d.ts +13 -0
  149. package/dist/generated/models/WebhookEventsList.js +1 -0
  150. package/dist/generated/models/WebhookList.d.ts +13 -0
  151. package/dist/generated/models/WebhookList.js +1 -0
  152. package/dist/generated/models/WebhookModificationRequest.d.ts +4 -0
  153. package/dist/generated/models/WebhookModificationRequest.js +1 -0
  154. package/dist/generated/models/WebhooksEvents.d.ts +12 -0
  155. package/dist/generated/models/WebhooksEvents.js +17 -0
  156. package/dist/generated/services/AliasService.d.ts +63 -0
  157. package/dist/generated/services/AliasService.js +84 -0
  158. package/dist/generated/services/ComptesService.d.ts +64 -0
  159. package/dist/generated/services/ComptesService.js +86 -0
  160. package/dist/generated/services/DemandeAnnulationService.d.ts +84 -0
  161. package/dist/generated/services/DemandeAnnulationService.js +99 -0
  162. package/dist/generated/services/DemandesDePaiementEnMasseService.d.ts +161 -0
  163. package/dist/generated/services/DemandesDePaiementEnMasseService.js +189 -0
  164. package/dist/generated/services/DemandesDePaiementService.d.ts +123 -0
  165. package/dist/generated/services/DemandesDePaiementService.js +161 -0
  166. package/dist/generated/services/NotificationService.d.ts +80 -0
  167. package/dist/generated/services/NotificationService.js +132 -0
  168. package/dist/generated/services/PaiementEnMasseService.d.ts +159 -0
  169. package/dist/generated/services/PaiementEnMasseService.js +187 -0
  170. package/dist/generated/services/PaiementImmediatService.d.ts +135 -0
  171. package/dist/generated/services/PaiementImmediatService.js +176 -0
  172. package/dist/generated/services/RetoursdeFondsService.d.ts +28 -0
  173. package/dist/generated/services/RetoursdeFondsService.js +37 -0
  174. package/dist/index.d.ts +14 -0
  175. package/dist/index.js +23 -0
  176. package/dist/query-builder.d.ts +91 -0
  177. package/dist/query-builder.js +187 -0
  178. package/dist/sdk.d.ts +88 -0
  179. package/dist/sdk.js +107 -0
  180. package/dist/services/alias.d.ts +72 -0
  181. package/dist/services/alias.js +82 -0
  182. package/dist/services/base.d.ts +9 -0
  183. package/dist/services/base.js +17 -0
  184. package/dist/services/comptes.d.ts +149 -0
  185. package/dist/services/comptes.js +158 -0
  186. package/dist/services/demandes-annulation.d.ts +97 -0
  187. package/dist/services/demandes-annulation.js +104 -0
  188. package/dist/services/demandes-paiement-en-masse.d.ts +139 -0
  189. package/dist/services/demandes-paiement-en-masse.js +139 -0
  190. package/dist/services/demandes-paiement.d.ts +144 -0
  191. package/dist/services/demandes-paiement.js +151 -0
  192. package/dist/services/paiements-en-masse.d.ts +152 -0
  193. package/dist/services/paiements-en-masse.js +153 -0
  194. package/dist/services/paiements.d.ts +135 -0
  195. package/dist/services/paiements.js +135 -0
  196. package/dist/services/retours-fonds.d.ts +94 -0
  197. package/dist/services/retours-fonds.js +100 -0
  198. package/dist/services/webhooks.d.ts +131 -0
  199. package/dist/services/webhooks.js +142 -0
  200. package/dist/types/alias.d.ts +64 -0
  201. package/dist/types/alias.js +73 -0
  202. package/dist/utils/constants.d.ts +93 -0
  203. package/dist/utils/constants.js +93 -0
  204. package/dist/utils/index.d.ts +60 -0
  205. package/dist/utils/index.js +115 -0
  206. package/package.json +81 -0
  207. package/scripts/post-generate.js +129 -0
  208. package/scripts/pre-generate.js +106 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] - 2024-12-28
8
+
9
+ [0.1.0]: https://github.com/lomiafrica/lomi./releases/tag/pi-spi-sdk-v0.1.0
10
+
11
+ ### Added
12
+
13
+ - Initial release of PI-SPI SDK
14
+ - Full TypeScript support with generated types from OpenAPI spec
15
+ - OAuth2 + mTLS authentication support
16
+ - Comprehensive API coverage for all PI-SPI endpoints
17
+ - Query builder utility for filtering, pagination, and sorting
18
+ - Custom error classes (`PiSpiError`, `PiSpiValidationError`, `PiSpiAuthError`, etc.)
19
+ - Support for all PI-SPI services:
20
+ - Accounts (Comptes)
21
+ - Aliases
22
+ - Webhooks
23
+ - Payment requests (Demandes de Paiement)
24
+ - Bulk payment requests
25
+ - Immediate payments (Paiements)
26
+ - Bulk payments
27
+ - Fund returns (Retours de Fonds)
28
+ - Cancellation requests (Demandes Annulation)
29
+
30
+ ### Fixed
31
+
32
+ - Empty type definitions in generated models
33
+ - Type safety improvements for error handling
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 lomi.
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,300 @@
1
+ # @lomi/pi-spi-sdk
2
+
3
+ > **This repository is a contribution from open-source payment processing company [lomi.](https://lomi.africa)**
4
+
5
+ The Interoperable Platform for the Instant Payment System (π-SPI) is a regional payment infrastructure designed and operated by the Central Bank of West African States (BCEAO).
6
+
7
+ It enables instant fund transfers between different financial institutions across the region, including banks, electronic money issuers, microfinance institutions, and payment establishments.
8
+
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pnpm add pi-spi-sdk
14
+ # or
15
+ npm install pi-spi-sdk
16
+ # or
17
+ yarn add pi-spi-sdk
18
+ ```
19
+ π-SPI enables **cross-border transactions** within the West African Economic and Monetary Union (UEMOA), which spans eight countries: Benin, Burkina Faso, Côte d'Ivoire, Guinea-Bissau, Mali, Niger, Senegal, and Togo.
20
+
21
+ The infrastructure operates on a single currency, the XOF (West African CFA Franc), and processes payments in real-time with instant confirmation. Users can send payments using alias-based methods, which means they don't need to share their actual account numbers.
22
+
23
+ **Transaction types supported:**
24
+
25
+ π-SPI supports seamless interoperability between different payment systems throughout the region. Payments can flow between traditional bank accounts across UEMOA countries, from bank accounts to mobile money wallets like MTN, Orange Money, and Moov, from mobile wallets back to bank accounts, and even between mobile money wallets regardless of which provider each person uses. All these transaction types work seamlessly through the unified infrastructure, enabling businesses and individuals to send and receive payments across different financial institutions and mobile money providers within the UEMOA region.
26
+
27
+ ## Usage example
28
+
29
+ ```typescript
30
+ import { PiSpiSDK } from 'pi-spi-sdk';
31
+
32
+ const sdk = new PiSpiSDK({
33
+ baseUrl: 'https://sandbox.api.pi-bceao.com/piz/v1',
34
+ accessToken: 'your-oauth2-access-token',
35
+ });
36
+
37
+ // Get account balance
38
+ const account = await sdk.comptes.getAccount('CIC2344256727788288822');
39
+
40
+ // Create a payment
41
+ const payment = await sdk.paiements.create({
42
+ comptePayeur: 'CIC2344256727788288822',
43
+ payeAlias: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f', // SHID alias
44
+ montant: 150000, // 1,500 XOF (amounts are in centimes)
45
+ motif: 'Paiement de services',
46
+ });
47
+ ```
48
+
49
+ ## Features
50
+
51
+ This SDK provides full TypeScript support with types generated from the official OpenAPI specification, ensuring type safety throughout your integration. It includes secure authentication through OAuth2 and mTLS, comprehensive coverage of all SPI endpoints, and custom error classes with detailed messages for easier debugging. The codebase is auto-generated from the official specification and includes developer-friendly utilities and constants to streamline your implementation.
52
+
53
+ ## Utilities & Constants
54
+
55
+ ### Utilities
56
+
57
+ ```typescript
58
+ import { formatAmount, xofToCentimes, isValidAccountNumber } from 'pi-spi-sdk';
59
+
60
+ // Format amounts for display
61
+ const displayAmount = formatAmount(150000); // "1 500 XOF"
62
+
63
+ // Convert XOF to centimes
64
+ const centimes = xofToCentimes(1500); // 150000
65
+
66
+ // Validate inputs
67
+ if (isValidAccountNumber(accountNumber)) {
68
+ // Valid account number
69
+ }
70
+ ```
71
+
72
+ ### Constants
73
+
74
+ ```typescript
75
+ import { PI_SPI_ENDPOINTS, PAYMENT_STATUS, CURRENCY } from 'pi-spi-sdk';
76
+
77
+ // Use constants instead of magic strings
78
+ const baseUrl = PI_SPI_ENDPOINTS.SANDBOX;
79
+ if (payment.statut === PAYMENT_STATUS.IRREVOCABLE) {
80
+ // Payment is confirmed
81
+ }
82
+ ```
83
+
84
+ ## Reference
85
+
86
+ ### Authentication
87
+
88
+ ```typescript
89
+ const sdk = new PiSpiSDK({
90
+ baseUrl: process.env.PI_SPI_BASE_URL,
91
+ accessToken: process.env.PI_SPI_ACCESS_TOKEN,
92
+ // Optional: mTLS certificates
93
+ // clientCert: process.env.PI_SPI_CLIENT_CERT,
94
+ // clientKey: process.env.PI_SPI_CLIENT_KEY,
95
+ });
96
+ ```
97
+
98
+ ### Services
99
+
100
+ #### Accounts
101
+
102
+ ```typescript
103
+ // Get account balance and details
104
+ // Endpoint: GET /comptes/{numero}
105
+ const account = await sdk.comptes.getAccount('CIC2344256727788288822');
106
+ // Returns: {
107
+ // type: 'CACC', // Account type (CACC = Current Account)
108
+ // numero: 'CIC2344256727788288822',
109
+ // solde: 150000000, // Balance in centimes (1,500,000 XOF)
110
+ // statut: 'OUVERT', // Status: OUVERT, BLOQUE, or CLOTURE
111
+ // dateOuverture: '2023-02-21T15:30:01.250Z'
112
+ // }
113
+
114
+ // List operations with pagination
115
+ await sdk.comptes.listOperations({
116
+ comptePayeur: 'CIC2344256727788288822',
117
+ page: 1,
118
+ size: 20,
119
+ });
120
+
121
+ // Transfer between accounts (using account numbers)
122
+ await sdk.comptes.transfer({
123
+ comptePayeur: 'CIC2344256727788288822',
124
+ comptePaye: 'SNC2344256727788288822',
125
+ montant: 150000, // 1,500 XOF
126
+ });
127
+
128
+ // Transfer using aliases
129
+ await sdk.comptes.transfer({
130
+ payeurAlias: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f',
131
+ payeAlias: '4r5ty499-3e50-435b-b757-ac7a83d67juio',
132
+ montant: 150000,
133
+ });
134
+ ```
135
+
136
+ #### Payments
137
+
138
+ ```typescript
139
+ // Create immediate payment (no confirmation)
140
+ await sdk.paiements.create({
141
+ comptePayeur: 'CIC2344256727788288822',
142
+ payeAlias: '9b1b2499-3e50-435b-b757-ac7a83d8aa8c', // SHID alias
143
+ montant: 150000, // 1,500 XOF
144
+ motif: 'Paiement de services',
145
+ });
146
+
147
+ // Create payment with confirmation
148
+ await sdk.paiements.create({
149
+ comptePayeur: 'CIC2344256727788288822',
150
+ payeAlias: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f',
151
+ montant: 3000000, // 30,000 XOF
152
+ confirmation: true,
153
+ });
154
+
155
+ // Get payment details
156
+ await sdk.paiements.get('23552722');
157
+
158
+ // List payments with filters
159
+ await sdk.paiements.list({
160
+ comptePayeur: 'CIC2344256727788288822',
161
+ statut: 'IRREVOCABLE',
162
+ });
163
+ ```
164
+
165
+ #### Aliases
166
+
167
+ ```typescript
168
+ import { AliasType } from 'pi-spi-sdk';
169
+
170
+ // Create SHID alias (available for all client types: P, C, B, G)
171
+ // SHID is a system-generated UUID (36 characters)
172
+ const shidAlias = await sdk.alias.create({
173
+ compte: 'CIC2344256727788288822',
174
+ type: AliasType.SHID,
175
+ });
176
+ // Returns: { cle: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f', type: 'SHID', ... }
177
+
178
+ // Create MCOD alias (business clients only: C, B, G)
179
+ // MCOD is a merchant code for USSD payments
180
+ const mcodAlias = await sdk.alias.create({
181
+ compte: 'SNC2344256727788288822',
182
+ type: AliasType.MCOD,
183
+ });
184
+ // Returns: { cle: 'SNF00_2E4TY', type: 'MCOD', ... }
185
+
186
+ // List all aliases for an account
187
+ await sdk.alias.list('CIC2344256727788288822');
188
+
189
+ // Delete an alias
190
+ await sdk.alias.delete('8b1b2499-3e50-435b-b757-ac7a83d8aa7f');
191
+ ```
192
+
193
+ #### Payment requests
194
+
195
+ ```typescript
196
+ // Create payment request (bill/invoice)
197
+ await sdk.demandesPaiement.create({
198
+ comptePaye: 'CIC2344256727788288822',
199
+ payeurAlias: '9b1b3499-3e50-435b-b757-ac7a83d8aa96', // Customer's alias
200
+ montant: 150000, // 1,500 XOF
201
+ categorie: '401', // Invoice category
202
+ dateLimitePaiement: '2023-12-31T23:59:59.999Z',
203
+ motif: 'Facture électricité mars 2023',
204
+ refDocType: 'CINV',
205
+ refDocNumero: 'FACT-ELEC-202303',
206
+ });
207
+
208
+ // Accept a payment request
209
+ await sdk.demandesPaiement.accept('RTP-2023-001');
210
+
211
+ // Reject a payment request
212
+ await sdk.demandesPaiement.reject('RTP-2023-001');
213
+ ```
214
+
215
+ #### Webhooks
216
+
217
+ ```typescript
218
+ await sdk.webhooks.create({
219
+ url: 'https://your-domain.com/webhooks/pi-spi',
220
+ events: ['PAIEMENT_RECU'],
221
+ });
222
+ await sdk.webhooks.list();
223
+ await sdk.webhooks.update(webhookId, { url: 'https://updated-url.com' });
224
+ await sdk.webhooks.delete(webhookId);
225
+ ```
226
+
227
+ ### Error handling
228
+
229
+ ```typescript
230
+ import { PiSpiError, PiSpiValidationError, PiSpiAuthError } from 'pi-spi-sdk';
231
+
232
+ try {
233
+ await sdk.paiements.create({ ... });
234
+ } catch (error) {
235
+ if (error instanceof PiSpiValidationError) {
236
+ console.error('Validation error:', error.errors);
237
+ } else if (error instanceof PiSpiAuthError) {
238
+ console.error('Authentication error:', error.message);
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### Filtering & pagination
244
+
245
+ The SDK includes a QueryBuilder that allows you to construct complex queries with multiple filters, sorting, and pagination. You can chain filter conditions using various operators, sort results in ascending or descending order (use `-` prefix for descending), and control pagination with page number and size parameters.
246
+
247
+ ```typescript
248
+ import { QueryBuilder } from 'pi-spi-sdk';
249
+
250
+ const query = new QueryBuilder()
251
+ .filter('statut', 'eq', 'IRREVOCABLE')
252
+ .filter('montant', 'gte', 10000)
253
+ .sort('-dateCreation')
254
+ .page(1)
255
+ .size(50)
256
+ .build();
257
+
258
+ const payments = await sdk.paiements.list(query);
259
+ ```
260
+
261
+ The QueryBuilder supports these operators: `eq` (equals), `ne` (not equals), `gt` (greater than), `gte` (greater than or equal), `lt` (less than), `lte` (less than or equal), `in` (in array), `contains`, `notContains`, `beginsWith`, `endsWith`, and `exists`.
262
+
263
+ ## Alias types
264
+
265
+ The SPI supports three types of account aliases that allow users to send and receive payments without sharing their full account numbers:
266
+
267
+ **SHID (System-Hosted Identifier)** is a system-generated UUID (36 characters, such as `8b1b2499-3e50-435b-b757-ac7a83d8aa7f`) available for all client types and serves as a general-purpose payment address.
268
+
269
+ **MCOD (Merchant Code)** is an alphanumeric code (like `SNF00_2E4TY`) that's system-generated and available exclusively for business clients (C, B, G), primarily used for USSD payment support.
270
+
271
+ **MBNO (Mobile Number)** uses phone number format and is available only for individual clients (P), designed specifically for mobile money integration.
272
+
273
+ **Example:**
274
+
275
+ ```typescript
276
+ import { AliasType, getAvailableAliasTypes, isValidAliasType } from 'pi-spi-sdk';
277
+
278
+ // Get available alias types for a business client
279
+ const businessAliasTypes = getAvailableAliasTypes('B'); // Returns: ['SHID', 'MCOD']
280
+
281
+ // Check if a string is a valid alias type
282
+ if (isValidAliasType('SHID')) {
283
+ // Valid alias type
284
+ }
285
+ ```
286
+
287
+ ## Documentation
288
+
289
+ - **[Developer Guide](./DEVELOPER_GUIDE.md)** - For contributors and advanced usage
290
+ - **[Changelog](./CHANGELOG.md)** - Version history
291
+
292
+ ## Support
293
+
294
+ - **π-SPI API**: [pisfn-sandbox@bceao.int](mailto:pisfn-sandbox@bceao.int)
295
+ - **SDK Support**: [hello@lomi.africa](mailto:hello@lomi.africa)
296
+ - **Documentation**: [https://developers.pi-bceao.com](https://developers.pi-bceao.com)
297
+
298
+ ## License
299
+
300
+ MIT
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PI-SPI SDK Configuration
3
+ */
4
+ export interface PiSpiConfig {
5
+ /**
6
+ * Base URL for the PI-SPI API
7
+ * @default 'https://sandbox.api.pi-bceao.com/piz/v1'
8
+ */
9
+ baseUrl?: string;
10
+ /**
11
+ * OAuth2 access token for authentication
12
+ */
13
+ accessToken: string;
14
+ /**
15
+ * Optional: Client certificate path for mTLS
16
+ */
17
+ clientCert?: string;
18
+ /**
19
+ * Optional: Client key path for mTLS
20
+ */
21
+ clientKey?: string;
22
+ /**
23
+ * Optional: CA certificate path for mTLS
24
+ */
25
+ caCert?: string;
26
+ /**
27
+ * Optional: Additional headers to include in requests
28
+ */
29
+ headers?: Record<string, string>;
30
+ /**
31
+ * Optional: Request timeout in milliseconds
32
+ * @default 30000
33
+ */
34
+ timeout?: number;
35
+ }
package/dist/config.js ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * PI-SPI SDK Configuration
3
+ */
4
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Error handler utility for converting API errors to SDK errors
3
+ */
4
+ /**
5
+ * Convert a generated API error to a SDK error
6
+ */
7
+ export declare function handleApiError(error: unknown): never;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Error handler utility for converting API errors to SDK errors
3
+ */
4
+ import { PiSpiError, PiSpiValidationError, PiSpiAuthError, PiSpiNotFoundError, PiSpiRateLimitError, } from './errors';
5
+ /**
6
+ * Convert a generated API error to a SDK error
7
+ */
8
+ export function handleApiError(error) {
9
+ // Check if it's an ApiError-like object (from generated code)
10
+ const isApiError = error &&
11
+ typeof error === 'object' &&
12
+ 'status' in error &&
13
+ 'statusText' in error &&
14
+ 'body' in error;
15
+ if (isApiError) {
16
+ const apiError = error;
17
+ const status = apiError.status;
18
+ const body = apiError.body;
19
+ // Extract error details from RFC 7807 Problem format
20
+ const type = body?.type;
21
+ const title = body?.title || apiError.statusText;
22
+ const detail = body?.detail || apiError.message;
23
+ const instance = body?.instance;
24
+ // Handle validation errors (400)
25
+ if (status === 400) {
26
+ const invalidParams = body?.invalidParams || body?.errors;
27
+ throw new PiSpiValidationError(detail || title || 'Validation error', status, apiError.statusText, invalidParams, type, detail);
28
+ }
29
+ // Handle authentication errors (401)
30
+ if (status === 401) {
31
+ throw new PiSpiAuthError(detail || title || 'Authentication failed', status, apiError.statusText);
32
+ }
33
+ // Handle forbidden errors (403)
34
+ if (status === 403) {
35
+ throw new PiSpiError(detail || title || 'Forbidden', status, apiError.statusText, type, detail, instance);
36
+ }
37
+ // Handle not found errors (404)
38
+ if (status === 404) {
39
+ throw new PiSpiNotFoundError(detail || title || 'Resource not found', status, apiError.statusText);
40
+ }
41
+ // Handle rate limit errors (429)
42
+ if (status === 429) {
43
+ // Retry-After header would be in the response, but ApiError doesn't expose it
44
+ // This can be enhanced if needed
45
+ throw new PiSpiRateLimitError(detail || title || 'Rate limit exceeded', status, apiError.statusText);
46
+ }
47
+ // Handle other errors
48
+ throw new PiSpiError(detail || title || apiError.message || 'API error', status, apiError.statusText, type, detail, instance);
49
+ }
50
+ // Re-throw if it's not an API error
51
+ throw error;
52
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Custom error classes for PI-SPI SDK
3
+ */
4
+ export declare class PiSpiError extends Error {
5
+ readonly statusCode: number;
6
+ readonly statusText: string;
7
+ readonly type?: string;
8
+ readonly detail?: string;
9
+ readonly instance?: string;
10
+ constructor(message: string, statusCode: number, statusText: string, type?: string, detail?: string, instance?: string);
11
+ }
12
+ export declare class PiSpiValidationError extends PiSpiError {
13
+ readonly errors?: Record<string, string[]>;
14
+ constructor(message: string, statusCode: number, statusText: string, errors?: Record<string, string[]>, type?: string, detail?: string);
15
+ }
16
+ export declare class PiSpiAuthError extends PiSpiError {
17
+ constructor(message: string, statusCode: number, statusText: string);
18
+ }
19
+ export declare class PiSpiNotFoundError extends PiSpiError {
20
+ constructor(message: string, statusCode: number, statusText: string);
21
+ }
22
+ export declare class PiSpiRateLimitError extends PiSpiError {
23
+ readonly retryAfter?: number;
24
+ constructor(message: string, statusCode: number, statusText: string, retryAfter?: number);
25
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Custom error classes for PI-SPI SDK
3
+ */
4
+ export class PiSpiError extends Error {
5
+ constructor(message, statusCode, statusText, type, detail, instance) {
6
+ super(message);
7
+ this.name = 'PiSpiError';
8
+ this.statusCode = statusCode;
9
+ this.statusText = statusText;
10
+ this.type = type;
11
+ this.detail = detail;
12
+ this.instance = instance;
13
+ }
14
+ }
15
+ export class PiSpiValidationError extends PiSpiError {
16
+ constructor(message, statusCode, statusText, errors, type, detail) {
17
+ super(message, statusCode, statusText, type, detail);
18
+ this.name = 'PiSpiValidationError';
19
+ this.errors = errors;
20
+ }
21
+ }
22
+ export class PiSpiAuthError extends PiSpiError {
23
+ constructor(message, statusCode, statusText) {
24
+ super(message, statusCode, statusText);
25
+ this.name = 'PiSpiAuthError';
26
+ }
27
+ }
28
+ export class PiSpiNotFoundError extends PiSpiError {
29
+ constructor(message, statusCode, statusText) {
30
+ super(message, statusCode, statusText);
31
+ this.name = 'PiSpiNotFoundError';
32
+ }
33
+ }
34
+ export class PiSpiRateLimitError extends PiSpiError {
35
+ constructor(message, statusCode, statusText, retryAfter) {
36
+ super(message, statusCode, statusText);
37
+ this.name = 'PiSpiRateLimitError';
38
+ this.retryAfter = retryAfter;
39
+ }
40
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Usage Examples for PI-SPI SDK
3
+ *
4
+ * These examples use production-like data from the PI-SPI OpenAPI specification.
5
+ *
6
+ * @see {@link https://developers.pi-bceao.com} Official PI-SPI Documentation
7
+ */
8
+ export {};
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Usage Examples for PI-SPI SDK
3
+ *
4
+ * These examples use production-like data from the PI-SPI OpenAPI specification.
5
+ *
6
+ * @see {@link https://developers.pi-bceao.com} Official PI-SPI Documentation
7
+ */
8
+ import { PiSpiSDK, QueryBuilder, AliasType } from './index';
9
+ // Initialize the SDK
10
+ const sdk = new PiSpiSDK({
11
+ baseUrl: 'https://sandbox.api.pi-bceao.com/piz/v1',
12
+ accessToken: process.env.PI_SPI_ACCESS_TOKEN,
13
+ });
14
+ // Example: Get account balance
15
+ // Account numbers follow format: [CountryCode][AccountNumber]
16
+ // Examples: 'CIC2344256727788288822' (Côte d'Ivoire), 'SNC2344256727788288822' (Senegal)
17
+ async function getAccountBalance() {
18
+ const account = await sdk.comptes.getAccount('CIC2344256727788288822');
19
+ // @ts-expect-error - Service implementation pending code generation
20
+ console.log('Account balance:', account?.solde ?? 'N/A');
21
+ // @ts-expect-error
22
+ console.log('Account status:', account?.statut);
23
+ }
24
+ // Example: Create alias
25
+ // SHID: System-generated UUID (36 chars) - available for all client types
26
+ // MCOD: Merchant code for USSD - business clients only (C, B, G)
27
+ // MBNO: Mobile number - individuals only (P)
28
+ async function createAliasExample() {
29
+ // Create SHID alias (available for all client types)
30
+ const shidAlias = await sdk.alias.create({
31
+ compte: 'CIC2344256727788288822',
32
+ type: AliasType.SHID,
33
+ });
34
+ // Returns: { cle: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f', type: 'SHID', ... }
35
+ // Create MCOD alias (business clients only)
36
+ const mcodAlias = await sdk.alias.create({
37
+ compte: 'SNC2344256727788288822',
38
+ type: AliasType.MCOD,
39
+ });
40
+ // Returns: { cle: 'SNF00_2E4TY', type: 'MCOD', ... }
41
+ }
42
+ // Example: Query builder usage
43
+ async function queryExample() {
44
+ const query = new QueryBuilder()
45
+ .filter('statut', 'eq', 'IRREVOCABLE')
46
+ .filter('montant', 'gte', 150000) // 1,500 XOF minimum
47
+ .sort('-dateCreation')
48
+ .page(1)
49
+ .size(50)
50
+ .build();
51
+ const payments = await sdk.paiements.list(query);
52
+ }
53
+ // Example: Create payment with realistic data
54
+ async function createPaymentExample() {
55
+ const payment = await sdk.paiements.create({
56
+ comptePayeur: 'CIC2344256727788288822',
57
+ payeAlias: '8b1b2499-3e50-435b-b757-ac7a83d8aa7f', // SHID alias (UUID format)
58
+ montant: 150000, // 1,500 XOF (amounts are in centimes)
59
+ motif: 'Paiement de services',
60
+ txId: '23552722', // Unique transaction ID
61
+ });
62
+ }
63
+ // Example: Error handling
64
+ import { PiSpiError, PiSpiValidationError, PiSpiAuthError } from './index';
65
+ async function errorHandlingExample() {
66
+ try {
67
+ await sdk.paiements.create({
68
+ comptePayeur: 'CIC2344256727788288822',
69
+ payeAlias: '9b1b2499-3e50-435b-b757-ac7a83d8aa8c', // SHID alias
70
+ montant: 150000, // 1,500 XOF
71
+ motif: 'Paiement de test',
72
+ });
73
+ }
74
+ catch (error) {
75
+ if (error instanceof PiSpiValidationError) {
76
+ console.error('Validation error:', error.errors);
77
+ }
78
+ else if (error instanceof PiSpiAuthError) {
79
+ console.error('Authentication error:', error.message);
80
+ }
81
+ else if (error instanceof PiSpiError) {
82
+ console.error('API error:', error.message, error.statusCode);
83
+ }
84
+ else if (error instanceof Error) {
85
+ console.error('Unexpected error:', error.message);
86
+ }
87
+ else {
88
+ console.error('Unknown error:', error);
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,10 @@
1
+ import type { ApiRequestOptions } from './ApiRequestOptions';
2
+ import type { ApiResult } from './ApiResult';
3
+ export declare class ApiError extends Error {
4
+ readonly url: string;
5
+ readonly status: number;
6
+ readonly statusText: string;
7
+ readonly body: any;
8
+ readonly request: ApiRequestOptions;
9
+ constructor(request: ApiRequestOptions, response: ApiResult, message: string);
10
+ }
@@ -0,0 +1,11 @@
1
+ export class ApiError extends Error {
2
+ constructor(request, response, message) {
3
+ super(message);
4
+ this.name = 'ApiError';
5
+ this.url = response.url;
6
+ this.status = response.status;
7
+ this.statusText = response.statusText;
8
+ this.body = response.body;
9
+ this.request = request;
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ export type ApiRequestOptions = {
2
+ readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
3
+ readonly url: string;
4
+ readonly path?: Record<string, any>;
5
+ readonly cookies?: Record<string, any>;
6
+ readonly headers?: Record<string, any>;
7
+ readonly query?: Record<string, any>;
8
+ readonly formData?: Record<string, any>;
9
+ readonly body?: any;
10
+ readonly mediaType?: string;
11
+ readonly responseHeader?: string;
12
+ readonly errors?: Record<number, string>;
13
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export type ApiResult = {
2
+ readonly url: string;
3
+ readonly ok: boolean;
4
+ readonly status: number;
5
+ readonly statusText: string;
6
+ readonly body: any;
7
+ };
@@ -0,0 +1 @@
1
+ export {};