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