Passed
Push — master ( de13f2...c385cb )
by Wei
02:39
created

WechatPay::sendRedPack()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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

998
				fwrite(/** @scrutinizer ignore-type */ $fp, json_encode($data));
Loading history...
999
				if ($fp) fclose($fp);
0 ignored issues
show
introduced by
$fp is of type resource|false, thus it always evaluated to false.
Loading history...
1000
			}
1001
			$ticket = $data->ticket;
1002
		}
1003
		return $ticket;
1004
	}
1005
1006
	private function post($url, $data,$cert = true) {
1007
		if(!isset($data['mch_id']) && !isset($data['mchid'])) $data["mch_id"] = $this->config["mch_id"];
1008
		if(!isset($data['nonce_str'])) $data["nonce_str"] = $this->getNonceStr();
1009
		if(!isset($data['sign'])) $data['sign'] = $this->sign($data);
1010
		$this->requestXML = $this->responseXML = null;
1011
		$this->requestArray = $this->responseArray = null;
1012
1013
		$this->requestArray = $data;
1014
		$this->requestXML = $this->array2xml($data);
1015
		$opts = [
1016
			CURLOPT_SSL_VERIFYPEER => false,
1017
			CURLOPT_SSL_VERIFYHOST => false,
1018
			CURLOPT_RETURNTRANSFER => true,
1019
			CURLOPT_TIMEOUT => 10
1020
		];
1021
		if($cert == true){
1022
			$opts[CURLOPT_SSLCERTTYPE] = 'PEM';
1023
			$opts[CURLOPT_SSLCERT] = $this->config['ssl_cert_path'];
1024
			$opts[CURLOPT_SSLKEYTYPE] = 'PEM';
1025
			$opts[CURLOPT_SSLKEY] = $this->config['ssl_key_path'];
1026
		}
1027
		$processResponse = true;
1028
		if(in_array($url,[self::URL_DOWNLOADBILL,self::URL_DOWNLOAD_FUND_FLOW,self::URL_BATCHQUERYCOMMENT])){
1029
			$processResponse = false;
1030
		}
1031
		if($this->sandbox === true){
1032
			$host = "https://api.mch.weixin.qq.com";
1033
			$url = str_replace($host,'',$url);
1034
			$url = "{$host}/sandboxnew{$url}";
1035
		}
1036
		$content = $this->httpClient->post($url,$this->requestXML,[],$opts);
1037
		if(!$content) throw new Exception("Empty response with {$this->requestXML}");
1038
1039
		$this->responseXML = $content;
1040
		if($processResponse)
1041
			return $this->processResponseXML($this->responseXML);
1042
		else return $this->responseXML;
1043
1044
	}
1045
1046
	private function processResponseXML($responseXML){
1047
		$result = $this->xml2array($responseXML);
1048
		$this->responseArray = $result;
1049
		if(empty($result['return_code'])){
1050
			throw new Exception("No return code presents in {$this->responseXML}");
1051
		}
1052
		$this->returnCode = $result["return_code"];
1053
		$this->returnMsg = isset($result['return_msg'])?$result['return_msg']:'';
1054
1055
		if ($this->returnCode == "SUCCESS") {
1056
			if(isset($result['result_code']) && $result['result_code'] == "FAIL"){
1057
				$this->resultCode = $result['result_code'];
1058
				$this->errCode = $result['err_code'];
1059
				$this->errCodeDes = $result['err_code_des'];
1060
				throw new Exception("[$this->errCode]$this->errCodeDes");
1061
			}else{
1062
				return $result;
1063
			}
1064
		} else {
1065
			if($result["return_code"] == "FAIL"){
1066
				throw new Exception($this->returnMsg);
1067
			}else{
1068
				$this->resultCode = $result['result_code'];
1069
				$this->errCode = $result['err_code'];
1070
				$this->errCodeDes = $result['err_code_des'];
1071
				throw new Exception("[$this->errCode]$this->errCodeDes");
1072
			}
1073
		}
1074
	}
1075
1076
	public function sign($data,$sign_type = WechatPay::SIGNTYPE_MD5) {
1077
		ksort($data);
1078
		$string1 = "";
1079
		foreach ($data as $k => $v) {
1080
			if ($v && trim($v)!='') {
1081
				$string1 .= "$k=$v&";
1082
			}
1083
		}
1084
		$stringSignTemp = $string1 . "key=" . $this->config["api_key"];
1085
		if($sign_type == WechatPay::SIGNTYPE_MD5){
1086
			$sign = strtoupper(md5($stringSignTemp));
1087
		}elseif($sign_type == WechatPay::SIGNTYPE_HMACSHA256){
1088
			$sign = strtoupper(hash_hmac('sha256',$stringSignTemp,$this->config["api_key"]));
1089
		}else throw new Exception("Not supported sign type - $sign_type");
1090
		return $sign;
1091
	}
1092
1093
	private function array2xml($array) {
1094
		$xml = "<xml>" . PHP_EOL;
1095
		foreach ($array as $k => $v) {
1096
			if($v && trim($v)!='')
1097
				$xml .= "<$k><![CDATA[$v]]></$k>" . PHP_EOL;
1098
		}
1099
		$xml .= "</xml>";
1100
		return $xml;
1101
	}
1102
1103
	private function xml2array($xml) {
1104
		$array = array();
1105
		$tmp = array();
0 ignored issues
show
Unused Code introduced by
The assignment to $tmp is dead and can be removed.
Loading history...
1106
		try{
1107
			$tmp = (array) simplexml_load_string($xml);
1108
		}catch(Exception $e){
1109
			throw $e;
1110
		}
1111
		foreach ( $tmp as $k => $v) {
1112
			$array[$k] = (string) $v;
1113
		}
1114
		return $array;
1115
	}
1116
1117
	private function getNonceStr() {
1118
		return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"),0,32);
1119
	}
1120
1121
}