XBoard, V2Board

将以下内容写入USDTPay.php, 并放到app/Payment 目录下。

<?php

namespace App\Payments;

use App\Exceptions\ApiException;

class UsdtPay
{
    protected $config;
    public function __construct($config)
    {
        $this->config = $config;
    }

    public function form()
    {
        return [
            'app_secret' => [
                'label' => '通信密钥',
                'description' => 'API Secret',
                'type' => 'input',
            ],
            'expire' => [
                'label' => '订单过期时间',
                'description' => '订单过期时间,单位秒, 默认为3600秒',
                'type' => 'input',
            ],
            'api_url' => [
                'label' => '接口入口',
                'description' => '',
                'type' => 'input'
            ],
            'ui_url' => [
                'label' => 'UI地址',
                'description' => '',
                'type' => 'input'
            ],
            'mch_id' => [
                'label' => 'MCHID',
                'description' => '随便填一个,反正是独立部署的',
                'type' => 'input'
            ],
            'pay_memo' => [
                'label' => '支付描述',
                'description' => '支付描述',
                'type' => 'input'
            ],
            'logo' => [
                'label' => 'Logo',
                'description' => '(Optional)',
                'type' => 'input'
            ]
        ];
    }

    public function pay($order)
    {
        $expire = $this->config['expire'] ?? 3600;
        $data = [
            'oid' => $order['trade_no'],
            'uid' => $order['user_id'],
            'amount' => sprintf('%.2f', $order['total_amount'] / 100),
            'memo' => $this->config['pay_memo'],
            'expiredAt' => (time() + $expire) * 1000,
            'timestamp' => time() * 1000,
            'nonce' => rand(10000000, 99999999),
            'mchId' => $this->config['mch_id'],
            'notifyUrl' => $order['notify_url'],
            'redirectUrl' => $order['return_url']
        ];

        // if logo
        if (!empty($this->config['logo'])) {
            $data['logo'] = $this->config['logo'];
        }

        $data['sign'] = $this->sign($data);
        $url = $this->config['api_url'] . '/api/v1/order';
        $response = $this->post($url, $data);
        // if not 200
        if (empty($response)) {
            throw new ApiException('request error');
        }

        $resp = json_decode($response, true);
        if ($resp['code'] != 1) {
            throw new ApiException($resp['msg']);
        }
        $jumpUrl = $this->config['ui_url'] . '/?id=' . $resp['data']['id'];
        return [
            'type' => 1, // 1 means redirect to url, 0 means qrcode
            'data' => $jumpUrl
        ];
    }

    public function notify($params)
    {
        $payload = trim(get_request_content());
        if (empty($payload)) {
            throw new ApiException('request error');
        }

        $json_params = json_decode($payload, true);

        $data = [
            'id' => $json_params['id'],
            'oid' => $json_params['oid'],
            'uid' => $json_params['uid'],
            'timestamp' => $json_params['timestamp'],
            'nonce' => $json_params['nonce'],
            'status' => $json_params['status'],
            'statusCode' => $json_params['statusCode']
        ];

        $sign = $this->sign($data);
        if ($sign != $json_params['sign']) {
            throw new ApiException('sign error');
        }

        if ($json_params['status'] == 'PAID') {
            return [
                'trade_no' => $data['oid'],
                'callback_no' => $data['id'],
            ];
        } else {
            return false;
        }
    }

    public function sign($data)
    {
        ksort($data);
        $str = '';

        // join $data with $key=$value&$key=$value
        foreach ($data as $key => $value) {
            $str .= $key . '=' . $value . '&';
        }
        //remove the last &
        $str = substr($str, 0, -1);
        $str .= $this->config['app_secret'];
        // sha256
        return hash('sha256', $str);
    }

    public function post($url, $data)
    {
        $jsonData = json_encode($data);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($jsonData)
        ]);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);


        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}

根据实际情况在配置页面填写对应的配置项,通信密钥填写安装服务器时候生成配置的通信密钥。

Last updated