这是一个
涨姿势的站点

原版sspanelv3增加当面付模块教程 | 设置f2fpay自定义金额

写一个比较基础,略微复杂的教程吧,手把手指导如何写代码。

原版指的是: sspanel v3 new_master 这个版本
支付宝当面付模块指的是: 当面付

如何获得当面付权限,自己想办法啦,群内一堆大佬可以解决这个问题。

正常安装sspanel v3

搭建

再说明一下,91vps.win改成自己的域名

cd /www/wwwroot/91vps.win
git clone https://github.com/glzjin/ss-panel-v3-mod.git tmp -b new_master && mv tmp/.git . && rm -rf tmp && git reset --hard
cp config/.config.php.example config/.config.php
chown -R root:root *
chmod -R 755 *
chown -R www:www storage
curl -sS https://install.phpcomposer.com/installer | php
chmod +x composer.phar
php composer.phar install
chattr -i .user.ini
mv .user.ini ./public
cd ./public
chattr +i .user.ini

注意的地方

如果非要说注意的地方:
1、伪静态
mark
2、目录别写错了
mark
3、PHP配置
关掉报错 以及 设置静态运行模式
mark
mark
修改完之后记得重新启动或者重新载入PHP

增加支付宝模块

根据 sspanel架构 大概需要增加如下几个部分的代码:

  • vender部分,把支付宝的SDK丢进去
  • .config.php以及routes.php,配置以及链接路径
  • app部分,主要是修改pay.php的代码,增加用户金额的话,需要改 UserController.php
  • 前端页面的代码 这部分主要在

大概应该是这几个部分,具体一遍写一遍看具体情况吧。
mark

  • vender部分
    这儿有一个SDK包,下载下来,放进自己的vender目录。下载链接,解压出来。
    mark
    然后vender内就多了一个文件夹
    mark
autoload_classmap.php路径声明

在 /www/wwwroot/bibili.li/vendor/composer/autoload_classmap.php 增加如下内容

'ExtendParams' => $vendorDir . '/alipay-f2fpay/f2fpay/model/builder/AlipayTradePrecreateContentBuilder.php',
'GoodsDetail' => $vendorDir . '/alipay-f2fpay/f2fpay/model/builder/AlipayTradePrecreateContentBuilder.php',
'AlipayTradePrecreateContentBuilder' => $vendorDir . '/alipay-f2fpay/f2fpay/model/builder/AlipayTradePrecreateContentBuilder.php',
'AlipayTradeQueryContentBuilder' => $vendorDir . '/alipay-f2fpay/f2fpay/model/builder/AlipayTradeQueryContentBuilder.php',
'AlipayTradeService' => $vendorDir . '/alipay-f2fpay/f2fpay/service/AlipayTradeService.php',
'AopClient' => $vendorDir . '/alipay-f2fpay/aop/AopClient.php',

如果改不来,用我的 替换掉自己的也行

关于vendor的建议

其实对于vendor这块,我的建议是。。要不直接把整个vender给换了吧,要不小毛病一大堆
先清空vendor文件夹,下载 vender压缩包 ,然后解压。
mark

  • config 部分
.config.php

增加以下5行,随便找个地方放都行。

#alipay,f2fpay
$System_Config['f2fpay_app_id']='';
$System_Config['f2fpay_p_id']='';
$System_Config['alipay_public_key']='';
$System_Config['merchant_private_key']='';

支付系统别忘修改了
mark
顺便说明一下,每个是干嘛的

第一个位置: $System_Config[‘f2fpay_app_id’]=” 这个是支付宝商家平台里的APPID,开通收款码服务后进入 支付宝商家平台签约管理,查看PID和Key,有一个基础应用,就是那个APPID

第二个位置: $System_Config[‘f2fpay_p_id’] 这个是收款的支付宝账号,用来确认阿里消息正确性的。 签约管理里合作伙伴身份PID

第三个位置: $System_Config[‘alipay_public_key’] 指的是这里的支付宝公钥,注意是支付宝公钥。

第四个位置: $System_Config[‘merchant_private_key’] 这个是你自己的私钥。注意,会很长。

.route.php部分

第140行附近,插入两行

