| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 | <?php/** * @note: 微信支付 App支付、小程序支付、扫码支付、H5支付 * @author: jdzor <895947580@qq.com> * @date: 2019/1/18 */namespace payment\wechat;/** * 文档地址:  https://pay.weixin.qq.com/wiki/doc/api/index.html * 预下单方法: *              $wechatPay = new WechatPay($config); *              $info = $wechatPay->unifiedOrder($payData); *              $info['return_code'] == 'FAIL' && json_error($info['return_msg'], -2); *              $info['result_code'] == 'FAIL' && json_error($info['err_code_des'], -2); * * 1.扫码支付:    $info['code_url']  此url用于生成支付二维码,然后提供给用户进行扫码支付。注意:code_url的值并非固定,使用时按照URL格式转成二维码即可 * 2.H5支付:      $info['mweb_url']  mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟 *                                 可拼接跳转链接:  $info['mweb_url'].'&redirect_url='.urlencode($returnUrl); * 3.App支付:     $wechatPay->getAppParam($info['prepay_id']);  将结果返回给App端即可 * 4.Jsapi支付:  $wechatPay->getJsapiParam($info['prepay_id']);  将结果返回给微信内H5支付或小程序端即可 * * Class WechatPay * @package app\common\extend\wechat */class WechatPay extends BaseWechat{    const UNIFIED_ORDER_URL = "/pay/unifiedorder"; //下单地址    const ORDER_QUERY_URL = "/pay/orderquery"; //查询订单    const CLOSE_ORDER_URL = "/pay/closeorder"; //关闭订单    public static $tradeMap = [        'jsapi' => 'JSAPI', //小程序支付、公众号支付(微信内H5环境)        'app' => 'APP', //APP支付        'native' => 'NATIVE', //扫码支付        'mweb' => 'MWEB' //H5支付,非微信内H5环境    ];    private $openid; //公众号支付 用户openid    private $wapUrl; //H5支付 WAP网站URL地址    private $wapName; //H5支付 WAP网站名    private $qrcodeTimeoutExpress; //扫码支付 二维码失效时间,单位:秒    public function __construct($config)    {        parent::__construct($config);    }    //下单参数检测    private function check($param)    {        isset($param['body']) || json_error('缺少参数:body');        isset($param['out_trade_no']) || json_error('缺少参数:out_trade_no');        isset($param['total_fee']) || json_error('缺少参数:total_fee');        isset($param['trade_type']) || json_error('缺少参数:trade_type');        isset($param['notify_url']) || json_error('缺少参数:notify_url');        //不同支付类型时 参数检测        if ($param['trade_type'] == self::$tradeMap['jsapi']) { //公众号支付            isset($param['openid']) || json_error('缺少参数:openid');            $this->openid = $param['openid'];        } elseif ($param['trade_type'] == self::$tradeMap['native']) { //扫码支付            isset($param['expire']) || json_error('缺少参数:expire');            $this->qrcodeTimeoutExpress = $param['expire'];        } elseif ($param['trade_type'] == self::$tradeMap['mweb']) { //H5支付            isset($param['wap_url']) || json_error('缺少参数:wap_url');            isset($param['wap_name']) || json_error('缺少参数:wap_name');            $this->wapUrl = $param['wap_url'];            $this->wapName = $param['wap_name'];        }    }    //下单方法    public function unifiedOrder($param)    {        $this->check($param);        $data['appid'] = $this->appId;        $data['mch_id'] = $this->mchId;        $data['notify_url'] = $this->notifyUrl;        $data['body'] = $param['body'];        $data['out_trade_no'] = $param['out_trade_no'];        $data['total_fee'] = $param['total_fee'];        $data['trade_type'] = $param['trade_type'];        $data['notify_url'] = $param['notify_url'];        $data['nonce_str'] = $this->getRandomString();        $data['spbill_create_ip'] = get_client_ip();        $data['sign_type'] = $this->signType;        //不同支付类型时 参数传入        if ($param['trade_type'] == self::$tradeMap['jsapi']) {            $data['openid'] = $this->openid;        } elseif ($param['trade_type'] == self::$tradeMap['native']) {            $data['time_start'] = date("YmdHis");            $data['time_expire'] = date("YmdHis", time() + $this->qrcodeTimeoutExpress);        } elseif ($param['trade_type'] == self::$tradeMap['mweb']) {            $senseInfo = ['h5_info' => ['type' => 'Wap', 'wap_url' => $this->wapUrl, 'wap_name' => $this->wapName]];            $data['scene_info'] = json_encode($senseInfo);        }        //获取签名数据        $data['sign'] = $this->makeSign($data);        $xml = $this->dataToXml($data);        $response = $this->postXmlCurl($xml, self::UNIFIED_ORDER_URL);        if (!$response) return false;        $result = $this->xmlToArray($response);        return $result;    }    //生成 APP端支付参数    public function getAppParam($prepayId)    {        $data['appid'] = $this->appId;        $data['partnerid'] = $this->mchId;        $data['prepayid'] = $prepayId;        $data['package'] = 'Sign=WXPay';        $data['noncestr'] = $this->getRandomString();        $data['timestamp'] = time();        $data['sign_type'] = $this->signType;        $data['sign'] = $this->makeSign($data);        return $data;    }    //生成微信内H5支付、小程序端支付参数 注意参数大小写    public function getJsapiParam($prepayId)    {        $data['appId'] = $this->appId;        $data['nonceStr'] = $this->getRandomString();        $data['package'] = 'prepay_id=' . $prepayId;        $data['timeStamp'] = time();        $data['signType'] = $this->signType;         $data['paySign'] = $this->makeSign($data);        return $data;    }    //查询订单    public function queryOrder($outTradeNo)    {        $data['appid'] = $this->appId;        $data['mch_id'] = $this->mchId;        $data['nonce_str'] = $this->getRandomString();        $data['out_trade_no'] = $outTradeNo;        $data['sign_type'] = $this->signType;        $data['sign'] = $this->makeSign($data);        $xml = $this->dataToXml($data);        $response = $this->postXmlCurl($xml, self::ORDER_QUERY_URL);        if (!$response) return false;        $result = $this->xmlToArray($response);        return $result;    }    //关闭订单    public function closeOrder($outTradeNo)    {        $data['appid'] = $this->appId;        $data['mch_id'] = $this->mchId;        $data['nonce_str'] = $this->getRandomString();        $data['out_trade_no'] = $outTradeNo;        $data['sign_type'] = $this->signType;        $data['sign'] = $this->makeSign($data);        $xml = $this->dataToXml($data);        $response = $this->postXmlCurl($xml, self::CLOSE_ORDER_URL);        if (!$response) return false;        $result = $this->xmlToArray($response);        return $result;    }    //获取支付结果通知数据    public function getNotifyData()    {        //获取通知的数据        $xml = file_get_contents('php://input');        if (!$xml) return false;        $data = $this->xmlToArray($xml);        if (isset($data['return_code']) && $data['return_code'] == 'FAIL') return false;        return $data;    }    //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。    //通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒    public function replyNotify()    {        $data['return_code'] = 'SUCCESS';        $data['return_msg'] = 'OK';        $xml = $this->dataToXml($data);        echo $xml;        die();    }}
 |