Completed
Push — master ( ec4bbc...f977bb )
by Wei
06:04
created

WechatPay::report()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 16
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 14
nc 64
nop 11
dl 0
loc 16
ccs 15
cts 15
cp 1
crap 7
rs 8.8333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * WechatPay
4
 *
5
 * @license MIT
6
 * @author zhangv
7
 */
8
namespace zhangv\wechat\pay;
9
10
use \Exception;
11
use zhangv\wechat\pay\util\HttpClient;
12
use zhangv\wechat\pay\util\WechatOAuth;
13
use zhangv\wechat\pay\cache\CacheProvider;
14
use zhangv\wechat\pay\cache\JsonFileCacheProvider;
15
16
/**
17
 * Class WechatPay
18
 * @package zhangv\wechat
19
 * @author zhangv
20
 * @license MIT
21
 *
22
 * @method static service\App       App(array $config)
23
 * @method static service\Jsapi     Jsapi(array $config)
24
 * @method static service\Micro     Micro(array $config)
25
 * @method static service\Mweb      Mweb(array $config)
26
 * @method static service\Native    Native(array $config)
27
 * @method static service\Weapp     Weapp(array $config)
28
 * @method static service\Mchpay    Mchpay(array $config)
29
 * @method static service\Redpack   Redpack(array $config)
30
 * @method static service\Coupon    Coupon(array $config)
31
 */
