【独角数卡】增加API接口

前言

因为要写个机器人,又不想让机器人直接操作数据库,所以给发卡加了api接口。

修改过程

新增文件

routes/common/api.php

<?php
/**
 * The file was created by Virgo.
 *
 * @author    virgo
 * @copyright virgo
 * @link      http://vxv.tw/
 */

use Illuminate\Support\Facades\Route;


Route::group(['middleware' => ['vxv.api'], 'namespace' => 'Api'], function () {
    // 首页
    Route::get('api/goodsGroups', 'ApiController@goodsGroups');
    Route::get('api/goodsGroups/{goodsGroupsId}/goods', 'ApiController@goods');
    Route::get('api/goods/{goodsId}', 'ApiController@goods_info');
    Route::post('api/createOrder', 'ApiController@create_order');

    Route::get('api/epusdt/{payway}/{orderSN}', 'Pay\EpusdtController@gateway');
    Route::post('api/epusdt/notify_url', 'EpusdtController@notifyUrl');
    Route::get('api/epusdt/return_url', 'EpusdtController@returnUrl')->name('epusdt-return');
});

app/Http/Controllers/Api/ApiController.php

<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\RuleValidationException;
use App\Http\Controllers\Controller;
use App\Models\Carmis;
use App\Models\Goods;
use App\Models\GoodsGroup;
use App\Models\TelegramOrder;
use App\Service\OrderProcessService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ApiController extends Controller
{

    /**
     * 商品服务层.
     * @var \App\Service\GoodsService
     */
    private $goodsService;
    /**
     * 支付服务层
     * @var \App\Service\PayService
     */
    private $payService;
    /**
     * 订单服务层
     * @var \App\Service\OrderService
     */
    private $orderService;
    /**
     * 订单处理层.
     * @var OrderProcessService
     */
    private $orderProcessService;

    public function __construct()
    {
        $this->goodsService = app('Service\GoodsService');
        $this->payService = app('Service\PayService');
        $this->orderService = app('Service\OrderService');
        $this->orderProcessService = app('Service\OrderProcessService');
    }

    public function goodsGroups(Request $request)
    {
        $goodsGroups = GoodsGroup::query()->get();
        $goodsGroups = $goodsGroups ? $goodsGroups->toArray() : [];
        return ["code" => 200, "msg" => 'ok', 'data' => $goodsGroups];
    }

    public function goods(Request $request, int $goodsGroupsId)
    {
        $goodsGroups = GoodsGroup::query()->get();
        $goods = Goods::query()->where('group_id', $goodsGroupsId)
            ->withCount(['carmis' => function ($query) {
                $query->where('status', Carmis::STATUS_UNSOLD);
            }])
            ->where('is_open', Goods::STATUS_OPEN)
            ->orderBy('ord', 'DESC')->get();

        $goodsGroups = $goodsGroups ? $goodsGroups->toArray() : [];
        return ["code" => 200, "msg" => 'ok', 'data' => $goods];
    }

    public function goods_info(Request $request, int $goodsId)
    {
        $goods = $this->goodsService->detail($goodsId);
        return ["code" => 200, "msg" => 'ok', 'data' => $goods];
    }

    public function create_order(Request $request)
    {

        $telegram_user_id = $request->input('telegram_user_id');
        DB::beginTransaction();
        try {
            $goods = $this->orderService->validatorGoods($request);
            $this->orderService->validatorLoopCarmis($request);
            // 设置商品
            $this->orderProcessService->setGoods($goods);
            $otherIpt = $this->orderService->validatorChargeInput($goods, $request);
            // 数量
            $this->orderProcessService->setBuyAmount($request->input('by_amount'));
            // 支付方式
            $this->orderProcessService->setPayID($request->input('payway'));
            // 下单邮箱
            $this->orderProcessService->setEmail($request->input("email"));
            // ip地址
            $this->orderProcessService->setBuyIP($request->getClientIp());
            // 查询密码
            $this->orderProcessService->setSearchPwd($request->input('search_pwd', ''));
            // 创建订单
            $order = $this->orderProcessService->createOrder();
            $tgOrder = new TelegramOrder();
            $tgOrder->telegram_user_id = $telegram_user_id;
            $tgOrder->order_id = $order['id'];
            $tgOrder->save();
            DB::commit();
            return response()->json(['code' => 200, 'msg' => 'ok', 'data' => ['orderSN' => $order->order_sn]]);
        } catch (RuleValidationException $exception) {
            DB::rollBack();
            return $this->err($exception->getMessage());
        }
    }


    protected function render(string $tpl, $data = [], string $pageTitle = '')
    {
        $layout = dujiaoka_config_get('template', 'unicorn');
        $tplPath = $layout . '/' . $tpl;
        return response()->json(['code' => 400, 'msg' => 'error']);
    }

    protected function err(string $content, $jumpUri = '')
    {
        return ['code' => 400, 'msg' => 'error'];
    }
}

