支付宝+银联统一支付功能实现

jerry thinkphp 2015年11月19日 收藏
这个model将支付宝和银行支付统一到一起,摆脱了对SDK的依赖,我尽量封在了这一个model里面,可根据自己项目需求修改。

应一些朋友要求,我把发起支付以及支付回调部分也放上来,我去掉了一些内容只留下了流程。

2015-8-14更新:很久没上这里了,发现好多消息说想要模板,我这里发出来。
PayAction:
<?php
class PayAction extends Action{
    //支付跳转
    function do_pay(){
        //构造参数
        $payment = array(
            'money'=>12,
            'deal_name'=>'充值',
            //支付银行,对应银行ID我在后面贴出来
            'bank_id'=>'',
            'notice_sn'=>'20140920123456',
        );
        echo D('Payment')->get_payment_code($payment);
    }
    
    //支付结果同步回调
    function response(){
        $request = $_GET;
        unset($request['_URL_']);
        $pay_res = D('Payment')->notify($request);

        if($pay_res['status']){
            //支付成功业务逻辑
        }else{
            $this->error('支付失败');
        }
    }
    
    //支付结果异步回调
    function notify(){
        $request = $_POST;
        $pay_res = D('Payment')->notify($request);

        if($pay_res['status']){
            //支付成功业务逻辑
            echo 'success';
        }else{
            echo 'fail';
        }
    }
}

//银行ID
$bank_id = array(
    'ICBCB2C'    =>    '中国工商银行',
    'CMB'        =>    '招商银行',
    'CCB'        =>    '中国建设银行',
    'ABC'        =>    '中国农业银行',
    'SPDB'        =>    '上海浦东发展银行',
    'SDB'        =>    '深圳发展银行',
    'CIB'        =>    '兴业银行',
    'BJBANK'    =>    '北京银行',
    'CEBBANK'    =>    '中国光大银行',
    'CMBC'        =>    '中国民生银行',
    'CITIC'        =>    '中信银行',
    'GDB'        =>    '广东发展银行',
    'SPABANK'    =>    '平安银行',
    'BOCB2C'    =>    '中国银行',
    'COMM'        =>    '交通银行',
        'ALIPAY'    =>    '支付宝',
);

?>
出现调试错误一般是参数传错了
1、配置model里面的config,model里其他东西根本不用看
2、构造请求参数$payment
money、deal_name和订单号notice_sn是你随便给的,bank_id在页面用 radio传过来的其值是我给的那些银行ID,比如工行就是ICBCB2C


PaymentModel:
<?php

