Skip to content

Commit 3aa9a89

Browse files
committed
feat(php-sdk): replace magic request option arrays with typed RequestOptions
Introduce SumUp\HttpClient\RequestOptions and use it across the SDK surface.\n\n- Update HttpClientInterface and built-in clients to accept typed request options\n- Update codegen to emit RequestOptions in generated service method signatures/docs\n- Regenerate service files\n- Update examples and README with typed request options usage
1 parent cab6f17 commit 3aa9a89

23 files changed

Lines changed: 246 additions & 140 deletions

File tree

README.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ try {
3737
// SDK automatically uses SUMUP_API_KEY environment variable
3838
$sumup = new \SumUp\SumUp();
3939

40-
$checkout = $sumup->checkouts()->create([
41-
'amount' => 10.00,
42-
'currency' => 'EUR',
43-
'checkout_reference' => 'your-checkout-ref',
44-
'merchant_code' => 'YOUR-MERCHANT-CODE',
45-
]);
40+
$request = new \SumUp\Types\CheckoutCreateRequest();
41+
$request->amount = 10.00;
42+
$request->currency = \SumUp\Types\CheckoutCreateRequestCurrency::EUR;
43+
$request->checkoutReference = 'your-checkout-ref';
44+
$request->merchantCode = 'YOUR-MERCHANT-CODE';
45+
46+
$checkout = $sumup->checkouts()->create($request);
4647

4748
$checkoutId = $checkout->id;
4849
// Pass the $checkoutId to the front-end to be processed
@@ -53,13 +54,16 @@ try {
5354
} catch (\SumUp\Exception\UnexpectedApiException $e) {
5455
echo 'Unexpected API error (status ' . $e->getStatusCode() . '): ' . $e->getMessage();
5556
// Body did not match an OpenAPI-described error shape.
56-
var_dump($e->getResponseBody());
57+
// Use the normalized envelope for stable logging/handling.
58+
var_dump($e->getErrorEnvelope()->toArray());
5759
} catch (\SumUp\Exception\SDKException $e) {
5860
echo 'SumUp SDK error (status ' . $e->getStatusCode() . '): ' . $e->getMessage();
5961
// Covers connection/configuration and other non-API failures.
6062
}
6163
```
6264

65+
For convenience, service methods still accept associative arrays as request payloads, but DTO objects from `\SumUp\Types\...` are the recommended and typed approach.
66+
6367
### Providing API Key Programmatically
6468

6569
If you prefer to provide the API key directly in your code instead of using the environment variable:
@@ -118,6 +122,21 @@ $sumup = new \SumUp\SumUp([
118122
]);
119123
```
120124

125+
### Request Options
126+
127+
Service methods accept typed request options via `\SumUp\HttpClient\RequestOptions`:
128+
129+
```php
130+
$options = new \SumUp\HttpClient\RequestOptions(
131+
timeout: 30,
132+
connectTimeout: 10,
133+
retries: 2,
134+
retryBackoffMs: 200
135+
);
136+
137+
$checkout = $sumup->checkouts()->get('checkout-id', $options);
138+
```
139+
121140
## API Reference
122141

123142
For a full list of available services and methods, explore the service files under `src/*/*.php` (for example `src/Checkouts/Checkouts.php`) or check the inline documentation in the code.

codegen/pkg/generator/services.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func (g *Generator) buildServiceBlock(tagKey string, operations []*operation) st
2020
var buf strings.Builder
2121
buf.WriteString("namespace SumUp\\Services;\n\n")
2222
buf.WriteString("use SumUp\\HttpClient\\HttpClientInterface;\n")
23+
buf.WriteString("use SumUp\\HttpClient\\RequestOptions;\n")
2324
if serviceHasRequestBody(operations) {
2425
buf.WriteString("use SumUp\\RequestEncoder;\n")
2526
}
@@ -196,7 +197,7 @@ func (g *Generator) renderServiceMethod(serviceClass string, op *operation) stri
196197
if op.HasBody {
197198
fmt.Fprintf(&buf, " * @param %s $body %s request payload\n", renderBodyDocType(op), renderBodyDocQualifier(op))
198199
}
199-
buf.WriteString(" * @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)\n")
200+
buf.WriteString(" * @param RequestOptions|null $requestOptions Optional typed request options\n")
200201

201202
buf.WriteString(" *\n")
202203
fmt.Fprintf(&buf, " * @return %s\n", renderOperationReturnDoc(op))
@@ -222,7 +223,7 @@ func (g *Generator) renderServiceMethod(serviceClass string, op *operation) stri
222223
if op.HasBody {
223224
args = append(args, renderBodyArgument(op))
224225
}
225-
args = append(args, "?array $requestOptions = null")
226+
args = append(args, "?RequestOptions $requestOptions = null")
226227

227228
buf.WriteString(" public function ")
228229
buf.WriteString(methodName)

examples/custom-http-client.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,13 @@ public function __construct(\SumUp\HttpClient\HttpClientInterface $wrappedClient
4242
$this->wrappedClient = $wrappedClient;
4343
}
4444

45-
public function send(string $method, string $url, array $body, array $headers, ?array $options = null): \SumUp\HttpClient\Response
46-
{
45+
public function send(
46+
string $method,
47+
string $url,
48+
array $body,
49+
array $headers,
50+
?\SumUp\HttpClient\RequestOptions $options = null
51+
): \SumUp\HttpClient\Response {
4752
// Log the request
4853
echo "[HTTP Request] {$method} {$url}\n";
4954
if (!empty($body)) {
@@ -86,6 +91,11 @@ public function send(string $method, string $url, array $body, array $headers, ?
8691
$merchant = $sumup->merchants()->get($merchantCode);
8792
echo "\nMerchant retrieved successfully!\n";
8893
echo "Merchant code: " . $merchant->merchantCode . "\n";
94+
} catch (\SumUp\Exception\ApiException $e) {
95+
echo "API error: " . $e->getMessage() . "\n";
96+
} catch (\SumUp\Exception\UnexpectedApiException $e) {
97+
echo "Unexpected API error: " . $e->getMessage() . "\n";
98+
echo "Envelope: " . json_encode($e->getErrorEnvelope()->toArray()) . "\n";
8999
} catch (\SumUp\Exception\SDKException $e) {
90100
echo "Error: " . $e->getMessage() . "\n";
91101
}

examples/guzzle-http-client.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
$merchant = $sumup->merchants()->get($merchantCode);
3939
echo "\nMerchant retrieved successfully!\n";
4040
echo "Merchant code: " . $merchant->merchantCode . "\n";
41+
} catch (\SumUp\Exception\ApiException $e) {
42+
echo "API error: " . $e->getMessage() . "\n";
43+
} catch (\SumUp\Exception\UnexpectedApiException $e) {
44+
echo "Unexpected API error: " . $e->getMessage() . "\n";
45+
echo "Envelope: " . json_encode($e->getErrorEnvelope()->toArray()) . "\n";
4146
} catch (\SumUp\Exception\SDKException $e) {
4247
echo "Error: " . $e->getMessage() . "\n";
4348
}

examples/oauth2/README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ $sumup = new \SumUp\SumUp();
8686
$sumup->setDefaultAccessToken($accessToken);
8787

8888
// Use the SDK normally
89-
$checkout = $sumup->checkouts()->create([
90-
'amount' => 10.00,
91-
'currency' => 'EUR',
92-
'checkout_reference' => 'order-123',
93-
'merchant_code' => $merchantCode,
94-
]);
89+
$request = new \SumUp\Types\CheckoutCreateRequest();
90+
$request->amount = 10.00;
91+
$request->currency = \SumUp\Types\CheckoutCreateRequestCurrency::EUR;
92+
$request->checkoutReference = 'order-123';
93+
$request->merchantCode = $merchantCode;
94+
95+
$checkout = $sumup->checkouts()->create($request);
9596
```
9697

9798
## Token Storage

examples/simple.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,17 @@
3333
// $sumup->setDefaultAccessToken('your-token-here');
3434

3535
// Use services with the default token
36-
$merchant = $sumup->merchants()->get($merchantCode);
37-
print_r($merchant);
36+
try {
37+
$requestOptions = new \SumUp\HttpClient\RequestOptions(timeout: 30, connectTimeout: 10);
38+
$merchant = $sumup->merchants()->get($merchantCode, null, $requestOptions);
39+
print_r($merchant);
40+
} catch (\SumUp\Exception\ApiException $e) {
41+
fwrite(STDERR, "API error: " . $e->getMessage() . "\n");
42+
} catch (\SumUp\Exception\UnexpectedApiException $e) {
43+
fwrite(STDERR, "Unexpected API error: " . $e->getMessage() . "\n");
44+
fwrite(STDERR, json_encode($e->getErrorEnvelope()->toArray(), JSON_PRETTY_PRINT) . "\n");
45+
} catch (\SumUp\Exception\SDKException $e) {
46+
fwrite(STDERR, "SDK error: " . $e->getMessage() . "\n");
47+
}
3848

3949
// Override the default token by creating a new client instance instead.

src/Checkouts/Checkouts.php

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace SumUp\Services;
88

99
use SumUp\HttpClient\HttpClientInterface;
10+
use SumUp\HttpClient\RequestOptions;
1011
use SumUp\RequestEncoder;
1112
use SumUp\ResponseDecoder;
1213
use SumUp\SdkInfo;
@@ -97,15 +98,15 @@ public function __construct(HttpClientInterface $client, string $accessToken)
9798
* Create a checkout
9899
*
99100
* @param \SumUp\Types\CheckoutCreateRequest|array<string, mixed> $body Required request payload
100-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
101+
* @param RequestOptions|null $requestOptions Optional typed request options
101102
*
102103
* @return \SumUp\Types\Checkout
103104
* @throws \SumUp\Exception\ApiException
104105
* @throws \SumUp\Exception\UnexpectedApiException
105106
* @throws \SumUp\Exception\ConnectionException
106107
* @throws \SumUp\Exception\SDKException
107108
*/
108-
public function create(\SumUp\Types\CheckoutCreateRequest|array $body, ?array $requestOptions = null): \SumUp\Types\Checkout
109+
public function create(\SumUp\Types\CheckoutCreateRequest|array $body, ?RequestOptions $requestOptions = null): \SumUp\Types\Checkout
109110
{
110111
$path = '/v0.1/checkouts';
111112
$payload = [];
@@ -130,15 +131,15 @@ public function create(\SumUp\Types\CheckoutCreateRequest|array $body, ?array $r
130131
* Deactivate a checkout
131132
*
132133
* @param string $id Unique ID of the checkout resource.
133-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
134+
* @param RequestOptions|null $requestOptions Optional typed request options
134135
*
135136
* @return \SumUp\Types\Checkout
136137
* @throws \SumUp\Exception\ApiException
137138
* @throws \SumUp\Exception\UnexpectedApiException
138139
* @throws \SumUp\Exception\ConnectionException
139140
* @throws \SumUp\Exception\SDKException
140141
*/
141-
public function deactivate(string $id, ?array $requestOptions = null): \SumUp\Types\Checkout
142+
public function deactivate(string $id, ?RequestOptions $requestOptions = null): \SumUp\Types\Checkout
142143
{
143144
$path = sprintf('/v0.1/checkouts/%s', rawurlencode((string) $id));
144145
$payload = [];
@@ -159,15 +160,15 @@ public function deactivate(string $id, ?array $requestOptions = null): \SumUp\Ty
159160
* Retrieve a checkout
160161
*
161162
* @param string $id Unique ID of the checkout resource.
162-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
163+
* @param RequestOptions|null $requestOptions Optional typed request options
163164
*
164165
* @return \SumUp\Types\CheckoutSuccess
165166
* @throws \SumUp\Exception\ApiException
166167
* @throws \SumUp\Exception\UnexpectedApiException
167168
* @throws \SumUp\Exception\ConnectionException
168169
* @throws \SumUp\Exception\SDKException
169170
*/
170-
public function get(string $id, ?array $requestOptions = null): \SumUp\Types\CheckoutSuccess
171+
public function get(string $id, ?RequestOptions $requestOptions = null): \SumUp\Types\CheckoutSuccess
171172
{
172173
$path = sprintf('/v0.1/checkouts/%s', rawurlencode((string) $id));
173174
$payload = [];
@@ -187,15 +188,15 @@ public function get(string $id, ?array $requestOptions = null): \SumUp\Types\Che
187188
* List checkouts
188189
*
189190
* @param CheckoutsListParams|null $queryParams Optional query string parameters
190-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
191+
* @param RequestOptions|null $requestOptions Optional typed request options
191192
*
192193
* @return \SumUp\Types\CheckoutSuccess[]
193194
* @throws \SumUp\Exception\ApiException
194195
* @throws \SumUp\Exception\UnexpectedApiException
195196
* @throws \SumUp\Exception\ConnectionException
196197
* @throws \SumUp\Exception\SDKException
197198
*/
198-
public function list(?CheckoutsListParams $queryParams = null, ?array $requestOptions = null): array
199+
public function list(?CheckoutsListParams $queryParams = null, ?RequestOptions $requestOptions = null): array
199200
{
200201
$path = '/v0.1/checkouts';
201202
if ($queryParams !== null) {
@@ -229,15 +230,15 @@ public function list(?CheckoutsListParams $queryParams = null, ?array $requestOp
229230
*
230231
* @param string $merchantCode The SumUp merchant code.
231232
* @param CheckoutsListAvailablePaymentMethodsParams|null $queryParams Optional query string parameters
232-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
233+
* @param RequestOptions|null $requestOptions Optional typed request options
233234
*
234235
* @return \SumUp\Services\CheckoutsListAvailablePaymentMethodsResponse
235236
* @throws \SumUp\Exception\ApiException
236237
* @throws \SumUp\Exception\UnexpectedApiException
237238
* @throws \SumUp\Exception\ConnectionException
238239
* @throws \SumUp\Exception\SDKException
239240
*/
240-
public function listAvailablePaymentMethods(string $merchantCode, ?CheckoutsListAvailablePaymentMethodsParams $queryParams = null, ?array $requestOptions = null): \SumUp\Services\CheckoutsListAvailablePaymentMethodsResponse
241+
public function listAvailablePaymentMethods(string $merchantCode, ?CheckoutsListAvailablePaymentMethodsParams $queryParams = null, ?RequestOptions $requestOptions = null): \SumUp\Services\CheckoutsListAvailablePaymentMethodsResponse
241242
{
242243
$path = sprintf('/v0.1/merchants/%s/payment-methods', rawurlencode((string) $merchantCode));
243244
if ($queryParams !== null) {
@@ -273,15 +274,15 @@ public function listAvailablePaymentMethods(string $merchantCode, ?CheckoutsList
273274
*
274275
* @param string $id Unique ID of the checkout resource.
275276
* @param \SumUp\Types\ProcessCheckout|array<string, mixed> $body Required request payload
276-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
277+
* @param RequestOptions|null $requestOptions Optional typed request options
277278
*
278279
* @return \SumUp\Types\CheckoutSuccess|\SumUp\Types\CheckoutAccepted
279280
* @throws \SumUp\Exception\ApiException
280281
* @throws \SumUp\Exception\UnexpectedApiException
281282
* @throws \SumUp\Exception\ConnectionException
282283
* @throws \SumUp\Exception\SDKException
283284
*/
284-
public function process(string $id, \SumUp\Types\ProcessCheckout|array $body, ?array $requestOptions = null): \SumUp\Types\CheckoutSuccess|\SumUp\Types\CheckoutAccepted
285+
public function process(string $id, \SumUp\Types\ProcessCheckout|array $body, ?RequestOptions $requestOptions = null): \SumUp\Types\CheckoutSuccess|\SumUp\Types\CheckoutAccepted
285286
{
286287
$path = sprintf('/v0.1/checkouts/%s', rawurlencode((string) $id));
287288
$payload = [];

src/Customers/Customers.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace SumUp\Services;
88

99
use SumUp\HttpClient\HttpClientInterface;
10+
use SumUp\HttpClient\RequestOptions;
1011
use SumUp\RequestEncoder;
1112
use SumUp\ResponseDecoder;
1213
use SumUp\SdkInfo;
@@ -59,15 +60,15 @@ public function __construct(HttpClientInterface $client, string $accessToken)
5960
* Create a customer
6061
*
6162
* @param \SumUp\Types\Customer|array<string, mixed> $body Required request payload
62-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
63+
* @param RequestOptions|null $requestOptions Optional typed request options
6364
*
6465
* @return \SumUp\Types\Customer
6566
* @throws \SumUp\Exception\ApiException
6667
* @throws \SumUp\Exception\UnexpectedApiException
6768
* @throws \SumUp\Exception\ConnectionException
6869
* @throws \SumUp\Exception\SDKException
6970
*/
70-
public function create(\SumUp\Types\Customer|array $body, ?array $requestOptions = null): \SumUp\Types\Customer
71+
public function create(\SumUp\Types\Customer|array $body, ?RequestOptions $requestOptions = null): \SumUp\Types\Customer
7172
{
7273
$path = '/v0.1/customers';
7374
$payload = [];
@@ -92,15 +93,15 @@ public function create(\SumUp\Types\Customer|array $body, ?array $requestOptions
9293
*
9394
* @param string $customerId Unique ID of the saved customer resource.
9495
* @param string $token Unique token identifying the card saved as a payment instrument resource.
95-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
96+
* @param RequestOptions|null $requestOptions Optional typed request options
9697
*
9798
* @return null
9899
* @throws \SumUp\Exception\ApiException
99100
* @throws \SumUp\Exception\UnexpectedApiException
100101
* @throws \SumUp\Exception\ConnectionException
101102
* @throws \SumUp\Exception\SDKException
102103
*/
103-
public function deactivatePaymentInstrument(string $customerId, string $token, ?array $requestOptions = null): null
104+
public function deactivatePaymentInstrument(string $customerId, string $token, ?RequestOptions $requestOptions = null): null
104105
{
105106
$path = sprintf('/v0.1/customers/%s/payment-instruments/%s', rawurlencode((string) $customerId), rawurlencode((string) $token));
106107
$payload = [];
@@ -123,15 +124,15 @@ public function deactivatePaymentInstrument(string $customerId, string $token, ?
123124
* Retrieve a customer
124125
*
125126
* @param string $customerId Unique ID of the saved customer resource.
126-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
127+
* @param RequestOptions|null $requestOptions Optional typed request options
127128
*
128129
* @return \SumUp\Types\Customer
129130
* @throws \SumUp\Exception\ApiException
130131
* @throws \SumUp\Exception\UnexpectedApiException
131132
* @throws \SumUp\Exception\ConnectionException
132133
* @throws \SumUp\Exception\SDKException
133134
*/
134-
public function get(string $customerId, ?array $requestOptions = null): \SumUp\Types\Customer
135+
public function get(string $customerId, ?RequestOptions $requestOptions = null): \SumUp\Types\Customer
135136
{
136137
$path = sprintf('/v0.1/customers/%s', rawurlencode((string) $customerId));
137138
$payload = [];
@@ -152,15 +153,15 @@ public function get(string $customerId, ?array $requestOptions = null): \SumUp\T
152153
* List payment instruments
153154
*
154155
* @param string $customerId Unique ID of the saved customer resource.
155-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
156+
* @param RequestOptions|null $requestOptions Optional typed request options
156157
*
157158
* @return \SumUp\Types\PaymentInstrumentResponse[]
158159
* @throws \SumUp\Exception\ApiException
159160
* @throws \SumUp\Exception\UnexpectedApiException
160161
* @throws \SumUp\Exception\ConnectionException
161162
* @throws \SumUp\Exception\SDKException
162163
*/
163-
public function listPaymentInstruments(string $customerId, ?array $requestOptions = null): array
164+
public function listPaymentInstruments(string $customerId, ?RequestOptions $requestOptions = null): array
164165
{
165166
$path = sprintf('/v0.1/customers/%s/payment-instruments', rawurlencode((string) $customerId));
166167
$payload = [];
@@ -184,15 +185,15 @@ public function listPaymentInstruments(string $customerId, ?array $requestOption
184185
*
185186
* @param string $customerId Unique ID of the saved customer resource.
186187
* @param CustomersUpdateRequest|array<string, mixed> $body Required request payload
187-
* @param array<string, mixed>|null $requestOptions Optional request options (timeout, connect_timeout, retries, retry_backoff_ms)
188+
* @param RequestOptions|null $requestOptions Optional typed request options
188189
*
189190
* @return \SumUp\Types\Customer
190191
* @throws \SumUp\Exception\ApiException
191192
* @throws \SumUp\Exception\UnexpectedApiException
192193
* @throws \SumUp\Exception\ConnectionException
193194
* @throws \SumUp\Exception\SDKException
194195
*/
195-
public function update(string $customerId, CustomersUpdateRequest|array $body, ?array $requestOptions = null): \SumUp\Types\Customer
196+
public function update(string $customerId, CustomersUpdateRequest|array $body, ?RequestOptions $requestOptions = null): \SumUp\Types\Customer
196197
{
197198
$path = sprintf('/v0.1/customers/%s', rawurlencode((string) $customerId));
198199
$payload = [];

0 commit comments

Comments
 (0)