tp5之 支付宝,当面付与网页支付

当面付 (原理场景使用范例)

https://blog.csdn.net/weixin_34111790/article/details/86344681

当面付 和 手机网站支付 在同一个文件中

https://blog.csdn.net/qq_21761149/article/details/84502416

我参考第2个

<?php
namespace app\admin\controller;

use think\Controller;
use app\index\controller\Commen;  
use think\Session;
use think\Db;
use think\Request;

/**
 * @author     mselect <445712421@qq.com>
 *
 * @DateTime 2018-11-16 10:43:44
 * 支付宝支付类
 */
class Alipay extends Commen 
{
 
    //是否沙盒环境
    public $is_sandbox = false;
    //沙盒地址
    private $sandurl = 'https://openapi.alipaydev.com/gateway.do';
    //正式地址
    private $url = 'https://openapi.alipay.com/gateway.do';   
    // private $url = 'https://openapi.alipaydev.com/gateway.do';

    //appid
    private $appid ;
    //商户应用私钥
    private $rsaPrivateKey = '';
 
    //支付宝公钥 验签使用
    private $alipayPublicKey= '';
 
    private $payment_id;
 
    private $charset = 'utf-8';
 
    public function __construct(){
         
        // $payment = Db::name('payment')->where('code', 'alipay')->find();
        // $json = json_decode($payment['json'], true);
        // $this->appid = $json['appid'];
        $this->appid = '';

        // $this->payment_id = $payment['id'];
         
    }
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-16 10:57:51
     * 发起支付
     */
    public function pay($order_id){
 
        $time = time();
        // 判断是否是沙箱环境
        if($this->is_sandbox){
            $url = $this->sandurl;
            $this->appid = '';
            $this->rsaPrivateKey = '';
            $this->alipayPublicKey = '';
            echo '111';
        }else {
            $url = $this->url;
            // echo '222';
        }
        // die;
        
        $notify_url = '异步回调';
        // $order = Db::name('order')->where('id', $order_id)->find();
 
        //请求参数的集合 json_encode
        $biz_content = [
            // 'out_trade_no' => $order['order_unique'],
            'out_trade_no' => '111111',

            //'seller_id' => ''
            // 'total_amount' => $order['real_total_fee'],
            'total_amount' => '666',

            //'discountable_amount' => '',
            'subject' => '标题',   
            //'goods_detail' => '',
            //'body' => $order['body'],
            //'operator_id' => '',
            //'store_id' => '',
            //'disable_pay_channels' => '',
            //'enable_pay_channels' => '',
            //'terminal_id'=> '',
            //'extend_params' => '',
            //'timeout_express' => '',
            //'settle_info' => '',
            //'business_params' => '',
            //'qr_code_timeout_express' => '',
        ];
 
        //参数
        $param = [
            'app_id' => $this->appid,                       //支付宝分配给开发者的应用ID
            'method' => 'alipay.trade.precreate',           //接口名称
            //'format' => 'JSON',                           //紧支持JSON
            'charset' => 'utf-8',                           //请求使用的编码格式
            'sign_type' => 'RSA2',                          //商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
            'sign' => 'RSA2',                               //商户请求参数的签名串
            'timestamp' => date('Y-m-d H:i:s', $time),      //发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
            'version' => '1.0',                             //调用的接口版本,固定为1.0
            'notify_url' => $notify_url,                    //支付宝服务器主动通知商户服务器里指定的页面http/https路径
            //'app_auth_token' => '',                       //app_auth_token
            'biz_content' => json_encode($biz_content),     //请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档
        ];
 
        //组合生成签名参数
        $signdata = [];
        $signdata['app_id'] = $param['app_id'];
        $signdata['method'] = $param['method'];
        $signdata['charset'] = $param['charset'];
        $signdata['sign_type'] = $param['sign_type'];
        $signdata['timestamp'] = $param['timestamp'];
        $signdata['version'] = $param['version'];
        $signdata['notify_url'] = $param['notify_url'];
        $signdata['biz_content'] = $param['biz_content'];
        //生成签名
        $sign = $this->generateSign($signdata, 'RSA2');
        $param['sign'] = $sign;

//  第1种
        $content = $this->curlPost($url,$param);
        $return  = json_decode($content, true);

        // echo '<pre>';
        // var_dump($content);
        // var_dump($return);
        // die;

//  第2种

        // $url = 'https://openapi.alipaydev.com/gateway.do?' . http_build_query($param);
     
        // $return = file_get_contents($url); //打开支付请求连接 获取二维码地址
     
        // $return = json_decode($return, true); //将返回的字符串转换为数组

        // echo '<pre>';
        // var_dump($return);
        // die;

        //file_put_contents('alipay.log', $content, FILE_APPEND);
       
        
        $return = $return['alipay_trade_precreate_response'];

        echo '<pre>';
        var_dump($return);
        die;


        if($return['code'] == 10000){
            $out_trade_no = $return['out_trade_no'];
            if($out_trade_no != $order['order_unique']){
                return ['code' => -1, 'msg' => '返回订单号错误'];
            }
 
            //生成成功
            $qr_code = $return['qr_code'];
            $data = [];
            $data['order_id'] = $order_id;
            $data['code_url'] = $qr_code;
            return ['code' => 1 , 'msg' => '成功' , 'data' => $data];
 
        }else {
            file_put_contents('alipay.log', 'err code:' . $return['code'] . ', err msg:' . $return['msg'] . '\r\n', FILE_APPEND);
            return ['code' => -1 , 'msg' => 'err_code:' . $return['code'] . ',err_msg:' . $return['msg']];
        }
 
    }
 
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-16 13:36:17 { function_description }
     * 支付宝支付通知
     *
     * @param      <type>  $data   The data
     */
    public function notify($data){
 
        //验签
        //组合验签数据
        $param = $data;
        unset($param['sign']);
        unset($param['sign_type']);
 
        $rst = $this->rsaCheck($param, $data['sign'] , $data['sign_type']);
        if($rst){
            //查询订单状态
            $order = Db::name("order")->where('order_unique', $data['out_trade_no'])->where('status', -1)->find();
            if(!empty($order)){ 
 
                //$rst = $this->orderquery($order, 'TRADE_SUCCESS');
                $rst = true;
                if($rst){
                    $time = time();
                     Db::startTrans();
 
                        try {
                            //修改订单状态
                            $order_data = [];
                            $order_data['status'] =1;
                            $order_data['pay_time'] = $time;
                            $order_data['trade_no'] = $data['trade_no'];
                            $order_data['payment_id'] = $this->payment_id;
                            $rst = Db::name('order')->where('id', $order['id'])->update($order_data);
 
                            if($order['type'] == 1){
 
                            }else if ($order['type'] == 2){
                                //添加订单记录
                                $log_order = [];
                                $log_order['order_id'] = $order['id'];
                                $log_order['content'] = '[代金券]购买代金券:' . $coupon['title'] . ', 已支付' ;
                                $log_order['create_time'] = $time;
                                $rst = Db::name('log_order')->insertGetId($log_order);

                            }
 
                            Db::commit();
                        }catch(\Exception $e){
                            Db::rollback();
                            file_put_contents('alipaynotify.log', '支付通知数据库操作错误:' . $e->getMessage() . '\r\n', FILE_APPEND);
                            exit;
                        }
 
 
                        if($order['type'] ==1 ){
                            //发送成功短信通知
                            $yunxin = new Yunxin;
                            $arr = [];
                            $arr[] = $match_member['name'];
                            $arr[] = $match['title'];
                            $arr[] = date("Y年m月d日H:i", $match['mhstart']);
                            $arr[] = $match_member['idno'];
                            $yunxin->sendSMSTemplate( 9294589, [$match_member['telephone']], $arr);
                        }
 
                        echo  "success";exit;
                }else {
                    file_put_contents('alipaynotify.log', '查询订单状态错误\r\n', FILE_APPEND);
                }
 
            }else {
                file_put_contents('alipaynotify.log', '未找到相应订单\r\n' , FILE_APPEND );
                exit;
            }
        }else {
            file_put_contents('alipaynotify.log', '验签失败\r\n' , FILE_APPEND );
            exit;
        }
    }
 
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-16 13:39:15
     * 支付查询接口
     * 
     * @param  order  
     * @param  status  要验证的状态  WAIT_BUYER_PAY-交易创建等待买家付款 TRADE_CLOSED-未付款交易超时关闭或支付完成后全额退款  TRADE_SUCCESS-交易支付成功 TRADE_FINISHED-交易结束不可退款
     */
    public function orderquery($order , $status){
 
        $time = time();
        $url = '';
        $biz_content = [
            'out_trade_no' => $order['order_unique'],
            'trade_no' => $order['trade_no'],
            //'org_pid' => '',
        ];
 
        $param = [
            'app_id' => $this->appid,
            'method' => 'alipay.trade.query',
            'charset' => 'utf-8',
            'sign_type' => 'RSA2',
            'sign' => '',
            'timestamp' => date('Y-m-d H:i:s', $time),
            'version' => '1.0',
            'biz_content' => json_encode($biz_content),
        ];
 
        //组合签名数组
        $signdata = [];
        $signdata['app_id'] = $param['app_id'];
        $signdata['method'] = $param['method'];
        $signdata['charset'] = $param['charset'];
        $signdata['sign_type'] = $param['sign_type'];
        $signdata['timestamp'] = $param['timestamp'];
        $signdata['version'] = $param['version'];
        $signdata['biz_content'] = $param['biz_content'];
 
        //生成签名
        $sign = $this->generateSign($signdata, 'RSA2');
        $param['sign'] = $sign;
 
        $content = $this->curlPost($url,$param);
        $return  = json_decode($content, true);
 
        if($return['code'] == 10000){
 
            if($return['trade_status'] == $status){
                return true;
            }else {
                return false;
            }
        }else {
            return false;
        }
    }
 