class PaymentModel extends Model{
    private $config;
    function _initialize(){
        $this->config = array(
            'alipay_partner'=>C('ALIPAY_PARTNER'),
            'alipay_account'=>C('ALIPAY_ACCOUNT'),
            'alipay_key'=>C('ALIPAY_KEY'),
            'return_url' => 'http://'.HOST_NAME.U('Pay/response'),
            'notify_url' => 'http://'.HOST_NAME.U('Pay/notify'),
        );
    }
    function get_payment_code($form){
        $link = $form['bank_id'] == 'ALIPAY' ? $this->alipay_link($form) : $this->bank_link($form);
        return $link;
    }
    // 银联接连
    function bank_link($form){
        $payment_notice = array(
            'money'=>$form['money'],
            'deal_name'=>$form['order_name'],
            'bank_id'=>$form['bank_id'],
            'notice_sn'=>$form['order_sn'],
        );
        $money = round($payment_notice['money'],2);
        $payment_info = $this->config;

        $subject = $payment_notice['deal_name'];
        
        $data_return_url = $payment_info['return_url'];
        $data_notify_url = $payment_info['notify_url'];

        $service = 'create_direct_pay_by_user';
        /* 银行类型 */
        $bank_type = $payment_notice['bank_id'];
        
        $parameter = array(
            'service'           => $service,
            'partner'           => $payment_info['alipay_partner'],
            //'partner'           => ALIPAY_ID,
            '_input_charset'    => 'utf-8',
            'notify_url'        => $data_notify_url,
            'return_url'        => $data_return_url,
            /* 业务参数 */
            'subject'           => $subject,
            'out_trade_no'      => $payment_notice['notice_sn'], 
            'price'             => $money,
            'quantity'          => 1,
            'payment_type'      => 1,
            /* 物流参数 */
            'logistics_type'    => 'EXPRESS',
            'logistics_fee'     => 0,
            'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE',
            'extend_param'    => 'changjianghu',
            /* 买卖双方信息 */
            'seller_email'      => $payment_info['alipay_account'],
            'defaultbank'    =>    $bank_type,
            'payment'    =>    'bankPay'
        );

        $parameter = $this->argSort($parameter);

        $param = '';
        $sign  = '';

        foreach ($parameter AS $key => $val){
            $param .= "$key=" .urlencode($val). "&";
            $sign  .= "$key=$val&";
        }

        $param = substr($param, 0, -1);
        $sign  = substr($sign, 0, -1). $payment_info['alipay_key'];
        $sign_md5 = md5($sign);

        
        $payLinks = '<form target="_blank" action="https://www.alipay.com/cooperate/gateway.do?'.$param. '&sign='.$sign_md5.'&sign_type=MD5" id="jumplink" method="post">正在连接支付接口...</form>';
        $payLinks.='<script type="text/javascript">document.getElementById("jumplink").submit();</script>';

        return $payLinks;
    }
    // 支付宝链接
    function alipay_link($form){
        $payment_notice = array(
            'money'=>$form['money'],
            'deal_name'=>$form['order_name'],
            'bank_id'=>$form['bank_id'],
            'notice_sn'=>$form['order_sn'],
        );
        $money = round($payment_notice['money'],2);
        $payment_info = $this->config;

        $subject = $payment_notice['deal_name'];
        
        $data_return_url = $payment_info['return_url'];
        $data_notify_url = $payment_info['notify_url'];
        
        $parameter = array(
            'service'           => 'create_direct_pay_by_user',
            'partner'           => $payment_info['alipay_partner'],
            //'partner'           => ALIPAY_ID,
            '_input_charset'    => 'utf-8',
            'notify_url'        => $data_notify_url,
            'return_url'        => $data_return_url,
            /* 业务参数 */
            'subject'           => $subject,
            'out_trade_no'      => $payment_notice['notice_sn'], 
            'price'             => $money,
            'quantity'          => 1,
            'payment_type'      => 1,
            /* 物流参数 */
            'logistics_type'    => 'EXPRESS',
            'logistics_fee'     => 0,
            'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE',
            'extend_param'        => 'changjianghu',
            /* 买卖双方信息 */
            'seller_email'      => $payment_info['alipay_account']
        );
        // print_r($parameter);exit;
        $parameter = $this->argSort($parameter);

        $param = '';
        $sign  = '';

        foreach ($parameter AS $key => $val)
        {
            $param .= "$key=" .urlencode($val). "&";
            $sign  .= "$key=$val&";
        }

        $param = substr($param, 0, -1);
        $sign  = substr($sign, 0, -1). $payment_info['alipay_key'];
        $sign_md5 = md5($sign);

        
        $payLinks = '<form action="https://www.alipay.com/cooperate/gateway.do?'.$param. '&sign='.$sign_md5.'&sign_type=MD5" id="jumplink" method="post">正在连接支付接口...</form>';
        $payLinks.='<script type="text/javascript">document.getElementById("jumplink").submit();</script>';
        
        return $payLinks;
    }

/*结果*/
    function notify($request){
        $return_res = array(
            'info'=>'',
            'status'=>false,
        );
        $payment = $this->config;
        
        $request = $this->argSort($request);

        /* 检查数字签名是否正确 */
        $isSign = $this->getSignVeryfy($request);
        if (!$isSign){//签名验证失败
            $return_res['info'] = '签名验证失败';
            return $return_res;
        }

        if ($request['trade_status'] == 'TRADE_SUCCESS' || $request['trade_status'] == 'TRADE_FINISHED' || $request['trade_status'] == 'WAIT_SELLER_SEND_GOODS' || $request['trade_status'] == 'WAIT_BUYER_CONFIRM_GOODS'){
            
            $return_res['status'] = true;
            
        }
        return $return_res;
    }

