Completed
Push — master ( f64a2b...48aedc )
by thomas
05:58
created

GuzzleHttpClient::post()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 0
cts 8
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 4
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Bip70\Client;
6
7
use Bip70\Protobuf\Codec\NonDiscardingBinaryCodec;
8
use Bip70\Protobuf\Proto\Payment;
9
use Bip70\Protobuf\Proto\PaymentACK;
10
use Bip70\Protobuf\Proto\PaymentDetails;
11
use Bip70\Protobuf\Proto\PaymentRequest;
12
use Bip70\X509\RequestValidation;
13
use Bip70\X509\PKIType;
14
use GuzzleHttp\Client;
15
use Psr\Http\Message\ResponseInterface;
16
17
class GuzzleHttpClient
18
{
19
    /**
20
     * @var \GuzzleHttp\Client
21
     */
22
    private $client;
23
24
    /**
25
     * @var bool
26
     */
27
    private $checkContentType = true;
28
29
    /**
30
     * HttpClient constructor.
31
     * @param Client|null $client
32
     */
33 4
    public function __construct(Client $client = null)
34
    {
35 4
        $this->client = $client ?: new Client();
36 4
    }
37
38
    /**
39
     * @param bool $setting
40
     * @return void
41
     */
42
    public function setCheckContentType(bool $setting)
43
    {
44
        $this->checkContentType = $setting;
45
    }
46
47
    /**
48
     * @param string $url
49
     * @param string $acceptType
50
     * @return ResponseInterface
51
     */
52 4
    private function get($url, string $acceptType)
53
    {
54
        $options = [
55 4
            "headers" => ["Accept" => $acceptType,]
56
        ];
57
58 4
        $response = $this->client->get($url, $options);
59
60 4
        if ($this->checkContentType) {
61 4
            $this->checkContentType($acceptType, $response);
62
        }
63
64 2
        return $response;
65
    }
66
67
    /**
68
     * @param string $url
69
     * @param string $acceptType
70
     * @param string $dataMIMEType
71
     * @param string $data
72
     * @return ResponseInterface
73
     */
74
    private function post(string $url, string $acceptType, string $dataMIMEType, string $data): ResponseInterface
75
    {
76
        $options = [
77
            "headers" => [
78
                "Accept" => $acceptType,
79
                "Content-Type" => $dataMIMEType,
80
            ],
81
            'body' => $data,
82
        ];
83
84
        $response = $this->client->post($url, $options);
85
86
        if ($this->checkContentType) {
87
            $this->checkContentType($acceptType, $response);
88
        }
89
90
        return $response;
91
    }
92
93
    /**
94
     * @param string $expectType
95
     * @param ResponseInterface $response
96
     */
97 4
    public function checkContentType(string $expectType, ResponseInterface $response)
98
    {
99 4
        if (!$response->hasHeader("Content-Type")) {
100 1
            throw new \RuntimeException("Missing content-type header");
101
        }
102
103 3
        $contentType = $response->getHeader("Content-Type");
104 3
        if (!in_array($expectType, $contentType)) {
105 1
            throw new \RuntimeException("Content-type was not " . $expectType);
106
        }
107 2
    }
108
109
    /**
110
     * @param string $requestUrl
111
     * @param RequestValidation $requestValidation
112
     * @return PaymentRequestInfo
113
     */
114 4
    public function getRequest(string $requestUrl, RequestValidation $requestValidation): PaymentRequestInfo
115
    {
116 4
        $response = $this->get($requestUrl, MIMEType::PAYMENT_REQUEST);
117 2
        $paymentRequest = new PaymentRequest();
118
119
        try {
120 2
            $contents = $response->getBody()->getContents();
121 2
            $paymentRequest->parse($contents, new NonDiscardingBinaryCodec());
122
        } catch (\Exception $e) {
123
            throw new \RuntimeException("Failed to decode payment request");
124
        }
125
126 2
        $validationResult = null;
127 2
        if ($paymentRequest->getPkiType() !== PKIType::NONE) {
128 1
            $validationResult = $requestValidation->verifyX509Details($paymentRequest);
129
        }
130
131 2
        return new PaymentRequestInfo($paymentRequest, $validationResult);
132
    }
133
134
    /**
135
     * @param PaymentDetails $details
136
     * @param string|null $memo
137
     * @param string ...$transactions
138
     * @return PaymentACK
139
     */
140
    public function sendPayment(PaymentDetails $details, string $memo = null, string ...$transactions): PaymentACK
141
    {
142
        if (!$details->hasPaymentUrl()) {
143
            throw new \RuntimeException("No payment url set on details");
144
        }
145
146
        $payment = new Payment();
147
        foreach ($transactions as $transaction) {
148
            $payment->addTransactions($transaction);
149
        }
150
151
        if ($details->hasMerchantData()) {
152
            $payment->setMerchantData($details->getMerchantData());
153
        }
154
155
        if ($memo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $memo of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
156
            $payment->setMemo($memo);
157
        }
158
159
        $paymentData = $payment->serialize();
160
        $result = $this->post($details->getPaymentUrl(), MIMEType::PAYMENT_ACK, MIMEType::PAYMENT, $paymentData);
161
162
        $ack = new PaymentACK();
163
164
        try {
165
            $ack->parse($result->getBody()->getContents());
166
        } catch (\Exception $e) {
167
            throw new \RuntimeException("Failed to decode Payment ACK message");
168
        }
169
170
        return $ack;
171
    }
172
}
173