$this->post('/code/f2fpay', 'App\Controllers\UserController:f2fpay');
$this->get('/code/f2fpay', 'App\Controllers\UserController:f2fpayget');

这两行其实相当于把 你的域名/code/f2fpay,在POST和GET方法下,指向到两个不同的函数,因此对应的UserController.php也要改一下。

  • 系统代码部分
  • UserController.php 部分
    增加两个函数
    public function f2fpayget($request, $response, $args)
    {
        $time = $request->getQueryParams()["time"];
        $res['ret'] = 1;
        return $response->getBody()->write(json_encode($res));
    }
    public function f2fpay($request, $response, $args)
    {
        $amount = $request->getParam('amount');
        if ($amount == "") {
            $res['ret'] = 0;
            $res['msg'] = "订单金额错误:".$amount;
            return $response->getBody()->write(json_encode($res));
        }
        $user = $this->user;

        //生成二维码
        $qrPayResult = Pay::alipay_get_qrcode($user, $amount, $qrPay);
        //  根据状态值进行业务处理
        switch ($qrPayResult->getTradeStatus()){
            case "SUCCESS":
                $aliresponse = $qrPayResult->getResponse();
                $res['ret'] = 1;
                $res['msg'] = "二维码生成成功";
                $res['amount'] = $amount;
                $res['qrcode'] = $qrPay->create_erweima_baidu($aliresponse->qr_code);

                break;
            case "FAILED":
                $res['ret'] = 0;
                $res['msg'] = "支付宝创建订单二维码失败!!! 请使用其他方式付款。";
                break;
            case "UNKNOWN":
                $res['ret'] = 0;
                $res['msg'] = "系统异常,状态未知!!!!!! 请使用其他方式付款。";

                break;
            default:
                $res['ret'] = 0;
                $res['msg'] = "创建订单二维码返回异常!!!!!! 请使用其他方式付款。";

                break;
        }

        return $response->getBody()->write(json_encode($res));
    }

mark

  • Pay.php部分
    增加页面结构
    private static function f2fpay_html($user)
    {
        return '
                        <p class="card-heading">使用支付宝充值</p>
                        <label for="number">请选择充值金额:</label>
                        <select id="type" class="form-control" name="amount">
                            <option value="10">10元</option>
                            <option value="20">20元</option>
                            <option value="50">50元</option>
                            <option value="100">100元</option>
                            <option value="200">200元</option>
                        </select>
                        <p></p>
                        <a class="btn btn-flat waves-attach" id="urlChange" ><span class="icon">check</span> 充值</a>
';
    }

