TPshop学习(8)微信支付

TPshop学习(8)微信支付

http://blog.csdn.net/phper8/article/details/76383415

学习内容:
https://www.kancloud.cn/tpshop/thinkphp5/305718

这节课讲微信扫码支付。

初步简单的理解微信支付对接流程:

流程图:初步简单的理解微信支付对接流程

选择支付方式

选择支付方式

* 什么是二维码?
打开下面url,将看到一个二维码。
demo5.tp-shop.cn/index.php?m=Home&c=index&a=qr_code&data=http%3A%2F%2Fwww.tp-shop.cn

查看项目中代码,qr_code方法:

 // 二维码
 public function qr_code(){        
     // 导入Vendor类库包 Library/Vendor/Zend/Server.class.php
     //http://www.tp-shop.cn/Home/Index/erweima/data/www.99soubao.com
      //require_once 'vendor/phpqrcode/phpqrcode.php';
      vendor('phpqrcode.phpqrcode'); 
       //import('Vendor.phpqrcode.phpqrcode');
         error_reporting(E_ERROR);            
         $url = urldecode($_GET["data"]);
         \QRcode::png($url);
exit;        
 }

附:
二维码解码器 在线识别系统
jiema.wwei.cn

== 下面开始讲 微信支付 ==

1.先申请微信支付商户号。。
2.后台填写,配置。
3.测试一条商品支付。
4.支付完成。

顺着支付订单的页面,看代码:

/application/home/controller/Cart.php

/*
     * 订单支付页面
     */
    public function cart4(){

        $order_id = I('order_id/d');
        $order = M('Order')->where("order_id", $order_id)->find();

        // 如果已经支付过的订单直接到订单详情页面. 不再进入支付页面
        if($order['pay_status'] == 1){            
            $order_detail_url = U("Home/User/order_detail",array('id'=>$order_id));
            header("Location: $order_detail_url");
            exit;
        }
        //如果是预售订单,支付尾款
        if($order['pay_status'] == 2 && $order['order_prom_type'] == 4){
            $pre_sell_info = M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->find();
            $pre_sell_info = array_merge($pre_sell_info,unserialize($pre_sell_info['ext_info']));
            if($pre_sell_info['retainage_start'] > time()){
                $this->error('还未到支付尾款时间'.date('Y-m-d H:i:s',$pre_sell_info['retainage_start']));
            }
            if($pre_sell_info['retainage_end'] < time()){
                $this->error('对不起,该预售商品已过尾款支付时间'.date('Y-m-d H:i:s',$pre_sell_info['retainage_start']));
            }
        }
        if($order['order_prom_type'] != 4){
            $userlogic = new UsersLogic();
            $res = $userlogic->abolishOrder($order['user_id'],$order['order_id'],$order['add_time']);  //检测是否超时没支付
            if($res['status']==1)
                $this->error('订单超时未支付已自动取消',U("Home/User/order_detail",array('id'=>$order_id)));
        }

        $payment_where = array(
            'type'=>'payment',
            'status'=>1,
            'scene'=>array('in',array(0,2))
        );
        //预售和抢购暂不支持货到付款
        $orderGoodsPromType = M('order_goods')->where(['order_id'=>$order['order_id']])->getField('prom_type',true);
        if($order['order_prom_type'] == 4 || in_array(1,$orderGoodsPromType)){
            $payment_where['code'] = array('neq','cod');
        }
        $paymentList = M('Plugin')->where($payment_where)->select();
        $paymentList = convert_arr_key($paymentList, 'code');

        foreach($paymentList as $key => $val)
        {
            $val['config_value'] = unserialize($val['config_value']);            
            if($val['config_value']['is_bank'] == 2)
            {
                $bankCodeList[$val['code']] = unserialize($val['bank_code']);        
            }                
        }                

        $bank_img = include APP_PATH.'home/bank.php'; // 银行对应图片        
        $this->assign('paymentList',$paymentList);        
        $this->assign('bank_img',$bank_img);
        $this->assign('order',$order);
        $this->assign('bankCodeList',$bankCodeList);        
        $this->assign('pay_date',date('Y-m-d', strtotime("+1 day")));

        return $this->fetch();
    }

然后进入

/template/pc/cart/cart4.html

<form action="{:U('Home/Payment/getCode')}" method="post" name="cart4_form" id="cart4_form">
</form>

 