app/Http/Controllers/Api/Pay/EpusdtController.php

<?php

namespace App\Http\Controllers\Api\Pay;


use App\Exceptions\RuleValidationException;
use App\Http\Controllers\Api\PayController;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;

class EpusdtController extends PayController
{
    public function gateway(string $payway, string $orderSN)
    {
        try {

            // 加载网关
            $this->loadGateWay($orderSN, $payway);

            //构造要请求的参数数组,无需改动
            $parameter = [
                "amount" => (float)$this->order->actual_price,//原价
                "order_id" => $this->order->order_sn, //可以是用户ID,站内商户订单号,用户名
                'redirect_url' => route('epusdt-return', ['order_id' => $this->order->order_sn]),
                'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
            ];
            $parameter['signature'] = $this->epusdtSign($parameter, $this->payGateway->merchant_id);
            $client = new Client([
                'headers' => ['Content-Type' => 'application/json']
            ]);

            $response = $client->post($this->payGateway->merchant_pem, ['body' => json_encode($parameter)]);

            $body = json_decode($response->getBody()->getContents(), true);

            if (!isset($body['status_code']) || $body['status_code'] != 200) {
                return api_response_error(400, $body['message']);
            }
            return api_response_success("ok", $body);
        } catch (RuleValidationException $exception) {
        } catch (GuzzleException $exception) {
            return api_response_error(400, $exception->getMessage());
        }
    }


    private function epusdtSign(array $parameter, string $signKey)
    {
        ksort($parameter);
        reset($parameter); //内部指针指向数组中的第一个元素
        $sign = '';
        $urls = '';
        foreach ($parameter as $key => $val) {
            if ($val == '') continue;
            if ($key != 'signature') {
                if ($sign != '') {
                    $sign .= "&";
                    $urls .= "&";
                }
                $sign .= "$key=$val"; //拼接为url参数形式
                $urls .= "$key=" . urlencode($val); //拼接为url参数形式
            }
        }
        $sign = md5($sign . $signKey);//密码追加进入开始MD5签名
        return $sign;
    }

    public function notifyUrl(Request $request)
    {
        $data = $request->all();
        $order = $this->orderService->detailOrderSN($data['order_id']);
        if (!$order) {
            return 'fail';
        }
        $payGateway = $this->payService->detail($order->pay_id);
        if (!$payGateway) {
            return 'fail';
        }
        if ($payGateway->pay_handleroute != 'pay/epusdt') {
            return 'fail';
        }
        $signature = $this->epusdtSign($data, $payGateway->merchant_id);
        if ($data['signature'] != $signature) { //不合法的数据
            return 'fail';  //返回失败 继续补单
        } else {
            //合法的数据
            //业务处理
            $this->orderProcessService->completedOrder($data['order_id'], $data['amount'], $data['trade_id']);
            return 'ok';
        }
    }

    public function returnUrl(Request $request)
    {
        $oid = $request->get('order_id');
        // 异步通知还没到就跳转了,所以这里休眠2秒
        sleep(2);
        return redirect(url('detail-order-sn', ['orderSN' => $oid]));
    }

}

app/Http/Controllers/Api/PayController.php

<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\RuleValidationException;
use App\Models\Order;
use App\Service\OrderProcessService;
use App\Http\Controllers\Controller;

class PayController extends Controller
{

