feat: 接入 CCpay 第三支付通道(越南银行QR代收)
- extend/pay/Ccpay.php: SDK封装(签名/验签/下单/查询) - traits/ccpayPay.php: 下单/回调/结算/轮询,pay_channel_id=9 - config.php: pay_list 加 ccpay 配置 - Pcapi/Order: 注册 ccpayPay trait
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
namespace pay;
|
||||
|
||||
use think\Db;
|
||||
|
||||
class Ccpay
|
||||
{
|
||||
private $config;
|
||||
private $apiUrl;
|
||||
private $mchNo;
|
||||
private $paySecret;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = config('pay_list.ccpay') ?: [];
|
||||
$this->apiUrl = $this->config['api_url'] ?? '';
|
||||
$this->mchNo = $this->config['mch_no'] ?? '';
|
||||
$this->paySecret = $this->config['pay_secret'] ?? '';
|
||||
}
|
||||
|
||||
public function getConfigInfo()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function generateSign(array $params)
|
||||
{
|
||||
unset($params['sign']);
|
||||
ksort($params);
|
||||
$str = '';
|
||||
foreach ($params as $k => $v) {
|
||||
if (is_string($v) && strlen($v) > 0) {
|
||||
$str .= "{$k}={$v}&";
|
||||
}
|
||||
}
|
||||
$str = substr($str, 0, -1) . '&paySecret=' . $this->paySecret;
|
||||
return strtoupper(md5($str));
|
||||
}
|
||||
|
||||
public function verifySign(array $params)
|
||||
{
|
||||
$received = $params['sign'] ?? '';
|
||||
if (!$received) return false;
|
||||
$calculated = $this->generateSign($params);
|
||||
return hash_equals($calculated, $received);
|
||||
}
|
||||
|
||||
public function createOrder($orderNo, $amount, $notifyUrl, $memberId = 'og_user', $callbackUrl = '')
|
||||
{
|
||||
$extra = [
|
||||
'bankType' => 'OFFLINE',
|
||||
'cardType' => '0',
|
||||
'orderPeriod' => '30',
|
||||
'memberId' => $memberId,
|
||||
'merchantName' => 'OG',
|
||||
'notifyUrl' => $notifyUrl,
|
||||
'callbackUrl' => $callbackUrl,
|
||||
];
|
||||
|
||||
$data = [
|
||||
'tradeType' => 'cs.pay.submit',
|
||||
'version' => '2.0',
|
||||
'channel' => 'union_pay',
|
||||
'mchNo' => $this->mchNo,
|
||||
'body' => 'online_pay',
|
||||
'mchOrderNo' => $orderNo,
|
||||
'amount' => strval(intval($amount)),
|
||||
'currency' => 'VND',
|
||||
'timePaid' => date('YmdHis'),
|
||||
'remark' => 'online-pay',
|
||||
];
|
||||
|
||||
$signParams = array_merge($data, $extra);
|
||||
$data['sign'] = $this->generateSign($signParams);
|
||||
$data['extra'] = json_encode($extra);
|
||||
|
||||
addLogToFile('ccpay 下单请求: order=' . $orderNo . ' amount=' . $amount . ' params=' . json_encode($data, JSON_UNESCAPED_UNICODE), 'ccpay_request', 'ccpay');
|
||||
|
||||
$result = $this->postForm($this->apiUrl, $data);
|
||||
|
||||
addLogToFile('ccpay 下单返回: ' . json_encode($result, JSON_UNESCAPED_UNICODE), 'ccpay_response', 'ccpay');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function queryOrder($orderNo)
|
||||
{
|
||||
$data = [
|
||||
'tradeType' => 'cs.order.query',
|
||||
'version' => '2.0',
|
||||
'mchNo' => $this->mchNo,
|
||||
'mchOrderNo' => $orderNo,
|
||||
];
|
||||
$data['sign'] = $this->generateSign($data);
|
||||
|
||||
return $this->postForm($this->apiUrl, $data);
|
||||
}
|
||||
|
||||
private function postForm($url, $params)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
$body = '';
|
||||
foreach ($params as $k => $v) {
|
||||
if (!is_string($v)) continue;
|
||||
$body .= $k . '=' . urlencode($v) . '&';
|
||||
}
|
||||
$body = rtrim($body, '&');
|
||||
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'],
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
]);
|
||||
|
||||
$resp = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($resp === false) {
|
||||
addLogToFile("ccpay curl 失败: code={$code} err={$err}", 'ccpay_error', 'ccpay');
|
||||
return null;
|
||||
}
|
||||
|
||||
return json_decode($resp, true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user