32
class WechatPay {
33
	const TRADETYPE_JSAPI = 'JSAPI',TRADETYPE_NATIVE = 'NATIVE',TRADETYPE_APP = 'APP',TRADETYPE_MWEB = 'MWEB';
34
	const SIGNTYPE_MD5 = 'MD5', SIGNTYPE_HMACSHA256 = 'HMAC-SHA256';
35
	const CHECKNAME_FORCECHECK = 'FORCE_CHECK',CHECKNAME_NOCHECK = 'NO_CHECK';
36
	const ACCOUNTTYPE_BASIC = 'Basic',ACCOUNTTYPE_OPERATION = 'Operation',ACCOUNTTYPE_FEES = 'Fees';
37
	const API_ENDPOINT = 'https://api.mch.weixin.qq.com/';
38
	/** 支付 */
39
	const URL_UNIFIEDORDER = 'pay/unifiedorder';
40
	const URL_ORDERQUERY = 'pay/orderquery';
41
	const URL_CLOSEORDER = 'pay/closeorder';
42
	const URL_REFUND = 'secapi/pay/refund';
43
	const URL_REFUNDQUERY = 'pay/refundquery';
44
	const URL_DOWNLOADBILL = 'pay/downloadbill';
45
	const URL_DOWNLOAD_FUND_FLOW = 'pay/downloadfundflow';
46
	const URL_REPORT = 'payitil/report';
47
	const URL_SHORTURL = 'tools/shorturl';
48
	const URL_MICROPAY = 'pay/micropay';
49
	const URL_BATCHQUERYCOMMENT = 'billcommentsp/batchquerycomment';
50
	const URL_REVERSE = 'secapi/pay/reverse';
51
	const URL_AUTHCODETOOPENID = 'tools/authcodetoopenid';
52
	/** 红包 */
53
	const URL_GETHBINFO = 'mmpaymkttransfers/gethbinfo';
54
	const URL_SENDREDPACK = 'mmpaymkttransfers/sendredpack';
55
	const URL_SENDGROUPREDPACK = 'mmpaymkttransfers/sendgroupredpack';
56
	/** 企业付款 */
57
	const URL_TRANSFER_WALLET = 'mmpaymkttransfers/promotion/transfers';
58
	const URL_QUERY_TRANSFER_WALLET = 'mmpaymkttransfers/gettransferinfo';
59
	const URL_TRANSFER_BANKCARD = 'mmpaysptrans/pay_bank';
60
	const URL_QUERY_TRANSFER_BANKCARD = 'mmpaysptrans/query_bank';
61
	/** 代金券 */
62
	const URL_SEND_COUPON = 'mmpaymkttransfers/send_coupon';
63
	const URL_QUERY_COUPON_STOCK = 'mmpaymkttransfers/query_coupon_stock';
64
	const URL_QUERY_COUPON_INFO = 'mmpaymkttransfers/querycouponsinfo';
65
	/** Sandbox获取测试公钥 */
66
	const URL_GETPUBLICKEY = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
67
	public static $BANKCODE = [
68
		'工商银行' => '1002', '农业银行' => '1005', '中国银行' => '1026', '建设银行' => '1003', '招商银行' => '1001',
69
		'邮储银行' => '1066', '交通银行' => '1020', '浦发银行' => '1004', '民生银行' => '1006', '兴业银行' => '1009',
70
		'平安银行' => '1010', '中信银行' => '1021', '华夏银行' => '1025', '广发银行' => '1027', '光大银行' => '1022',
71
		'北京银行' => '1032', '宁波银行' => '1056',
72
	];
73
74
	public $getSignKeyUrl = "sandboxnew/pay/getsignkey";
75
	public $sandbox = false;
76
77
	/** @var string */
78
	public $returnCode;
79
	/** @var string */
80
	public $returnMsg;
81
	/** @var string */
82
	public $resultCode;
83
	/** @var string */
84
	public $errCode;
85
	/** @var string */
86
	public $errCodeDes;
87
	/** @var string */
88
	public $requestXML = null;
89
	/** @var string */
90
	public $responseXML = null;
91
	/** @var array */
92
	public $requestArray = null;
93
	/** @var array */
94
	public $responseArray = null;
95
	/** @var array */
96
	protected $config;
97
	/** @var HttpClient */
98
	protected $httpClient = null;
99
	/** @var WechatOAuth */
100
	protected $wechatOAuth = null;
101
	/** @var string */
102
	public $publicKey = null;
103
	/** @var CacheProvider */
104
	public $cacheProvider = null;
105
106
	/**
107
	 * @param $config array 配置
108
	 */
109 54
	public function __construct(array $config) {
110 54
		$this->config = $config;
111 54
		$this->httpClient = new HttpClient(5);
112 54
		$this->cacheProvider = new JsonFileCacheProvider();
113 54
	}
114
115
	/**
116
	 * @param string $name
117
	 * @param string $config
118
	 * @return mixed
119
	 */
120 30
	private static function load($name, $config) {
121 30
		$service = __NAMESPACE__ . "\\service\\{$name}";
122 30
		return new $service($config);
123
	}
124
125
	/**
126
	 * @param string $name
127
	 * @param array  $config
128
	 *
129
	 * @return mixed
130
	 */
131 30
	public static function __callStatic($name, $config) {
132 30
		return self::load($name, ...$config);
0 ignored issues
show
Bug introduced by
$config is expanded, but the parameter $config of zhangv\wechat\pay\WechatPay::load() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

132
		return self::load($name, /** @scrutinizer ignore-type */ ...$config);
Loading history...
133
	}
134
135 1
	public function setWechatOAuth($wechatOAuth){
136 1
		$this->wechatOAuth = $wechatOAuth;
137 1
	}
138
139 1
	public function getWechatOAuth(){
140 1
		if(!$this->wechatOAuth){
141 1
			$this->wechatOAuth = new WechatOAuth($this->config['app_id'],$this->config['app_secret']);
142
		}
143 1
		return $this->wechatOAuth;
144
	}
145
146 1
	public function setConfig($config){
147 1
		$this->config = $config;
148 1
	}
149
150 3
	public function getConfig(){
151 3
		return $this->config;
152
	}
153
154 39
	public function setHttpClient($httpClient){
155 39
		$this->httpClient = $httpClient;
156 39
	}
157
158 54
	public function setCacheProvider($cacheProvider){
159 54
		$this->cacheProvider = $cacheProvider;
160 54
	}
161
162 1
	public function getCacheProvider(){
163 1
		return $this->cacheProvider;
164
	}
165
166
	/**
167
	 * 统一下单接口
168
	 * @link https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
169
	 * @param array $params
170
	 * @throws Exception
171
	 * @return array
172
	 */
173 8
	public function unifiedOrder($params) {
174 8
		$data = array();
175 8
		$data["appid"] = $this->config["app_id"];
176 8
		$data["device_info"] = (isset($params['device_info'])&&trim($params['device_info'])!='')?$params['device_info']:null;
177 8
		$data["body"] = $params['body'];
178 8
		$data["detail"] = isset($params['detail'])?$params['detail']:null;//optional
179 8
		$data["attach"] = isset($params['attach'])?$params['attach']:null;//optional
180 8
		$data["out_trade_no"] = isset($params['out_trade_no'])?$params['out_trade_no']:null;
181 8
		$data["fee_type"] = isset($params['fee_type'])?$params['fee_type']:'CNY';
182 8
		$data["total_fee"]    = $params['total_fee'];
183 8
		$data["spbill_create_ip"] = $params['spbill_create_ip'];
184 8
		$data["time_start"] = isset($params['time_start'])?$params['time_start']:null;//optional
185 8
		$data["time_expire"] = isset($params['time_expire'])?$params['time_expire']:null;//optional
186 8
		$data["goods_tag"] = isset($params['goods_tag'])?$params['goods_tag']:null;
187 8
		$data["notify_url"] = $this->config["notify_url"];
188 8
		$data["trade_type"] = $params['trade_type'];
189 8
		if($params['trade_type'] == WechatPay::TRADETYPE_NATIVE){
190 1
			if(!isset($params['product_id'])) throw new Exception('product_id is required when trade_type is NATIVE');
191 1
			$data["product_id"] = $params['product_id'];
192
		}
193 8
		if($params['trade_type'] == WechatPay::TRADETYPE_JSAPI){
194 5
			if(!isset($params['openid'])) throw new Exception('openid is required when trade_type is JSAPI');
195 5
			$data["openid"] = $params['openid'];
196
		}
197 8
		$result = $this->post(self::URL_UNIFIEDORDER, $data);
198 5
		return $result;
199
	}
200
201
	/**
202
	 * 查询订单(根据微信订单号)
203
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
204
	 * @param $transaction_id string 微信订单号
205
	 * @return array
206
	 */
207 2
	public function queryOrderByTransactionId($transaction_id){
208 2
		$data = array();
209 2
		$data["appid"] = $this->config["app_id"];
210 2
		$data["transaction_id"] = $transaction_id;
211 2
		$result = $this->post(self::URL_ORDERQUERY, $data);
212 1
		return $result;
213
	}
214
215
	/**
216
	 * 查询订单(根据商户订单号)
217
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
218
	 * @param $out_trade_no string 商户订单号
219
	 * @return array
220
	 */
221 1
	public function queryOrderByOutTradeNo($out_trade_no){
222 1
		$data = array();
223 1
		$data["appid"] = $this->config["app_id"];
224 1
		$data["out_trade_no"] = $out_trade_no;
225 1
		$result = $this->post(self::URL_ORDERQUERY, $data);
226 1
		return $result;
227
	}
228
229
	/**
230
	 * 查询退款(根据微信订单号)
231
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
232
	 * @param $transaction_id string 微信交易号
233
	 * @param $offset int 偏移
234
	 * @return array
235
	 */
236 1
	public function queryRefundByTransactionId($transaction_id,$offset = 0){
237 1
		$data = array();
238 1
		$data["appid"] = $this->config["app_id"];
239 1
		$data["transaction_id"] = $transaction_id;
240 1
		$data["offset"] = $offset;
241 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
242 1
		return $result;
243
	}
244
245
	/**
246
	 * 查询退款(根据商户订单号)
247
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
248
	 * @param $out_trade_no string 商户交易号
249
	 * @param $offset int 偏移
250
	 * @return array
251
	 */
252 1
	public function queryRefundByOutTradeNo($out_trade_no,$offset = 0){
253 1
		$data = array();
254 1
		$data["appid"] = $this->config["app_id"];
255 1
		$data["out_trade_no"] = $out_trade_no;
256 1
		$data["offset"] = $offset;
257 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
258 1
		return $result;
259
	}
260
261
	/**
262
	 * 查询退款(根据微信退款单号)
263
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
264
	 * @param $refund_id string 微信退款单号
265
	 * @param $offset int 偏移
266
	 * @return array
267
	 */
268 1
	public function queryRefundByRefundId($refund_id,$offset = 0){
269 1
		$data = array();
270 1
		$data["appid"] = $this->config["app_id"];
271 1
		$data["refund_id"] = $refund_id;
272 1
		$data["offset"] = $offset;
273 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
274 1
		return $result;
275
	}
276
277
	/**
278
	 * 查询退款(根据商户退款单号)
279
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
280
	 * @param $out_refund_no string 商户退款单号
281
	 * @param $offset int 偏移
282
	 * @return array
283
	 */
284 1
	public function queryRefundByOutRefundNo($out_refund_no,$offset = 0){
285 1
		$data = array();
286 1
		$data["appid"] = $this->config["app_id"];
287 1
		$data["out_refund_no"] = $out_refund_no;
288 1
		$data["offset"] = $offset;
289 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
290 1
		return $result;
291
	}
292
293
	/**
294
	 * 关闭订单
295
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
296
	 * @param $out_trade_no string 商户订单号
297
	 * @return array
298
	 */
299 1
	public function closeOrder($out_trade_no){
300 1
		$data = array();
301 1
		$data["appid"] = $this->config["app_id"];
302 1
		$data["out_trade_no"] = $out_trade_no;
303 1
		$result = $this->post(self::URL_CLOSEORDER, $data,false);
304 1
		return $result;
305
	}
306
307
	/**
308
	 * 退款 - 使用商户订单号
309
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
310
	 * @link  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
311
	 * @param $out_trade_no string 商户订单号
312
	 * @param $out_refund_no string 商户退款单号
313
	 * @param $total_fee int 总金额(单位:分)
314
	 * @param $refund_fee int 退款金额(单位:分)
315
	 * @param $ext array 扩展数组
316
	 * @return array
317
	 */
318 1
	public function refundByOutTradeNo($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
319 1
		$data = ($ext && is_array($ext))?$ext:array();
320 1
		$data["appid"] = $this->config["app_id"];
321 1
		$data["out_trade_no"] = $out_trade_no;
322 1
		$data["out_refund_no"] = $out_refund_no;
323 1
		$data["total_fee"] = $total_fee;
324 1
		$data["refund_fee"] = $refund_fee;
325 1
		$result = $this->post(self::URL_REFUND, $data,true);
326 1
		return $result;
327
	}
328
329
	/**
330
	 * 退款 - 使用微信订单号
331
	 * @param $transaction_id string 微信订单号
332
	 * @param $out_refund_no string 商户退款单号
333
	 * @param $total_fee int 总金额(单位:分)
334
	 * @param $refund_fee int 退款金额(单位:分)
335
	 * @param $ext array 扩展数组
336
	 * @return array
337
	 */
338 1
	public function refundByTransactionId($transaction_id,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
339 1
		$data = ($ext && is_array($ext))?$ext:array();
340 1
		$data["appid"] = $this->config["app_id"];
341 1
		$data["transaction_id"] = $transaction_id;
342 1
		$data["out_refund_no"] = $out_refund_no;
343 1
		$data["total_fee"] = $total_fee;
344 1
		$data["refund_fee"] = $refund_fee;
345 1
		$result = $this->post(self::URL_REFUND, $data,true);
346 1
		return $result;
347
	}
348
349
	/**
350
	 * 下载对账单
351
	 * @link https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_6
352
	 * @param $bill_date string 下载对账单的日期,格式:20140603
353
	 * @param $bill_type string 类型 ALL|SUCCESS
354
	 * @return array
355
	 */
356 1
	public function downloadBill($bill_date,$bill_type = 'ALL'){
357 1
		$data = array();
358 1
		$data["appid"] = $this->config["app_id"];
359 1
		$data["bill_date"] = $bill_date;
360 1
		$data["bill_type"] = $bill_type;
361 1
		$result = $this->post(self::URL_DOWNLOADBILL, $data);
362 1
		return $result;
363
	}
364
365
	/**
366
	 * 下载资金账单
367
	 * @link https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_18&index=7
368
	 * @param $bill_date string 资金账单日期,格式:20140603
369
	 * @param $account_type string 资金账户类型 Basic|Operation|Fees
370
	 * @param $tar_type string 压缩账单
371
	 * @return array
372
	 */
373 1
	public function downloadFundFlow($bill_date,$account_type = self::ACCOUNTTYPE_BASIC,$tar_type = 'GZIP'){
374 1
		$data = array();
375 1
		$data["appid"] = $this->config["app_id"];
376 1
		$data["bill_date"] = $bill_date;
377 1
		$data["account_type"] = $account_type;
378 1
		$data["tar_type"] = $tar_type;
379 1
		$result = $this->post(self::URL_DOWNLOAD_FUND_FLOW, $data);
380 1
		return $result;
381
	}
382
383
	/**
384
	 * 拉取订单评价数据
385
	 * @link https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
386
	 * @param string $begin_time 开始时间,格式为yyyyMMddHHmmss
387
	 * @param string $end_time 结束时间,格式为yyyyMMddHHmmss
388
	 * @param int $offset 偏移
389
	 * @param int $limit 条数
390
	 * @return array
391
	 */
392 1
	public function batchQueryComment($begin_time,$end_time,$offset = 0,$limit = 200){
393 1
		$data = array();
394 1
		$data["appid"] = $this->config["app_id"];
395 1
		$data["begin_time"] = $begin_time;
396 1
		$data["end_time"] = $end_time;
397 1
		$data["offset"] = $offset;
398 1
		$data["limit"] = $limit;
399 1
		$data["sign"] = $this->sign($data,WechatPay::SIGNTYPE_HMACSHA256);
400 1
		$result = $this->post(self::URL_BATCHQUERYCOMMENT, $data, true); //cert is required
401 1
		return $result;
402
	}
403
404
	/**
405
	 * 支付结果通知处理
406
	 * @param $notify_data array|string 通知数据
407
	 * @param $callback callable 回调
408
	 * @return null
409
	 * @throws Exception
410
	 */
411 2
	public function onPaidNotify($notify_data,callable $callback = null){
412 2
		if(!is_array($notify_data)) $notify_data = $this->xml2array($notify_data);
413 2
		if(!$this->validateSign($notify_data)) throw new Exception('Invalid paid notify data');
414 1
		if($callback && is_callable($callback)){
415 1
			return call_user_func_array( $callback , [$notify_data] );
416
		}
417
	}
418
419
	/**
420
	 * 退款结果通知处理
421
	 * @param string|array $notify_data 通知数据(XML/array)
422
	 * @param callable $callback 回调
423
	 * @return mixed
424
	 * @throws Exception
425
	 */
426 2
	public function onRefundedNotify($notify_data,callable $callback = null){
427 2
		if(!is_array($notify_data)) $notify_data = $this->xml2array($notify_data);
428 2
		if(!$this->validateSign($notify_data)) throw new Exception('Invalid refund notify data');
429 1
		if($callback && is_callable($callback)){
430 1
			return call_user_func_array( $callback ,[$notify_data] );
431
		}
432
	}
433
434
	/**
435
	 * 验证数据签名
436
	 * @param $data array 数据数组
437
	 * @return boolean 数据校验结果
438
	 */
439 5
	public function validateSign($data) {
440 5
		if (!isset($data["sign"])) {
441 1
			return false;
442
		}
443 4
		$sign = $data["sign"];
444 4
		unset($data["sign"]);
445 4
		return $this->sign($data) == $sign;
446
	}
447
448
	/**
449
	 * 响应微信支付后台通知
450
	 * @param array $data
451
	 * @param string $return_code 返回状态码 SUCCESS/FAIL
452
	 * @param string $return_msg  返回信息
453
	 * @param bool $print
454
	 * @return string
455
	 */
456 1
	public function responseNotify($print = true,$data = [],$return_code="SUCCESS", $return_msg= 'OK') {
457 1
		$data["return_code"] = $return_code;
458 1
		if ($return_msg) {
459 1
			$data["return_msg"] = $return_msg;
460
		}
461 1
		$xml = $this->array2xml($data);
462 1
		if($print === true) print $xml;
463 1
		else return $xml;
464
	}
465
466
	/**
467
	 * 交易保障
468
	 * @link https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_8&index=8
469
	 * @param string $interface_url
470
	 * @param string $execution_time
471
	 * @param string $return_code
472
	 * @param string $result_code
473
	 * @param string $user_ip
474
	 * @param string $out_trade_no
475
	 * @param string $time
476
	 * @param string $device_info
477
	 * @param string $return_msg
478
	 * @param string $err_code
479
	 * @param string $err_code_des
480
	 * @return array
481
	 */
482 1
	public function report($interface_url,$execution_time,$return_code,$result_code,$user_ip,$out_trade_no = null,$time = null,$device_info = null,
483
	                       $return_msg = null,$err_code = null,$err_code_des = null){
484 1
		$data = array();
485 1
		$data["appid"] = $this->config["app_id"];
486 1
		$data["interface_url"] = $interface_url;
487 1
		$data["execution_time"] = $execution_time;
488 1
		$data["return_code"] = $return_code;
489 1
		$data["result_code"] = $result_code;
490 1
		$data["user_ip"] = $user_ip;
491 1
		if($out_trade_no) $data["out_trade_no"] = $out_trade_no;
492 1
		if($time) $data["time"] = $time;
493 1
		if($device_info) $data["device_info"] = $device_info;
494 1
		if($return_msg) $data["return_msg"] = $return_msg;
495 1
		if($err_code) $data["err_code"] = $err_code;
496 1
		if($err_code_des) $data["err_code_des"] = $err_code_des;
497 1
		return $this->post(self::URL_REPORT, $data, false);
498
	}
499
500
	/**
501
	 * 转换短链接
502
	 * @link https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
503
	 * @param $longurl
504
	 * @return string
505
	 */
506 1
	public function shortUrl($longurl){
507 1
		$data = array();
508 1
		$data["appid"] = $this->config["app_id"];
509 1
		$data["long_url"] = $longurl;
510 1
		$result = $this->post(self::URL_SHORTURL,$data,false);
511 1
		return $result['short_url'];
512
	}
513
514
	/**
515
	 * sandbox环境获取验签秘钥
516
	 * @link https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_1
517
	 * @return array
518
	 */
519 1
	public function getSignKey(){
520 1
		$data = array();
521 1
		$data["mch_id"] = $this->config["mch_id"];
522 1
		$result = $this->post($this->getSignKeyUrl,$data,false);
523 1
		return $result['sandbox_signkey'];
524
	}
525
526
	/**
527
	 * 获取JSAPI所需要的页面参数
528
	 * @param string $url
529
	 * @param string $ticket
530
	 * @return array
531
	 */
532 1
	public function getSignPackage($url, $ticket = null){
533 1
		if(!$ticket) $ticket = $this->getTicket();
534 1
		$timestamp = time();
535 1
		$nonceStr = $this->getNonceStr();
536 1
		$rawString = "jsapi_ticket=$ticket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
537 1
		$signature = sha1($rawString);
538
539
		$signPackage = array(
540 1
			"appId" => $this->config['app_id'],
541 1
			"nonceStr" => $nonceStr,
542 1
			"timestamp" => $timestamp,
543 1
			"url" => $url,
544 1
			"signature" => $signature,
545 1
			"rawString" => $rawString
546
		);
547 1
		return $signPackage;
548
	}
549
550
	/**
551
	 * 获取JSAPI Ticket
552
	 * @param boolean $cache
553
	 * @return string
554
	 */
555 1
	public function getTicket($cache = true){
556 1
		$ticket = null;
557 1
		$cacheKey = 'jsapi_ticket';
558 1
		if($cache === true){
559 1
			$data = $this->cacheProvider->get($cacheKey);
560 1
			if ($data && $data->expires_at > time()) {
561 1
				$ticket = $data->ticket;
562
			}
563
		}
564 1
		if(!$ticket){
565 1
			$data = $this->getWechatOAuth()->getTicket();
566 1
			if($cache === true){
567 1
				$this->cacheProvider->set($cacheKey,$data,time() + $data->expires_in);
568
			}
569 1
			$ticket = $data->ticket;
570
		}
571 1
		return $ticket;
572
	}
573
574 39
	protected function post($url, $data,$cert = true) {
575 39
		if(!isset($data['mch_id']) && !isset($data['mchid'])) $data["mch_id"] = $this->config["mch_id"];
576 39
		if(!isset($data['nonce_str'])) $data["nonce_str"] = $this->getNonceStr();
577 39
		if(!isset($data['sign'])) $data['sign'] = $this->sign($data);
578 39
		$this->requestXML = $this->responseXML = null;
579 39
		$this->requestArray = $this->responseArray = null;
580
581 39
		$this->requestArray = $data;
582 39
		$this->requestXML = $this->array2xml($data);
583
		$opts = [
584 39
			CURLOPT_SSL_VERIFYPEER => false,
585 39
			CURLOPT_SSL_VERIFYHOST => false,
586 39
			CURLOPT_RETURNTRANSFER => true,
587 39
			CURLOPT_TIMEOUT => 10
588
		];
589 39
		if($cert == true){
590 32
			$opts[CURLOPT_SSLCERTTYPE] = 'PEM';
591 32
			$opts[CURLOPT_SSLCERT] = $this->config['ssl_cert_path'];
592 32
			$opts[CURLOPT_SSLKEYTYPE] = 'PEM';
593 32
			$opts[CURLOPT_SSLKEY] = $this->config['ssl_key_path'];
594
		}
595 39
		$processResponse = true;
596 39
		if(in_array($url,[self::URL_DOWNLOADBILL,self::URL_DOWNLOAD_FUND_FLOW,self::URL_BATCHQUERYCOMMENT])){
597 3
			$processResponse = false;
598
		}
599 39
		if($this->sandbox === true) $url = "sandboxnew/{$url}";
600
601 39
		$content = $this->httpClient->post(self::API_ENDPOINT . $url,$this->requestXML,[],$opts);
602 39
		if(!$content) throw new Exception("Empty response with {$this->requestXML}");
603
604 39
		$this->responseXML = $content;
605 39
		if($processResponse)
606 36
			return $this->processResponseXML($this->responseXML);
607 3
		else return $this->responseXML;
608
	}
609
610
	/**
611
	 * @param $responseXML
612
	 * @return array
613
	 * @throws Exception
614
	 */
615 36
	private function processResponseXML($responseXML){
616 36
		$result = $this->xml2array($responseXML);
617 36
		$this->responseArray = $result;
618 36
		if(empty($result['return_code'])){
619 1
			throw new Exception("No return code presents in {$this->responseXML}");
620
		}
621 35
		$this->returnCode = $result["return_code"];
622 35
		$this->returnMsg = isset($result['return_msg'])?$result['return_msg']:'';
623
624 35
		if ($this->returnCode == "SUCCESS") {
625 29
			if(isset($result['result_code']) && $result['result_code'] == "FAIL"){
626 3
				$this->resultCode = $result['result_code'];
627 3
				$this->errCode = $result['err_code'];
628 3
				$this->errCodeDes = $result['err_code_des'];
629 3
				throw new Exception("[$this->errCode]$this->errCodeDes");
630
			}else{
631 26
				return $result;
632
			}
633 6
		} else if($this->returnCode == 'FAIL'){
634 6
			throw new Exception($this->returnMsg);
635
		}
636
	}
637
638 48
	public function sign($data,$sign_type = WechatPay::SIGNTYPE_MD5) {
639 48
		ksort($data);
640 48
		$string1 = "";
641 48
		foreach ($data as $k => $v) {
642 48
			if ($v && trim($v)!='') {
643 48
				$string1 .= "$k=$v&";
644
			}
645
		}
646 48
		$stringSignTemp = $string1 . "key=" . $this->config["api_key"];
647 48
		if($sign_type == WechatPay::SIGNTYPE_MD5){
648 46
			$sign = strtoupper(md5($stringSignTemp));
649 3
		}elseif($sign_type == WechatPay::SIGNTYPE_HMACSHA256){
650 2
			$sign = strtoupper(hash_hmac('sha256',$stringSignTemp,$this->config["api_key"]));
651 1
		}else throw new Exception("Not supported sign type - $sign_type");
652 47
		return $sign;
653
	}
654
655 40
	private function array2xml($array) {
656 40
		$xml = "<xml>" . PHP_EOL;
657 40
		foreach ($array as $k => $v) {
658 40
			if($v && trim($v)!='')
659 40
				$xml .= "<$k><![CDATA[$v]]></$k>" . PHP_EOL;
660
		}
661 40
		$xml .= "</xml>";
662 40
		return $xml;
663
	}
664
665 38
	private function xml2array($xml) {
666 38
		$array = [];
667 38
		$tmp = (array) simplexml_load_string($xml);
668 38
		foreach ( $tmp as $k => $v) {
669 38
			$array[$k] = (string) $v;
670
		}
671 38
		return $array;
672
	}
673
674 43
	protected function getNonceStr() {
675 43
		return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"),0,32);
676
	}
677
678
}