前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Thinkphp5实现支付宝支付、余额提现、订单查询、取消/关闭订单

Thinkphp5实现支付宝支付、余额提现、订单查询、取消/关闭订单

作者头像
程序猿的栖息地
发布2022-04-29 14:22:11
1.9K0
发布2022-04-29 14:22:11
举报
文章被收录于专栏:程序猿的栖息地

作者:阿dai哥

教程分享

TUTORIAL TO SHAR

最近很多朋友在博客给我留言问,叫我写一个支付宝支付的功能,今天整理了一套比较完整的支付宝支付相关的demo改进版,下面的代码都是在我一个真实的项目中改进出来的。包含:【pc扫码支付】、【查询订单】、【余额提现】、【取消订单】、【关闭订单】

效果说明

SHARE THE BODY

1、pc扫码支付

2、手机支付成功截图

3、支付宝商家后台账单截图

开发前提

SHARE THE BODY

开发支付宝必须用注册一个企业账号,现在支付宝比较人性化了,如果你没有企业的信息也是可以只用的,因为支付宝有一个沙箱的测试功能,个人也是可以开发支付宝支付的功能。

登录支付开发平台后添加一个应用,填写你的开发者信息等待审核,沙箱模式下直接使用即可。下图就是我本地测试的域名和祝福吧异步通知回调地址。

实现代码

THE IMPLEMENTATION CODE

先建一个数据表吧,具体的表设计根据自己的项目该设计,因为我在此只是给大家展示功能,我就大概的设计了一下:

代码语言:javascript
复制
CREATE TABLE `jk_users_financial` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户id',
`subject` varchar(100) NOT NULL DEFAULT '余额充值' COMMENT '订单标题',
`body` varchar(255) NOT NULL DEFAULT '余额充值' COMMENT '描述',
`total_amount` decimal(10,2) NOT NULL COMMENT '金额',
`gmt_create` varchar(50) DEFAULT '0' COMMENT '交易创建时间',
`gmt_payment` varchar(50) DEFAULT '0' COMMENT '交易付款时间',
`out_trade_no` varchar(50) DEFAULT '0' COMMENT '商户订单号',
`trade_no` varchar(50) DEFAULT '0' COMMENT '支付宝交易号',
`out_biz_no` varchar(50) DEFAULT '0' COMMENT '商户业务ID,主要是退款通知中返回退款申请的流水号',
`buyer_id` varchar(50) DEFAULT '0' COMMENT '买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字',
`seller_id` varchar(50) DEFAULT '0' COMMENT '卖家支付宝用户号',
`trade_status` varchar(32) DEFAULT 'WAIT_BUYER_PAY' COMMENT '交易状态',
`status` tinyint(1) DEFAULT '1' COMMENT '支付状态:1-未支付,2-支付成功,3-退款种,4-已退款',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='用户消费表';
}

下面正式进入代码的介绍阶段。由于我使用的是Thinkphp5框架实现的效果,所以开发先composer一下要用到的包。

代码语言:javascript
复制
"require": {
    "php": ">=5.4.0",
    "topthink/framework": "5.0.*",    "yansongda/pay": "^2.6",    "phpoffice/phpexcel": "^1.8"
},

二话不说先引入要用到的命名空间吧

代码语言:javascript
复制
use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;

任何的支付功能都必须要配置一些参数,支付宝也一样,下面这个是标准的格式,具体的参数在支付宝开发平台都能拿到,不懂的话使用沙箱的功能自己了解一下,反正都是傻瓜式操作,瞎子也能看懂。

代码语言:javascript
复制
protected $config = [
       'app_id' => '2018120562457322',
       'return_url' => 'http://www.jobya.cc/pay/index/notify',
       'notify_url' => 'http://www.jobya.cc/pay/index/notify',
       'ali_public_key' => 'xxxxxx',
       // 加密方式: **RSA2**
       'private_key' => '',
       'log' => [ // optional
           'file' => './logs/alipay.log',
           'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
           'type' => 'single', // optional, 可选 daily.
           'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
       ],
       'http' => [ // optional
           'timeout' => 5.0,
           'connect_timeout' => 5.0,
       ],
       // 'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
   ];

这是一个支付的方法,下面的代码我都是实现逻辑,没有html代码的部分,模拟用户的数据。直接访问当前的方法就是在数据库生成一条没有付款的订单;

模拟支付代码如下

代码语言:javascript
复制
public function index()
{
    $order = [
        'out_trade_no' => time(),   //订单号
        'total_amount' => '0.01',
        'subject' => '测试账户余额充值',
        'body'  => '余额充值',
        'gmt_create'  => time(),    //交易创建时间
        'status'  => 1,
        'user_id' => 1
    ];
    // dump($order);exit;
    $alipay = Pay::alipay($this->config)->web($order);
    // dump($alipay);exit;
    \think\Db::table('jk_users_financial')->insert($order);
    return $alipay->send();// laravel 框架中请直接 `return $alipay`
}

