Completed
Push — master ( 0deadb...30819c )
by recca
01:49
created

Api::calculateHash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 2.0185
1
<?php
2
3
namespace PayumTW\Ips;
4
5
use Http\Message\MessageFactory;
6
use Payum\Core\HttpClientInterface;
7
8
class Api
9
{
10
    /**
11
     * @var \Payum\Core\HttpClientInterface
12
     */
13
    protected $client;
14
15
    /**
16
     * @var \Http\Message\MessageFactory
17
     */
18
    protected $messageFactory;
19
20
    /**
21
     * @var array
22
     */
23
    protected $options = [];
24
25
    /**
26
     * @var array
27
     */
28
    protected $heads = [
29
        'Version',
30
        'MerCode',
31
        'MerName',
32
        'Account',
33
        'MsgId',
34
        'ReqDate',
35
        'Signature',
36
        'ReferenceID',
37
        'RspCode',
38
        'RspMsg',
39
        'RspDate',
40
    ];
41
42
    /**
43
     * @var array
44
     */
45
    protected $cdata = [
46
        'Merchanturl',
47
        'FailUrl',
48
        'ServerUrl',
49
        'GoodsName',
50
        'MsgId',
51
        'RspMsg',
52
        'Msg',
53
    ];
54
55
    /**
56
     * @param array $options
57
     * @param \Payum\Core\HttpClientInterface $client
58
     * @param \Http\Message\MessageFactory $messageFactory
59
     *
60
     * @throws \Payum\Core\Exception\InvalidArgumentException if an option is invalid
61
     */
62 4
    public function __construct(array $options, HttpClientInterface $client, MessageFactory $messageFactory)
63
    {
64 4
        $this->options = $options;
65 4
        $this->client = $client;
66 4
        $this->messageFactory = $messageFactory;
67 4
    }
68
69
    /**
70
     * getApiEndpoint.
71
     *
72
     * @return string
73
     */
74
    public function getApiEndpoint($type = 'capture')
75
    {
76
        $map = [
77
            'capture' => 'https://newpay.ips.com.cn/psfp-entry/gateway/payment.do',
78
            'h5' => 'https://mobilegw.ips.com.cn/psfp-mgw/paymenth5.do',
79
            'refund' => 'https://newpay.ips.com.cn/psfp-entry/services/refund?wsdl',
80
            'order' => 'https://newpay.ips.com.cn/psfp-entry/services/order?wsdl',
81
            'trade' => 'https://newpay.ips.com.cn/psfp-entry/services/trade?wsdl',
82
        ];
83
84
        return $map[$type];
85
    }
86
87
    /**
88
     * createTransaction.
89
     *
90
     * @param array $params
91
     * @return array
92
     */
93 1
    public function createTransaction(array $params)
94
    {
95
        $supportedParams = [
96 1
            'Version' => $this->options['Version'],
97 1
            'MerCode' => $this->options['MerCode'],
98 1
            'MerName' => $this->options['MerName'],
99 1
            'Account' => $this->options['Account'],
100
            'MsgId' => null,
101 1
            'ReqDate' => date('YmdHis'),
102
103
            'MerBillNo' => null,
104 1
            'GatewayType' => '01',
105 1
            'Date' => date('Ymd'),
106 1
            'CurrencyType' => 156,
107 1
            'Amount' => 0,
108 1
            'Lang' => 'GB',
109
            'Merchanturl' => null,
110
            'FailUrl' => null,
111
            'Attach' => null,
112
            /*
113
             * 说明:存放商户所选择订单支 付接口加密方式。
114
             * 5#订单支付采用 Md5 的摘要 讣证方式
115
             */
116 1
            'OrderEncodeType' => 5,
117
            /*
118
             *返回给商户其所选用的交易 返回签名方式
119
             *16#Md5WithRsa 数字签 名方式
120
             *17#Md5数字签名方式
121
             */
122 1
            'RetEncodeType' => 17,
123
            /*
124
             * Server to Server 返回。
125
             * 1#S2S返回
126
             */
127 1
            'RetType' => 1,
128
            'ServerUrl' => null,
129
            'BillEXP' => null,
130
            'GoodsName' => null,
131
            'IsCredit' => null,
132
            'BankCode' => null,
133
            'ProductType' => null,
134
        ];
135
136 1
        $params = array_filter(array_replace(
137
            $supportedParams,
138
            array_intersect_key($params, $supportedParams)
139
        ));
140
141
        return [
142 1
            'pGateWayReq' => $this->generatGetwayRequest($params),
143
        ];
144
    }
145
146
    /**
147
     * getTransactionData.
148
     *
149
     * @param mixed $params
150
     * @return array
151
     */
152
    public function getTransactionData(array $params)
1 ignored issue
show
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
153
    {
154
        return [];
155
    }
156
157
    /**
158
     * Verify if the hash of the given parameter is correct.
159
     *
160
     * @param array $params
161
     * @return bool
162
     */
163
    public function verifyHash(array $params)
164
    {
165
        return $params['Signature'] === $this->calculateHash($params);
166
    }
167
168
    /**
169
     * parseResponse.
170
     *
171
     * @param string $response
172
     * @return string
173
     */
174 2
    public function parseResponse($response)
175
    {
176 2
        $paymentResult = str_replace(['<![CDATA[', ']]>'], '', $response['paymentResult']);
177 2
        $tags = $this->parseResultTags($paymentResult);
178 2
        $regexp = '/<(?<key>'.implode('|', $tags).')>(?<value>[^<]*)<\/('.implode('|', $tags).')>/';
179 2
        if (preg_match_all($regexp, $paymentResult, $matches, PREG_SET_ORDER)) {
180 2
            foreach ($matches as $match) {
181 2
                $response[$match['key']] = $match['value'];
182
            }
183
        }
184
185 2
        return $response;
186
    }
187
188
    /**
189
     * generatGetwayRequest.
190
     *
191
     * @param array $params
192
     * @return string
193
     */
194 2
    protected function generatGetwayRequest($params)
195
    {
196 2
        $params['Signature'] = $this->calculateHash($params);
197 2
        $params = $this->split($this->addCdata($params));
198
199 2
        return $this->convertToXML([
200
            'Ips' => [
201 2
                'GateWayReq' => $params,
202
            ],
203
        ]);
204
    }
205
206
    /**
207
     * convertToXML.
208
     *
209
     * @param array $params
210
     * @return string
211
     */
212 2
    protected function convertToXML($params)
213
    {
214 2
        $xml = '';
215 2
        foreach ($params as $key => $value) {
216 2
            if (is_array($value) === true) {
217 2
                $value = $this->convertToXML($value);
218
            }
219
220 2
            $xml .= '<'.$key.'>'.$value.'</'.$key.'>';
221
        }
222
223 2
        return $xml;
224
    }
225
226
    /**
227
     * split.
228
     *
229
     * @param array $params
230
     * @return array
231
     */
232 2
    protected function split($params)
233
    {
234 2
        $head = [];
235 2
        $body = [];
236
237 2
        foreach ($params as $key => $value) {
238 2
            if (in_array($key, $this->heads, true) === true) {
239 2
                $head[$key] = $value;
240
            } else {
241 2
                $body[$key] = $value;
242
            }
243
        }
244
245 2
        return compact('head', 'body');
246
    }
247
248
    /**
249
     * addCdata.
250
     *
251
     * @param array $params
252
     * @return array
253
     */
254 2
    protected function addCdata($params)
255
    {
256 2
        foreach ($this->cdata as $cdata) {
257 2
            if (empty($params[$cdata]) === false) {
258 2
                $params[$cdata] = '<![CDATA['.$params[$cdata].']]>';
259
            }
260
        }
261
262 2
        return $params;
263
    }
264
265
    /**
266
     * calculateHash.
267
     *
268
     * @param array $params
269
     * @return string
270
     */
271 2
    protected function calculateHash(array $params)
272
    {
273 2
        if (isset($params['paymentResult']) === true) {
274
            unset($params['paymentResult']);
275
        }
276
277 2
        $params = $this->split($params);
278 2
        $body = $this->addCdata($params['body']);
279
280 2
        return hash('md5', $this->convertToXML(['body' => $body]).$this->options['MerCode'].$this->options['MerKey']);
281
    }
282
283
    /**
284
     * parseResultTags.
285
     *
286
     * @param string $paymentResult
287
     * @return array
288
     */
289 2
    protected function parseResultTags($paymentResult)
290
    {
291 2
        $result = [];
292 2
        if (preg_match_all('/<([^\/]+?)>/', $paymentResult, $tags)) {
293 2
            $result = array_diff($tags[1], ['Ips', 'GateWayRsp', 'head', 'body']);
294
        }
295
296 2
        return $result;
297
    }
298
299
    /**
300
     * isSandbox.
301
     *
302
     * @return bool
303
     */
304 1
    public function isSandbox()
305
    {
306 1
        return $this->options['sandbox'];
307
    }
308
309
    /**
310
     * generateTestingResponse.
311
     *
312
     * @param array $params
313
     * @return array
314
     */
315 1
    public function generateTestingResponse($params = [])
316
    {
317
        $supportedParams = [
318 1
            'ReferenceID' => '',
319 1
            'RspCode' => '000000',
320 1
            'RspMsg' => '交易成功!',
321 1
            'ReqDate' => date('YmdHis'),
322 1
            'RspDate' => date('YmdHis'),
323 1
            'CurrencyType' => 156,
324
            'Amount' => null,
325 1
            'Date' => date('Ymd'),
326 1
            'Status' => 'Y',
327 1
            'Msg' => '支付成功!',
328 1
            'IpsBillNo' => date('YmdHis'),
329 1
            'IpsTradeNo' => date('YmdHis'),
330 1
            'RetEncodeType' => 17,
331 1
            'BankBillNo' => '710002875951',
332 1
            'ResultType' => 0,
333 1
            'IpsBillTime' => date('YmdHis'),
334
        ];
335
336 1
        $params = array_filter(array_replace(
337
            $supportedParams,
338
            array_intersect_key($params, $supportedParams)
339
        ));
340
341
        return [
342 1
            'paymentResult' => $this->generatGetwayRequest($params),
343
        ];
344
    }
345
}
346