支付宝接口开发

来源:互联网 发布:淘宝同行低价恶意竞争 编辑:程序博客网 时间:2024/04/30 07:20
<?php
/**
 * 此代码基于 TP3.2框架开发写的
 * 代码中参数配置有重复,参考时自行整理,让代码更加简洁
 * 回调地址 异步处理,和同步处理,如果用户输入完支付密码立马关闭支付页面,地址没回调本网站,充值有可能会失败,
 * 输入完密码自行跳回本网站会成功。这个问题尚未解决,本人功力尚浅,如你解决办法 欢迎修改。
 * 问题:先去支付宝支付,跳转回来以后给用户账号增加金额。但是有时候用户支付密码支付成功,没有让网站自动跳回本网站,
 * 而是关闭了支付网站,这样的话就会导致用户增加金额失败。
 * 共同学习: QQ:870422471 QQ群:294088839
 */
namespace Member\Controller;
use Think\Controller;
class ZfbController extends Controller{


    public function _initialize() {
        vendor('Alipay.Corefunction');
        vendor('Alipay.Md5function');
        vendor('Alipay.Notify');
        vendor('Alipay.Submit');
    }






    //支付宝充值
    public function recharge(){
        header("Content-type:text/html;charset=utf-8");


        //获取所有传输的参数
        $data=I('post.');


        $money = round($data["money"],2);


        //生成订单号
        $orderNo = create_order_no();


        //获取个人信息
        //获取用户的Id
        $user_id = session('user_id');
        //传输过来的充值金额只保留小数点前两位
        $member_where['user_id'] = [ 'eq', $user_id ];
        $user=M('user');
        $member_info = $user->where($member_where)->field('user_name,user_id')->find();
        //把登录的名字和订单号 用户id 要充值的钱 以-连接
        $body = $member_info['user_name'] . '-' . $orderNo . '-' . $member_info['user_id'].'-'.$money;


        //把数据写进充值表中
        //充值金额
        $arr['reg_money']=$money;
        //充值方式
        $arr['reg_way']='ZFB';
        //支付用户
        $arr['user_id']=$member_info['user_id'];
        //支付订单号
        $arr['reg_number']=$orderNo;
        //支付时间
        $arr['reg_addtime']=time();
        //充值状态 1充值成功,0充值失败,2,正在充值
        $arr['reg_status']=2;


        //写进充值记录
        $result =M('recharge')->add($arr);


        if($result===false){
            $this->error("充值失败,请联系管理员");
        }else{
            $sys=M('zfb_sys');
            //获取合作身份者ID
            $alipay_partner=$sys->where(array('sys_id'=>86))->field('sys_value')->find();
            // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
            $key=$sys->where(array('sys_id'=>87))->field('sys_value')->find();
            //构造函数中所需参数
            $alipay_config=[
                //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串
                'partner'=>$alipay_partner['sys_value'],
                //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
                'seller_id'=>$alipay_partner['sys_value'],
                // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
                'key'=>$key['sys_value'],
                // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
                'notify_url'=>U('Member/Finance/notifyUrl',[ ],false, true),
                // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
                'return_url'=>U('Member/Finance/returnUrl',[ ],false, true),
                //签名方式
                'sign_type'=>strtoupper('MD5'),
                //字符编码格式 目前支持 gbk 或 utf-8
                'input_charset'=>strtolower('utf-8'),
                //ca证书路径地址,用于curl中ssl校验
                //请保证cacert.pem文件在当前文件夹目录中
                'cacert'=>'.'.DS.'ThinkPHP'.DS.'Library'.DS.'Vendor'.DS.'Alipay'.DS.'cacert.pem',
                //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
                'transport'=>'http',
                //支付类型 ,无需修改
                'payment_type'=>'1',
                //产品类型,无需修改
                'service'=>'create_direct_pay_by_user',
                // 防钓鱼时间戳  若要使用请调用类文件submit中的query_timestamp函数
                'anti_phishing_key'=>'',
                // 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1
                'exter_invoke_ip'=>''
            ];
            //构造要请求的参数数组,无需改动
            $parameter = array(
                //支付方式
                "service"       => 'create_direct_pay_by_user',
                //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串
                "partner"       => $alipay_partner['sys_value'],
                //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
                "seller_id"  => $alipay_partner['sys_value'],
                // 支付类型 ,无需修改
                "payment_type" => '1',


                "notify_url" => $alipay_config['notify_url'],
                "return_url" => $alipay_config['return_url'],


                 // 防钓鱼时间戳  若要使用请调用类文件submit中的query_timestamp函数
                "anti_phishing_key"=> '',
                // 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1
                "exter_invoke_ip"=> '',
                //商户订单号,商户网站订单系统中唯一订单号,必填
                "out_trade_no" =>$orderNo,
                //订单名称
                "subject" =>'帝通科技'."-".$_SERVER['SERVER_NAME'],
                //付款金额
                "total_fee" => $money,
                //订单描述内容
                "body" => $body,
                //编码格式
                "_input_charset" => trim(strtolower('utf-8'))
            );
            //支付宝支付
            $alipaySubmit = new \Vendor\Alipay\AlipaySubmit($alipay_config);
            $html_text =$alipaySubmit->buildRequestForm($parameter,"get", "确认");
            echo $html_text;
        }
    }