上面的方法会生成一个付款的二维码。

然后,根据支付宝异步返回的数据判断用户是否成功支付了,根据返回来的标示在我们的服务器修改用户成功付款的状态。核心的代码还是在回调的方法里面。回调的方法如下:

代码语言:javascript
复制
public function notify()
{
    $alipay = Pay::alipay($this->config);
    try{
        $data = $alipay->verify(); // 是的,验签就这么简单!
        $data = json_decode( json_encode( $data),true); // 把支付宝回调的json数据转数组
        //a.先判断用户是否支付成功
        $is_pay_data = $this->find($data['out_trade_no']);
        $is_pay_data = json_decode( json_encode( $is_pay_data),true); // 查询订单的json数据转数组
        if($is_pay_data['trade_status'] == 'TRADE_SUCCESS'){
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
            $is_order = ['user_id' => 1, 'out_trade_no' => $data['out_trade_no']];
            $is_data =  \think\Db::table('jk_users_financial')->where($is_order)->find();    //在数据库中查出的订单数据
            if(!$is_data){
                echo '没有该订单'; exit;
            }
            // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
            if($is_data['total_amount'] != $data['total_amount']){
                echo '充值金额异常~'; exit;
            }
            // 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
            if($data['seller_id'] != $is_pay_data['buyer_user_id']) {
                echo '不是当前订单'; exit;
            }
            // 4、验证app_id是否为该商户本身。
            if($this->config['app_id'] != $data['app_id']){
                echo '不是当前支付的商户';exit;
            }
            // 5、其它业务逻辑情况
            $update = array(
                'gmt_payment' => $data['timestamp'],        //付款时间
                'trade_no' => $is_pay_data['trade_no'], //支付宝交易号
                'buyer_id' => $is_pay_data['buyer_logon_id'],   //买家账户
                'seller_id' => $data['seller_id'],
                'trade_status' => $is_pay_data['trade_status'],
                'status' => 2
            );
            $is_ok =  \think\Db::table('jk_users_financial')->where($is_order)->update($update);
            if($is_ok){
                echo '支付成功,可以设置跳转';exit;
            } else{
                echo '操作失败';exit;
            }
        } else{
            echo '请你先支付~'; exit;
        }
        Log::debug('Alipay notify', $data->all());
    } catch (\Exception $e) {
        $aa = $e->getMessage();
        echo '错误信息--';
        dump($aa);exit;
        测试
    }
    // exit;
    return $alipay->success()->send();// laravel 框架中请直接 `return $alipay->success()`
}

话付款成功后,数据库中的订单等信息都更新了,如下

订单查询

代码语言:javascript
复制
//查询订单 out_trade_no 订单号
public function find($out_trade_no)
{
    $order = [
        'out_trade_no' => $out_trade_no,
        'bill_type' => 'trade'
    ];
    // $order = '1514027114';
    $alipay = Pay::alipay($this->config);
    $result = $alipay->find($order);    //json格式
    return $result;
}

余额提现

代码语言:javascript
复制
//单笔转账(提现)
public function zhuanzhang($payee_account = '18826747803')
{
    $order = [
        'out_biz_no' => time(), //商户转账唯一订单号
        'payee_type' => 'ALIPAY_LOGONID',
        'payee_account' => $payee_account,
        'amount' => '0.2',
        'remark' => '提现余额'
    ];
    $alipay = Pay::alipay($this->config);
    $result = $alipay->transfer($order);
    dump($result);
}

取消订单

代码语言:javascript
复制
//取消订单
public function quxiao($out_trade_no = '1551253633')
{
    //先查看当前定时是否已经完成交易
    $res = json_decode($this->find($out_trade_no), true);
    if($res['trade_status'] == 'TRADE_FINISHED' || $res['trade_status'] == 'TRADE_SUCCESS'){
        echo '订单已经完成不能退款';exit;
    }
    dump($res);exit;
    $order = [
        'out_trade_no' => $out_trade_no
    ];
    // $order = '1514027114';
    $alipay = Pay::alipay($this->config);
    $result = $alipay->cancel($order);
    dump($result);
}

关闭订单

代码语言:javascript
复制
//关闭订单
public function close($out_trade_no = '1551253633')
{
   
    $order = [
        'out_trade_no' => $out_trade_no
    ];
    $alipay = Pay::alipay($this->config);
    $result = $alipay->close($order);
    dump($result);
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序猿的栖息地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档