修改 getHTML函数
增加f2fpay_html选项
mark
增加几个函数
第一个函数是获得配置文件里边的那些东西
第二个新建订单,获得二维码

    private static function get_alipay_config()
    {
        //获取支付宝接口配置
        $config = array (
            //签名方式,默认为RSA2(RSA2048)
            'sign_type' => "RSA2",
            //支付宝公钥
            'alipay_public_key' => Config::get("alipay_public_key"),
            //商户私钥
            'merchant_private_key' => Config::get("merchant_private_key"),
            //编码格式
            'charset' => "UTF-8",
            //支付宝网关
            'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
            //应用ID
            'app_id' => Config::get("f2fpay_app_id"),
            //异步通知地址,只有扫码支付预下单可用
            'notify_url' => Config::get("baseUrl")."/pay_callback",
            //最大查询重试次数
            'MaxQueryRetry' => "10",
            //查询间隔
            'QueryDuration' => "3"
        );

        return $config;
    }

    public static function alipay_get_qrcode($user, $amount, &$qrPay)
    {
        //创建订单
        $pl = new Paylist();
        $pl->userid = $user->id;
        $pl->total = $amount;
        $pl->save();

        //获取支付宝接口配置
        $config = Pay::get_alipay_config();

        //$timestamp
        /**************************请求参数**************************/
        // (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
        // 需保证商户系统端不能重复,建议通过数据库sequence生成,
        //$outTradeNo = "qrpay".date('Ymdhis').mt_rand(100,1000);
        $outTradeNo = $pl->id;

        // (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        $subject = "在".Config::get("appName")."充值".$pl->total."元";

        // (必填) 订单总金额,单位为元,不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        $totalAmount = $pl->total;

        // (不推荐使用) 订单可打折金额,可以配合商家平台配置折扣活动,如果订单部分商品参与打折,可以将部分商品总价填写至此字段,默认全部商品可打折
        // 如果该值未传入,但传入了【订单总金额】,【不可打折金额】 则该值默认为【订单总金额】- 【不可打折金额】
        //String discountableAmount = "1.00"; //

        // (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        $undiscountableAmount = "0.01";

        // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)
        // 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
        //$sellerId = "";

        // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
        $body = "用户名:".$user->user_name." 用户ID:".$user->id." 用户充值共计".$pl->total."元";

        //商户操作员编号,添加此参数可以为商户操作员做销售统计
        $operatorId = "bak_admin0001";

        // (可选) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
        $storeId = "bak_store001";

        // 支付宝的店铺编号
        //$alipayStoreId= "2016041400077000000003314986";

        // 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),系统商开发使用,详情请咨询支付宝技术支持
        $providerId = ""; //系统商pid,作为系统商返佣数据提取的依据
        $extendParams = new \ExtendParams();
        $extendParams->setSysServiceProviderId($providerId);
        $extendParamsArr = $extendParams->getExtendParams();

        // 支付超时,线下扫码交易定义为5分钟
        $timeExpress = "5m";

        // 商品明细列表,需填写购买商品详细信息,
        $goodsDetailList = array();

        // 创建一个商品信息,参数含义分别为商品id(使用国标)、名称、单价(单位为分)、数量,如果需要添加商品类别,详见GoodsDetail
        $goods1 = new \GoodsDetail();
        $goods1->setGoodsId($pl->total);
        $goods1->setGoodsName("充值");
        $goods1->setPrice($pl->total);
        $goods1->setQuantity(1);
        //得到商品1明细数组
        $goods1Arr = $goods1->getGoodsDetail();
        $goodsDetailList = array($goods1Arr);

        //第三方应用授权令牌,商户授权系统商开发模式下使用
        $appAuthToken = "";//根据真实值填写

        // 创建请求builder,设置请求参数
        $qrPayRequestBuilder = new \AlipayTradePrecreateContentBuilder();
        $qrPayRequestBuilder->setOutTradeNo($outTradeNo);
        $qrPayRequestBuilder->setTotalAmount($totalAmount);
        $qrPayRequestBuilder->setTimeExpress($timeExpress);
        $qrPayRequestBuilder->setSubject($subject);
        $qrPayRequestBuilder->setBody($body);
        $qrPayRequestBuilder->setUndiscountableAmount($undiscountableAmount);
        $qrPayRequestBuilder->setExtendParams($extendParamsArr);
        $qrPayRequestBuilder->setGoodsDetailList($goodsDetailList);
        $qrPayRequestBuilder->setStoreId($storeId);
        $qrPayRequestBuilder->setOperatorId($operatorId);
        //$qrPayRequestBuilder->setAlipayStoreId($alipayStoreId);
        $qrPayRequestBuilder->setAppAuthToken($appAuthToken);

        // 调用qrPay方法获取当面付应答
        $qrPay = new \AlipayTradeService($config);
        $qrPayResult = $qrPay->qrPay($qrPayRequestBuilder);

        return $qrPayResult;
    }

    private static function f2fpay_gen($user, $amount)
    {
        //$qrPayResult = Pay::query_alipay_order(2017052112230123456);
        //return ;
        //生成二维码
        $qrPayResult = Pay::alipay_get_qrcode($user, $amount, $qrPay);

        //  根据状态值进行业务处理
        switch ($qrPayResult->getTradeStatus()){
            case "SUCCESS":
                echo "支付金额: RMB ".$amount." 元";
                echo "确认无误后请用支付宝App扫描二维码支付:"."<br>---------------------------------------<br>";
                $response = $qrPayResult->getResponse();
                $qrcode = $qrPay->create_erweima_baidu($response->qr_code);
                echo $qrcode."<br>";
                break;
            case "FAILED":
                echo "支付宝创建订单二维码失败!!!"."<br>--------------------------<br>";
                if(!empty($qrPayResult->getResponse())){
                    print_r($qrPayResult->getResponse());
                }
                echo "请使用其他方式付款。";
                break;
            case "UNKNOWN":
                echo "系统异常,状态未知!!!"."<br>--------------------------<br>";
                if(!empty($qrPayResult->getResponse())){
                    print_r($qrPayResult->getResponse());
                }
                echo "请使用其他方式付款。";
                break;
            default:
                echo "创建订单二维码返回异常!!!"."<br>--------------------------<br>";
                echo "请使用其他方式付款。";
                break;
        }

        if ($qrPayResult->getTradeStatus()) {
            sleep(1);
            echo "轮询处理:";
        }

        return ;
    }

    private static function f2fpay_callback()
    {
        $aop = new \AopClient();
        $alipayrsaPublicKey = Config::get("alipay_public_key");
        $aop->alipayrsaPublicKey = $alipayrsaPublicKey;

        //获取支付宝返回参数
        $arr=$_POST;
        //调用验签的方法
        $result = $aop->rsaCheckV1($arr,$alipayrsaPublicKey,$_POST['sign_type']);
        if($result) {//验证成功
            //系统订单号
            $out_trade_no = $_POST['out_trade_no'];
            //支付宝交易号
            $trade_no = $_POST['trade_no'];
            //交易状态
            $trade_status = $_POST['trade_status'];

            // 查询系统订单
            $alipayPID = Config::get("f2fpay_p_id");
            if ($_POST['seller_id']!=$alipayPID){
                exit("success");
            }
            $trade = Paylist::where("id", '=', $out_trade_no)->where('status', 0)->where('total', $_POST['total_amount'])->first();
            if ($trade == null) {//没有符合的订单,或订单已经处理
                exit("success");
            }

            //订单查询到,处理业务
            if($trade_status == 'TRADE_FINISHED'||$trade_status == 'TRADE_SUCCESS') {

                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                //如果有做过处理,不执行商户的业务程序

                //注意:
                //付款完成后,支付宝系统发送该交易状态通知
                //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知

                //更新订单状态
                $trade->tradeno = $trade_no;
                $trade->status = 1;
                $trade->save();

                //更新用户账户
                $user=User::find($trade->userid);
                $user->money=$user->money+$_POST['total_amount'];
                if ($user->class==0) {
                    $user->class_expire=date("Y-m-d H:i:s", time());
                    $user->class_expire=date("Y-m-d H:i:s", strtotime($user->class_expire)+86400);
                    $user->class=1;
                }
                $user->save();

                //更新充值(捐赠)记录
                $codeq=new Code();
                $codeq->code="支付宝 充值";
                $codeq->isused=1;
                $codeq->type=-1;
                $codeq->number=$_POST['total_amount'];
                $codeq->usedatetime=date("Y-m-d H:i:s");
                $codeq->userid=$user->id;
                $codeq->save();

                //更新返利
                if ($user->ref_by!=""&&$user->ref_by!=0&&$user->ref_by!=null) {
                    $gift_user=User::where("id", "=", $user->ref_by)->first();
                    $gift_user->money=($gift_user->money+($codeq->number*(Config::get('code_payback')/100)));
                    $gift_user->save();

                    $Payback=new Payback();
                    $Payback->total=$_POST['total_amount'];
                    $Payback->userid=$user->id;
                    $Payback->ref_by=$user->ref_by;
                    $Payback->ref_get=$codeq->number*(Config::get('code_payback')/100);
                    $Payback->datetime=time();
                    $Payback->save();
                }

                if (Config::get('enable_donate') == 'true') {
                    if ($user->is_hide == 1) {
                        Telegram::Send("一位不愿透露姓名的大老爷给我们捐了 ".$codeq->number." 元!");
                    } else {
                        Telegram::Send($user->user_name." 大老爷给我们捐了 ".$codeq->number." 元!");
                    }
                }

                //业务处理完毕,向支付宝系统返回成功
                echo "success";     //请不要修改或删除
            }
        }else {
            //验证失败
            echo "fail";    //请不要修改或删除
        }
    }

