This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace PayumTW\Esunbank; |
||
4 | |||
5 | use LogicException; |
||
6 | use Detection\MobileDetect; |
||
7 | use Http\Message\MessageFactory; |
||
8 | use Payum\Core\HttpClientInterface; |
||
9 | use Payum\Core\Exception\Http\HttpException; |
||
10 | |||
11 | class Api |
||
12 | { |
||
13 | /** |
||
14 | * @var \Payum\Core\HttpClientInterface |
||
15 | */ |
||
16 | protected $client; |
||
17 | |||
18 | /** |
||
19 | * @var \Http\Message\MessageFactory |
||
20 | */ |
||
21 | protected $messageFactory; |
||
22 | |||
23 | /** |
||
24 | * @var array |
||
25 | */ |
||
26 | protected $options = []; |
||
27 | |||
28 | /** |
||
29 | * $encrypter. |
||
30 | * |
||
31 | * @var Encrypter |
||
32 | */ |
||
33 | protected $encrypter; |
||
34 | |||
35 | /** |
||
36 | * @param array $options |
||
37 | * @param \Payum\Core\HttpClientInterface $client |
||
38 | * @param \Http\Message\MessageFactory $messageFactory |
||
39 | * @param Encrypter $encrypter |
||
40 | * |
||
41 | * @throws \Payum\Core\Exception\InvalidArgumentException if an option is invalid |
||
42 | */ |
||
43 | 14 | public function __construct(array $options, HttpClientInterface $client, MessageFactory $messageFactory, Encrypter $encrypter = null) |
|
44 | { |
||
45 | 14 | $this->options = $options; |
|
46 | 14 | $this->client = $client; |
|
47 | 14 | $this->messageFactory = $messageFactory; |
|
48 | 14 | $this->encrypter = $encrypter ?: new Encrypter(); |
|
49 | 14 | $this->encrypter->setKey($this->options['M']); |
|
50 | 14 | } |
|
51 | |||
52 | /** |
||
53 | * parseResponse. |
||
54 | * |
||
55 | * @param array $response |
||
56 | 3 | * @return array |
|
57 | */ |
||
58 | 3 | public function parseResponse($response) |
|
59 | 3 | { |
|
60 | 3 | if (is_string($response) === true) { |
|
61 | $response = $this->parseStr($response); |
||
62 | 3 | } |
|
63 | |||
64 | 3 | if (empty($response['DATA']) === true) { |
|
65 | throw new LogicException('Response content is not valid'); |
||
66 | } |
||
67 | |||
68 | 3 | $data = json_decode($response['DATA'], true); |
|
69 | 3 | ||
70 | 3 | if (json_last_error() !== JSON_ERROR_NONE) { |
|
71 | $data = []; |
||
72 | parse_str(str_replace(',', '&', $response['DATA']), $data); |
||
73 | } |
||
74 | |||
75 | if (isset($data['returnCode']) === true) { |
||
76 | $response['returnCode'] = $data['returnCode']; |
||
77 | } |
||
78 | |||
79 | 9 | if (isset($data['version']) === true) { |
|
80 | $response['version'] = $data['version']; |
||
81 | 9 | } |
|
82 | 9 | ||
83 | 9 | if (isset($data['txnData']) === true) { |
|
84 | $response = array_merge($response, $data['txnData']); |
||
85 | 9 | unset($data['txnData']); |
|
86 | } |
||
87 | |||
88 | return array_merge($response, $data); |
||
89 | 9 | } |
|
90 | |||
91 | 9 | /** |
|
92 | 7 | * getApiEndpoint. |
|
93 | 7 | * |
|
94 | 7 | * @return string |
|
95 | */ |
||
96 | 9 | public function getApiEndpoint($type = 'capture') |
|
97 | 2 | { |
|
98 | 2 | if ($this->options['sandbox'] === false) { |
|
99 | $urls = [ |
||
100 | 9 | 'capture' => $this->isMobile() === false ? 'https://acq.esunbank.com.tw/ACQTrans/esuncard/txnf014s' : 'https://acq.esunbank.com.tw/ACQTrans/esuncard/txnf014m', |
|
101 | 2 | 'cancel' => 'https://acq.esunbank.com.tw/ACQTrans/esuncard/txnf0150', |
|
102 | 2 | 'refund' => 'https://acq.esunbank.com.tw/ACQTrans/esuncard/txnf0160', |
|
103 | 'sync' => 'https://acq.esunbank.com.tw/ACQQuery/esuncard/txnf0180', |
||
104 | 9 | ]; |
|
105 | 2 | } else { |
|
106 | 2 | $urls = [ |
|
107 | 2 | 'capture' => $this->isMobile() === false ? 'https://acqtest.esunbank.com.tw/ACQTrans/esuncard/txnf014s' : 'https://acqtest.esunbank.com.tw/ACQTrans/esuncard/txnf014m', |
|
108 | 'cancel' => 'https://acqtest.esunbank.com.tw/ACQTrans/esuncard/txnf0150', |
||
109 | 9 | 'refund' => 'https://acqtest.esunbank.com.tw/ACQTrans/esuncard/txnf0160', |
|
110 | 'sync' => 'https://acqtest.esunbank.com.tw/ACQQuery/esuncard/txnf0180', |
||
111 | ]; |
||
112 | } |
||
113 | |||
114 | return $urls[$type]; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | 9 | * createTransaction. |
|
119 | * |
||
120 | 9 | * @param array $params |
|
121 | 9 | * @return array |
|
122 | */ |
||
123 | 9 | public function createTransaction(array $params) |
|
124 | { |
||
125 | $supportedParams = [ |
||
126 | // 訂單編號, 由特約商店產生,不可重複,不可 包含【_】字元,英數限用大寫 |
||
127 | 'ONO' => '', |
||
128 | // 回覆位址, 'https://acqtest.esunbank.com.tw/ACQTrans/test/print.jsp' |
||
129 | 'U' => 'https://acqtest.esunbank.com.tw/ACQTrans/test/print.jsp', |
||
130 | // 特店代碼 |
||
131 | 3 | 'MID' => $this->options['MID'], |
|
132 | // 銀行紅利折抵, Y:使用銀行紅利交易。 N:不使用銀行紅利交易 |
||
133 | 3 | 'BPF' => 'N', |
|
134 | // 分期代碼, 三期:0100103 六期:0100106 正式環境參數由業務經辦提供 |
||
135 | 'IC' => '', |
||
136 | // 交易金額, 台幣(901) |
||
137 | 'TA' => '', |
||
138 | // 終端機代號, EC000001(一般交易) EC000002(分期) |
||
139 | 'TID' => 'EC000001', |
||
140 | ]; |
||
141 | |||
142 | 3 | $params = array_replace( |
|
143 | 3 | $supportedParams, |
|
144 | 3 | array_intersect_key($params, $supportedParams) |
|
145 | 3 | ); |
|
146 | 3 | ||
147 | if (empty($params['IC']) === true) { |
||
148 | unset($params['IC']); |
||
149 | 3 | } else { |
|
150 | $params['TID'] = 'EC000002'; |
||
151 | } |
||
152 | |||
153 | $params['BPF'] = strtoupper($params['BPF']); |
||
154 | if ($params['BPF'] === 'N') { |
||
155 | unset($params['BPF']); |
||
156 | } |
||
157 | |||
158 | 4 | return $this->encrypter->encryptRequest($params); |
|
159 | } |
||
160 | |||
161 | /** |
||
162 | 4 | * getTransactionData. |
|
163 | * |
||
164 | 4 | * @param mixed $params |
|
165 | * @return array |
||
166 | 4 | */ |
|
167 | View Code Duplication | public function getTransactionData(array $params) |
|
0 ignored issues
–
show
|
|||
168 | 4 | { |
|
169 | $supportedParams = [ |
||
170 | 4 | // 訂單編號, 由特約商店產生,不可重複,不可 包含【_】字元,英數限用大寫 |
|
171 | 'ONO' => '', |
||
172 | 4 | // 特店代碼 |
|
173 | 'MID' => $this->options['MID'], |
||
174 | 4 | ]; |
|
175 | 4 | ||
176 | $params = array_replace( |
||
177 | 4 | $supportedParams, |
|
178 | 4 | array_intersect_key($params, $supportedParams) |
|
179 | 4 | ); |
|
180 | 4 | ||
181 | return $this->doRequest($params, 'sync'); |
||
182 | 4 | } |
|
183 | 2 | ||
184 | 2 | /** |
|
185 | 2 | * refundTransaction. |
|
186 | * |
||
187 | * @param array $params |
||
188 | 4 | * @return array |
|
189 | 4 | */ |
|
190 | 2 | public function refundTransaction(array $params) |
|
191 | 2 | { |
|
192 | $supportedParams = [ |
||
193 | 4 | // 05:授權 51:取消授權 71:退貨授權 |
|
194 | 'TYP' => '71', |
||
195 | // 訂單編號, 由特約商店產生,不可重複,不可 包含【_】字元,英數限用大寫 |
||
196 | 'ONO' => null, |
||
197 | // 特店代碼 |
||
198 | 'MID' => $this->options['MID'], |
||
199 | // 專案資訊 |
||
200 | 'C' => null, |
||
201 | ]; |
||
202 | 1 | ||
203 | $params = array_replace( |
||
204 | $supportedParams, |
||
205 | array_intersect_key($params, $supportedParams) |
||
206 | 1 | ); |
|
207 | |||
208 | 1 | return $this->doRequest($params, 'refund'); |
|
209 | 1 | } |
|
210 | |||
211 | 1 | /** |
|
212 | 1 | * cancelTransaction. |
|
213 | 1 | * |
|
214 | 1 | * @param array $params |
|
215 | * @return array |
||
216 | 1 | */ |
|
217 | View Code Duplication | public function cancelTransaction(array $params) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
218 | { |
||
219 | $supportedParams = [ |
||
220 | // 訂單編號, 由特約商店產生,不可重複,不可 包含【_】字元,英數限用大寫 |
||
221 | 'ONO' => '', |
||
222 | // 特店代碼 |
||
223 | 'MID' => $this->options['MID'], |
||
224 | ]; |
||
225 | 1 | ||
226 | $params = array_replace( |
||
227 | $supportedParams, |
||
228 | array_intersect_key($params, $supportedParams) |
||
229 | 1 | ); |
|
230 | |||
231 | 1 | return $this->doRequest($params, 'cancel'); |
|
232 | } |
||
233 | 1 | ||
234 | /** |
||
235 | 1 | * @param array $params |
|
236 | 1 | * @return string |
|
237 | */ |
||
238 | 1 | public function calculateHash($params) |
|
239 | 1 | { |
|
240 | 1 | return $this->encrypter->encrypt($params); |
|
241 | 1 | } |
|
242 | |||
243 | 1 | /** |
|
244 | * verifyHash. |
||
245 | * |
||
246 | * @param array $response |
||
247 | * @return bool |
||
248 | */ |
||
249 | public function verifyHash($response) |
||
250 | { |
||
251 | // 尚未確定 |
||
252 | 1 | return empty($response['MACD']) === true |
|
253 | ? false |
||
254 | : $this->calculateHash($response) === $response['MACD']; |
||
255 | } |
||
256 | 1 | ||
257 | /** |
||
258 | 1 | * @param array $fields |
|
259 | 1 | * @return array |
|
260 | */ |
||
261 | 1 | protected function doRequest(array $fields, $type = 'sync') |
|
262 | 1 | { |
|
263 | 1 | $request = $this->messageFactory->createRequest('POST', $this->getApiEndpoint($type), [ |
|
264 | 1 | 'Content-Type' => 'application/x-www-form-urlencoded', |
|
265 | ], http_build_query($this->encrypter->encryptRequest($fields))); |
||
266 | 1 | ||
267 | $response = $this->client->send($request); |
||
268 | |||
269 | if (false === ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300)) { |
||
270 | throw HttpException::factory($request, $response); |
||
271 | } |
||
272 | |||
273 | 4 | return $this->parseResponse( |
|
274 | $response->getBody()->getContents() |
||
275 | 4 | ); |
|
276 | } |
||
277 | |||
278 | /** |
||
279 | * parseStr. |
||
280 | * |
||
281 | * @param string $str |
||
282 | * @return array |
||
283 | */ |
||
284 | 4 | protected function parseStr($str) |
|
285 | { |
||
286 | $response = []; |
||
287 | 4 | parse_str($str, $response); |
|
288 | 4 | ||
289 | 4 | return $response; |
|
290 | } |
||
291 | |||
292 | /** |
||
293 | * isMobile. |
||
294 | * |
||
295 | * @return bool |
||
296 | */ |
||
297 | 3 | protected function isMobile() |
|
298 | { |
||
299 | 3 | if (isset($this->options['mobile']) === true && is_null($this->options['mobile']) === false) { |
|
300 | return $this->options['mobile']; |
||
301 | } |
||
302 | |||
303 | 3 | $detect = new MobileDetect(); |
|
304 | |||
305 | 3 | return ($detect->isMobile() === false && $detect->isTablet() === false) ? false : true; |
|
306 | } |
||
307 | } |
||
308 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.