123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <?php
- /**
- * WxPay.php
- *
- * 微信小程序开发API接口
- * - 小程序码
- * - 安全内容
- * - 微信支付
- *
- */
- namespace echowx;
- use think\Exception;
- use echowx\utils\HttpCurl;
- use echowx\utils\Error;
- use echowx\utils\SHA1;
- use echowx\utils\Xml;
- class WxPay
- {
-
- // 开发者中心-配置项-AppID(应用ID)
- protected $appId;
- // 开发者中心-配置项-AppSecret(应用密钥)
- protected $appSecret;
- // 微信支付商户号,商户申请微信支付后,由微信支付分配的商户收款账号
- protected $payMchId;
- // API密钥,微信商户平台(pay.weixin.qq.com)-->账户设置-->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();
- }
-
-
-
-
- }
|