    // 异步跳转 处理数据
    public function notifyUrl($callback = ''){
        $sys=M('zfb_sys');
        //获取合作身份者ID
        $alipay_partner=$sys->where(array('sys_id'=>86))->field('sys_value')->find();
        // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
        $key=$sys->where(array('sys_id'=>87))->field('sys_value')->find();
        //构造函数中所需参数
        $alipay_config=[
            //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串
            'partner'=>$alipay_partner['sys_value'],
            //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
            'seller_id'=>$alipay_partner['sys_value'],
            // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
            'key'=>$key['sys_value'],
            // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
            'notify_url'=>U('Member/Finance/notifyUrl',[ ],false, true),
            // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
            'return_url'=>U('Member/Finance/returnUrl',[ ],false, true),
            //签名方式
            'sign_type'=>strtoupper('MD5'),
            //字符编码格式 目前支持 gbk 或 utf-8
            'input_charset'=>strtolower('utf-8'),
            //ca证书路径地址,用于curl中ssl校验
            //请保证cacert.pem文件在当前文件夹目录中 DS 代表 /
            'cacert'=>'.'.DS.'ThinkPHP'.DS.'Library'.DS.'Vendor'.DS.'Alipay'.DS.'cacert.pem',
            //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
            'transport'=>'http',
            //支付类型 ,无需修改
            'payment_type'=>'1',
            //产品类型,无需修改
            'service'=>'create_direct_pay_by_user',
            // 防钓鱼时间戳  若要使用请调用类文件submit中的query_timestamp函数
            'anti_phishing_key'=>'',
            // 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1
            'exter_invoke_ip'=>''
        ];
        //计算得出通知验证结果
        $alipayNotify = new \Vendor\Alipay\AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();
        if($verify_result) {//验证成功
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代


            if (is_callable($callback)) {
                $callback($_POST);
            }


            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——


            //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表


            //商户订单号


            $out_trade_no = $_POST['out_trade_no'];


            //支付宝交易号


            $trade_no = $_POST['trade_no'];


            //交易状态
            $trade_status = $_POST['trade_status'];


            //交易金额
            $total_fee = $_POST['total_fee'];


            //交易参数
            $body = $_POST['body'];


            if($_POST['trade_status'] == 'TRADE_FINISHED') {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                //如果有做过处理,不执行商户的业务程序


                //注意:
                //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知


                //调试用,写文本函数记录程序运行情况是否正常
                //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录");
            }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {


                //在充值记录表 查到信息 然后充值到用户
                $recharge= M('recharge');
                $row = $recharge->where(array('reg_number'=>$out_trade_no))->field('reg_id,reg_money,user_id')->find();


                $user=M('user');
                $balance=$user->where(array('user_id'=>$row['user_id']))->field('user_money')->find();
                $newMoney=$balance['user_money']+$row['reg_money'];
                if($user->where(array('user_id'=>$row['user_id']))->save(array('user_money'=>$newMoney))){
                    $result= $recharge->where(array('reg_id'=>$row['reg_id']))->save(array('reg_status'=>1));
                    if($result == null){
                        echo "fail"; //请不要修改或删除
                    }
                }


            }


            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——


            echo "success"; //请不要修改或删除


            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        }else{
            //验证失败
            echo "fail";
            //调试用,写文本函数记录程序运行情况是否正常
            //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录");
        }
    }