    // 获取返回时的签名验证结果
    function getSignVeryfy($para_temp) {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = $this->paraFilter($para_temp);
        //对待签名参数数组排序
        $para_sort = $this->argSort($para_filter);
        //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = $this->createLinkstring($para_sort);
        
        $isSgin = false;
        $isSgin = $this->md5Verify($prestr, $para_temp['sign'], $this->config['alipay_key']);
        return $isSgin;
    }
    // 验证签名
    function md5Verify($prestr, $sign, $key) {
        $prestr = $prestr . $key;
        $mysgin = md5($prestr);

        if($mysgin == $sign) {
            return true;
        }
        else {
            return false;
        }
    }
    // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    function createLinkstring($para) {
        $arg  = "";
        while (list ($key, $val) = each ($para)) {
            $arg.=$key."=".$val."&";
        }
        //去掉最后一个&字符
        $arg = substr($arg,0,count($arg)-2);
        
        //如果存在转义字符,那么去掉转义
        if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
        
        return $arg;
    }
    // 除去数组中的空值和签名参数
    function paraFilter($para) {
        $para_filter = array();
        while (list ($key, $val) = each ($para)) {
            if($key == "sign" || $key == "sign_type" || $val == "")continue;
            else    $para_filter[$key] = $para[$key];
        }
        return $para_filter;
    }
    // 对数组排序
    function argSort($para) {
        ksort($para);
        reset($para);
        return $para;
    }
    
}

?>
HTML模板:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="Generator" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>预购一个梦想 - 唱江湖音乐众筹网</title>
<meta name="keywords" content="SEO关键词" />
<meta name="description" content="SEO描述" />
<link rel="shortcut icon" href="http://www.changjianghu.com/changjianghu.ico" />
<link rel="Bookmark" href="http://www.changjianghu.com/changjianghu.ico" />
<link rel="stylesheet" type="text/css" href="http://zc.changjianghu.com/public/runtime/statics/391193fc2ea545d4d734bbcdb39a0800.css" />
<script type="text/javascript" src="http://zc.changjianghu.com/public/runtime/statics/a993c626b1aaba476c2ab25f899d7d13.js"></script>

</head>

<body>    
<div class="header">
    <div class="wrap">
        <div class="logo f_l">
                            <div class="link">
                                <img src="http://zc.changjianghu.com/public/attachment/201406/23/11/53a79d9ab641c.jpg" usemap="#Map" width="137" height="72">
<map name="Map" id="Map">
    <area shape="rect" title="唱江湖" coords="12,18,47,55" href="http://www.changjianghu.com">
    <area shape="rect" title="唱江湖" coords="48,35,81,50" href="http://www.changjianghu.com">
    <area shape="rect" title="音乐众筹" coords="64,18,102,34" href="http://zc.changjianghu.com">
    <area shape="rect" title="音乐众筹" coords="83,38,121,56" href="http://zc.changjianghu.com">
