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

WechatPay::getPublicKey()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 16
nc 5
nop 1
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
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
}