Passed
Push — master ( c65cc4...4fcf9e )
by Wei
03:50
created

WechatPay::sendRedPack()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 11
dl 0
loc 17
ccs 17
cts 17
cp 1
crap 3
rs 9.7
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;
9
10
use \Exception;
11
use zhangv\wechat\cache\CacheProvider;
12
use zhangv\wechat\cache\JsonFileCacheProvider;
13
14
class WechatPay {
15
	const TRADETYPE_JSAPI = 'JSAPI',TRADETYPE_NATIVE = 'NATIVE',TRADETYPE_APP = 'APP',TRADETYPE_MWEB = 'MWEB';
16
	const SIGNTYPE_MD5 = 'MD5', SIGNTYPE_HMACSHA256 = 'HMAC-SHA256';
17
	const CHECKNAME_FORCECHECK = 'FORCE_CHECK',CHECKNAME_NOCHECK = 'NO_CHECK';
18
	const ACCOUNTTYPE_BASIC = 'Basic',ACCOUNTTYPE_OPERATION = 'Operation',ACCOUNTTYPE_FEES = 'Fees';
19
	const API_ENDPOINT = 'https://api.mch.weixin.qq.com/';
20
	/** 支付 */
21
	const URL_UNIFIEDORDER = 'pay/unifiedorder';
22
	const URL_ORDERQUERY = 'pay/orderquery';
23
	const URL_CLOSEORDER = 'pay/closeorder';
24
	const URL_REFUND = 'secapi/pay/refund';
25
	const URL_REFUNDQUERY = 'pay/refundquery';
26
	const URL_DOWNLOADBILL = 'pay/downloadbill';
27
	const URL_DOWNLOAD_FUND_FLOW = 'pay/downloadfundflow';
28
	const URL_REPORT = 'payitil/report';
29
	const URL_SHORTURL = 'tools/shorturl';
30
	const URL_MICROPAY = 'pay/micropay';
31
	const URL_BATCHQUERYCOMMENT = 'billcommentsp/batchquerycomment';
32
	const URL_REVERSE = 'secapi/pay/reverse';
33
	const URL_AUTHCODETOOPENID = 'tools/authcodetoopenid';
34
	/** 红包 */
35
	const URL_GETHBINFO = 'mmpaymkttransfers/gethbinfo';
36
	const URL_SENDREDPACK = 'mmpaymkttransfers/sendredpack';
37
	const URL_SENDGROUPREDPACK = 'mmpaymkttransfers/sendgroupredpack';
38
	/** 企业付款 */
39
	const URL_TRANSFER_WALLET = 'mmpaymkttransfers/promotion/transfers';
40
	const URL_QUERY_TRANSFER_WALLET = 'mmpaymkttransfers/gettransferinfo';
41
	const URL_TRANSFER_BANKCARD = 'mmpaysptrans/pay_bank';
42
	const URL_QUERY_TRANSFER_BANKCARD = 'mmpaysptrans/query_bank';
43
	/** 代金券 */
44
	const URL_SEND_COUPON = 'mmpaymkttransfers/send_coupon';
45
	const URL_QUERY_COUPON_STOCK = 'mmpaymkttransfers/query_coupon_stock';
46
	const URL_QUERY_COUPON_INFO = 'mmpaymkttransfers/querycouponsinfo';
47
	/** Sandbox获取测试公钥 */
48
	const URL_GETPUBLICKEY = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
49
	public static $BANKCODE = ['工商银行' => '1002', '农业银行' => '1005', '中国银行' => '1026', '建设银行' => '1003', '招商银行' => '1001',
50
		'邮储银行' => '1066', '交通银行' => '1020', '浦发银行' => '1004', '民生银行' => '1006', '兴业银行' => '1009', '平安银行' => '1010',
51
		'中信银行' => '1021', '华夏银行' => '1025', '广发银行' => '1027', '光大银行' => '1022', '北京银行' => '1032', '宁波银行' => '1056',];
52
53
	public $getSignKeyUrl = "sandboxnew/pay/getsignkey";
54
	public $sandbox = false;
55
56
	/** @var string */
57
	public $returnCode;
58
	/** @var string */
59
	public $returnMsg;
60
	/** @var string */
61
	public $resultCode;
62
	/** @var string */
63
	public $errCode;
64
	/** @var string */
65
	public $errCodeDes;
66
	/** @var string */
67
	public $requestXML = null;
68
	/** @var string */
69
	public $responseXML = null;
70
	/** @var array */
71
	public $requestArray = null;
72
	/** @var array */
73
	public $responseArray = null;
74
	/** @var array */
75
	private $config;
76
	/** @var HttpClient */
77
	private $httpClient = null;
78
	/** @var WechatOAuth */
79
	private $wechatOAuth = null;
80
	/** @var string */
81
	public $publicKey = null;
82
	/** @var CacheProvider */
83
	public $cacheProvider = null;
84
85
	/**
86
	 * @param $config array 配置
87
	 */
88 51
	public function __construct(array $config) {
89 51
		$this->config = $config;
90 51
		$this->httpClient = new HttpClient(5);
91 51
		$this->cacheProvider = new JsonFileCacheProvider();
92 51
	}
93
94 1
	public function setWechatOAuth($wechatOAuth){
95 1
		$this->wechatOAuth = $wechatOAuth;
96 1
	}
97
98 1
	public function getWechatOAuth(){
99 1
		if(!$this->wechatOAuth){
100 1
			$this->wechatOAuth = new WechatOAuth($this->config['app_id'],$this->config['app_secret']);
101
		}
102 1
		return $this->wechatOAuth;
103
	}
104
105 1
	public function setConfig($config){
106 1
		$this->config = $config;
107 1
	}
108
109 3
	public function getConfig(){
110 3
		return $this->config;
111
	}
112
113 38
	public function setHttpClient($httpClient){
114 38
		$this->httpClient = $httpClient;
115 38
	}
116
117 51
	public function setCacheProvider($cacheProvider){
118 51
		$this->cacheProvider = $cacheProvider;
119 51
	}
120
121 1
	public function getCacheProvider(){
122 1
		return $this->cacheProvider;
123
	}
124
125
	/**
126
	 * 获取JSAPI(公众号/小程序)的预支付单信息(prepay_id)
127
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
128
	 * @param $body string 内容
129
	 * @param $out_trade_no string 商户订单号
130
	 * @param $total_fee int 总金额
131
	 * @param $openid string openid
132
	 * @param $spbill_create_ip
133
	 * @param $ext array
134
	 * @return string
135
	 * @throws \Exception
136
	 */
137 4
	public function getPrepayId($body,$out_trade_no,$total_fee,$openid,$spbill_create_ip = null,$ext = null) {
138 4
		$data = ($ext && is_array($ext))?$ext:array();
139 4
		$data["body"]         = $body;
140 4
		$data["out_trade_no"] = $out_trade_no;
141 4
		$data["total_fee"]    = $total_fee;
142 4
		$data["spbill_create_ip"] = $spbill_create_ip?:$_SERVER["REMOTE_ADDR"];
143 4
		$data["notify_url"]   = $this->config["notify_url"];
144 4
		$data["trade_type"]   = WechatPay::TRADETYPE_JSAPI;
145 4
		if(!$openid) throw new Exception('openid is required when trade_type is JSAPI');
146 4
		$data["openid"]   = $openid;
147 4
		$result = $this->unifiedOrder($data);
148 1
		return $result["prepay_id"];
149
	}
150
151
	/**
152
	 * 获取APP的的预支付单信息(prepay_id)(注意这里的appid是从开放平台申请的)
153
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
154
	 * @param $body string 内容
155
	 * @param $out_trade_no string 商户订单号
156
	 * @param $total_fee int 总金额
157
	 * @param $spbill_create_ip string 终端ID
158
	 * @param $ext array
159
	 * @return string
160
	 */
161 1
	public function getPrepayIdAPP($body,$out_trade_no,$total_fee,$spbill_create_ip,$ext = null) {
162 1
		$data = ($ext && is_array($ext))?$ext:array();
163 1
		$data["body"]         = $body;
164 1
		$data["out_trade_no"] = $out_trade_no;
165 1
		$data["total_fee"]    = $total_fee;
166 1
		$data["spbill_create_ip"] = $spbill_create_ip;
167 1
		$data["notify_url"]   = $this->config["notify_url"];
168 1
		$data["trade_type"]   = WechatPay::TRADETYPE_APP;
169 1
		$result = $this->unifiedOrder($data);
170 1
		return $result["prepay_id"];
171
	}
172
173
	/**
174
	 * 扫码支付(模式二)获取支付二维码
175
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
176
	 * @param $body
177
	 * @param $out_trade_no
178
	 * @param $total_fee
179
	 * @param $product_id
180
	 * @param $spbill_create_ip string 本地IP
181
	 * @param $ext array
182
	 * @return string
183
	 * @throws Exception
184
	 */
185 1
	public function getCodeUrl($body,$out_trade_no,$total_fee,$product_id,$spbill_create_ip = null,$ext = null){
186 1
		$data = ($ext && is_array($ext))?$ext:array();
187 1
		$data["body"]         = $body;
188 1
		$data["out_trade_no"] = $out_trade_no;
189 1
		$data["total_fee"]    = $total_fee;
190 1
		$data["spbill_create_ip"] = $spbill_create_ip?:$_SERVER["SERVER_ADDR"];
191 1
		$data["notify_url"]   = $this->config["notify_url"];
192 1
		$data["trade_type"]   = self::TRADETYPE_NATIVE;
193 1
		if(!$product_id) throw new Exception('product_id is required when trade_type is NATIVE');
194 1
		$data["product_id"]   = $product_id;
195 1
		$result = $this->unifiedOrder($data);
196 1
		return $result["code_url"];
197
	}
198
199
	/**
200
	 * H5支付获取支付跳转链接
201
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
202
	 * @param $body string 商品描述
203
	 * @param $out_trade_no string 商户订单号
204
	 * @param $total_fee int 总金额(分)
205
	 * @param $ext array
206
	 * @return string
207
	 * @throws Exception
208
	 */
209 1
	public function getMwebUrl($body,$out_trade_no,$total_fee,$ext = null){
210 1
		$data = ($ext && is_array($ext))?$ext:array();
211 1
		$data["body"]         = $body;
212 1
		$data["out_trade_no"] = $out_trade_no;
213 1
		$data["total_fee"]    = $total_fee;
214 1
		$data["spbill_create_ip"] = isset($_SERVER["REMOTE_ADDR"])?$_SERVER["REMOTE_ADDR"]:'';
215 1
		$data["notify_url"]   = $this->config["notify_url"];
216 1
		$data["trade_type"]   = self::TRADETYPE_MWEB;
217 1
		if(!isset($this->config['h5_scene_info'])) throw new Exception('h5_scene_info should be configured');
218 1
		$data["scene_info"]   = json_encode($this->config['h5_scene_info']);
219 1
		$result = $this->unifiedOrder($data);
220 1
		return $result["mweb_url"];
221
	}
222
223
	/**
224
	 * 统一下单接口
225
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
226
	 * @param array $params
227
	 * @throws Exception
228
	 * @return string JSON
229
	 */
230 7
	public function unifiedOrder($params) {
231 7
		$data = array();
232 7
		$data["appid"] = $this->config["app_id"];
233 7
		$data["device_info"] = (isset($params['device_info'])&&trim($params['device_info'])!='')?$params['device_info']:null;
234 7
		$data["body"] = $params['body'];
235 7
		$data["detail"] = isset($params['detail'])?$params['detail']:null;//optional
236 7
		$data["attach"] = isset($params['attach'])?$params['attach']:null;//optional
237 7
		$data["out_trade_no"] = isset($params['out_trade_no'])?$params['out_trade_no']:null;
238 7
		$data["fee_type"] = isset($params['fee_type'])?$params['fee_type']:'CNY';
239 7
		$data["total_fee"]    = $params['total_fee'];
240 7
		$data["spbill_create_ip"] = $params['spbill_create_ip'];
241 7
		$data["time_start"] = isset($params['time_start'])?$params['time_start']:null;//optional
242 7
		$data["time_expire"] = isset($params['time_expire'])?$params['time_expire']:null;//optional
243 7
		$data["goods_tag"] = isset($params['goods_tag'])?$params['goods_tag']:null;
244 7
		$data["notify_url"] = $this->config["notify_url"];
245 7
		$data["trade_type"] = $params['trade_type'];
246 7
		if($params['trade_type'] == WechatPay::TRADETYPE_NATIVE){
247 1
			if(!isset($params['product_id'])) throw new Exception('product_id is required when trade_type is NATIVE');
248 1
			$data["product_id"] = $params['product_id'];
249
		}
250 7
		if($params['trade_type'] == WechatPay::TRADETYPE_JSAPI){
251 4
			if(!isset($params['openid'])) throw new Exception('openid is required when trade_type is JSAPI');
252 4
			$data["openid"] = $params['openid'];
253
		}
254 7
		$result = $this->post(self::URL_UNIFIEDORDER, $data);
255 4
		return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type array which is incompatible with the documented return type string.
Loading history...
256
	}
257
258
	/**
259
	 * 查询订单(根据微信订单号)
260
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
261
	 * @param $transaction_id string 微信订单号
262
	 * @return array
263
	 */
264 2
	public function queryOrderByTransactionId($transaction_id){
265 2
		$data = array();
266 2
		$data["appid"] = $this->config["app_id"];
267 2
		$data["transaction_id"] = $transaction_id;
268 2
		$result = $this->post(self::URL_ORDERQUERY, $data);
269 1
		return $result;
270
	}
271
272
	/**
273
	 * 查询订单(根据商户订单号)
274
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
275
	 * @param $out_trade_no string 商户订单号
276
	 * @return array
277
	 */
278 1
	public function queryOrderByOutTradeNo($out_trade_no){
279 1
		$data = array();
280 1
		$data["appid"] = $this->config["app_id"];
281 1
		$data["out_trade_no"] = $out_trade_no;
282 1
		$result = $this->post(self::URL_ORDERQUERY, $data);
283 1
		return $result;
284
	}
285
286
	/**
287
	 * 查询退款(根据微信订单号)
288
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
289
	 * @param $transaction_id string 微信交易号
290
	 * @param $offset int 偏移
291
	 * @return array
292
	 */
293 1
	public function queryRefundByTransactionId($transaction_id,$offset = 0){
294 1
		$data = array();
295 1
		$data["appid"] = $this->config["app_id"];
296 1
		$data["transaction_id"] = $transaction_id;
297 1
		$data["offset"] = $offset;
298 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
299 1
		return $result;
300
	}
301
302
	/**
303
	 * 查询退款(根据商户订单号)
304
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
305
	 * @param $out_trade_no string 商户交易号
306
	 * @param $offset int 偏移
307
	 * @return array
308
	 */
309 1
	public function queryRefundByOutTradeNo($out_trade_no,$offset = 0){
310 1
		$data = array();
311 1
		$data["appid"] = $this->config["app_id"];
312 1
		$data["out_trade_no"] = $out_trade_no;
313 1
		$data["offset"] = $offset;
314 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
315 1
		return $result;
316
	}
317
318
	/**
319
	 * 查询退款(根据微信退款单号)
320
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
321
	 * @param $refund_id string 微信退款单号
322
	 * @param $offset int 偏移
323
	 * @return array
324
	 */
325 1
	public function queryRefundByRefundId($refund_id,$offset = 0){
326 1
		$data = array();
327 1
		$data["appid"] = $this->config["app_id"];
328 1
		$data["refund_id"] = $refund_id;
329 1
		$data["offset"] = $offset;
330 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
331 1
		return $result;
332
	}
333
334
	/**
335
	 * 查询退款(根据商户退款单号)
336
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
337
	 * @param $out_refund_no string 商户退款单号
338
	 * @param $offset int 偏移
339
	 * @return array
340
	 */
341 1
	public function queryRefundByOutRefundNo($out_refund_no,$offset = 0){
342 1
		$data = array();
343 1
		$data["appid"] = $this->config["app_id"];
344 1
		$data["out_refund_no"] = $out_refund_no;
345 1
		$data["offset"] = $offset;
346 1
		$result = $this->post(self::URL_REFUNDQUERY, $data);
347 1
		return $result;
348
	}
349
350
	/**
351
	 * 关闭订单
352
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
353
	 * @param $out_trade_no string 商户订单号
354
	 * @return array
355
	 */
356 1
	public function closeOrder($out_trade_no){
357 1
		$data = array();
358 1
		$data["appid"] = $this->config["app_id"];
359 1
		$data["out_trade_no"] = $out_trade_no;
360 1
		$result = $this->post(self::URL_CLOSEORDER, $data,false);
361 1
		return $result;
362
	}
363
364
	/**
365
	 * 申请退款 - 使用商户订单号
366
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
367
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
368
	 * @param $out_trade_no string 商户订单号
369
	 * @param $out_refund_no string 商户退款单号
370
	 * @param $total_fee int 总金额(单位:分)
371
	 * @param $refund_fee int 退款金额(单位:分)
372
	 * @param $ext array 扩展数组
373
	 * @return array
374
	 */
375 1
	public function refundByOutTradeNo($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
376 1
		$data = ($ext && is_array($ext))?$ext:array();
377 1
		$data["appid"] = $this->config["app_id"];
378 1
		$data["out_trade_no"] = $out_trade_no;
379 1
		$data["out_refund_no"] = $out_refund_no;
380 1
		$data["total_fee"] = $total_fee;
381 1
		$data["refund_fee"] = $refund_fee;
382 1
		$result = $this->post(self::URL_REFUND, $data,true);
383 1
		return $result;
384
	}
385
386
	/**
387
	 * 申请退款 - 使用微信订单号
388
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
389
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
390
	 * @param $transaction_id string 微信订单号
391
	 * @param $out_refund_no string 商户退款单号
392
	 * @param $total_fee int 总金额(单位:分)
393
	 * @param $refund_fee int 退款金额(单位:分)
394
	 * @param $ext array 扩展数组
395
	 * @return array
396
	 */
397 1
	public function refundByTransactionId($transaction_id,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
398 1
		$data = ($ext && is_array($ext))?$ext:array();
399 1
		$data["appid"] = $this->config["app_id"];
400 1
		$data["transaction_id"] = $transaction_id;
401 1
		$data["out_refund_no"] = $out_refund_no;
402 1
		$data["total_fee"] = $total_fee;
403 1
		$data["refund_fee"] = $refund_fee;
404 1
		$result = $this->post(self::URL_REFUND, $data,true);
405 1
		return $result;
406
	}
407
408
	/**
409
	 * 撤销订单 - 使用商户订单号
410
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
411
	 * @param $out_trade_no string 商户订单号
412
	 * @return array
413
	 */
414 1
	public function reverseByOutTradeNo($out_trade_no){
415 1
		$data = array();
416 1
		$data["appid"] = $this->config["app_id"];
417 1
		$data["out_trade_no"] = $out_trade_no;
418 1
		$result = $this->post(self::URL_REVERSE, $data,true);
419 1
		return $result;
420
	}
421
422
	/**
423
	 * 撤销订单 - 使用微信订单号
424
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
425
	 * @param $transaction_id string 微信订单号
426
	 * @return array
427
	 */
428 1
	public function reverseByTransactionId($transaction_id){
429 1
		$data = array();
430 1
		$data["appid"] = $this->config["app_id"];
431 1
		$data["transaction_id"] = $transaction_id;
432 1
		$result = $this->post(self::URL_REVERSE, $data,true);
433 1
		return $result;
434
	}
435
436
	/**
437
	 * 下载对账单
438
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_6
439
	 * @param $bill_date string 下载对账单的日期,格式:20140603
440
	 * @param $bill_type string 类型 ALL|SUCCESS
441
	 * @return array
442
	 */
443 1
	public function downloadBill($bill_date,$bill_type = 'ALL'){
444 1
		$data = array();
445 1
		$data["appid"] = $this->config["app_id"];
446 1
		$data["bill_date"] = $bill_date;
447 1
		$data["bill_type"] = $bill_type;
448 1
		$result = $this->post(self::URL_DOWNLOADBILL, $data);
449 1
		return $result;
450
	}
451
452
	/**
453
	 * 下载资金账单
454
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_18&index=7
455
	 * @param $bill_date string 资金账单日期,格式:20140603
456
	 * @param $account_type string 资金账户类型 Basic|Operation|Fees
457
	 * @param $tar_type string 压缩账单
458
	 * @return array
459
	 */
460 1
	public function downloadFundFlow($bill_date,$account_type = self::ACCOUNTTYPE_BASIC,$tar_type = 'GZIP'){
461 1
		$data = array();
462 1
		$data["appid"] = $this->config["app_id"];
463 1
		$data["bill_date"] = $bill_date;
464 1
		$data["account_type"] = $account_type;
465 1
		$data["tar_type"] = $tar_type;
466 1
		$result = $this->post(self::URL_DOWNLOAD_FUND_FLOW, $data);
467 1
		return $result;
468
	}
469
470
	/**
471
	 * 发放普通红包
472
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
473
	 * @param $mch_billno string 商户订单号
474
	 * @param $send_name string 商户名称
475
	 * @param $re_openid string 用户openid
476
	 * @param $total_amount int 付款金额 单位分
477
	 * @param $total_num int 红包发放总人数
478
	 * @param $wishing string 红包祝福语
479
	 * @param $act_name string 活动名称
480
	 * @param $remark string 备注
481
	 * @param $scene_id string 场景id,发放红包使用场景,红包金额大于200时必传 PRODUCT_1:商品促销 PRODUCT_2:抽奖 PRODUCT_3:虚拟物品兑奖 PRODUCT_4:企业内部福利 PRODUCT_5:渠道分润 PRODUCT_6:保险回馈 PRODUCT_7:彩票派奖 PRODUCT_8:税务刮奖
482
	 * @param $riskinfo string 活动信息
483
	 * @param $consume_mch_id string 资金授权商户号
484
	 * @return array
485
	 * @throws Exception
486
	 */
487 2
	public function sendRedPack($mch_billno,$send_name,$re_openid,$total_amount,$total_num,$wishing,$act_name,$remark,$scene_id = '',$riskinfo = '',$consume_mch_id = ''){
488 2
		$data = array();
489 2
		$data["wxappid"] = $this->config["app_id"];
490 2
		$data["mch_billno"] = $mch_billno;
491 2
		$data["send_name"] = $send_name;
492 2
		$data["re_openid"] = $re_openid;
493 2
		$data["total_amount"] = $total_amount;
494 2
		if($total_amount > 20000 && trim($scene_id)=='') throw new Exception("scene_id is required when total_amount beyond 20000");
495 2
		$data["total_num"] = $total_num;
496 2
		$data["wishing"] = $wishing;
497 2
		$data["act_name"] = $act_name;
498 2
		$data["remark"] = $remark;
499 2
		$data["scene_id"] = $scene_id;
500 2
		$data["riskinfo"] = $riskinfo;
501 2
		$data["consume_mch_id"] = $consume_mch_id;
502 2
		$result = $this->post(self::URL_SENDREDPACK, $data, true); //cert is required
503 1
		return $result;
504
	}
505
506
	/**
507
	 * 发放裂变红包
508
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
509
	 * @param $mch_billno string 商户订单号
510
	 * @param $send_name string 商户名称
511
	 * @param $re_openid string 用户openid
512
	 * @param $total_amount int 付款金额 单位分
513
	 * @param $total_num int 红包发放总人数
514
	 * @param $wishing string 红包祝福语
515
	 * @param $act_name string 活动名称
516
	 * @param $remark string 备注
517
	 * @param $scene_id string 场景id,发放红包使用场景,红包金额大于200时必传 PRODUCT_1:商品促销 PRODUCT_2:抽奖 PRODUCT_3:虚拟物品兑奖 PRODUCT_4:企业内部福利 PRODUCT_5:渠道分润 PRODUCT_6:保险回馈 PRODUCT_7:彩票派奖 PRODUCT_8:税务刮奖
518
	 * @param $riskinfo string 活动信息
519
	 * @param $consume_mch_id string 资金授权商户号
520
	 * @return array
521
	 * @throws Exception
522
	 */
523 2
	public function sendGroupRedPack($mch_billno,$send_name,$re_openid,$total_amount,$total_num,$wishing,$act_name,$remark,$scene_id = '',$riskinfo = '',$consume_mch_id = ''){
524 2
		$data = array();
525 2
		$data["wxappid"] = $this->config["app_id"];//NOTE: WXappid
526 2
		$data["mch_billno"] = $mch_billno;
527 2
		$data["send_name"] = $send_name;
528 2
		$data["re_openid"] = $re_openid;
529 2
		$data["total_amount"] = $total_amount;
530 2
		if($total_amount > 20000 && trim($scene_id)=='') throw new Exception("scene_id is required when total_amount beyond 20000(200rmb)");
531 2
		$data["total_num"] = $total_num;
532 2
		$data["amt_type"] = 'ALL_RAND'; //红包金额设置方式 ALL_RAND—全部随机
533 2
		$data["wishing"] = $wishing;
534 2
		$data["act_name"] = $act_name;
535 2
		$data["remark"] = $remark;
536 2
		$data["scene_id"] = $scene_id;
537 2
		$data["riskinfo"] = $riskinfo;
538 2
		$data["consume_mch_id"] = $consume_mch_id;
539 2
		$result = $this->post(self::URL_SENDGROUPREDPACK, $data, true); //cert is required
540 1
		return $result;
541
	}
542
543
	/**
544
	 * 查询红包记录
545
	 * @param $mch_billno string 商户订单号
546
	 * @return array
547
	 * @throws Exception
548
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_6&index=5
549
	 */
550 2
	public function getHbInfo($mch_billno){
551 2
		$data = array();
552 2
		$data["mch_billno"] = $mch_billno;
553 2
		$data["appid"] = $this->config["app_id"];
554 2
		$data["bill_type"] = 'MCHT'; //MCHT:通过商户订单号获取红包信息。
555 2
		$result = $this->post(self::URL_GETHBINFO, $data, true); //cert is required
556 1
		return $result;
557
	}
558
559
	/**
560
	 * 拉取订单评价数据
561
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
562
	 * @param string $begin_time 开始时间,格式为yyyyMMddHHmmss
563
	 * @param string $end_time 结束时间,格式为yyyyMMddHHmmss
564
	 * @param int $offset 偏移
565
	 * @param int $limit 条数
566
	 * @return array
567
	 */
568 1
	public function batchQueryComment($begin_time,$end_time,$offset = 0,$limit = 200){
569 1
		$data = array();
570 1
		$data["appid"] = $this->config["app_id"];
571 1
		$data["begin_time"] = $begin_time;
572 1
		$data["end_time"] = $end_time;
573 1
		$data["offset"] = $offset;
574 1
		$data["limit"] = $limit;
575 1
		$data["sign"] = $this->sign($data,WechatPay::SIGNTYPE_HMACSHA256);
576 1
		$result = $this->post(self::URL_BATCHQUERYCOMMENT, $data, true); //cert is required
577 1
		return $result;
578
	}
579
580
	/**
581
	 * 获取支付参数(JSAPI - 公众号/小程序支付 , APP - APP支付)
582
	 * @param $prepay_id string 预支付ID
583
	 * @param $trade_type string 支付类型
584
	 * @return array
585
	 */
586 1
	public function getPackage($prepay_id, $trade_type = WechatPay::TRADETYPE_JSAPI) {
587 1
		$data = array();
588 1
		if ($trade_type == WechatPay::TRADETYPE_JSAPI){
589 1
			$data["package"]   = "prepay_id=$prepay_id";
590 1
			$data["timeStamp"] = time();
591 1
			$data["nonceStr"]  = $this->getNonceStr();
592 1
			$data["appId"] = $this->config["app_id"];
593 1
			$data["signType"]  = "MD5";
594 1
			$data["paySign"]   = $this->sign($data);
595 1
		} else if ($trade_type == WechatPay::TRADETYPE_APP){
596 1
			$data["package"]   = "Sign=WXPay";
597 1
			$data['prepayid'] = $prepay_id;
598 1
			$data['partnerid'] = $this->config["mch_id"];
599 1
			$data["timestamp"] = time();
600 1
			$data["noncestr"]  = $this->getNonceStr();
601 1
			$data["appid"] = $this->config["app_id"];
602 1
			$data["sign"]   = $this->sign($data);
603
		}
604 1
		return $data;
605
	}
606
607
	/**
608
	 * 提交刷卡支付
609
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
610
	 * @param $body
611
	 * @param $out_trade_no
612
	 * @param $total_fee
613
	 * @param $spbill_create_ip
614
	 * @param $auth_code
615
	 * @param array $ext
616
	 * @return array
617
	 */
618 1
	public function microPay($body,$out_trade_no,$total_fee,$spbill_create_ip,$auth_code,$ext = array()){
619 1
		$data = (!empty($ext) && is_array($ext))?$ext:array();
620 1
		$data["appid"] = $this->config["app_id"];
621 1
		$data["body"]         = $body;
622 1
		$data["out_trade_no"] = $out_trade_no;
623 1
		$data["total_fee"]    = $total_fee;
624 1
		$data["spbill_create_ip"] = $spbill_create_ip;
625 1
		$data["auth_code"] = $auth_code;
626 1
		$result = $this->post(self::URL_MICROPAY,$data,false);
627 1
		return $result;
628
	}
629
630
	/**
631
	 * 支付结果通知处理
632
	 * @param $notify_data array|string 通知数据
633
	 * @param $callback callable 回调
634
	 * @return null
635
	 * @throws Exception
636
	 */
637 2
	public function onPaidNotify($notify_data,callable $callback = null){
638 2
		if(!is_array($notify_data)) $notify_data = $this->xml2array($notify_data);
639 2
		if(!$this->validateSign($notify_data)) throw new Exception('Invalid paid notify data');
640 1
		if($callback && is_callable($callback)){
641 1
			return call_user_func_array( $callback , [$notify_data] );
642
		}
643
	}
644
645
	/**
646
	 * 退款结果通知处理
647
	 * @param string|array $notify_data 通知数据(XML/array)
648
	 * @param callable $callback 回调
649
	 * @return mixed
650
	 * @throws Exception
651
	 */
652 2
	public function onRefundedNotify($notify_data,callable $callback = null){
653 2
		if(!is_array($notify_data)) $notify_data = $this->xml2array($notify_data);
654 2
		if(!$this->validateSign($notify_data)) throw new Exception('Invalid refund notify data');
655 1
		if($callback && is_callable($callback)){
656 1
			return call_user_func_array( $callback ,[$notify_data] );
657
		}
658
	}
659
660
	/**
661
	 * 验证数据签名
662
	 * @param $data array 数据数组
663
	 * @return boolean 数据校验结果
664
	 */
665 5
	public function validateSign($data) {
666 5
		if (!isset($data["sign"])) {
667 1
			return false;
668
		}
669 4
		$sign = $data["sign"];
670 4
		unset($data["sign"]);
671 4
		return $this->sign($data) == $sign;
672
	}
673
674
	/**
675
	 * 响应微信支付后台通知
676
	 * @param array $data
677
	 * @param string $return_code 返回状态码 SUCCESS/FAIL
678
	 * @param string $return_msg  返回信息
679
	 * @param bool $print
680
	 * @return string
681
	 */
682 1
	public function responseNotify($print = true,$data = [],$return_code="SUCCESS", $return_msg= 'OK') {
683 1
		$data["return_code"] = $return_code;
684 1
		if ($return_msg) {
685 1
			$data["return_msg"] = $return_msg;
686
		}
687 1
		$xml = $this->array2xml($data);
688 1
		if($print === true) print $xml;
689 1
		else return $xml;
690
	}
691
692
	/**
693
	 * 交易保障
694
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_8&index=8
695
	 * @param string $interface_url
696
	 * @param string $execution_time
697
	 * @param string $return_code
698
	 * @param string $result_code
699
	 * @param string $user_ip
700
	 * @param string $out_trade_no
701
	 * @param string $time
702
	 * @param string $device_info
703
	 * @param string $return_msg
704
	 * @param string $err_code
705
	 * @param string $err_code_des
706
	 * @return array
707
	 */
708 1
	public function report($interface_url,$execution_time,$return_code,$result_code,$user_ip,$out_trade_no = null,$time = null,$device_info = null,
709
	                       $return_msg = null,$err_code = null,$err_code_des = null){
710 1
		$data = array();
711 1
		$data["appid"] = $this->config["app_id"];
712 1
		$data["interface_url"] = $interface_url;
713 1
		$data["execution_time"] = $execution_time;
714 1
		$data["return_code"] = $return_code;
715 1
		$data["result_code"] = $result_code;
716 1
		$data["user_ip"] = $user_ip;
717 1
		if($out_trade_no) $data["out_trade_no"] = $out_trade_no;
718 1
		if($time) $data["time"] = $time;
719 1
		if($device_info) $data["device_info"] = $device_info;
720 1
		if($return_msg) $data["return_msg"] = $return_msg;
721 1
		if($err_code) $data["err_code"] = $err_code;
722 1
		if($err_code_des) $data["err_code_des"] = $err_code_des;
723 1
		return $this->post(self::URL_REPORT, $data, false);
724
	}
725
726
	/**
727
	 * 转换短链接
728
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
729
	 * @param $longurl
730
	 * @return string
731
	 */
732 1
	public function shortUrl($longurl){
733 1
		$data = array();
734 1
		$data["appid"] = $this->config["app_id"];
735 1
		$data["long_url"] = $longurl;
736 1
		$result = $this->post(self::URL_SHORTURL,$data,false);
737 1
		return $result['short_url'];
738
	}
739
740
	/**
741
	 * 授权码查询openid
742
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=10
743
	 * @param $auth_code
744
	 * @return mixed
745
	 */
746 1
	public function authCodeToOpenId($auth_code){
747 1
		$data = array();
748 1
		$data["appid"] = $this->config["app_id"];
749 1
		$data["auth_code"] = $auth_code;
750 1
		$result = $this->post(self::URL_AUTHCODETOOPENID,$data,false);
751 1
		return $result['openid'];
752
	}
753
754
	/**
755
	 * 企业付款到零钱
756
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
757
	 * @param $partner_trade_no
758
	 * @param $openid
759
	 * @param $amount
760
	 * @param $desc
761
	 * @param $spbill_create_ip
762
	 * @param $check_name
763
	 * @param $re_user_name
764
	 * @return array
765
	 * @throws Exception
766
	 */
767 2
	public function transferWallet($partner_trade_no,$openid,$amount,$desc,$spbill_create_ip = null,$re_user_name = null,$check_name = WechatPay::CHECKNAME_FORCECHECK){
768 2
		$data = array();
769 2
		if($check_name == WechatPay::CHECKNAME_FORCECHECK && !$re_user_name) throw new Exception('Real name is required');
770 2
		$data["mch_appid"] = $this->config["app_id"];
771 2
		$data["mchid"] = $this->config["mch_id"];
772 2
		$data["partner_trade_no"] = $partner_trade_no;
773 2
		$data["openid"] = $openid;
774 2
		$data["amount"] = $amount;
775 2
		$data["desc"] = $desc;
776 2
		$data['spbill_create_ip'] = $spbill_create_ip?:$_SERVER['SERVER_ADDR'];
777 2
		$data["check_name"] = $check_name;
778 2
		$data["re_user_name"] = $re_user_name;
779 2
		$result = $this->post(self::URL_TRANSFER_WALLET,$data,true);
780 1
		return $result;
781
	}
782
783
	/**
784
	 * 查询企业付款
785
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
786
	 * @param $partner_trade_no
787
	 * @return array
788
	 */
789 1
	public function queryTransferWallet($partner_trade_no){
790 1
		$data = array();
791 1
		$data["appid"] = $this->config["app_id"];
792 1
		$data["mch_id"] = $this->config["mch_id"];
793 1
		$data["partner_trade_no"] = $partner_trade_no;
794 1
		$result = $this->post(self::URL_QUERY_TRANSFER_WALLET,$data,true);
795 1
		return $result;
796
	}
797
798
	/**
799
	 * 企业付款到银行卡
800
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
801
	 * @param $partner_trade_no
802
	 * @param $bank_no
803
	 * @param $true_name
804
	 * @param $bank_code
805
	 * @param $amount
806
	 * @param $desc
807
	 * @return array
808
	 * @throws Exception
809
	 */
810 2
	public function transferBankCard($partner_trade_no,$bank_no,$true_name,$bank_code,$amount,$desc){
811 2
		if(!in_array($bank_code,array_values(self::$BANKCODE))) throw new Exception("Unsupported bank code: $bank_code");
812 2
		$data = array();
813 2
		$data["partner_trade_no"] = $partner_trade_no;
814 2
		$enc_bank_no = $this->rsaEncrypt($bank_no);
815 1
		$data["enc_bank_no"] = $enc_bank_no;
816 1
		$enc_true_name = $this->rsaEncrypt($true_name);
817 1
		$data["enc_true_name"] = $enc_true_name;
818 1
		$data["bank_code"] = $bank_code;
819 1
		$data["desc"] = $desc;
820 1
		$data["amount"] = $amount;
821 1
		$result = $this->post(self::URL_TRANSFER_BANKCARD,$data,true);
822 1
		return $result;
823
	}
824
825
	/**
826
	 * 查询企业付款银行卡
827
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
828
	 * @param $partner_trade_no
829
	 * @return array
830
	 */
831 1
	public function queryTransferBankCard($partner_trade_no){
832 1
		$data = array();
833 1
		$data["appid"] = $this->config["app_id"];
834 1
		$data["mch_id"] = $this->config["mch_id"];
835 1
		$data["partner_trade_no"] = $partner_trade_no;
836 1
		$result = $this->post(self::URL_QUERY_TRANSFER_WALLET,$data,true);
837 1
		return $result;
838
	}
839
840
	/**
841
	 * 发放代金券
842
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3&index=4
843
	 * @param $coupon_stock_id
844
	 * @param $open_id
845
	 * @param $partner_trade_no
846
	 * @param string $op_user_id
847
	 * @param array $ext
848
	 * @return array
849
	 */
850 2
	public function sendCoupon($coupon_stock_id,$open_id,$partner_trade_no,$op_user_id = '',$ext = array()){
851 2
		$data = (!empty($ext) && is_array($ext))?$ext:array();
852 2
		$data["partner_trade_no"] = $partner_trade_no;
853 2
		$data["coupon_stock_id"] = $coupon_stock_id;
854 2
		$data["openid_count"] = 1;
855 2
		$data["open_id"] = $open_id;
856 2
		$data["op_user_id"] = $op_user_id;
857 2
		$result = $this->post(self::URL_SEND_COUPON,$data,true);
858 1
		return $result;
859
	}
860
861
	/**
862
	 * 查询代金券批次
863
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_4&index=5
864
	 * @param $coupon_stock_id
865
	 * @param string $op_user_id
866
	 * @return array
867
	 */
868 1
	public function queryCouponStock($coupon_stock_id,$op_user_id = ''){
869 1
		$data = array();
870 1
		$data["coupon_stock_id"] = $coupon_stock_id;
871 1
		$data["op_user_id"] = $op_user_id;
872 1
		$result = $this->post(self::URL_QUERY_COUPON_STOCK,$data,false);
873 1
		return $result;
874
	}
875
876
	/**
877
	 * 查询代金券信息
878
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_5&index=6
879
	 * @param $coupon_id
880
	 * @param $open_id
881
	 * @param $stock_id
882
	 * @param string $op_user_id
883
	 * @param array $ext
884
	 * @return array
885
	 */
886 1
	public function queryCouponsInfo($coupon_id,$open_id,$stock_id,$op_user_id = '',$ext = array()){
887 1
		$data = (!empty($ext) && is_array($ext))?$ext:array();
888 1
		$data["coupon_id"] = $coupon_id;
889 1
		$data["stock_id"] = $stock_id;
890 1
		$data["open_id"] = $open_id;
891 1
		$data["op_user_id"] = $op_user_id;
892 1
		$result = $this->post(self::URL_QUERY_COUPON_INFO,$data,false);
893 1
		return $result;
894
	}
895
896
	/**
897
	 * 获取RSA加密公钥
898
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
899
	 * @param bool $refresh
900
	 * @return string
901
	 * @throws Exception
902
	 */
903 3
	public function getPublicKey($refresh = false){
904 3
		if(!$this->publicKey) {
905 2
			if (!$refresh && file_exists($this->config["rsa_pubkey_path"])) {
906 1
				$this->publicKey = file_get_contents($this->config["rsa_pubkey_path"]);
907
			}else{
908 2
				$data = array();
909 2
				$data["mch_id"] = $this->config["mch_id"];
910 2
				$data["sign_type"] = $this->config["sign_type"];
911 2
				$result = $this->post(self::URL_GETPUBLICKEY, $data, true);
912 1
				$pubkey = $result['pub_key'];
913 1
				$this->publicKey = $this->convertPKCS1toPKCS8($pubkey);
914 1
				$fp = @fopen($this->config["rsa_pubkey_path"], "w");
915 1
				fwrite($fp, $this->publicKey);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

915
				fwrite(/** @scrutinizer ignore-type */ $fp, $this->publicKey);
Loading history...
916 1
				fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

916
				fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
917
			}
918
		}
919 2
		return $this->publicKey;
920
	}
921
922 2
	public function setPublicKey($publicKey){
923 2
		$this->publicKey = $publicKey;
924 2
	}
925
926 1
	private function convertPKCS1toPKCS8($pkcs1){
927 1
		$start_key = $pkcs1;
928 1
		$start_key = str_replace('-----BEGIN RSA PUBLIC KEY-----', '', $start_key);
929 1
		$start_key = trim(str_replace('-----END RSA PUBLIC KEY-----', '', $start_key));
930 1
		$key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' . str_replace("\n", '', $start_key);
931 1
		$key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
932 1
		return $key;
933
	}
934
935 4
	public function rsaEncrypt($data,$pubkey = null){
936 4
		if(!$pubkey) $pubkey = $this->getPublicKey();
937 3
		$encrypted = null;
938 3
		$pubkey = openssl_get_publickey($pubkey);
939 3
		if (@openssl_public_encrypt($data, $encrypted, $pubkey,OPENSSL_PKCS1_OAEP_PADDING))
940 2
			$data = base64_encode($encrypted);
941
		else
942 1
			throw new Exception('Unable to encrypt data');
943 2
		return $data;
944
	}
945
946
	/**
947
	 * sandbox环境获取验签秘钥
948
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_1
949
	 * @return array
950
	 */
951 1
	public function getSignKey(){
952 1
		$data = array();
953 1
		$data["mch_id"] = $this->config["mch_id"];
954 1
		$result = $this->post($this->getSignKeyUrl,$data,false);
955 1
		return $result['sandbox_signkey'];
956
	}
957
958
	/**
959
	 * 获取JSAPI所需要的页面参数
960
	 * @param string $url
961
	 * @param string $ticket
962
	 * @return array
963
	 */
964 1
	public function getSignPackage($url, $ticket = null){
965 1
		if(!$ticket) $ticket = $this->getTicket();
966 1
		$timestamp = time();
967 1
		$nonceStr = $this->getNonceStr();
968 1
		$rawString = "jsapi_ticket=$ticket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
969 1
		$signature = sha1($rawString);
970
971
		$signPackage = array(
972 1
			"appId" => $this->config['app_id'],
973 1
			"nonceStr" => $nonceStr,
974 1
			"timestamp" => $timestamp,
975 1
			"url" => $url,
976 1
			"signature" => $signature,
977 1
			"rawString" => $rawString
978
		);
979 1
		return $signPackage;
980
	}
981
982
	/**
983
	 * 获取JSAPI Ticket
984
	 * @param boolean $cache
985
	 * @return string
986
	 */
987 1
	public function getTicket($cache = true){
988 1
		$ticket = null;
989 1
		$cacheKey = 'jsapi_ticket';
990 1
		if($cache === true){
991 1
			$data = $this->cacheProvider->get($cacheKey);
992 1
			if ($data && $data->expires_at > time()) {
993 1
				$ticket = $data->ticket;
994
			}
995
		}
996 1
		if(!$ticket){
997 1
			$data = $this->getWechatOAuth()->getTicket();
998 1
			if($cache === true){
999 1
				$this->cacheProvider->set($cacheKey,$data,time() + $data->expires_in);
1000
			}
1001 1
			$ticket = $data->ticket;
1002
		}
1003 1
		return $ticket;
1004
	}
1005
1006 38
	private function post($url, $data,$cert = true) {
1007 38
		if(!isset($data['mch_id']) && !isset($data['mchid'])) $data["mch_id"] = $this->config["mch_id"];
1008 38
		if(!isset($data['nonce_str'])) $data["nonce_str"] = $this->getNonceStr();
1009 38
		if(!isset($data['sign'])) $data['sign'] = $this->sign($data);
1010 38
		$this->requestXML = $this->responseXML = null;
1011 38
		$this->requestArray = $this->responseArray = null;
1012
1013 38
		$this->requestArray = $data;
1014 38
		$this->requestXML = $this->array2xml($data);
1015
		$opts = [
1016 38
			CURLOPT_SSL_VERIFYPEER => false,
1017 38
			CURLOPT_SSL_VERIFYHOST => false,
1018 38
			CURLOPT_RETURNTRANSFER => true,
1019 38
			CURLOPT_TIMEOUT => 10
1020
		];
1021 38
		if($cert == true){
1022 30
			$opts[CURLOPT_SSLCERTTYPE] = 'PEM';
1023 30
			$opts[CURLOPT_SSLCERT] = $this->config['ssl_cert_path'];
1024 30
			$opts[CURLOPT_SSLKEYTYPE] = 'PEM';
1025 30
			$opts[CURLOPT_SSLKEY] = $this->config['ssl_key_path'];
1026
		}
1027 38
		$processResponse = true;
1028 38
		if(in_array($url,[self::URL_DOWNLOADBILL,self::URL_DOWNLOAD_FUND_FLOW,self::URL_BATCHQUERYCOMMENT])){
1029 3
			$processResponse = false;
1030
		}
1031 38
		if($this->sandbox === true) $url = "sandboxnew/{$url}";
1032
1033 38
		$content = $this->httpClient->post(self::API_ENDPOINT . $url,$this->requestXML,[],$opts);
1034 38
		if(!$content) throw new Exception("Empty response with {$this->requestXML}");
1035
1036 38
		$this->responseXML = $content;
1037 38
		if($processResponse)
1038 35
			return $this->processResponseXML($this->responseXML);
1039 3
		else return $this->responseXML;
1040
1041
	}
1042
1043
	/**
1044
	 * @param $responseXML
1045
	 * @return array
1046
	 * @throws Exception
1047
	 */
1048 35
	private function processResponseXML($responseXML){
1049 35
		$result = $this->xml2array($responseXML);
1050 35
		$this->responseArray = $result;
1051 35
		if(empty($result['return_code'])){
1052 1
			throw new Exception("No return code presents in {$this->responseXML}");
1053
		}
1054 34
		$this->returnCode = $result["return_code"];
1055 34
		$this->returnMsg = isset($result['return_msg'])?$result['return_msg']:'';
1056
1057 34
		if ($this->returnCode == "SUCCESS") {
1058 28
			if(isset($result['result_code']) && $result['result_code'] == "FAIL"){
1059 3
				$this->resultCode = $result['result_code'];
1060 3
				$this->errCode = $result['err_code'];
1061 3
				$this->errCodeDes = $result['err_code_des'];
1062 3
				throw new Exception("[$this->errCode]$this->errCodeDes");
1063
			}else{
1064 25
				return $result;
1065
			}
1066 6
		} else if($this->returnCode == 'FAIL'){
1067 6
			throw new Exception($this->returnMsg);
1068
		}
1069
	}
1070
1071 45
	public function sign($data,$sign_type = WechatPay::SIGNTYPE_MD5) {
1072 45
		ksort($data);
1073 45
		$string1 = "";
1074 45
		foreach ($data as $k => $v) {
1075 45
			if ($v && trim($v)!='') {
1076 45
				$string1 .= "$k=$v&";
1077
			}
1078
		}
1079 45
		$stringSignTemp = $string1 . "key=" . $this->config["api_key"];
1080 45
		if($sign_type == WechatPay::SIGNTYPE_MD5){
1081 43
			$sign = strtoupper(md5($stringSignTemp));
1082 3
		}elseif($sign_type == WechatPay::SIGNTYPE_HMACSHA256){
1083 2
			$sign = strtoupper(hash_hmac('sha256',$stringSignTemp,$this->config["api_key"]));
1084 1
		}else throw new Exception("Not supported sign type - $sign_type");
1085 44
		return $sign;
1086
	}
1087
1088 39
	private function array2xml($array) {
1089 39
		$xml = "<xml>" . PHP_EOL;
1090 39
		foreach ($array as $k => $v) {
1091 39
			if($v && trim($v)!='')
1092 39
				$xml .= "<$k><![CDATA[$v]]></$k>" . PHP_EOL;
1093
		}
1094 39
		$xml .= "</xml>";
1095 39
		return $xml;
1096
	}
1097
1098 37
	private function xml2array($xml) {
1099 37
		$array = [];
1100 37
		$tmp = (array) simplexml_load_string($xml);
1101 37
		foreach ( $tmp as $k => $v) {
1102 37
			$array[$k] = (string) $v;
1103
		}
1104 37
		return $array;
1105
	}
1106
1107 40
	private function getNonceStr() {
1108 40
		return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"),0,32);
1109
	}
1110
1111
}