再看:Home/Payment/getCode

  • 1

其中:this>payment>getcode(order,$config_value);
这就要看__construct(),可知,指的是,plugins/payment/weixin/weixin.class.php
代码如下(代码中是以alipay举例)

class Payment extends Base {

    public $payment; //  具体的支付类
    public $pay_code; //  具体的支付code

    /**
     * 析构流函数
     */
    public function  __construct() {   
        parent::__construct();           

        // tpshop 订单支付提交
        $pay_radio = $_REQUEST['pay_radio'];
        if(!empty($pay_radio)) 
        {                         
            $pay_radio = parse_url_param($pay_radio);
            $this->pay_code = $pay_radio['pay_code']; // 支付 code
        }
        else // 第三方 支付商返回
        {            
            //file_put_contents('./a.html',$_GET,FILE_APPEND);    
            $this->pay_code = I('get.pay_code');
            unset($_GET['pay_code']); // 用完之后删除, 以免进入签名判断里面去 导致错误
        }                        
        //获取通知的数据
        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];      

        if(empty($this->pay_code))
            exit('pay_code 不能为空');
        // 导入具体的支付类文件                
        include_once  "plugins/payment/{$this->pay_code}/{$this->pay_code}.class.php"; // D:\wamp\www\svn_tpshop\www\plugins\payment\alipay\alipayPayment.class.php                       
        $code = '\\'.$this->pay_code; // \alipay
        $this->payment = new $code();
    }
   ...略
/**
     * tpshop 提交支付方式
     */
    public function getCode(){        
            //C('TOKEN_ON',false); // 关闭 TOKEN_ON
            header("Content-type:text/html;charset=utf-8");            
            $order_id = I('order_id/d'); // 订单id
            session('order_id',$order_id); // 最近支付的一笔订单 id
            // 修改订单的支付方式
            $payment_arr = M('Plugin')->where("`type` = 'payment'")->getField("code,name");
            M('order')->where("order_id",$order_id)->save(array('pay_code'=>$this->pay_code,'pay_name'=>$payment_arr[$this->pay_code]));

            $order = M('order')->where("order_id", $order_id)->find();
            if($order['pay_status'] == 1){
                $this->error('此订单,已完成支付!');
            }            
            // tpshop 订单支付提交
            $pay_radio = $_REQUEST['pay_radio'];
            $config_value = parse_url_param($pay_radio); // 类似于 pay_code=alipay&bank_code=CCB-DEBIT 参数

            //微信JS支付
           if($this->pay_code == 'weixin' && $_SESSION['openid'] && strstr($_SERVER['HTTP_USER_AGENT'],'MicroMessenger')){
               $code_str = $this->payment->getJSAPI($order,$config_value);
               exit($code_str);
           }else{
            $code_str = $this->payment->get_code($order,$config_value);
           }
           $this->assign('code_str', $code_str); 
           $this->assign('order_id', $order_id);           
           return $this->fetch('payment');  // 分跳转 和不 跳转 
    }
   ...略
}

注意:this>payment>getcode(order,$config_value);

是weixin.class.php中的get_code

 /**
     * 生成支付代码
     * @param   array   $order      订单信息
     * @param   array   $config_value    支付方式信息
     */
    function get_code($order, $config_value)
    {       
            $notify_url = SITE_URL.'/index.php/Home/Payment/notifyUrl/pay_code/weixin'; // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
            //$notify_url = C('site_url').U('Home/Payment/notifyUrl',array('pay_code'=>'weixin')); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
            //$notify_url = C('site_url')."/index.php?m=Home&c=Payment&a=notifyUrl&pay_code=weixin";
            $input = new WxPayUnifiedOrder();
            $input->SetBody("TPshop商品"); // 商品描述
            $input->SetAttach("weixin"); // 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
            $input->SetOut_trade_no($order['order_sn'].time()); // 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
            $input->SetTotal_fee($order['order_amount']*100); // 订单总金额,单位为分,详见支付金额
            $input->SetNotify_url($notify_url); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
            $input->SetTrade_type("NATIVE"); // 交易类型   取值如下:JSAPI,NATIVE,APP,详细说明见参数规定    NATIVE--原生扫码支付
            $input->SetProduct_id("123456789"); // 商品ID trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。
            $notify = new NativePay();
            $result = $notify->GetPayUrl($input); // 获取生成二维码的地址
            $url2 = $result["code_url"];
            return '<img alt="模式二扫码支付" src="/index.php?m=Home&c=Index&a=qr_code&data='.urlencode($url2).'" style="width:110px;height:110px;"/>';        
    }    