getGen函数也要修改一下
mark
callback函数对应的也要改一下
mark
其余的都有中文提示,应该可以看懂。
如果实在自己搞不来,直接 用我写好的 UserController.php 替换掉 原UserController.php即可

  • 前端部分
    /resources/views/material/user/code.tpl 主要是这个文件

js部分加入

    $("#urlChange").click(function () {
            $.ajax({
                type: "GET",
                url: "code/f2fpay",
                dataType: "json",
                data: {
                    time: timestamp
                },
                success: function (data) {
                    if (data.ret) {
                        $("#readytopay").modal();
                    }
                }

            })
        });

        $("#readytopay").on('shown.bs.modal', function () {
            $.ajax({
                type: "POST",
                url: "code/f2fpay",
                dataType: "json",
                data: {
                        amount: $("#type").find("option:selected").val()
                    },
                success: function (data) {
                    $("#readytopay").modal('hide');
                    if (data.ret) {
                        $("#qrcode").html(data.qrcode);
                        $("#info").html("您的订单金额为:"+data.amount+"元。");
                        $("#alipay").modal();
                    } else {
                        $("#result").modal();
                        $("#msg").html(data.msg);
                    }
                },
                error: function (jqXHR) {
                    $("#readytopay").modal('hide');
                    $("#result").modal();
                    $("#msg").html(data.msg+"  发生了错误。");
                }
            })
        }); 

