国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > 程序人生 > 随笔 > CI框架集成支付宝即时到账

CI框架集成支付宝即时到账

来源:程序员人生   发布时间:2016-06-02 17:32:03 阅读次数:8261次

不多说,直接上代码,让CI框架集成支付宝即时到账

第一步,下载支付宝即时支付demo,我以utf8版本为例,下载下来的文件目录如下

CI框架集成支付宝即时到账

第二步,在CodeIgniter中 application/third_party 目录下,新建文件夹alipay,将支付宝lib文件夹下的4个子文件全部放到alipay中

第三步,配置文件

在CodeIgniter中  application/config,新建alipay.php,将支付宝alipay.config.php的内容,全部搬进来,并且将数组$alipay_config重命名为$config

CI框架集成支付宝即时到账


第四步,新建一个订单控制器,代码如下


load->view('order_show');
	}
	

  // 提交订单,付款
  public function pay() {
     $order=$this->input->post();
	 
        //商户订单号,商户网站订单系统中唯一订单号,必填
        $out_trade_no = $order['WIDout_trade_no'];
        //订单名称,必填
        $subject = $order['WIDsubject'];
        //付款金额,必填
        $total_fee = $order['WIDtotal_fee'];
        //商品描述,可空
        $body = $order['WIDbody'];


    // 加载支付宝配置
    $this->config->load('alipay', TRUE);
    // 加载支付宝支付请求类库
    require_once(APPPATH."third_party/alipay/alipay_submit.class.php");
    $submit = new AlipaySubmit($this->config->item('alipay'));
   //构造要请求的参数数组,无需改
    $html_text = $submit->buildRequestForm(array(
		"service"       =>$this->config->item('service', 'alipay'),
		"partner"       => $this->config->item('partner', 'alipay'),
		"seller_id"  => $this->config->item('seller_id', 'alipay'),
		"payment_type"	=> $this->config->item('payment_type', 'alipay'),
		"notify_url"	=> $this->config->item('notify_url', 'alipay'),
		"return_url"	=> $this->config->item('return_url', 'alipay'),
		"anti_phishing_key"=>$this->config->item('anti_phishing_key', 'alipay'),
		"exter_invoke_ip"=>$this->config->item('exter_invoke_ip', 'alipay'),
		
		"out_trade_no"	=> $out_trade_no,
		"subject"	=> $subject,
		"total_fee"	=> $total_fee,
		"body"	=> $body,

      '_input_charset'    => $this->config->item('input_charset', 'alipay')
    ));

    // 渲染模板,原生的这么写,我自己另外用smarty3
  echo $html_text;
  }

//支付宝付款后回调
// $method参数只能是'return'或'notify',对应URL
  public function callback ($method) {
    // 加载支付宝配置
    $this->config->load('alipay', TRUE);
    // 加载支付宝返回通知类库
    require_once(APPPATH."third_party/alipay/alipay_notify.class.php");
    // 初始化支付宝返回通知类
    $alipayNotify = new AlipayNotify($this->config->item('alipay'));

    $input = array();
    $is_ajax = FALSE;
    $notify_status = 'success';
	

    // 这里做同步还是异步的判断并获取返回数据验证请求
    switch ($method) {
      case 'notify':
        $result = $alipayNotify->verifyNotify();
        $input = $this->input->post();
        $is_ajax = TRUE;
        break;

      case 'return':
        $result = $alipayNotify->verifyReturn();
        $input = $this->input->get();
        break;
      
      default:
        return $this->out_not_found();
        break;
    }
	
	var_dump($input);exit;

    // 支付宝返回支付成功和交易结束标志
    if ($result && ($input['trade_status'] == 'TRADE_FINISHED' || $input['trade_status'] == 'TRADE_SUCCESS')) {
      $id = $input['out_trade_no'];

      // 验证成功则更新订单信息(略)
      // ...
    } else {
      // 否则置状态为失败
      $notify_status = 'fail';
    }

    if ($is_ajax) {
      // 异步方式调用模板输出状态
     // $this->view->load('alipay', array('status' => $notify_status));
	// echo "异步成功";
    } else {
      // 同步方式跳转到订单详情控制器,redirect方法要你自己写
      //return $this->redirect("order/view/$id#status:$notify_status");
	  //echo "同步成功";//
    }
  }

}
	

订单显示页面,参考支付宝原来的就可以了,至此,就支付宝即时付款就集成好了,当然中间业务逻辑还没有写,各位根据自己的网站需要进行编写吧

会遇到的问题,我约到过下面问题,通过百度解决了

MD5签名验证不通过

这才是真正坑爹的问题!之前测试一直是支付成功但返回调用验证失败,直到我一步一步跟到SDK的源码里去对比要验证的签名串,才发现这根本就是SDK的一个BUG!请看alipay_core.function.php文件的paraFilter函数,这个函数的作用是过滤掉签名参数和空值参数,以便生成签名串。原来的SDK是这么写的:

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;
}

问题就出在while循环的条件里,每次过滤参数,这里直接就把第一个返回参数body=xxx给过滤掉了,一旦我加上body=xxx变成完整的签名参数,生成的MD5签名就能对上。我百思不得其解的时候去查了PHP的文档,根据each方法说明,每调用一次游标就会发生改变,而首次调用之前没有调用reset()的话,就很可能被之前调用过这个数组的each()给弄错游标。而每次代码中每次都是从第二个参数开始,说明数组可能已经被其他程序调用过了(这个数组实际上是系统变量$_GET,但我实在没在CI框架代码中找到哪里调用的)。所以我想说的是: 好!好!写!个!foreach!循环会死么! 修改后的代码如下:

function paraFilter($para) {  // 增加这一行  reset($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;
}

这才算解决了签名不正确的问题。


生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生