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