</map>            </div>

        </div>
        <ul class="main_nav f_l">
                                    <li >
                        <span>
                        <a href="/"  target="" title="首页">首页</a>
                        </span>        
                    </li>
                                    <li >
                        <span>
                        <a href="/deals"  target="" title="音乐众筹">音乐众筹</a>
                        </span>        
                    </li>
                                    <li >
                        <span>
                        <a href="/seckill"  target="" title="秒杀">秒杀</a>
                        </span>        
                    </li>
                                    <li >
                        <span>
                        <a href="/help-intro"  target="" title="帮助中心">帮助中心</a>
                        </span>        
                    </li>
                                <li style="position: relative;">
                    <span>
                            <a class="start_project_action" style="color: #f60;" href="/project-add" title="发起众筹">发起众筹</a>
                    </span>
                     <span>
                            <a class="start_project_action" style="color: #690;" href="/seckill-add" title="发起秒杀">发起秒杀</a>
                    </span>
                </li>
        </ul>
        <div class="f_r">
            <div class="login_tip">    
                    <a href="#" id="mymessage">消息</a>  |  
    <a href="#" id="mycenter" style="color: #5b8902;">Badri</a>  |          
    <a href="/user-loginout" title="登出" id="user_login_out">登出</a>
    
    
    <div id="mymessage_drop" style="position:absolute; display:none;">
        <div class="drop_box">
            <span><a href="/news-fav">关注动态</a></span>
            <span><a href="/comment">查看评论</a></span>
            <span><a href="/message">查看私信</a></span>
            <span><a href="/notify">查看通知</a></span>

        </div>
    </div>
    <div id="mycenter_drop" style="position:absolute; display:none;">
        <div class="drop_box">
            <span><a href="/home/id-7">我的主页</a></span>
            <span><a href="/account">项目管理</a></span>
            <span><a href="/project/act-add">发起项目</a></span>
            <span><a href="/seckill/act-seckill_list">秒杀管理</a></span>
            <span><a href="/seckill/act-add">发起秒杀</a></span>
            <span><a href="/settings">个人设置</a></span>

        </div>
    </div>
    
            </div>            
            <form action="/deals" method="get" id="header_search_form">
            <div class="header_seach">
            <input type="button" value="" class="seach_submit" id="header_submit" />
            <input type="text" id="header_keyword" name="k" value="搜索你想要的..." class="seach_text">
            <input type="hidden" name="redirect" value="1" />                
            </div>
            </form>    
            
    
            
        </div>
        
        

        
    </div>        
</div>

<link rel="stylesheet" type="text/css" href="http://zc.changjianghu.com/public/runtime/statics/62b8ae03a51d1a8aa629c5101e8d9dbf.css" />
<script type="text/javascript" src="http://zc.changjianghu.com/public/runtime/statics/3183381acbb3fdb4aff11ebe4bf850c5.js"></script>
<div class="blank"></div>

