Api   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 338
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 89.31%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 0
dl 0
loc 338
ccs 117
cts 131
cp 0.8931
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getApiEndpoint() 0 12 1
A getTransactionData() 0 4 1
A verifyHash() 0 4 1
A createTransaction() 0 52 1
A parseResponse() 0 13 3
A isSandbox() 0 4 1
B generateTestingResponse() 0 30 1
A generatGetwayRequest() 0 11 1
A convertToXML() 0 13 3
A split() 0 15 3
A addCdata() 0 10 3
A calculateHash() 0 11 2
A parseResultTags() 0 9 2
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 1
            'MsgId' => null,
101 1
            'ReqDate' => date('YmdHis'),
102
103 1
            'MerBillNo' => null,
104 1
            'GatewayType' => '01',
105 1
            'Date' => date('Ymd'),
106 1
            'CurrencyType' => 156,
107 1
            'Amount' => 0,
108 1
            'Lang' => 'GB',
109 1
            'Merchanturl' => null,
110 1
            'FailUrl' => null,
111 1
            '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 1
            'ServerUrl' => null,
129 1
            'BillEXP' => null,
130 1
            'GoodsName' => null,
131 1
            'IsCredit' => null,
132 1
            'BankCode' => null,
133 1
            'ProductType' => null,
134 1
        ];
135
136 1
        $params = array_filter(array_replace(
137 1
            $supportedParams,
138 1
            array_intersect_key($params, $supportedParams)
139 1
        ));
140
141
        return [
142 1
            'pGateWayReq' => $this->generatGetwayRequest($params),
143 1
        ];
144
    }
145
146
    /**
147
     * getTransactionData.
148
     *
149
     * @param mixed $params
150
     * @return array
151
     */
152
    public function getTransactionData(array $params)
0 ignored issues
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 2
            }
183 2
        }
184
185 2
        return $response;
186
    }
187
188
    /**
189
     * isSandbox.
190
     *
191
     * @return bool
192
     */
193 1
    public function isSandbox()
194
    {
195 1
        return $this->options['sandbox'];
196
    }
197
198
    /**
199
     * generateTestingResponse.
200
     *
201
     * @param array $params
202
     * @return array
203
     */
204 1
    public function generateTestingResponse($params = [])
205
    {
206
        $supportedParams = [
207 1
            'ReferenceID' => '',
208 1
            'RspCode' => '000000',
209 1
            'RspMsg' => '交易成功!',
210 1
            'ReqDate' => date('YmdHis'),
211 1
            'RspDate' => date('YmdHis'),
212 1
            'CurrencyType' => 156,
213 1
            'Amount' => null,
214 1
            'Date' => date('Ymd'),
215 1
            'Status' => 'Y',
216 1
            'Msg' => '支付成功!',
217 1
            'IpsBillNo' => date('YmdHis'),
218 1
            'IpsTradeNo' => date('YmdHis'),
219 1
            'RetEncodeType' => 17,
220 1
            'BankBillNo' => '710002875951',
221 1
            'ResultType' => 0,
222 1
            'IpsBillTime' => date('YmdHis'),
223 1
        ];
224
225 1
        $params = array_filter(array_replace(
226 1
            $supportedParams,
227 1
            array_intersect_key($params, $supportedParams)
228 1
        ));
229
230
        return [
231 1
            'paymentResult' => $this->generatGetwayRequest($params),
232 1
        ];
233
    }
234
235
    /**
236
     * generatGetwayRequest.
237
     *
238
     * @param array $params
239
     * @return string
240
     */
241 2
    protected function generatGetwayRequest($params)
242
    {
243 2
        $params['Signature'] = $this->calculateHash($params);
244 2
        $params = $this->split($this->addCdata($params));
245
246 2
        return $this->convertToXML([
247
            'Ips' => [
248 2
                'GateWayReq' => $params,
249 2
            ],
250 2
        ]);
251
    }
252
253
    /**
254
     * convertToXML.
255
     *
256
     * @param array $params
257
     * @return string
258
     */
259 2
    protected function convertToXML($params)
260
    {
261 2
        $xml = '';
262 2
        foreach ($params as $key => $value) {
263 2
            if (is_array($value) === true) {
264 2
                $value = $this->convertToXML($value);
265 2
            }
266
267 2
            $xml .= '<'.$key.'>'.$value.'</'.$key.'>';
268 2
        }
269
270 2
        return $xml;
271
    }
272
273
    /**
274
     * split.
275
     *
276
     * @param array $params
277
     * @return array
278
     */
279 2
    protected function split($params)
280
    {
281 2
        $head = [];
282 2
        $body = [];
283
284 2
        foreach ($params as $key => $value) {
285 2
            if (in_array($key, $this->heads, true) === true) {
286 2
                $head[$key] = $value;
287 2
            } else {
288 2
                $body[$key] = $value;
289
            }
290 2
        }
291
292 2
        return compact('head', 'body');
293
    }
294
295
    /**
296
     * addCdata.
297
     *
298
     * @param array $params
299
     * @return array
300
     */
301 2
    protected function addCdata($params)
302
    {
303 2
        foreach ($this->cdata as $cdata) {
304 2
            if (empty($params[$cdata]) === false) {
305 2
                $params[$cdata] = '<![CDATA['.$params[$cdata].']]>';
306 2
            }
307 2
        }
308
309 2
        return $params;
310
    }
311
312
    /**
313
     * calculateHash.
314
     *
315
     * @param array $params
316
     * @return string
317
     */
318 2
    protected function calculateHash(array $params)
319
    {
320 2
        if (isset($params['paymentResult']) === true) {
321
            unset($params['paymentResult']);
322
        }
323
324 2
        $params = $this->split($params);
325 2
        $body = $this->addCdata($params['body']);
326
327 2
        return hash('md5', $this->convertToXML(['body' => $body]).$this->options['MerCode'].$this->options['MerKey']);
328
    }
329
330
    /**
331
     * parseResultTags.
332
     *
333
     * @param string $paymentResult
334
     * @return array
335
     */
336 2
    protected function parseResultTags($paymentResult)
337
    {
338 2
        $result = [];
339 2
        if (preg_match_all('/<([^\/]+?)>/', $paymentResult, $tags)) {
340 2
            $result = array_diff($tags[1], ['Ips', 'GateWayRsp', 'head', 'body']);
341 2
        }
342
343 2
        return $result;
344
    }
345
}
346