@paykit-sdk/gopay 1.0.4 → 1.1.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @paykit-sdk/gopay
2
2
 
3
- Stripe provider for PayKit
3
+ GoPay provider for PayKit
4
4
 
5
5
  ## Quick Start
6
6
 
@@ -9,15 +9,16 @@ import { createEndpointHandlers, PayKit } from '@paykit-sdk/core';
9
9
  import { gopay, createGopay } from '@paykit-sdk/gopay';
10
10
 
11
11
  // Method 1: Using environment variables
12
- const provider = gopay(); // Ensure GOPAY_CLIENT_ID, GOPAY_CLIENT_SECRET, GOPAY_GO_ID, GOPAY_SANDBOX, GOPAY_WEBHOOK_URL environment variables are set
12
+ const provider = gopay(); // Ensure required environment variables are set
13
13
 
14
14
  // Method 2: Direct configuration
15
15
  const provider = createGopay({
16
- clientId: 'sk_test_...',
17
- clientSecret: 'clsec_...',
18
- goId: 'go...',
16
+ clientId: process.env.GOPAY_CLIENT_ID,
17
+ clientSecret: process.env.GOPAY_CLIENT_SECRET,
18
+ goId: process.env.GOPAY_GO_ID,
19
19
  isSandbox: true,
20
- webhookUrl: 'http://localhost:8080/api/paykit/webhook',
20
+ webhookUrl: 'https://your-domain.com/api/paykit/webhooks',
21
+ debug: true, // Enable to see helpful logs about provider_metadata
21
22
  });
22
23
 
23
24
  export const paykit = new PayKit(provider);
@@ -27,16 +28,18 @@ export const endpoints = createEndpointHandlers(paykit);
27
28
  ### Next.js Catch All API Route (/api/paykit/[...endpoint]/route.ts)
28
29
 
29
30
  ```typescript
30
- import { paykit } from '@/lib/paykit';
31
+ import { endpoints } from '@/lib/paykit';
31
32
  import { EndpointPath } from '@paykit-sdk/core';
33
+ import { NextRequest, NextResponse } from 'next/server';
32
34
 
33
35
  export async function POST(
34
36
  request: NextRequest,
35
- { params }: { params: { endpoint: string[] } },
37
+ { params }: { params: Promise<{ endpoint: string[] }> },
36
38
  ) {
37
39
  try {
40
+ const { endpoint: endpointArray } = await params;
38
41
  // Construct the endpoint path with full type safety
39
- const endpoint = ('/' + params.endpoint.join('/')) as EndpointPath;
42
+ const endpoint = ('/' + endpointArray.join('/')) as EndpointPath;
40
43
  const handler = endpoints[endpoint];
41
44
 
42
45
  if (!handler) {
@@ -62,36 +65,42 @@ export async function POST(
62
65
 
63
66
  ### Next.js Webhooks (/api/paykit/webhooks/route.ts)
64
67
 
68
+ **⚠️ IMPORTANT:** GoPay webhooks use GET requests instead of POST. Your webhook route must export a GET handler, not POST.
69
+
65
70
  ```typescript
66
71
  import { paykit } from '@/lib/paykit';
67
- import { NextRequest } from 'next/server';
72
+ import { NextRequest, NextResponse } from 'next/server';
68
73
 
69
- export async function POST(request: NextRequest) {
74
+ export async function GET(request: NextRequest) {
70
75
  const webhook = paykit.webhooks
71
- .setup({ webhookSecret: '' })
76
+ .setup({ webhookSecret: '' }) // GoPay doesn't use webhook secrets
72
77
  .on('customer.created', async event => {
73
78
  console.log('Customer created:', event.data);
74
- });
79
+ })
75
80
  .on('subscription.created', async event => {
76
81
  console.log('Subscription created:', event.data);
77
- });
82
+ })
78
83
  .on('payment.created', async event => {
79
84
  console.log('Payment created:', event.data);
80
- });
85
+ })
81
86
  .on('refund.created', async event => {
82
- console.log('Refund created:', event.data);
83
- });
87
+ console.log('Refund created:', event.data);
88
+ })
84
89
  .on('invoice.generated', async event => {
85
90
  console.log('Invoice generated:', event.data);
86
91
  });
87
92
 
88
- const body = await request.text();
89
- const headers = Object.fromEntries(request.headers.entries());
90
- const url = request.url
91
- await webhook.handle({ body, headers, fullUrl: url });
93
+ const headers = request.headers;
94
+ const url = request.url;
92
95
 
