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 CloudyCity\IPayNowSDK; |
||
4 | |||
5 | use CloudyCity\IPayNowSDK\Exceptions\BusinessException; |
||
6 | use CloudyCity\IPayNowSDK\Exceptions\GatewayException; |
||
7 | use CloudyCity\IPayNowSDK\Exceptions\InvalidConfigException; |
||
8 | use CloudyCity\IPayNowSDK\Exceptions\InvalidSignException; |
||
9 | use GuzzleHttp\Client; |
||
10 | use GuzzleHttp\Exception\GuzzleException; |
||
11 | |||
12 | class IPayNow |
||
13 | { |
||
14 | const TRADE_URL = 'https://pay.ipaynow.cn'; |
||
15 | const TRADE_URL_TEST = 'https://tls-pay.ipaynow.cn'; |
||
16 | const TRADE_TIME_OUT = '3600'; |
||
17 | const TRADE_FUNCODE = 'WP001'; |
||
18 | const QUERY_FUNCODE = 'MQ002'; |
||
19 | const NOTIFY_FUNCODE = 'N001'; |
||
20 | const FRONT_NOTIFY_FUNCODE = 'N002'; |
||
21 | const TRADE_TYPE = '01'; |
||
22 | const TRADE_CURRENCY_TYPE = '156'; |
||
23 | const TRADE_CHARSET = 'UTF-8'; |
||
24 | const TRADE_DEVICE_TYPE = '0601'; |
||
25 | const TRADE_SIGN_TYPE = 'MD5'; |
||
26 | const TRADE_QSTRING_EQUAL = '='; |
||
27 | const TRADE_QSTRING_SPLIT = '&'; |
||
28 | const TRADE_FUNCODE_KEY = 'funcode'; |
||
29 | const TRADE_SIGNATURE_KEY = 'mhtSignature'; |
||
30 | const TRADE_OUTPUT_TYPE = '2'; |
||
31 | const SIGNATURE_KEY = 'signature'; |
||
32 | const VERSION = '1.0.0'; |
||
33 | const ALI_PAY_CHANNEL = 12; // 用户所选渠道类型 支付宝:12 |
||
34 | const WECHAT_PAY_CHANNEL = 13; // 用户所选渠道类型 微信:13 |
||
35 | |||
36 | /** |
||
37 | * 应用ID. |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $appid; |
||
42 | |||
43 | /** |
||
44 | * 应用Key. |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | protected $key; |
||
49 | |||
50 | /** |
||
51 | * 支付渠道. |
||
52 | * |
||
53 | * @var string |
||
54 | */ |
||
55 | protected $channel; |
||
56 | |||
57 | /** |
||
58 | * 异步回调地址 |
||
59 | * |
||
60 | * @var string |
||
61 | */ |
||
62 | protected $notifyUrl; |
||
63 | |||
64 | /** |
||
65 | * 同步回调地址 |
||
66 | * |
||
67 | * @var string |
||
68 | */ |
||
69 | protected $returnUrl; |
||
70 | |||
71 | /** |
||
72 | * NowSdk constructor. |
||
73 | * |
||
74 | * @param $appid |
||
75 | * @param $key |
||
76 | * @param $channel |
||
77 | * @param $notifyUrl |
||
78 | * @param $returnUrl |
||
79 | */ |
||
80 | protected function __construct($appid, $key, $channel, $notifyUrl, $returnUrl) |
||
81 | { |
||
82 | $this->appid = $appid; |
||
83 | $this->key = $key; |
||
84 | $this->channel = $channel; |
||
85 | $this->notifyUrl = $notifyUrl; |
||
86 | $this->returnUrl = $returnUrl; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * 获取现在支付微信SDK. |
||
91 | * |
||
92 | * @param $config |
||
93 | * |
||
94 | * @throws InvalidConfigException |
||
95 | * |
||
96 | * @return IPayNow |
||
97 | */ |
||
98 | View Code Duplication | public static function wechat($config) |
|
0 ignored issues
–
show
|
|||
99 | { |
||
100 | try { |
||
101 | return new static( |
||
102 | $config['appid'], |
||
103 | $config['key'], |
||
104 | static::WECHAT_PAY_CHANNEL, |
||
105 | isset($config['notify_url']) ? $config['notify_url'] : '', |
||
106 | isset($config['return_url']) ? $config['return_url'] : '' |
||
107 | ); |
||
108 | } catch (\Exception $e) { |
||
109 | throw new InvalidConfigException($e->getMessage()); |
||
110 | } |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * 获取现在支付支付宝SDK. |
||
115 | * |
||
116 | * @param $config |
||
117 | * |
||
118 | * @throws InvalidConfigException |
||
119 | * |
||
120 | * @return IPayNow |
||
121 | */ |
||
122 | View Code Duplication | public static function ali($config) |
|
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. ![]() |
|||
123 | { |
||
124 | try { |
||
125 | return new static( |
||
126 | $config['appid'], |
||
127 | $config['key'], |
||
128 | static::ALI_PAY_CHANNEL, |
||
129 | isset($config['notify_url']) ? $config['notify_url'] : '', |
||
130 | isset($config['return_url']) ? $config['return_url'] : '' |
||
131 | ); |
||
132 | } catch (\Exception $e) { |
||
133 | throw new InvalidConfigException($e->getMessage()); |
||
134 | } |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * 预下单. |
||
139 | * |
||
140 | * @see https://mch.ipaynow.cn/h5Pay |
||
141 | * |
||
142 | * @param array $order |
||
143 | * |
||
144 | * @throws \CloudyCity\IPayNowSDK\Exceptions\GatewayException |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | public function pre(array $order) |
||
149 | { |
||
150 | $params = [ |
||
151 | 'appId' => $this->appid, |
||
152 | 'deviceType' => static::TRADE_DEVICE_TYPE, // 设备类型 |
||
153 | 'frontNotifyUrl' => $this->returnUrl, // 前端通知URL |
||
154 | 'funcode' => static::TRADE_FUNCODE, // 功能码 |
||
155 | 'mhtCharset' => static::TRADE_CHARSET, // 商户字符编码 |
||
156 | 'mhtCurrencyType' => static::TRADE_CURRENCY_TYPE, // 商户订单币种类型 |
||
157 | 'mhtOrderAmt' => (int) ($order['money'] * 100), // 商户订单交易金额 |
||
158 | 'mhtOrderDetail' => isset($order['detail']) ? $order['detail'] : '', // 商户订单详情 |
||
159 | 'mhtOrderName' => (string) $order['money'], // 商户商品名称 |
||
160 | 'mhtOrderNo' => $order['no'], // 商户订单号 |
||
161 | 'mhtOrderStartTime' => date('YmdHis'), // 商户订单开始时间 |
||
162 | 'mhtOrderTimeOut' => static::TRADE_TIME_OUT, // 商户订单超时时间 |
||
163 | 'mhtOrderType' => static::TRADE_TYPE, // 商户交易类型 |
||
164 | 'mhtReserved' => isset($order['attach']) ? $order['attach'] : '', // 商户保留域 |
||
165 | 'mhtSignType' => static::TRADE_SIGN_TYPE, // 商户签名方法 |
||
166 | 'notifyUrl' => $this->notifyUrl, // 商户后台通知URL |
||
167 | 'outputType' => static::TRADE_OUTPUT_TYPE, // 输出格式 |
||
168 | 'payChannelType' => $this->channel, // 用户所选渠道类型: 12-支付宝 13-微信 |
||
169 | 'version' => static::VERSION, |
||
170 | 'consumerCreateIp' => isset($order['ip']) ? $order['ip'] : '', // 消费者下单ip: 微信时必填 |
||
171 | ]; |
||
172 | |||
173 | $reqString = $this->getRequestString($params); |
||
174 | |||
175 | try { |
||
176 | $res = (new Client())->post(static::TRADE_URL, [ |
||
177 | 'body' => $reqString, |
||
178 | ]); |
||
179 | } catch (GuzzleException $e) { |
||
180 | throw new GatewayException($e->getMessage()); |
||
181 | } |
||
182 | |||
183 | $resContent = $res->getBody()->getContents(); |
||
184 | $resArray = queryStringToArray($resContent, false); |
||
185 | $resCode = isset($resArray['responseCode']) ? $resArray['responseCode'] : ''; |
||
186 | $resMsg = isset($resArray['responseMsg']) ? $resArray['responseMsg'] : ''; |
||
187 | |||
188 | if ($resCode !== 'A001') { |
||
189 | throw new BusinessException(urldecode($resMsg)); |
||
190 | } |
||
191 | $url = isset($resArray['tn']) ? $resArray['tn'] : ''; |
||
192 | |||
193 | return urldecode($url); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * 验证回调通知. |
||
198 | * |
||
199 | * @param $params |
||
200 | * |
||
201 | * @throws InvalidSignException |
||
202 | */ |
||
203 | public function verify($params = null) |
||
204 | { |
||
205 | if (!$params) { |
||
206 | $inputString = file_get_contents('php://input'); |
||
207 | $params = queryStringToArray($inputString); |
||
208 | } |
||
209 | |||
210 | if (!isset($params['signature'])) { |
||
211 | throw new InvalidSignException('缺少签名'); |
||
212 | } |
||
213 | |||
214 | if ($params['signature'] != $this->getSignature($params)) { |
||
215 | throw new InvalidSignException('签名错误'); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * 获取下单请求的字符串. |
||
221 | * |
||
222 | * @param array $params |
||
223 | * |
||
224 | * @return string |
||
225 | */ |
||
226 | protected function getRequestString(array $params) |
||
227 | { |
||
228 | $params = $this->filterParams($params); |
||
229 | $signature = $this->getSignature($params); |
||
230 | $reqString = ''; |
||
231 | foreach ($params as $k => $v) { |
||
232 | if ($v != '') { |
||
233 | $reqString .= $k.static::TRADE_QSTRING_EQUAL.urlencode($v).static::TRADE_QSTRING_SPLIT; |
||
234 | } |
||
235 | } |
||
236 | $reqString .= static::TRADE_SIGNATURE_KEY.static::TRADE_QSTRING_EQUAL.$signature; |
||
237 | |||
238 | return $reqString; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * 计算签名. |
||
243 | * |
||
244 | * @param array $params 参数 |
||
245 | * |
||
246 | * @return string |
||
247 | */ |
||
248 | protected function getSignature(array $params) |
||
249 | { |
||
250 | $signature = ''; |
||
251 | ksort($params); |
||
252 | foreach ($params as $key => $value) { |
||
253 | if ($value == '' || $key == 'signature') { |
||
254 | continue; |
||
255 | } |
||
256 | $signature .= "{$key}={$value}&"; |
||
257 | } |
||
258 | $signature = md5($signature.md5($this->key)); |
||
259 | |||
260 | return $signature; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * 过滤参数. |
||
265 | * |
||
266 | * @param array $params |
||
267 | * |
||
268 | * @return array |
||
269 | */ |
||
270 | protected function filterParams(array $params) |
||
271 | { |
||
272 | $result = []; |
||
273 | $funcode = $params[static::TRADE_FUNCODE_KEY]; |
||
274 | foreach ($params as $key => $value) { |
||
275 | View Code Duplication | if (($funcode == static::TRADE_FUNCODE) |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
276 | && !($key == static::TRADE_SIGNATURE_KEY || $key == static::SIGNATURE_KEY)) { |
||
277 | $result[$key] = $value; |
||
278 | continue; |
||
279 | } |
||
280 | View Code Duplication | if (($funcode == static::NOTIFY_FUNCODE || $funcode == static::FRONT_NOTIFY_FUNCODE) |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
281 | && !($key == static::SIGNATURE_KEY)) { |
||
282 | $result[$key] = $value; |
||
283 | continue; |
||
284 | } |
||
285 | View Code Duplication | if (($funcode == static::QUERY_FUNCODE) && |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
286 | !($key == static::TRADE_SIGNATURE_KEY || $key == static::SIGNATURE_KEY)) { |
||
287 | $result[$key] = $value; |
||
288 | continue; |
||
289 | } |
||
290 | } |
||
291 | |||
292 | return $result; |
||
293 | } |
||
294 | } |
||
295 |
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.