    // 同步跳转  展示给用户看的页面
    public function returnUrl($callback = ''){
        $sys=M('zfb_sys');
        //获取合作身份者ID
        $alipay_partner=$sys->where(array('sys_id'=>86))->field('sys_value')->find();
        // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
        $key=$sys->where(array('sys_id'=>87))->field('sys_value')->find();
        //构造函数中所需参数
        $alipay_config=[
            //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串
            'partner'=>$alipay_partner['sys_value'],
            //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
            'seller_id'=>$alipay_partner['sys_value'],
            // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
            'key'=>$key['sys_value'],
            // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
            'notify_url'=>U('Member/Finance/notifyUrl',[ ],false, true),
            // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
            'return_url'=>U('Member/Finance/returnUrl',[ ],false, true),
            //签名方式
            'sign_type'=>strtoupper('MD5'),
            //字符编码格式 目前支持 gbk 或 utf-8
            'input_charset'=>strtolower('utf-8'),
            //ca证书路径地址,用于curl中ssl校验
            //请保证cacert.pem文件在当前文件夹目录中
            'cacert'=>'.'.DS.'ThinkPHP'.DS.'Library'.DS.'Vendor'.DS.'Alipay'.DS.'cacert.pem',
            //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
            'transport'=>'http',
            //支付类型 ,无需修改
            'payment_type'=>'1',
            //产品类型,无需修改
            'service'=>'create_direct_pay_by_user',
            // 防钓鱼时间戳  若要使用请调用类文件submit中的query_timestamp函数
            'anti_phishing_key'=>'',
            // 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1
            'exter_invoke_ip'=>''
        ];
        //计算得出通知验证结果
        $alipayNotify = new \Vendor\Alipay\AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyReturn();
        if($verify_result) {//验证成功
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代码


            if (is_callable($callback)) {
                $callback($_POST);
            }


            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表


            //商户订单号


            $out_trade_no = $_GET['out_trade_no'];


            //支付宝交易号


            $trade_no = $_GET['trade_no'];


            //交易状态
            $trade_status = $_GET['trade_status'];


            //交易金额
            $total_fee = $_GET['total_fee'];


            //交易参数
            $body = $_GET['body'];


            if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序
                $recharge= M('recharge');
                $row = $recharge->where(array('reg_number'=>$out_trade_no))->field('reg_id')->find();
                $result= $recharge->where(array('reg_id'=>$row['reg_id']))->save(array('reg_status'=>1));
                if($result){
                    $msg = '支付金额:' . $total_fee . '元,充值成功';
                    $message = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><head></html><script>alert("' . $msg . '");</script>';
                    redirect(U('Member/Finance/memberTransactionsList','',false),3,$message);
                }
            }
            else {
                echo "trade_status=".$_GET['trade_status'];
            }


            echo "验证成功<br />";


            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——


            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        }
        else {
            //验证失败
            //如要调试,请看alipay_notify.php页面的verifyReturn函数
            echo "验证失败";
        }
    }
}
原创粉丝点击