    /**
     * 支付网关
     * @var \App\Models\Pay
     */
    protected $payGateway;


    /**
     * 订单
     * @var \App\Models\Order
     */
    protected $order;

    /**
     * 订单服务层
     * @var \App\Service\OrderService
     */
    protected $orderService;

    /**
     * 支付服务层
     * @var \App\Service\PayService
     */
    protected $payService;

    /**
     * 订单处理层.
     * @var OrderProcessService
     */
    protected $orderProcessService;


    public function __construct()
    {
        $this->orderService = app('Service\OrderService');
        $this->payService = app('Service\PayService');
        $this->orderProcessService = app('Service\OrderProcessService');
    }

    /**
     * 订单检测
     *
     * @param string $orderSN
     * @throws RuleValidationException
     *
     * @author    assimon<ashang@utf8.hk>
     * @copyright assimon<ashang@utf8.hk>
     * @link      http://utf8.hk/
     */
    public function checkOrder(string $orderSN)
    {
        // 订单
        $this->order = $this->orderService->detailOrderSN($orderSN);
        if (!$this->order) {
            throw new RuleValidationException(__('dujiaoka.prompt.order_does_not_exist'));
        }
        // 订单过期
        if ($this->order->status == Order::STATUS_EXPIRED) {
            throw new RuleValidationException(__('dujiaoka.prompt.order_is_expired'));
        }
        // 已经支付了
        if ($this->order->status > Order::STATUS_WAIT_PAY) {
            throw new RuleValidationException(__('dujiaoka.prompt.order_already_paid'));
        }
    }

    /**
     * 加载支付网关
     *
     * @param string $orderSN 订单号
     * @param string $payCheck 支付标识
     * @throws RuleValidationException
     *
     * @author    assimon<ashang@utf8.hk>
     * @copyright assimon<ashang@utf8.hk>
     * @link      http://utf8.hk/
     */
    public function loadGateWay(string $orderSN, string $payCheck)
    {
        $this->checkOrder($orderSN);
        // 支付配置
        $this->payGateway = $this->payService->detailByCheck($payCheck);
        if (!$this->payGateway) {
            throw new RuleValidationException(__('dujiaoka.prompt.pay_gateway_does_not_exist'));
        }
        // 临时保存支付方式
        $this->order->pay_id = $this->payGateway->id;
        $this->order->save();
    }

    /**
     * 网关处理.
     *
     * @param string $handle 跳转方法
     * @param string $payway 支付标识
     * @param string $orderSN 订单.
     *
     * @author    assimon<ashang@utf8.hk>
     * @copyright assimon<ashang@utf8.hk>
     * @link      http://utf8.hk/
     */
    public function redirectGateway(string $handle,string $payway, string $orderSN)
    {
        try {
            $this->checkOrder($orderSN);
            $bccomp = bccomp($this->order->actual_price, 0.00, 2);
            // 如果订单金额为0 代表无需支付,直接成功
            if ($bccomp == 0) {
                $this->orderProcessService->completedOrder($this->order->order_sn, 0.00);
                return redirect(url('detail-order-sn', ['orderSN' => $this->order->order_sn]));
            }
            return redirect(url(urldecode($handle), ['payway' => $payway, 'orderSN' => $orderSN]));
        } catch (RuleValidationException $exception) {
            return $this->err($exception->getMessage());
        }

    }

}

app/Models/TelegramOrder.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\SoftDeletes;

class TelegramOrder extends BaseModel
{

    use SoftDeletes;

    protected $table = 'telegram_order';


    /**
     * 关联商品
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     *
     * @author    assimon<ashang@utf8.hk>
     * @copyright assimon<ashang@utf8.hk>
     * @link      http://utf8.hk/
     */
    public function order()
    {
        return $this->belongsTo(Order::class, 'order_id');
    }

}

app/Jobs/TgFakaBot.php

<?php

namespace App\Jobs;

use App\Models\Order;
use App\Models\TelegramOrder;
use GuzzleHttp\Client;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;