    public function generateSign($params, $signType = "RSA") {
        return $this->sign($this->getSignContent($params), $signType);
    }
 
     public function getSignContent($params) {
        ksort($params);
        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
                // 转换成目标字符集
                $v = $this->characet($v, $this->charset);
                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        unset ($k, $v);
        return $stringToBeSigned;
    }
 
    /**
     * 转换字符集编码
     * @param $data
     * @param $targetCharset
     * @return string
     */
    function characet($data, $targetCharset) {
        if (!empty($data)) {
            $fileType = $this->charset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset, $fileType);
                //$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
            }
        }
        return $data;
    }
 
 
     /**
     * 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected function checkEmpty($value) {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }
 
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-16 12:05:26
     * 签名函数
     *
     * @param      <type>  $data      The data
     * @param      string  $signType  The sign type
     *
     * @return     <type>  ( description_of_the_return_value )
     */
    protected function sign($data, $signType = "RSA") {
        $priKey=$this->rsaPrivateKey;
        $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
            wordwrap($priKey, 64, "\n", true) .
            "\n-----END RSA PRIVATE KEY-----";
        ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
        if ("RSA2" == $signType) {
            openssl_sign($data, $sign, $res, version_compare(PHP_VERSION,'5.4.0', '<') ? SHA256 : OPENSSL_ALGO_SHA256); //OPENSSL_ALGO_SHA256是php5.4.8以上版本才支持
        } else {
            openssl_sign($data, $sign, $res);
        }
        $sign = base64_encode($sign);
        return $sign;
    }
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-16 12:06:12
     * 验签函数
     *
     * @param      <type>  $data        The data    带签名数据
     * @param      <type>  $sign        The sign    要校对的签名结果
     * @param      string  $type        The type
     *
     * @return     <type>  ( description_of_the_return_value )
     */
    public function rsaCheck($data, $sign,$type = 'RSA'){
        $public_key = $this->alipayPublicKey;
        $search = [
            "-----BEGIN PUBLIC KEY-----",
            "-----END PUBLIC KEY-----",
            "\n",
            "\r",
            "\r\n"
        ];
        $public_key=str_replace($search,"",$public_key);
        $public_key=$search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
        $res=openssl_get_publickey($public_key);
        if($res)
        {
            if($type == 'RSA'){
                $result = (bool)openssl_verify($this->getSignContent($data), base64_decode($sign), $res);
            }elseif($type == 'RSA2'){
                $result = (bool)openssl_verify($this->getSignContent($data), base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
            }
            openssl_free_key($res);
        }else{
            return false;
        }
        return true;
    }
 
    public function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
 
 
    /**
     * @author     mselect <445712421@qq.com>
     *
     * @DateTime 2018-11-19 15:03:28
     * PC网站支付
     */
    public function pagepay($order_id){
 
        if($this->is_sandbox){
            $url = $this->sandurl;
            $this->appid = '';
            $this->rsaPrivateKey = '';    // 商户私钥
            $this->alipayPublicKey = '';
        }else {
            $url = $this->url;
        }
        // $order = Db::name('order')->where('id' , $order_id)->find();
        // if($order['type'] ==1 ){
            
        //     $return_url = cmf_url('user/match/mindex', '', true, true);
        // }elseif($order['type'] ==2 ) {
            // $return_url = cmf_url('user/order/index', '', true, true);
            $return_url = '';

        // }
        $notify_url = '异步回调地址';
        $time = time();
 
        $biz_content = [
            // 'out_trade_no' => $order['order_unique'],
            'out_trade_no' => '111111',

            'product_code' => 'FAST_INSTANT_TRADE_PAY',
            // 'total_amount' => $order['real_total_fee'],
            'total_amount' => '666',

            // 'subject' => $order['body'],
            'subject' => 'en',

            //'body' => '',
            //'goods_detail' => '',
            //'passback_params' => '',
            //'extend_params' => '',
            //'goods_type' => '',
            //'timeout_express' => '',
            //'enable_pay_channels' => '',
            //'disable_pay_channels' => '',
            //'auth_token' => '',
            //'qr_pay_mode' => '',
            //'qrcode_width' => '',
        ];
 
        //生成参数
        $param = [
            'app_id' => $this->appid,
            'method' => 'alipay.trade.page.pay',
            //'format' => 'JSON',
            'return_url' => $return_url,
            'charset' => 'utf-8',
            'sign_type' => 'RSA2',
            'sign' => '',
            'timestamp' => date('Y-m-d H:i:s', $time),
            'version' => '1.0',
            'notify_url' => $notify_url,
            'biz_content' => json_encode($biz_content),
        ];
         
        //组合签名数组
        $signdata = [];
        $signdata['app_id'] = $param['app_id'];
        $signdata['method'] = $param['method'];
        $signdata['return_url'] = $param['return_url'];
        $signdata['charset'] = $param['charset'];
        $signdata['sign_type'] = $param['sign_type'];
        $signdata['timestamp'] = $param['timestamp'];
        $signdata['version'] = $param['version'];
        $signdata['notify_url'] = $param['notify_url'];
        $signdata['biz_content'] = $param['biz_content'];
        $sign = $this->generateSign($signdata, 'RSA2');
        $param['sign'] = $sign;
 
        $data = [];
        $data['param'] = $param;
        $data['url'] = $url;

        echo '<pre>';
        var_dump($data);
        die;
 
        return ['code' => 1 , 'msg' => '成功', 'data' => $data];
 
    }

}

?>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值