这里就出来了,二维码的图片。主要就是这个get_code。
这里成功后,用户扫码。扫码成功后,返回到$notify_url的地址。

 $notify_url = SITE_URL.'/index.php/Home/Payment/notifyUrl/pay_code/weixin';

    1

/application/home/controller/Payment.php 看notifyUrl()

    // 服务器点对点 // http://www.tp-shop.cn/index.php/Home/Payment/notifyUrl        
    public function notifyUrl(){            
        $this->payment->response();            
        exit();
    }

再看weixin.class.php中的response()

/**
     * 服务器点对点响应操作给支付接口方调用
     * 
     */
    function response()
    {                        
        require_once("example/notify.php");  
        $notify = new PayNotifyCallBack();
        $notify->Handle(false);       
    }

 

主要是:plugins/payment/weixin/example/notify.php

//重写回调处理函数
    public function NotifyProcess($data, &$msg)
    {                       
        Log::DEBUG("call back:" . json_encode($data));
        $notfiyOutput = array();

        if(!array_key_exists("transaction_id", $data)){
            $msg = "输入参数不正确";
            return false;
        }
        //查询订单,判断订单真实性
        if(!$this->Queryorder($data["transaction_id"])){
            $msg = "订单查询失败";
            return false;
        }         
                $appid = $data['appid']; //公众账号ID
                $order_sn = $out_trade_no = $data['out_trade_no']; //商户系统的订单号,与请求一致。
                $attach = $data['attach']; //商家数据包,原样返回                
                //file_put_contents('/web/tpshop2/c.html',print_r($data,true),FILE_APPEND);
        //20160316 JSAPI支付情况 去掉订单号后面的十位时间戳
        if(strlen($order_sn) > 18){
            $order_sn = substr($order_sn,0,18);
        }
        update_pay_status($order_sn); // 修改订单支付状态

        return true;
    }

 

update_pay_status($order_sn); // 修改订单支付状态
  • 1

这个方法在common.php

/**
 * 支付完成修改订单
 * @param $order_sn 订单号
 * @param array $ext 额外参数
 * @return bool|void
 */
function update_pay_status($order_sn,$ext=array())
{
    if(stripos($order_sn,'recharge') !== false){
        //用户在线充值
        $count = M('recharge')->where(['order_sn'=>$order_sn,'pay_status'=>0])->count();   // 看看有没已经处理过这笔订单  支付宝返回不重复处理操作
        if($count == 0) return false;
        $order = M('recharge')->where("order_sn", $order_sn)->find();
        M('recharge')->where("order_sn",$order_sn)->save(array('pay_status'=>1,'pay_time'=>time()));
        accountLog($order['user_id'],$order['account'],0,'会员在线充值');
    }else{
        // 如果这笔订单已经处理过了
        $count = M('order')->master()->where("order_sn = :order_sn and pay_status = 0 OR pay_status = 2")->bind(['order_sn'=>$order_sn])->count();   // 看看有没已经处理过这笔订单  支付宝返回不重复处理操作
        if($count == 0) return false;
        // 找出对应的订单
        $order = M('order')->master()->where("order_sn",$order_sn)->find();
        //预售订单
        if ($order['order_prom_type'] == 4) {
            $orderGoodsArr = M('OrderGoods')->where(array('order_id'=>$order['order_id']))->find();
            // 预付款支付 有订金支付 修改支付状态  部分支付
            if($order['total_amount'] != $order['order_amount'] && $order['pay_status'] == 0){
                //支付订金
                M('order')->where("order_sn", $order_sn)->save(array('order_sn'=> date('YmdHis').mt_rand(1000,9999) ,'pay_status' => 2, 'pay_time' => time(),'paid_money'=>$order['order_amount']));
                M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->setInc('act_count',$orderGoodsArr['goods_num']);
            }else{
                //全额支付 无订金支付 支付尾款
                M('order')->where("order_sn", $order_sn)->save(array('pay_status' => 1, 'pay_time' => time()));
                $pre_sell = M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->find();
                $ext_info = unserialize($pre_sell['ext_info']);
                //全额支付 活动人数加一
                if(empty($ext_info['deposit'])){
                    M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->setInc('act_count',$orderGoodsArr['goods_num']);
                }
            }
        } else {
            // 修改支付状态  已支付
            M('order')->where("order_sn", $order_sn)->save(array('pay_status'=>1,'pay_time'=>time()));
        }
        // 减少对应商品的库存
        minus_stock($order['order_id']);
        // 给他升级, 根据order表查看消费记录 给他会员等级升级 修改他的折扣 和 总金额
        update_user_level($order['user_id']);
        // 记录订单操作日志
        if(array_key_exists('admin_id',$ext)){
            logOrder($order['order_id'],$ext['note'],'付款成功',$ext['admin_id']);
        }else{
            logOrder($order['order_id'],'订单付款成功','付款成功',$order['user_id']);
        }
        //分销设置
        M('rebate_log')->where("order_id" ,$order['order_id'])->save(array('status'=>1));
        // 成为分销商条件
        $distribut_condition = tpCache('distribut.condition');
        if($distribut_condition == 1)  // 购买商品付款才可以成为分销商
            M('users')->where("user_id", $order['user_id'])->save(array('is_distribut'=>1));

        //用户支付, 发送短信给商家
        $res = checkEnableSendSms("4");
        if(!$res || $res['status'] !=1) return ;

        $sender = tpCache("shop_info.mobile");
        if(empty($sender))return;
        $params = array('order_sn'=>$order_sn);
        sendSms("4", $sender, $params);
    }

}