class TgFakaBot implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * 任务最大尝试次数。
     *
     * @var int
     */
    public $tries = 1;

    /**
     * 任务运行的超时时间。
     *
     * @var int
     */
    public $timeout = 30;

    /**
     * @var Order
     */
    private $order;

    /**
     * 商品服务层.
     * @var \App\Service\GoodsService
     */
    private $goodsService;


    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
        $this->goodsService = app('Service\GoodsService');
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $tgOrder = TelegramOrder::query()->where('order_id', $this->order['id'])->first();
        $goodInfo = $this->goodsService->detail($this->order->goods_id);
        $formatText = '*' . '支付成功通知' . '(' . $this->order->actual_price . '元)*%0A'
            . __('order.fields.order_id') . ': `' . $this->order->id . '`%0A'
            . __('order.fields.order_sn') . ': `' . $this->order->order_sn . '`%0A'
            . __('order.fields.pay_id') . ': `' . $this->order->pay->pay_name . '`%0A'
            . __('order.fields.title') . ': ' . $this->order->title . '%0A'
            . __('order.fields.actual_price') . ': ' . $this->order->actual_price . '%0A'
            . __('goods.fields.gd_name') . ': `' . $goodInfo->gd_name . '`%0A'
            . __('order.fields.order_created') . ': ' . $this->order->created_at. '%0A'
            . "卡密信息". '%0A'
            . "```". '%0A'
            . $this->order['info']. '%0A'
            . "```";
        $client = new Client([
            'timeout' => 30,
            'proxy' => '127.0.0.1:7890'
        ]);
        Log::info(dujiaoka_config_get('telegram_bot_token'));
        $apiUrl = 'https://api.telegram.org/bot' . dujiaoka_config_get('telegram_bot_token') .
            '/sendMessage?chat_id=' . $tgOrder->telegram_user_id . '&parse_mode=Markdown&text=' . $formatText;
        Log::info($apiUrl);
        $client->post($apiUrl);
    }

}

修改原有代码文件

app/Helpers/functions.php

在代码末尾插入以下代码

if (!function_exists('api_response_build')) {
    function api_response_build(int $code, string $msg, $data = null)
    {
        return response()->json(['code' => $code, 'msg' => $msg, 'data' => $data]);
    }
}

if (!function_exists('api_response_success')) {
    function api_response_success(string $msg = 'ok', $data = null)
    {
        return ['code' => 200, 'msg' => $msg, 'data' => $data];
    }
}

if (!function_exists('api_response_error')) {
    function api_response_error(int $code = 400, string $msg = 'error', $data = null)
    {
        return response()->json(['code' => $code, 'msg' => $msg, 'data' => $data]);
    }
}

app/Exceptions/Handler.php

图片[1]-【独角数卡】增加API接口-LShare

在红框位置处插入如下代码

if (str_starts_with($request->path(), "api/")) {
            return response()->json(['code' => 400, 'msg' => $exception->getMessage()]);
        }

app/Service/OrderProcessService.php

图片[2]-【独角数卡】增加API接口-LShare

在头部加上引用代码

use App\Jobs\TgFakaBot;

然后找到这个函数

图片[3]-【独角数卡】增加API接口-LShare

ApiHook::dispatch($order); 前面添加如下代码

图片[4]-【独角数卡】增加API接口-LShare
// 发卡机器人推送订单信息
            TgFakaBot::dispatch($order);

app/Http/Middleware/VerifyCsrfToken.php

直接在这加一个 'api/*'

图片[5]-【独角数卡】增加API接口-LShare

接口

[获取全部分类] – GET /api/goodsGroups

[获取分类下商品] – GET /api/goodsGroups/2/goods

2为分组的id

[获取商品详情] – GET /api/goods/2

2为商品的id

[创建订单] – POST /api/createOrder

请求头

keyvalue
Content-Typeapplication/x-www-form-urlencoded
请求内容
字段名示例值描述
gid2商品id
emailaaa@gmail.com下单邮箱
by_amount1固定为1
payway27支付方式
telegram_user_id1405597912telegram用户id

[获取支付信息] – GET /api/epusdt/epusdt/K7WQDNWGI2N3DXJ3

K7WQDNWGI2N3DXJ3 替换为上一步创建订单得到的订单号

© 版权声明
THE END
喜欢就支持一下吧
点赞1 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容