pc端微信、支付宝扫码支付

本文详细介绍了一种在Web应用中集成微信和支付宝支付的方法,包括生成二维码供用户扫码支付,以及后端如何处理支付回调验证的过程。文章深入探讨了支付流程中的关键步骤,如生成支付链接、验证支付结果、订单状态更新等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、前端调用后台生成的二维码

var wxcode    = "/index.php/WebPay/thirdPaymentQrcode/user_id/52398/payType/weChat/fromType/3/price/";
var alipycode = "/index.php/WebPay/alipyCode?url=/index.php/WebPay/thirdPaymentQrcode/user_id/52398/payType/aliPay/fromType/3/price/";

2、用户扫码支付, 后端回调验证

class WebPayController extends WebController {
	protected $pc_wechat_log;
	protected $pc_alipay_log;
	protected $base_url;
	protected $wechat_notify_url;
	protected $wechat_order_query;
	protected $alipay_notify_url;
	protected $alipay_return_url;
	protected $pay_success_url;

	protected $userModel;

	//第三方支付,引入第三方支付库(微信,支付宝)
	public function _initialize(){
        //引入WxPayPubHelper
        vendor('WxPayPubHelper.WxPayPubHelper');
        // 引入支付宝类库
        vendor('Alipay.Corefunction');
        vendor('Alipay.Md5function');
        vendor('Alipay.Notify');
        vendor('Alipay.Submit');

        //初始化模型
        $this->userModel = D('User');

        //log文件路径
        $this->pc_wechat_log="/data/web/web/Public/pc_wechat_log.log";
        $this->pc_alipay_log="/data/web/web/Public/pc_alipay_log.log";
        //创建文件夹
        if(!is_dir('/data/web/web/Public/')){
            $res=mkdir('/data/web/web/Public/',0777,true);
        }
        //回调地址域名
		$this->base_url           = 'http://'.$_SERVER['HTTP_HOST'];
		//订单来源(fromType):1某币,2微课,3积分
		//微信回调地址
		$this->wechat_notify_url  = [
			'1'	=>	$this->base_url.'/index.php/Home/WebPay/wechatNotify',
			'2'	=>	$this->base_url.'/index.php/Home/WebPay/wechatNotifyCourse',
			'3'	=>	$this->base_url.'/index.php/Home/WebPay/wechatNotifyBean',
            '5'	=>	$this->base_url.'/index.php/Home/WebPay/wechatNotifyMaster',
		];
		//微信主动查询订单地址
		$this->wechat_order_query = [
			'1'	=>	'',
			'2'	=>	'',
			'3'	=>	'',
			'5'	=>	'',
		];
		//支付宝回调地址
		$this->alipay_notify_url = [
			'1'	=>	$this->base_url.'/index.php/Home/WebPay/alipayNotify',
			'2'	=>	$this->base_url.'/index.php/Home/WebPay/alipayNotifyCourse',
			'3'	=>	$this->base_url.'/index.php/Home/WebPay/alipayNotifyBean',
            '5'	=>	$this->base_url.'/index.php/Home/WebPay/alipayNotifyMaster',
		];
		//支付宝跳转地址
		$this->alipay_return_url = [
			'1'	=>	'',
			'2'	=>	'',
			'3'	=>	'',
			'5'	=>	'',
		];
		//支付成功展示页地址
		$this->pay_success_url = [
			'1'	=>	'',
			'2'	=>	'',
			'3'	=>	'',
            '5'	=>	'',
		];
    }
	//第三方支付,将信息生成二维码(微信,支付宝)
	public function thirdPaymentQrcode(){
		// 接收参数
		$user_id      = I('user_id');
		$user_id      = decrypt(cookie('uid'));
		$order_sn     = I("order_sn",'');
		$price        = I("price",0);//均为实际金额
		$payType      = I("payType",'');// 支付类型,aliPay/weChat
		$fromType     = I("fromType",0);// 订单来源:1某币,2微课,3积分,4微课打赏,5大咖购买
		$typeId       = I("typeId",0);// 来源id
		$is_usemoney  = I('is_usemoney','1');//是否某币抵扣:1抵扣,0不抵扣

		//生成订单号-- 商户网站唯一订单号out_trade_no
		// $order_sn = $order_sn ? $order_sn : build_ruth_order_no('',$user_id);

		// 判断是否登录
		if(!$user_id){
			$this->error('请先登录');
		}

		// 判断是否缺少参数
		if(!$order_sn || !$payType || !$fromType || (($fromType==2 || $fromType==5) && !$typeId)){
			$this->error('缺少参数');
		}

		//某币
		$mymoney = $this->userModel->getMoneyCount($user_id);
		$mymoney = $mymoney>0 ? $mymoney : '0';
		//某币抵扣
		if($is_usemoney && $fromType !='2' && $fromType !='5'){

			//如果用户本身没有某币,则is_usermoney应为0
			if($mymoney == 0){
				$is_usemoney = 0;
			}

			$price = $price - $mymoney;

			if($price <= 0){
				$this->error('金额异常');
			}
		}else{
			$price = $price;
		}

		// 订单金额
		if($price < 1){
			$this->error('金额不能小于1元');
		}

		// 判断是否为注册用户
		$user_info = M('user') -> where(['id'=>$user_id]) -> find();
		if(!$user_info){
			$this->error('非法用户');
		}

		//获取参数值
		switch ($fromType) {
			case '1':#某币
				$title = "PC端充值某币";
				break;
			case '2':#微课
				$title = "PC端购买微课";
				//微课信息
				$course_info = M('course_courses')->field('price')->where(['id'=>$typeId])->find();
				$course_price = $course_info['price'];

				//某币抵扣
				if($is_usemoney){
					//如果用户本身没有某币,则is_usermoney应为0
					if($mymoney == 0){
						$is_usemoney = 0;
					}

					$price = $course_price - $mymoney;

					if($price <= 0){
						$this->error('金额异常');
					}
				}else{
					$price = $course_price;
				}
				break;
            case '3':#积分
				$title = "PC端购买积分";
				break;
            case '5':#大咖
                $title = "PC端购买大咖";
                //微课信息
                $course_info = M('course_courses')->field('price')->where(['id'=>$typeId])->find();
                $course_price = $course_info['price'];
                $price = $course_price;
                break;
            default:
				# code...
				break;
		}

		// 测试专用
		if(in_array($user_id,[111111])){
			$price = 0.01;
		}

		// 数据库生成订单
		$cashOrders['sn']          = $order_sn;
		$cashOrders['userId']      = $user_id;
		$cashOrders['status']      = 'created';
		$cashOrders['payment']     = $payType;
		$cashOrders['fromType']    = $fromType;
		$cashOrders['typeId']      = $typeId;
		$cashOrders['amount']      = $price;
		$cashOrders['title']       = $title;
		$cashOrders['createdTime'] = time();
		$cashOrders['is_usemoney'] = $is_usemoney;

		$order_info = M('cash_orders')->where(['sn'=>$order_sn])->find();
		if($order_info){
			$res=M('cash_orders')->where(['sn'=>$order_sn])->save($cashOrders);
		}else{
			$res=M('cash_orders')->add($cashOrders);
		}

		$total_fee = $price;
		if($res !== false){
			//输出支付页面
			if($payType == 'weChat') {
			// 调用微信生成二维码
		        //使用统一支付接口
		        $unifiedOrder = new \UnifiedOrder_pub();
		        //设置统一支付接口参数
		        $unifiedOrder->setParameter("body","某某消费");//商品描述

		        $unifiedOrder->setParameter("out_trade_no","$order_sn");//商户订单号
		        $unifiedOrder->setParameter("total_fee",($total_fee * 100));//总金额
		        $unifiedOrder->setParameter("product_id",($total_fee * 100));//总金额
		        $unifiedOrder->setParameter("notify_url", $this->wechat_notify_url[$fromType]);//通知地址
		        $unifiedOrder->setParameter("trade_type","NATIVE");//交易类型

		        //获取统一支付接口结果
		        $unifiedOrderResult = $unifiedOrder->getResult();

		        //商户根据实际情况设置相应的处理流程
		        if ($unifiedOrderResult["return_code"] == "FAIL")
		        {
		            //商户自行增加处理流程
		            echo "通信出错:".$unifiedOrderResult['return_msg']."<br>";
		        }
		        elseif($unifiedOrderResult["result_code"] == "FAIL")
		        {
		            //商户自行增加处理流程
		            echo "错误代码:".$unifiedOrderResult['err_code']."<br>";
		            echo "错误代码描述:".$unifiedOrderResult['err_code_des']."<br>";
		        }
		        elseif($unifiedOrderResult["code_url"] != NULL)
		        {
		            //从统一支付接口获取到code_url
		            $code_url = $unifiedOrderResult["code_url"];
		            //商户自行增加处理流程
		            //......
		        }
		        $this->assign('out_trade_no',$order_sn);
		        $this->assign('code_url',$code_url);
		        $this->assign('wechat_order_query_url',$this->wechat_order_query[$fromType]);
		        $this->assign('pay_success_url',$this->pay_success_url[$fromType]);
		        $this->assign('unifiedOrderResult',$unifiedOrderResult);
		        $this->display('Web/Pay/qrcode');
			} elseif($payType == 'aliPay') {
			// 支付宝支付
				//得到订单提交时的地址,区分不同各类订单
				$alipay_config     = C('alipay_config');
				/**************************请求参数**************************/
				$payment_type      = "1"; //支付类型 //必填,不能修改
				// $notify_url        = C('alipay.notify_url'); //服务器异步通知页面路径
				$notify_url        = $this->alipay_notify_url[$fromType];
				// $return_url        = C('alipay.return_url'); //页面跳转同步通知页面路径
				$return_url        = $this->alipay_return_url[$fromType];
				$seller_email      = C('alipay.seller_email');//卖家支付宝帐户必填
				$out_trade_no      = $order_sn;//商户订单号 通过支付页面的表单进行传递,注意要唯一!
				// $new_order      =substr($out_trade_no,0,1);
				//订单名称 //必填 通过支付页面的表单进行传递
				$subject           = '某某消费';
				$body              = "某某消费";  //订单描述 通过支付页面的表单进行传递
				$show_url          = $this->pay_success_url[$fromType];  //商品展示地址 通过支付页面的表单进行传递
				//商品展示地址 通过支付页面的表单进行传递
				$anti_phishing_key = "";//防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数
				$exter_invoke_ip   = get_client_ip(); //客户端的IP地址*/
				$qr_pay_mode	   = 3;//PC扫码支付的方式:0,1,2,3,4
		        //**********************************************************

		        //构造要请求的参数数组,无需改动
		        $parameter = array(
					"service"           => "create_direct_pay_by_user",
					"partner"           => trim($alipay_config['partner']),
					"payment_type"      => $payment_type,
					"notify_url"        => $notify_url,
					"return_url"        => $return_url,
					"seller_email"      => $seller_email,
					"out_trade_no"      => $out_trade_no,
					"subject"           => $subject,
					"total_fee"         => $total_fee,
					"body"              => $body,
					"show_url"          => $show_url,
					"anti_phishing_key" => $anti_phishing_key,
					"exter_invoke_ip"   => $exter_invoke_ip,
					"qr_pay_mode"       => $qr_pay_mode,
					"_input_charset"    => trim(strtolower($alipay_config['input_charset']))
		        );

		        //建立请求
				$alipaySubmit = new \AlipaySubmit($alipay_config);
				$html_text    = $alipaySubmit->buildRequestForm($parameter,"post", "确认");
		        echo($html_text);
			}
		}else{
			$this->error('生成订单失败');
		}
	}
	//对支付宝二维码进行包装显示
	public function alipyCode(){
		$url = I('url','');

		$this->assign('url',$url);
		$this->display('Web/Pay/alipycode');
	}
	
	
	
