账户设置-->API安全-->密钥设置 protected $payKey; // 微信支付回调地址 protected $payNotifyUrl; /** * 设定配置项 * * @param 微信小程序配置文件读取 */ public function __construct() { $this->appId = config('wxconfig.appId'); $this->appSecret = config('wxconfig.appSecret'); $this->payMchId = config('wxconfig.payMchId'); $this->payKey = config('wxconfig.payKey'); $this->payNotifyUrl = config('wxconfig.payNotifyUrl'); } /** * 校验access_token是否过期 * @param string $token * @return bool */ public function valid_access_token($token) { return $token && isset($token['expires_in']) && ($token['expires_in'] > time() + 1200); } /** * 生成新的access_token * @return mixed */ public function new_access_token() { $url = self::API_DOMAIN . 'cgi-bin/token?grant_type=client_credential&appid=' . $this->appId . '&secret=' . $this->appSecret; $res = HttpCurl::get($url, 'json'); // 异常处理: 获取access_token网络错误 if ($res === false) { @error_log('Http Get AccessToken Error.', 0); return false; } // 异常处理: access_token获取失败 if (!isset($res['access_token'])) { @error_log('Get AccessToken Error: ' . json_encode($res), 0); return false; } $res['expires_in'] += time(); $fp = fopen(dirname(__FILE__)."/json/access_token.json", "w"); fwrite($fp, json_encode($res)); fclose($fp); return $res; } /** * 获取access_token * @return string */ public function get_access_token() { $token = json_decode(file_get_contents(dirname(__FILE__)."/json/access_token.json"), true); // 验证AccessToken是否有效 if (!$this->valid_access_token($token)) { // 生成新的AccessToken $token = $this->new_access_token(); if ($token === false) { return false; } } return $token['access_token']; } /** * WxPay - 统一下单 - 生成预订单 * @param array $conf 配置数组 * @return bool|mixed */ public function wxpay_unified_order($conf = []) { // [必填]公众账号ID、应用ID $conf['appid'] = $this->appId; // [必填]商户号、 $conf['mch_id'] = $this->payMchId; // 设备号 // - device_info // [必填]nonce_str 随机字符串 $conf['nonce_str'] = SHA1::get_random_str(32); // 签名类型 $conf['sign_type'] = 'MD5'; // [必填]商品描述 // - body // 商品详情 // - detail // 附加数据 // - attach // [必填]商户订单号 // - out_trade_no // 货币类型 // - fee_type // [必填]总金额 // - total_fee // [必填]终端IP $conf['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; // 交易起始时间 // - time_start // 交易结束时间 // - time_expire // 商品标记 // - goods_tag // [必填]通知地址 $conf['notify_url'] = $this->payNotifyUrl; // [必填]交易类型 $conf['trade_type'] = "JSAPI"; // 指定支付方式 // - limit_pay // 用户标识, trade_type=JSAPI时(即公众号支付),此参数必传 // - openid // [必填]签名 $conf['sign'] = SHA1::getSign2($conf, 'key='.$this->payKey); // 生成xml $xml = Xml::toXml($conf); // 调用接口 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; try { $res = HttpCurl::post($url, $xml); libxml_disable_entity_loader(true); $datas = json_decode(json_encode(simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA)), true); if($datas['return_code'] == 'FAIL'){ $result = array('status'=>40014,'data'=>$datas['return_msg']); return $result; }if($datas['result_code'] == 'FAIL'){ $result = array('status'=>40014,'data'=>$datas['err_code'].":".$datas['err_code_des']); return $result; } //判断签名是否存在,及签名是否正确 if(!array_key_exists('sign', $datas)){ $result = array('status'=>40011,'data'=>'签名错误!'); return $result; } $result = array('status'=>1,'data'=>$datas); return $result; } catch (\Exception $e) { $result = array('status'=>40011,'data'=>'下单失败,请稍后重试!'); return $result; } } /** * WxPay - 获取jsapi支付的参数 * 用于直接填入js函数作为参数 * @param string $prepayId 预生成订单ID * @return string */ public function get_jsapi_param($prepayId) { $input = [ 'appId' => $this->appId, 'nonceStr' => SHA1::get_random_str(32), 'package' => 'prepay_id='.$prepayId, 'timeStamp' => (string)time(), 'signType' => 'MD5' ]; $input['paySign'] = SHA1::getSign2($input, 'key='.$this->payKey); return $input; } /** * WxPay - 处理微信支付异步通知 * 包含 * @return array [是否支付成功, 异步通知的原始数据, 回复微信异步通知的数据] */ public function notify() { $xml = file_get_contents('php://input'); try { libxml_disable_entity_loader(true); $data = Xml::toArr($xml); if (! is_array($data)) { $result = array('status'=>40014,'data'=>'支付回调出错。'); return $result; } // 格式是否正确 if (! array_key_exists('return_code', $data)) { $result = array('status'=>40011,'data'=>'return_code is not set。'); return $result; } // 是否支付成功 if ($data['return_code'] != 'SUCCESS') { $result = array('status'=>40011,'data'=>'return_code is '.$data['return_code']); return $result; } // 签名是否正确 $sign1 = SHA1::getSign2($data, 'key='.$this->payKey); if ($sign1 != $data['sign']) { $result = array('status'=>40011,'data'=>'签名验证失败。'); return $result; } //返回结果 $result = array('status'=>1,'data'=>$data); return $result; } catch (\Exception $e) { $result = array('status'=>40011,'data'=>'回调失败!'); return $result; } } /** * WxPay - 回复微信异步通知 * 包含 * @param array $info 回复内容数组 */ public function reply_notify() { $data['return_code'] = 'SUCCESS'; $data['return_msg'] = 'OK'; $xml = Xml::toXml($data); echo $xml; die(); } }