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 Yansongda\Pay\Gateways; |
||
4 | |||
5 | use Symfony\Component\HttpFoundation\Request; |
||
6 | use Symfony\Component\HttpFoundation\Response; |
||
7 | use Yansongda\Pay\Contracts\GatewayApplicationInterface; |
||
8 | use Yansongda\Pay\Contracts\GatewayInterface; |
||
9 | use Yansongda\Pay\Exceptions\InvalidGatewayException; |
||
10 | use Yansongda\Pay\Exceptions\InvalidSignException; |
||
11 | use Yansongda\Pay\Gateways\Alipay\Support; |
||
12 | use Yansongda\Pay\Log; |
||
13 | use Yansongda\Supports\Collection; |
||
14 | use Yansongda\Supports\Config; |
||
15 | use Yansongda\Supports\Str; |
||
16 | |||
17 | /** |
||
18 | * @method Response app(array $config) APP 支付 |
||
19 | * @method Collection pos(array $config) 刷卡支付 |
||
20 | * @method Collection scan(array $config) 扫码支付 |
||
21 | * @method Collection transfer(array $config) 帐户转账 |
||
22 | * @method Response wap(array $config) 手机网站支付 |
||
23 | * @method Response web(array $config) 电脑支付 |
||
24 | */ |
||
25 | class Alipay implements GatewayApplicationInterface |
||
26 | { |
||
27 | /** |
||
28 | * Const mode_normal. |
||
29 | */ |
||
30 | const MODE_NORMAL = 'normal'; |
||
31 | |||
32 | /** |
||
33 | * Const mode_dev. |
||
34 | */ |
||
35 | const MODE_DEV = 'dev'; |
||
36 | |||
37 | /** |
||
38 | * Const url. |
||
39 | */ |
||
40 | const URL = [ |
||
41 | self::MODE_NORMAL => 'https://openapi.alipay.com/gateway.do', |
||
42 | self::MODE_DEV => 'https://openapi.alipaydev.com/gateway.do', |
||
43 | ]; |
||
44 | |||
45 | /** |
||
46 | * Alipay payload. |
||
47 | * |
||
48 | * @var array |
||
49 | */ |
||
50 | protected $payload; |
||
51 | |||
52 | /** |
||
53 | * Alipay gateway. |
||
54 | * |
||
55 | * @var string |
||
56 | */ |
||
57 | protected $gateway; |
||
58 | |||
59 | /** |
||
60 | * Bootstrap. |
||
61 | * |
||
62 | * @author yansongda <[email protected]> |
||
63 | * |
||
64 | * @param Config $config |
||
65 | * |
||
66 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
67 | */ |
||
68 | public function __construct(Config $config) |
||
69 | { |
||
70 | $this->gateway = Support::getInstance($config)->getBaseUri(); |
||
71 | $this->payload = [ |
||
72 | 'app_id' => $config->get('app_id'), |
||
73 | 'method' => '', |
||
74 | 'format' => 'JSON', |
||
75 | 'charset' => 'utf-8', |
||
76 | 'sign_type' => 'RSA2', |
||
77 | 'version' => '1.0', |
||
78 | 'return_url' => $config->get('return_url'), |
||
79 | 'notify_url' => $config->get('notify_url'), |
||
80 | 'timestamp' => date('Y-m-d H:i:s'), |
||
81 | 'sign' => '', |
||
82 | 'biz_content' => '', |
||
83 | ]; |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Magic pay. |
||
88 | * |
||
89 | * @author yansongda <[email protected]> |
||
90 | * |
||
91 | * @param string $method |
||
92 | * @param array $params |
||
93 | * |
||
94 | * @throws InvalidGatewayException |
||
95 | * |
||
96 | * @return Response|Collection |
||
97 | */ |
||
98 | public function __call($method, $params) |
||
99 | { |
||
100 | return $this->pay($method, ...$params); |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Pay an order. |
||
105 | * |
||
106 | * @author yansongda <[email protected]> |
||
107 | * |
||
108 | * @param string $gateway |
||
109 | * @param array $params |
||
110 | * |
||
111 | * @throws InvalidGatewayException |
||
112 | * |
||
113 | * @return Response|Collection |
||
114 | */ |
||
115 | public function pay($gateway, $params = []) |
||
116 | { |
||
117 | Log::debug('Starting To Alipay', [$gateway, $params]); |
||
118 | |||
119 | $this->payload['return_url'] = $params['return_url'] ?? $this->payload['return_url']; |
||
120 | $this->payload['notify_url'] = $params['notify_url'] ?? $this->payload['notify_url']; |
||
121 | |||
122 | unset($params['return_url'], $params['notify_url']); |
||
123 | |||
124 | $this->payload['biz_content'] = json_encode($params); |
||
125 | |||
126 | $gateway = get_class($this).'\\'.Str::studly($gateway).'Gateway'; |
||
127 | |||
128 | if (class_exists($gateway)) { |
||
129 | return $this->makePay($gateway); |
||
130 | } |
||
131 | |||
132 | throw new InvalidGatewayException("Pay Gateway [{$gateway}] not exists"); |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Verify sign. |
||
137 | * |
||
138 | * @author yansongda <[email protected]> |
||
139 | * |
||
140 | * @param null|array $data |
||
141 | * @param bool $refund |
||
142 | * |
||
143 | * @throws InvalidSignException |
||
144 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
145 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
146 | * |
||
147 | * @return Collection |
||
148 | */ |
||
149 | public function verify($data = null, $refund = false): Collection |
||
150 | { |
||
151 | if (is_null($data)) { |
||
152 | $request = Request::createFromGlobals(); |
||
153 | |||
154 | $data = $request->request->count() > 0 ? $request->request->all() : $request->query->all(); |
||
155 | $data = Support::encoding($data, 'utf-8', $data['charset'] ?? 'gb2312'); |
||
156 | } |
||
157 | |||
158 | Log::info('Received Alipay Request', $data); |
||
159 | |||
160 | if (Support::verifySign($data)) { |
||
161 | return new Collection($data); |
||
162 | } |
||
163 | |||
164 | Log::warning('Alipay Sign Verify FAILED', $data); |
||
165 | |||
166 | throw new InvalidSignException('Alipay Sign Verify FAILED', $data); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * Query an order. |
||
171 | * |
||
172 | * @author yansongda <[email protected]> |
||
173 | * |
||
174 | * @param string|array $order |
||
175 | * @param bool $refund |
||
176 | * @param bool $transfer |
||
177 | * |
||
178 | * @throws InvalidSignException |
||
179 | * @throws \Yansongda\Pay\Exceptions\GatewayException |
||
180 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
181 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
182 | * |
||
183 | * @return Collection |
||
184 | */ |
||
185 | public function find($order, $refund = false, $transfer = false): Collection |
||
186 | { |
||
187 | $method = 'alipay.trade.query'; |
||
188 | $requestOrder = is_array($order) ? $order : ['out_trade_no' => $order]; |
||
189 | if ($refund) { |
||
190 | $method = 'alipay.trade.fastpay.refund.query'; |
||
191 | } |
||
192 | if ($transfer) { |
||
193 | $requestOrder = is_array($order) ? $order : ['out_biz_no' => $order]; |
||
194 | $method = 'alipay.fund.trans.order.query'; |
||
195 | } |
||
196 | $this->payload['method'] = $method; |
||
197 | $this->payload['biz_content'] = json_encode($requestOrder); |
||
198 | $this->payload['sign'] = Support::generateSign($this->payload); |
||
199 | |||
200 | Log::info('Starting To Find An Alipay Order', [$this->gateway, $this->payload]); |
||
201 | |||
202 | return Support::requestApi($this->payload); |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Refund an order. |
||
207 | * |
||
208 | * @author yansongda <[email protected]> |
||
209 | * |
||
210 | * @param array $order |
||
211 | * |
||
212 | * @throws InvalidSignException |
||
213 | * @throws \Yansongda\Pay\Exceptions\GatewayException |
||
214 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
215 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
216 | * |
||
217 | * @return Collection |
||
218 | */ |
||
219 | public function refund($order): Collection |
||
220 | { |
||
221 | $this->payload['method'] = 'alipay.trade.refund'; |
||
222 | $this->payload['biz_content'] = json_encode($order); |
||
223 | $this->payload['sign'] = Support::generateSign($this->payload); |
||
224 | |||
225 | Log::info('Starting To Refund An Alipay Order', [$this->gateway, $this->payload]); |
||
226 | |||
227 | return Support::requestApi($this->payload); |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Cancel an order. |
||
232 | * |
||
233 | * @author yansongda <[email protected]> |
||
234 | * |
||
235 | * @param string|array $order |
||
236 | * |
||
237 | * @throws InvalidSignException |
||
238 | * @throws \Yansongda\Pay\Exceptions\GatewayException |
||
239 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
240 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
241 | * |
||
242 | * @return Collection |
||
243 | */ |
||
244 | View Code Duplication | public function cancel($order): Collection |
|
0 ignored issues
–
show
|
|||
245 | { |
||
246 | $this->payload['method'] = 'alipay.trade.cancel'; |
||
247 | $this->payload['biz_content'] = json_encode(is_array($order) ? $order : ['out_trade_no' => $order]); |
||
248 | $this->payload['sign'] = Support::generateSign($this->payload); |
||
249 | |||
250 | Log::info('Starting To Cancel An Alipay Order', [$this->gateway, $this->payload]); |
||
251 | |||
252 | return Support::requestApi($this->payload); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Close an order. |
||
257 | * |
||
258 | * @author yansongda <[email protected]> |
||
259 | * |
||
260 | * @param string|array $order |
||
261 | * |
||
262 | * @throws InvalidSignException |
||
263 | * @throws \Yansongda\Pay\Exceptions\GatewayException |
||
264 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
265 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
266 | * |
||
267 | * @return Collection |
||
268 | */ |
||
269 | View Code Duplication | public function close($order): Collection |
|
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.
Loading history...
|
|||
270 | { |
||
271 | $this->payload['method'] = 'alipay.trade.close'; |
||
272 | $this->payload['biz_content'] = json_encode(is_array($order) ? $order : ['out_trade_no' => $order]); |
||
273 | $this->payload['sign'] = Support::generateSign($this->payload); |
||
274 | |||
275 | Log::info('Starting To Close An Alipay Order', [$this->gateway, $this->payload]); |
||
276 | |||
277 | return Support::requestApi($this->payload); |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Download bill. |
||
282 | * |
||
283 | * @author yansongda <[email protected]> |
||
284 | * |
||
285 | * @param string|array $bill |
||
286 | * |
||
287 | * @throws InvalidSignException |
||
288 | * @throws \Yansongda\Pay\Exceptions\GatewayException |
||
289 | * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException |
||
290 | * @throws \Yansongda\Pay\Exceptions\InvalidConfigException |
||
291 | * |
||
292 | * @return string |
||
293 | */ |
||
294 | public function download($bill): string |
||
295 | { |
||
296 | $this->payload['method'] = 'alipay.data.dataservice.bill.downloadurl.query'; |
||
297 | $this->payload['biz_content'] = json_encode(is_array($bill) ? $bill : ['bill_type' => 'trade', 'bill_date' => $bill]); |
||
298 | $this->payload['sign'] = Support::generateSign($this->payload); |
||
299 | |||
300 | Log::info('Starting To Download The Alipay Bill', [$this->gateway, $this->payload]); |
||
301 | |||
302 | $result = Support::requestApi($this->payload); |
||
303 | |||
304 | return ($result instanceof Collection) ? $result->bill_download_url : ''; |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Reply success to alipay. |
||
309 | * |
||
310 | * @author yansongda <[email protected]> |
||
311 | * |
||
312 | * @return Response |
||
313 | */ |
||
314 | public function success(): Response |
||
315 | { |
||
316 | return Response::create('success'); |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Make pay gateway. |
||
321 | * |
||
322 | * @author yansongda <[email protected]> |
||
323 | * |
||
324 | * @param string $gateway |
||
325 | * |
||
326 | * @throws InvalidGatewayException |
||
327 | * |
||
328 | * @return Response|Collection |
||
329 | */ |
||
330 | View Code Duplication | protected function makePay($gateway) |
|
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.
Loading history...
|
|||
331 | { |
||
332 | $app = new $gateway(); |
||
333 | |||
334 | if ($app instanceof GatewayInterface) { |
||
335 | return $app->pay($this->gateway, $this->payload); |
||
336 | } |
||
337 | |||
338 | throw new InvalidGatewayException("Pay Gateway [{$gateway}] Must Be An Instance Of GatewayInterface"); |
||
339 | } |
||
340 | } |
||
341 |
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.