mark

HTML部分增加

                    <div aria-hidden="true" class="modal modal-va-middle fade" id="readytopay" role="dialog" tabindex="-1">
                        <div class="modal-dialog modal-xs">
                            <div class="modal-content">
                                <div class="modal-heading">
                                    <a class="modal-close" data-dismiss="modal">×</a>
                                    <h2 class="modal-title">正在连接支付宝</h2>
                                </div>
                                <div class="modal-inner">
                                    <p id="title">正在处理...</p>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div aria-hidden="true" class="modal modal-va-middle fade" id="alipay" role="dialog" tabindex="-1">
                        <div class="modal-dialog modal-xs">
                            <div class="modal-content">
                                <div class="modal-heading">
                                    <a class="modal-close" data-dismiss="modal">×</a>
                                    <h2 class="modal-title">请使用支付宝App扫码充值:</h2>
                                </div>
                                <div class="modal-inner">
                                    <p id="title">手机点击二维码转跳支付宝</p>
                                    <p id="divide">-------------------------------------------------------------</p>
                                    <p id="qrcode"></p>
                                    <p id="info"></p>
                                </div>

                                <div class="modal-footer">
                                    <p class="text-right"><button class="btn btn-flat btn-brand waves-attach" data-dismiss="modal" id="alipay_cancel" type="button">取消</button></p>
                                </div>
                            </div>
                        </div>
                    </div>
附录
  • f2f金额自定义设置
    pay.php 修改 f2fpay_html 函数
    mark
    return 改成
                        <p class="card-heading">使用支付宝充值</p>
                        <label for="number">请选择充值金额:</label>
                        <form class="form-control" name="amount">
                        <input id="type" type="number" name="amount" />
                        <a class="btn btn-flat waves-attach" id="urlChange" ><span class="icon">check</span> 充值</a>
                        </form>

mark
效果
mark

                        <p class="card-heading"><font color="red">使用支付宝充值(推荐)</font></p>
                        <p>使用支付宝充值,支持自定义充值金额</p>
                        <div class="form-group form-group-label">
                            <label class="floating-label" for="number">请输入充值金额</label>
                            <input class="form-control" id="type" type="text" name="amount">
                        </div>
                        <p></p>
                        <div class="card-action-btn">
                            <p id="checkin-btn">
                                <button id="urlChange" class="btn btn-block btn-brand waves-attach waves-light waves-effect">使用支付宝充值</button>
                            </p>
                        </div>

效果图
mark

当然别忘了修改 网站根目录/resources/views/material/user/code.tpl
将第224行的

                        amount: $("#type").find("option:selected").val()

替换为

                        amount: $("#type").val()
可以转载,注明出处。91vps » 原版sspanelv3增加当面付模块教程 | 设置f2fpay自定义金额

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址