<div class="shadow_bg">
    <div class="wrap white_box"">
        <div class="page_title">
            专为音乐人设计的便携式监听音箱iLoud            <div class="support_price">
                <font class="delivery_fee">
                支持金额  ¥1990.00            
                        
                邮费:¥15.00
                                </font>
                应付总额 <span>¥2002.00</span> 元    
            </div>
        </div>
        
        <div class="switch_nav" style="height:1px;"></div>
        
        <div class="blank"></div>
        
        <div class="public_left">
            
            <form class="pay_form" action="/kcart-kgo_pay" target="_blank" method="post">                                    
                
                                    <div class="form_row">
                        <div class="blank15"></div>
                        <label class="title">使用余额支付:</label>
                        <input type="text" class="textbox" value="0" name="credit" style="width:100px;" />
                        <label class="title" style="padding-left:10px;">可用余额:¥82,800.00</label>
                        <input type="hidden" name="max_credit" value="82800.0000" />
                        <input type="hidden" name="max_pay" value="2002.00" />
                        <div class="blank15"></div>
                    </div>
                                        
                <div><style type='text/css'>.alibank_types{float:left; display:block; background:url(http://zc.changjianghu.com/system/payment/AlipayBank/banklogo.gif); font-size:0px; width:150px; height:10px; text-align:left; padding:15px 0px;}.bk_typeCMB{background-position:15px -444px; }.bk_typeICBCB2C{background-position:15px -404px; }.bk_typeCCB{background-position:15px -84px; }.bk_typeABC{background-position:15px -44px; }.bk_typeSPDB{background-position:15px -364px; }.bk_typeSDB{background-position:15px -324px; }.bk_typeCIB{background-position:15px -484px; }.bk_typeBJBANK{background-position:15px -610px; }.bk_typeCEBBANK{background-position:15px -124px; }.bk_typeCMBC{background-position:15px -164px; }.bk_typeCITIC{background-position:15px -284px; }.bk_typeGDB{background-position:15px -244px; }.bk_typeSPABANK{background-position:15px -903px; }.bk_typeBOCB2C{background-position:15px -939px; }.bk_typeCOMM{background-position:15px -204px; }.bk_typeICBCBTB{background-position:15px -782px; }.bk_typePSBC-DEBIT{background-position:15px -524px; }</style><script type='text/javascript'>function set_bank(bank_id){$("input[name='bank_id']").val(bank_id);}</script><label class='alibank_types bk_typeICBCB2C'><input type='radio' name='payment' value='24' rel='ICBCB2C' onclick='set_bank("ICBCB2C")' /></label><label class='alibank_types bk_typeCMB'><input type='radio' name='payment' value='24' rel='CMB' onclick='set_bank("CMB")' /></label><label class='alibank_types bk_typeCCB'><input type='radio' name='payment' value='24' rel='CCB' onclick='set_bank("CCB")' /></label><label class='alibank_types bk_typeABC'><input type='radio' name='payment' value='24' rel='ABC' onclick='set_bank("ABC")' /></label><label class='alibank_types bk_typeSPDB'><input type='radio' name='payment' value='24' rel='SPDB' onclick='set_bank("SPDB")' /></label><label class='alibank_types bk_typeSDB'><input type='radio' name='payment' value='24' rel='SDB' onclick='set_bank("SDB")' /></label><label class='alibank_types bk_typeCIB'><input type='radio' name='payment' value='24' rel='CIB' onclick='set_bank("CIB")' /></label><label class='alibank_types bk_typeBJBANK'><input type='radio' name='payment' value='24' rel='BJBANK' onclick='set_bank("BJBANK")' /></label><label class='alibank_types bk_typeCMBC'><input type='radio' name='payment' value='24' rel='CMBC' onclick='set_bank("CMBC")' /></label><label class='alibank_types bk_typeCITIC'><input type='radio' name='payment' value='24' rel='CITIC' onclick='set_bank("CITIC")' /></label><label class='alibank_types bk_typeGDB'><input type='radio' name='payment' value='24' rel='GDB' onclick='set_bank("GDB")' /></label><label class='alibank_types bk_typeSPABANK'><input type='radio' name='payment' value='24' rel='SPABANK' onclick='set_bank("SPABANK")' /></label><label class='alibank_types bk_typeBOCB2C'><input type='radio' name='payment' value='24' rel='BOCB2C' onclick='set_bank("BOCB2C")' /></label><label class='alibank_types bk_typeCOMM'><input type='radio' name='payment' value='24' rel='COMM' onclick='set_bank("COMM")' /></label><label class='alibank_types bk_typePSBC-DEBIT'><input type='radio' name='payment' value='24' rel='PSBC-DEBIT' onclick='set_bank("PSBC-DEBIT")' /></label><input type='hidden' name='bank_id' /><div class='blank'></div></div><div><div style='float:left;'><input type='radio' name='payment' value='25' /> 支付宝即时到帐支付:</div><div style='float:left; padding-left:10px;'><img src='http://zc.changjianghu.com/public/attachment/201406/20/13/53a3cb3a6be08.jpg' /></div><div style='float:left; padding-left:10px;'></div><div class='blank'></div></div>                
                <div class="blank"></div>
                <div>
                    <div class="ui-button green" rel="green">
                        <div>
                            <span>确定,去付款</span>
                        </div>
                    </div>                
                    <input type="hidden" id="back_url" value="/seckill-seckill_goods" />    
                    <input type="hidden" value="" name="memo" />    
                    <input type="hidden" value="65" name="id" />
                    <input type="hidden" value="14" name="consignee_id" />    
                    <input type="hidden" value="1" name="ajax" />                    
                    <div class="blank15"></div>
                </div>
                
            </form>
            
        </div><!--left-->
        <div class="public_right">
                
                <div class="deal_item_box">
                    <div class="deal_content_box">
                    <img class="deal_box_img"  src="http://zc.changjianghu.com/public/attachment/201407/09/16/5d32f3aade3afe0f00b56ad1923d285821_205x160.jpg" />
                    <div class="blank"></div>
                    <a href="/deal-show/id-15" class="deal_title" title="专为音乐人设计的便携式监听音箱iLoud">专为音乐人设计的便携式监听音箱iLoud</a>
                    <div class="blank"></div>
                    <a href="/home/id-61">百音堂</a>

                    </div>
                    <div class="deal_item_dash" style="position:relative;">
                        <div class="seckill_status"></div>
                    </div>
                    <div class="deal_content_box">
                        <div class="ui-progress">
                            <span style="width:90%;"></span>
                        </div>
                        <div class="blank"></div>
                        <div class="div3"><span class="num">90%</span><span class="til">剩余</span></div>
                        <div class="div3" style="text-align:center;"><span class="num" ><font>9</font>份</span><span class="til">剩余份数</span></div>
                        <div class="div3" style="text-align:right;"><span class="num" ><font>1990</font>元</span><span class="til">价格</span></div>
                
                        <div class="blank1"></div>
                    </div>
                </div>
                
                
                
            </div>
        
        <div class="blank"></div>
        
    </div>
</div>
<div class="blank"></div>

<div style="" id="share_window_bg" class="wap_bg"></div>
<div class="popup t_share" id="share_window" style="display:none">
    <div class="tag_adfo dis_wap">
        <div class="vip_link">
            <dl>
                <h3>来自唱江湖的信息:</h3>
                <dd class="vip_link_btn" id="vip_link_btn"><!--   --></dd>
            </dl>
        </div>
        <div class="share">
            <h4>您可以分享到:</h4>
            <ul id="fenxiang">
                <li class="share_qzone">
                    <a href="javascript:;" title="QQ空间" u="qzone" onclick="share_music('qzone',this);">QQ空间</a>
                </li>
                <li class="share_weibo">
                    <a href="javascript:;" title="新浪微博" u='sna' onclick="share_music('sna',this);">新浪微博</a>
                </li>
                <li class="share_qwei">
                    <a href="javascript:;" title="腾讯微博" u="wbo" onclick="share_music('wbo',this);">腾讯微博</a>
                </li>
                <li class="share_renren">
                    <a href="javascript:;" title="人人网" u="rr" onclick="share_music('rr',this);">人人网</a>
                </li>
            </ul>
        </div>
        <input type="hidden" id="share_title_items" value="" />
        <div title="关闭" id="share_window_close" class="fancybox_item fancybox_close"></div>
    </div>
</div><div id="gotop"></div>
<div class="blank"></div>
<div class="footer">
    <div class="wrap">
        <div class="help_row">
            <a href="/faq" title="常见问题">常见问题</a>
                           |  <a href="/help-term" title="服务条款">服务条款</a>
                           |  <a href="/help-intro" title="帮助中心">帮助中心</a>
                           |  <a href="/help-privacy" title="隐私策略">隐私策略</a>
                           |  <a href="/help-about" title="关于我们">关于我们</a>
                           |  <a href="/help-6" title="费用价格">费用价格</a>
                    </div>
        <div class="license">
                    </div>
        <div style="text-align: center;">
            <p>changjianghu.com    © 2007 - 2014   唱江湖
                  蜀ICP备13015358号 
                <script type="text/javascript">
                    var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
                    document.write(unescape("%3Cspan id='cnzz_stat_icon_1000286563'%3E%3C/span%3E%3Cscript src='"
                            + cnzz_protocol
                            + "s23.cnzz.com/z_stat.php%3Fid%3D1000286563%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));
                </script>
            </p>
        </div>
    </div>
</div>