Completed
Push — master ( c47873...6c8a44 )
by Taosikai
11:16
created

Requestor::setRequest()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 27
rs 8.5806
cc 4
eloc 16
nc 5
nop 3
1
<?php
2
/*
3
 * This file is part of the slince/youzan-pay package.
4
 *
5
 * (c) Slince <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Slince\YouzanPay;
12
13
use GuzzleHttp\Client;
14
use Slince\YouzanPay\Api\QRCode;
15
use Slince\YouzanPay\Api\Token;
16
use Slince\YouzanPay\Api\Trade;
17
18
class Requestor
19
{
20
    /**
21
     * @var ApiContext
22
     */
23
    protected static $apiContext;
24
25
    /**
26
     * @var Client
27
     */
28
    protected static $httpClient;
29
30
    /**
31
     * @var Token
32
     */
33
    protected static $token;
34
35
    /**
36
     * 获取 access token.
37
     *
38
     * @var string
39
     */
40
    const GET_TOKEN_ENDPOINT = 'https://open.youzan.com/oauth/token';
41
42
    /**
43
     * 创建支付二维码
44
     *
45
     * @var string
46
     */
47
    const CREATE_QR_ENDPOINT = 'https://open.youzan.com/api/oauthentry/youzan.pay.qrcode/3.0.0/create';
48
49
    /**
50
     * 获取支付二维码
51
     *
52
     * @var string
53
     */
54
    const GET_QR_ENDPOINT = 'https://open.youzan.com/api/oauthentry/youzan.pay.qrcode/3.0.0/get';
55
56
    /**
57
     * 获取qr对应的交易.
58
     *
59
     * @var string
60
     */
61
    const GET_TRADES_ENDPOINT = 'https://open.youzan.com/api/oauthentry/youzan.trades.qr/3.0.0/get';
62
63
    /**
64
     * 获取交易.
65
     *
66
     * @var string
67
     */
68
    const GET_TRADE_ENDPOINT = 'https://open.youzan.com/api/oauthentry/youzan.trade/3.0.0/get';
69
70
    /**
71
     * 获取access token.
72
     *
73
     * @return Token
74
     */
75
    public static function getAccessToken()
76
    {
77
        if (static::$token) {
78
            return static::$token;
79
        }
80
        $response = static::$httpClient->post(static::GET_TOKEN_ENDPOINT, [
81
            'form_params' => [
82
                'client_id' => static::$apiContext->getClientId(),
83
                'client_secret' => static::$apiContext->getClientSecret(),
84
                'grant_type' => 'silent',
85
                'kdt_id' => static::$apiContext->getKdtId(),
86
            ]
87
        ]);
88
        $json = \GuzzleHttp\json_decode((string) $response->getBody(), true);
89
        $expiresAt = new \DateTime($json['expires_in'] . ' seconds');
90
91
        return static::$token = new Token($json['access_token'], $expiresAt);
92
    }
93
94
    /**
95
     * 持久化qrcode.
96
     *
97
     * @param QRCode $qrCode
98
     */
99
    public static function persistQrCode(QRCode $qrCode)
100
    {
101
        $json = static::setRequest('post', static::CREATE_QR_ENDPOINT, [
102
            'qr_name' => $qrCode->getName(),
103
            'qr_price' => $qrCode->getPrice(),
104
            'qr_type' => $qrCode->getType(),
105
        ])['response'];
106
        $qrCode
107
            ->setId($json['qr_id'])
108
            ->setCode($json['qr_code'])
109
            ->setUrl($json['qr_url']);
110
    }
111
112
    /**
113
     * 检查QRCode支付结果.
114
     *
115
     * @param int|QRCode $qrCode
116
     *
117
     * @return bool
118
     */
119
    public static function checkQRCodePayResult($qrCode)
120
    {
121
        if ($qrCode instanceof QRCode) {
122
            $qrID = $qrCode->getId();
123
        } else {
124
            $qrID = $qrCode;
125
        }
126
        $json = static::setRequest('get', static::GET_TRADES_ENDPOINT, [
127
            'qr_id' => $qrID,
128
            'status' => 'TRADE_RECEIVED',
129
        ])['response'];
130
131
        return $json['total_results'] > 0;
132
    }
133
134
    /**
135
     * 获取交易.
136
     *
137
     * @param int $id
138
     *
139
     * @return Trade
140
     */
141
    public static function getTrade($id)
142
    {
143
        $json = static::setRequest('get', static::GET_TRADE_ENDPOINT, [
144
            'tid' => $id,
145
        ])['response'];
146
        $trade = new Trade();
147
        $trade->setId($id)
148
            ->setCreated(new \DateTime($json['created']))
149
            ->setQrId($json['qr_id'])
150
            ->setStatus($json['status']);
151
152
        return $trade;
153
    }
154
155
    protected static function setRequest($method, $uri, $parameters)
156
    {
157
        $token = static::getAccessToken();
158
        if (!$token->isValid()) {
159
            throw new \InvalidArgumentException(sprintf('The token "%s" is invalid', $token->getAccessToken()));
160
        }
161
        $parameters['access_token'] = $token->getAccessToken();
162
163
        if (strcasecmp($method, 'post') === 0) {
164
            $options['form_params'] = $parameters;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
165
        } else {
166
            $options['query'] = $parameters;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
167
        }
168
169
        $response = static::$httpClient->request($method, $uri, $options);
170
171
        $json = \GuzzleHttp\json_decode((string) $response->getBody(), true);
172
173
        if (isset($json['error_response'])) {
174
            throw new \RuntimeException(sprintf('Error request, "%d": "%s"',
175
                $json['error_response']['code'],
176
                $json['error_response']['msg']
177
            ));
178
        }
179
180
        return $json;
181
    }
182
183
    /**
184
     * @param ApiContext $apiContext
185
     */
186
    public static function setApiContext($apiContext)
187
    {
188
        self::$apiContext = $apiContext;
189
    }
190
191
    /**
192
     * @param Client $httpClient
193
     */
194
    public static function setHttpClient($httpClient)
195
    {
196
        self::$httpClient = $httpClient;
197
    }
198
199
    /**
200
     * @param Token $token
201
     */
202
    public static function setToken($token)
203
    {
204
        self::$token = $token;
205
    }
206
}