93
- // Return immediately, processing happens in background
94
- return NextResponse.json({ success: true });
96
+ try {
97
+ console.log('Webhook handled');
98
+ await webhook.handle({ body: '', headers, fullUrl: url });
99
+ return NextResponse.json({ success: true });
100
+ } catch (error) {
101
+ console.error('Webhook error:', error);
102
+ return NextResponse.json({ success: false }, { status: 500 });
103
+ }
95
104
  }
96
105
  ```
97
106
 
@@ -99,51 +108,46 @@ export async function POST(request: NextRequest) {
99
108
 
100
109
  ```typescript
101
110
  import { paykit, endpoints } from '@/lib/paykit';
102
- import { createEndpointHandlers, EndpointPath } from '@paykit-sdk/core';
111
+ import { EndpointPath } from '@paykit-sdk/core';
103
112
  import express from 'express';
104
113
 
105
114
  const app = express();
106
115
 
107
- // IMPORTANT: Webhook route must come BEFORE express.json() middleware
108
- // This ensures we get the raw body for signature verification
109
- app.post(
110
- '/api/webhooks/gopay',
111
- express.raw({ type: 'application/json' }),
112
- async (req, res) => {
113
- try {
114
- const webhook = paykit.webhooks
115
- .setup({ webhookSecret: '' })
116
- .on('customer.created', async event => {
117
- console.log('Customer created:', event.data);
118
- })
119
- .on('subscription.created', async event => {
120
- console.log('Subscription created:', event.data);
121
- })
122
- .on('payment.created', async event => {
123
- console.log('Payment created:', event.data);
124
- })
125
- .on('refund.created', async event => {
126
- console.log('Refund created:', event.data);
127
- })
128
- .on('invoice.generated', async event => {
129
- console.log('Invoice generated:', event.data);
130
- });
131
-
132
- const body = req.body; // Raw buffer from express.raw()
133
- const headers = req.headers;
134
- const url = request.url;
135
- await webhook.handle({ body, headers, fullUrl: url });
136
-
137
- // Return immediately, processing happens in background
138
- res.json({ success: true });
139
- } catch (error) {
140
- console.error('Webhook error:', error);
141
- res.status(500).json({
142
- message: error instanceof Error ? error.message : 'Webhook processing failed',
116
+ // IMPORTANT: GoPay webhooks use GET requests, not POST
117
+ app.get('/api/webhooks/gopay', async (req, res) => {
118
+ try {
119
+ const webhook = paykit.webhooks
120
+ .setup({ webhookSecret: '' }) // GoPay doesn't use webhook secrets
121
+ .on('customer.created', async event => {
122
+ console.log('Customer created:', event.data);
123
+ })
124
+ .on('subscription.created', async event => {
125
+ console.log('Subscription created:', event.data);
126
+ })
127
+ .on('payment.created', async event => {
128
+ console.log('Payment created:', event.data);
129
+ })
130
+ .on('refund.created', async event => {
131
+ console.log('Refund created:', event.data);
132
+ })
133
+ .on('invoice.generated', async event => {
134
+ console.log('Invoice generated:', event.data);
143
135
  });
144
- }
145
- },
146
- );
136
+
137
+ const body = ''; // GoPay sends data via URL query params
138
+ const headers = req.headers;
139
+ const url = req.url;
140
+ await webhook.handle({ body, headers, fullUrl: url });
141
+
142
+ // Return immediately, processing happens in background
143
+ res.json({ success: true });
144
+ } catch (error) {
145
+ console.error('Webhook error:', error);
146
+ res.status(500).json({
147
+ message: error instanceof Error ? error.message : 'Webhook processing failed',
148
+ });
149
+ }
150
+ });
147
151
 
148
152
  // Regular API routes use JSON middleware
149
153
  app.use(express.json());
@@ -173,19 +177,52 @@ app.listen(3000, () => {
173
177
  });
174
178
  ```
175
179
 
180
+ ## Subscription Management
181
+
182
+ ```typescript
183
+ // Cancel subscription
184
+ await paykit.subscriptions.cancel('sub_123');
185
+ ```
186
+
187
+ ## Provider Metadata
188
+
189
+ GoPay requires specific `provider_metadata` fields for different operations. Enable `debug: true` when initializing the provider to see helpful console logs that recommend which fields to use.
190
+
191
+ ```typescript
192
+ const checkout = await paykit.checkouts.create({
193
+ customer: { email: 'user@example.com' },
194
+ item_id: 'item_123',
195
+ session_type: 'one_time',
196
+ quantity: 1,
197
+ metadata: { plan: 'pro' },
198
+ success_url: 'http://localhost:3000/success',
199
+ cancel_url: 'http://localhost:3000/cancel',
200
+ provider_metadata: {
201
+ amount: '2900',
202
+ currency: 'CZK',
203
+ lang: 'en', // Language for the payment gateway (default: 'EN')
204
+ },
205
+ });
206
+ ```
207
+
176
208
  ## Environment Variables
177
209
 
178
210
  ```bash
179
- GOPAY_CLIENT_ID=sk_test_...
180
- GOPAY_CLIENT_SECRET=clsec_...
181
- GOPAY_GO_ID=go...
211
+ GOPAY_CLIENT_ID=140...
212
+ GOPAY_CLIENT_SECRET=n6W...
213
+ GOPAY_GO_ID=864....
182
214
  GOPAY_SANDBOX=true
183
- GOPAY_WEBHOOK_URL=http://localhost:8080/api/paykit/webhook
215
+ GOPAY_WEBHOOK_URL=https://your-domain.com/api/paykit/webhooks
184
216
  ```
185
217
 
218
+ ## Documentation
219
+
220
+ For detailed documentation, including setup guides, webhook configuration, and provider metadata requirements, see the [GoPay Provider Documentation](https://usepaykit.com/docs/providers/gopay).
221
+
186
222
  ## Support
187
223
 
188
- - [Gopay Documentation](https://doc.gopay.com/)
224
+ - [GoPay Documentation](https://doc.gopay.com/)
225
+ - [PayKit Issues](https://github.com/usepaykit/paykit-sdk/issues)
189
226
 
190
227
  ## License
191
228
 
@@ -24,25 +24,29 @@ var AuthController = class {
24
24
  const credentials = Buffer.from(
25
25
  `${this.opts.clientId}:${this.opts.clientSecret}`
26
26
  ).toString("base64");
27
+ const body = new URLSearchParams({
28
+ grant_type: "client_credentials",
29
+ scope: "payment-all"
30
+ }).toString();
27
31
  const response = await this._client.post("/oauth2/token", {
28
32
  headers: {
29
33
  Authorization: `Basic ${credentials}`,
30
- "Content-Type": "application/x-www-form-urlencoded"
34
+ "Content-Type": "application/x-www-form-urlencoded",
35
+ Accept: "application/json"
31
36
  },
32
- body: new URLSearchParams({
33
- grant_type: "client_credentials",
34
- scope: "payment-all"
35
- }).toString()
37
+ body
36
38
  });
37
- if (!response.ok || !response.value.access_token) {
39
+ if (!response.ok || !response.value?.access_token) {
38
40
  throw new core.OperationFailedError("getAccessToken", "gopay", {
39
- cause: new Error("Failed to obtain GoPay access token")
41
+ cause: new Error(
42
+ `Failed to obtain GoPay access token: ${JSON.stringify(response.value || response.error)}`
43
+ )
40
44
  });
41
45
  }
42
46
  const expiryTime = Date.now() + (response.value.expires_in - 300) * 1e3;
43
47
  const accessToken = `${response.value.access_token}::paykit::${expiryTime}`;
44
48
  this._accessToken = accessToken;
45
- return accessToken;
49
+ return response.value.access_token;
46
50
  };
47
51
  getAuthHeaders = async () => {
48
52
  const token = await this.getAccessToken();
@@ -22,25 +22,29 @@ var AuthController = class {
22
22
  const credentials = Buffer.from(
23
23
  `${this.opts.clientId}:${this.opts.clientSecret}`
24
24
  ).toString("base64");
25
+ const body = new URLSearchParams({
26
+ grant_type: "client_credentials",
27
+ scope: "payment-all"
28
+ }).toString();
25
29
  const response = await this._client.post("/oauth2/token", {
26
30
  headers: {
27
31
  Authorization: `Basic ${credentials}`,
28
- "Content-Type": "application/x-www-form-urlencoded"
32
+ "Content-Type": "application/x-www-form-urlencoded",
33
+ Accept: "application/json"
29
34
  },
30
- body: new URLSearchParams({
31
- grant_type: "client_credentials",
32
- scope: "payment-all"
33
- }).toString()
35
+ body
34
36
  });
35
- if (!response.ok || !response.value.access_token) {
37
+ if (!response.ok || !response.value?.access_token) {
36
38
  throw new OperationFailedError("getAccessToken", "gopay", {
37
- cause: new Error("Failed to obtain GoPay access token")
39
+ cause: new Error(
40
+ `Failed to obtain GoPay access token: ${JSON.stringify(response.value || response.error)}`
41
+ )
38
42
  });
39
43
  }
40
44
  const expiryTime = Date.now() + (response.value.expires_in - 300) * 1e3;
41
45
  const accessToken = `${response.value.access_token}::paykit::${expiryTime}`;
42
46
  this._accessToken = accessToken;
43
- return accessToken;
47
+ return response.value.access_token;
44
48
  };
45
49
  getAuthHeaders = async () => {
46
50
  const token = await this.getAccessToken();