	//微信,异步通知,积分
	public function wechatNotifyBean(){
        //使用通用通知接口
        $notify = new \Notify_pub();
        //存储微信的回调
        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $notify->saveData($xml);
      	//将xml转为array
        //验证签名,并回应微信。
        //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
        //微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
        //尽可能提高通知的成功率,但微信不保证通知最终能成功。

        //商家交易单号
        $out_trade_no = $notify->data['out_trade_no'];
        //微信交易单号
        $transaction_id = $notify->data['transaction_id'];
        //交易金额,单位分
        $price  = $notify->data['total_fee']/100;

        //==商户根据实际情况设置相应的处理流程,此处仅作举例=======

        //以log文件形式记录回调信息
        $log_name= $this->pc_wechat_log;//log文件路径

        log_into_txt($log_name,"【微信】订单号:$out_trade_no",'head');
        log_into_txt($log_name,"【接收到微信的notify通知】:\t".$xml."\t");
        if($notify->checkSign() == TRUE) {
            if($notify->data["return_code"] == "FAIL") {
                //此处应该更新一下订单状态,商户自行增删操作
                log_into_txt($log_name,"【通信出错】:\t",'foot');
                $notify->setReturnParameter("return_code","FAIL");
            }elseif($notify->data["result_code"] == "FAIL"){
                //此处应该更新一下订单状态,商户自行增删操作
                log_into_txt($log_name,"【业务出错】:\t",'foot');
                $notify->setReturnParameter("return_code","FAIL");
            }else{
        		//得到订单数据
	            $order_data=M('cash_orders')->where(['sn'=>$out_trade_no])->find();
            	log_into_txt($log_name,"【支付成功】:\t".json_encode($order_data)."\t");

	            //商户自行增加处理流程,

	            //支付成功信息是否已入库
	            if($order_data['status'] == 'paid'){
	            	log_into_txt($log_name,"【查询已支付成功】",'foot');
					$notify->setReturnParameter("return_code","SUCCESS");
	            }else{
					//修改已支付状态
					$save_res=M('cash_orders')->where(['sn'=>$out_trade_no])->save(['status'=>'paid','paidTime'=>time(),'note'=>$transaction_id]);
					if($save_res === false){
						log_into_txt($log_name,"【订单状态修改失败】:\t".M('cash_orders')->_sql()."\t",'foot');
						$notify->setReturnParameter("return_code","FAIL");
					}else{
						//某币抵扣
						if($order_data['is_usemoney']){
							//某币
							$mymoney = $this->userModel->getMoneyCount($order_data['userId']);
							$money_count = $mymoney>0 ? $mymoney : '0';

							//扣某币
							$insert_data=[
								'user_id'      =>	$order_data['userId'],
								'money_count'  =>	-$money_count,
								'money_time'   =>	date('Y-m-d H:i:s'),
								'money_detail' =>	'PC端购买积分抵扣',
							];
							$money_res=M('user_money')->data($insert_data)->add();
						}

						$user_id      = $order_data['userId'];
						$bean_count   = $order_data['amount']*10;
						$bean_detail1 = "充值送积分";
						$bean_type    = 8;
		            	// 购买积分
						$bean_res = insert_user_been($user_id, $bean_count, $bean_detail1, $bean_type);;
						if($bean_res === false){
							log_into_txt($log_name,"【购买数据入库失败】:\t".M('user_bean')->_sql()."\t",'foot');
							$notify->setReturnParameter("return_code","FAIL");
						}else{
							log_into_txt($log_name,"【购买成功】",'foot');
							$notify->setReturnParameter("return_code","SUCCESS");
						}
					}
	            }
            }
        }else{
        	$notify->setReturnParameter("return_code","FAIL");//返回状态码
            $notify->setReturnParameter("return_msg","签名失败");//返回信息
        }

        //返回通知
        $returnXml = $notify->returnXml();

        header("Access-Control-Allow-Origin:*" );/*星号表示所有的域都可以接受,*/
        header("Access-Control-Allow-Methods:POST,GET" );
        header('Access-Control-Allow-Headers:origin, x-requested-with,x-requested_with, content-type, accept');
        echo $returnXml;
        exit;
    }
	
	
	//支付宝,异步通知,积分
    public function alipayNotifyBean(){
        /*
        同理去掉以下两句代码;
        */
        //这里还是通过C函数来读取配置项,赋值给$alipay_config
        $alipay_config=C('alipay_config');
        //计算得出通知验证结果
        $alipayNotify = new \AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();
        $log_name= $this->pc_alipay_log;//log文件路径
        log_into_txt($log_name,"【支付宝】\t订单号:".$_POST['out_trade_no'],'head');
        log_into_txt($log_name,"【接收到支付宝的notifyurl通知】:\t".json_encode($_POST));
        if($verify_result) {
            //验证成功
            //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
            $out_trade_no   = $_POST['out_trade_no'];      //商户订单号
            $trade_no       = $_POST['trade_no'];          //支付宝交易号
            $trade_status   = $_POST['trade_status'];      //交易状态
            $total_fee      = $_POST['total_fee'];         //交易金额
            $notify_id      = $_POST['notify_id'];         //通知校验ID。
            $notify_time    = $_POST['notify_time'];       //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。
            $buyer_email    = $_POST['buyer_email'];       //买家支付宝帐号;
            $parameter = array(
				"out_trade_no" => $out_trade_no, //商户订单编号;
				"trade_no"     => $trade_no,     //支付宝交易号;
				"total_fee"    => $total_fee,    //交易金额;
				"trade_status" => $trade_status, //交易状态
				"notify_id"    => $notify_id,    //通知校验ID。
				"notify_time"  => $notify_time,  //通知的发送时间。
				"buyer_email"  => $buyer_email,  //买家支付宝帐号;
            );

            if($_POST['trade_status'] == 'TRADE_FINISHED') {
                //
            }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
	            //商户自行增加处理流程,
            	// 得到订单数据
            	$order_data=M('cash_orders')->where(['sn'=>$out_trade_no])->find();
            	log_into_txt($log_name,"【支付成功】:\t".json_encode($parameter)."\t");
            	//验证订单号和金额
            	if($out_trade_no == $order_data['sn'] && $total_fee == $order_data['amount']){
					//支付成功信息是否已入库
		            if($order_data['status'] == 'paid'){
		            	log_into_txt($log_name,"【查询已支付成功】",'foot');
						echo "success";exit;
		            }else{
						//修改已支付状态
						$save_res=M('cash_orders')->where(['sn'=>$out_trade_no])->save(['status'=>'paid','paidTime'=>time(),'note'=>$trade_no]);
						if($save_res === false){
							log_into_txt($log_name,"【订单状态修改失败】:\t".M('cash_orders')->_sql()."\t",'foot');
							echo "fail";exit;
						}

						//某币抵扣
						if($order_data['is_usemoney']){
							//某币
							$mymoney = $this->userModel->getMoneyCount($order_data['userId']);
							$money_count = $mymoney>0 ? $mymoney : '0';

							//扣某币
							$insert_data=[
								'user_id'      =>	$order_data['userId'],
								'money_count'  =>	-$money_count,
								'money_time'   =>	date('Y-m-d H:i:s'),
								'money_detail' =>	'PC端购买积分抵扣',
							];
							$money_res=M('user_money')->data($insert_data)->add();
						}

						$user_id      = $order_data['userId'];
						$bean_count   = $order_data['amount']*10;
						$bean_detail1 = "充值送积分";
						$bean_type    = 8;
		            	// 购买积分
						$bean_res = insert_user_been($user_id, $bean_count, $bean_detail1, $bean_type);;
						if($bean_res === false){
							log_into_txt($log_name,"【购买数据入库失败】:\t".M('user_bean')->_sql()."\t",'foot');
							echo "fail";exit;
						}else{
							log_into_txt($log_name,"【购买成功】",'foot');
							echo "success";exit;
						}
		            }
			    }else{
			    	log_into_txt($log_name,"【订单号或金额验证失败】:\t".json_encode($data)."\t",'foot');
			        echo "fail";exit;
			    }
            }
            echo "success";        //请不要修改或删除
        }else {
            //验证失败
            echo "fail";
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值