Tpshop的微信支付就简单介绍到此,
需要我们再多研究,不是一下子就能理解和掌握。
加油!

学习改变命运,技术成就梦想!
坚持不懈的努力,其结果一定是成功!

回调业务处理逻辑:
回调业务处理逻辑

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/113628.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 双边滤波——原理及matlab实现

      思维闭塞时可外出采采风。1、双边滤波简介:   双边滤波(Bilateral filter)是一种非线性滤波方法(空间权值+相似权值)——空间权值:模糊去噪;相似权值:保护边缘。2、双边滤波原理  双边滤波具有两个权重:空间权重与相似权重  1)空间权重:与像素位置有关,为像素之间的距离(欧式距离,空间度量),故可定义为全局变量放在循环外,通常定义为…

  • Oracle存储过程及参数理解

    Oracle存储过程及参数理解一、过程(存储过程)    过程是一个能执行某个特定操作的子程序。使用CREATEORREPLACE创建或者替换保存在数据库中的一个子程序。示例1:声明存储过程,该过程返回dept表行数DECLARE  PROCEDUREgetDeptCount  AS    deptCountINT;  BEGIN    SELECTCOUNT(*)INTOdeptCountFROMDEPT…

  • JAVA布局模式:GridBagConstraints终极技巧参数详解「建议收藏」

    JAVA布局模式:GridBagConstraints终极技巧参数详解「建议收藏」布局模式:GridBagConstraints布局,先发一个实例:gridx=2;//X2gridy=0;//Y0gridwidth=1;//横占一个单元格gridheight=1;//列占一个单元格weightx=0.0;//当窗口放大时,长度不变weighty=0.0;//当窗口放大时,高度不变anchor=Gr

  • 天气预报代码调用

    天气预报代码调用

    2021年10月11日
  • laravel5 报错419,form 添加crrf_field 后让然失败,本地环境配置问题

    laravel5 报错419,form 添加crrf_field 后让然失败,本地环境配置问题

  • 383. 观光(最短路拓扑图)「建议收藏」

    383. 观光(最短路拓扑图)「建议收藏」“您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。比荷卢经济联盟有很多公交线路。每天公共汽车都会从一座城市开往另一座城市。沿途汽车可能会在一些城市(零或更多)停靠。旅行社计划旅途从 S 城市出发,到 F 城市结束。由于不同旅客的景点偏好不同,所以为了迎合更多旅客,旅行社将为客户提供多种不同线路。游客可以选择的行进路线有所限制,要么满足所选路线总路程为 S 到 F 的最小路程,要么满足所选路线总路程仅比最小路程多一个单位长度。如上图所示,如果 S=1,F=5,则这里有两条最短路线 1→

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号