177 行
6.5 KiB
PHP
177 行
6.5 KiB
PHP
<?php
|
|
class CodePayGateway implements PaymentGatewayInterface
|
|
{
|
|
private $type;
|
|
private $gateway;
|
|
private $pid;
|
|
private $key;
|
|
private $lastHttpCode = 0;
|
|
private $lastRaw = '';
|
|
private $lastError = '';
|
|
public function __construct()
|
|
{
|
|
$this->type = getSetting('pay_codepay_type', 'epay');
|
|
$this->gateway = rtrim(getSetting('pay_codepay_url', ''), '/');
|
|
$this->pid = getSetting('pay_codepay_pid', '');
|
|
$this->key = getSetting('pay_codepay_key', '');
|
|
}
|
|
public function getName()
|
|
{
|
|
return '码支付/易支付';
|
|
}
|
|
public function getType() { return $this->type; }
|
|
public function getGateway() { return $this->gateway; }
|
|
public function getPid() { return $this->pid; }
|
|
public function createOrder(array $order)
|
|
{
|
|
$outTradeNo = $order['order_no'];
|
|
$money = sprintf('%.2f', (float) ($order['amount'] ?? 0));
|
|
$name = $order['subject'] ?? '积分充值';
|
|
$notify = $order['notify_url'] ?? '';
|
|
$return = $order['return_url'] ?? '';
|
|
$channel = $order['channel'] ?? 'alipay';
|
|
if ($this->type === 'codepay') {
|
|
return $this->createCodePay($outTradeNo, $money, $name, $notify, $return, $channel);
|
|
}
|
|
return $this->createEpay($outTradeNo, $money, $name, $notify, $return, $channel);
|
|
}
|
|
private function createEpay($outTradeNo, $money, $name, $notify, $return, $channel)
|
|
{
|
|
$typeMap = ['alipay' => 'alipay', 'wxpay' => 'wepay', 'qq' => 'qq'];
|
|
$type = $typeMap[$channel] ?? 'alipay';
|
|
$params = [
|
|
'pid' => $this->pid,
|
|
'type' => $type,
|
|
'out_trade_no' => $outTradeNo,
|
|
'notify_url' => $notify,
|
|
'return_url' => $return,
|
|
'name' => $name,
|
|
'money' => $money,
|
|
];
|
|
$params['sign'] = $this->epaySign($params);
|
|
$params['sign_type'] = 'MD5';
|
|
$url = $this->gateway . '/submit.php?' . http_build_query($params);
|
|
return ['url' => $url, 'form' => ''];
|
|
}
|
|
private function createCodePay($outTradeNo, $money, $name, $notify, $return, $channel)
|
|
{
|
|
$typeMap = ['alipay' => '1', 'wxpay' => '2', 'qq' => '3'];
|
|
$type = $typeMap[$channel] ?? '1';
|
|
$param = $outTradeNo;
|
|
$params = [
|
|
'id' => $this->pid,
|
|
'pay_id' => $outTradeNo,
|
|
'price' => $money,
|
|
'param' => $param,
|
|
'type' => $type,
|
|
'notify_url' => $notify,
|
|
'return_url' => $return,
|
|
];
|
|
$params['sign'] = $this->codepaySign($params);
|
|
$params['sign_type'] = 'MD5';
|
|
$url = $this->gateway . '/codepay_gateway?' . http_build_query($params);
|
|
return ['url' => $url, 'form' => ''];
|
|
}
|
|
private function epaySign($params)
|
|
{
|
|
$data = $params;
|
|
unset($data['sign'], $data['sign_type']);
|
|
ksort($data);
|
|
$str = '';
|
|
foreach ($data as $k => $v) {
|
|
$str .= $k . '=' . $v . '&';
|
|
}
|
|
$str = rtrim($str, '&') . $this->key;
|
|
return md5($str);
|
|
}
|
|
private function codepaySign($params)
|
|
{
|
|
$str = $this->pid . $params['price'] . $params['type'] . $params['param'] . $this->key;
|
|
return md5($str);
|
|
}
|
|
public function verifyNotify(array $params)
|
|
{
|
|
if ($this->type === 'codepay') {
|
|
$calc = md5($this->pid . ($params['price'] ?? '') . ($params['type'] ?? '') . ($params['param'] ?? '') . $this->key);
|
|
return hash_equals($calc, (string) ($params['sign'] ?? ''));
|
|
}
|
|
$data = $params;
|
|
unset($data['sign'], $data['sign_type']);
|
|
ksort($data);
|
|
$str = '';
|
|
foreach ($data as $k => $v) {
|
|
$str .= $k . '=' . $v . '&';
|
|
}
|
|
$str = rtrim($str, '&') . $this->key;
|
|
return hash_equals(md5($str), (string) ($params['sign'] ?? ''));
|
|
}
|
|
public function getTradeNo(array $params)
|
|
{
|
|
return $params['trade_no'] ?? ($params['pay_no'] ?? ($params['param'] ?? ''));
|
|
}
|
|
public function isPaid(array $params)
|
|
{
|
|
if ($this->type === 'codepay') {
|
|
return ($params['trade_status'] ?? '') === 'TRADE_SUCCESS'
|
|
|| ($params['status'] ?? '') === '1'
|
|
|| isset($params['pay_no']);
|
|
}
|
|
return ($params['trade_status'] ?? '') === 'TRADE_SUCCESS'
|
|
|| ($params['status'] ?? '') === 'success';
|
|
}
|
|
public function respondSuccess()
|
|
{
|
|
echo $this->type === 'epay' ? 'success' : 'ok';
|
|
exit;
|
|
}
|
|
private function post($url, $params)
|
|
{
|
|
$this->lastHttpCode = 0;
|
|
$this->lastRaw = '';
|
|
$this->lastError = '';
|
|
$body = http_build_query($params);
|
|
if (function_exists('curl_init')) {
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $body,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 20,
|
|
CURLOPT_CONNECTTIMEOUT => 15,
|
|
CURLOPT_FOLLOWLOCATION => true,
|
|
CURLOPT_MAXREDIRS => 3,
|
|
CURLOPT_SSL_VERIFYPEER => false,
|
|
CURLOPT_SSL_VERIFYHOST => false,
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
|
|
]);
|
|
$r = curl_exec($ch);
|
|
$this->lastHttpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
if ($r === false) {
|
|
$this->lastError = curl_error($ch);
|
|
$r = '';
|
|
}
|
|
curl_close($ch);
|
|
$this->lastRaw = (string) $r;
|
|
return (string) $r;
|
|
}
|
|
$ctx = stream_context_create(['http' => [
|
|
'method' => 'POST',
|
|
'header' => 'Content-Type: application/x-www-form-urlencoded',
|
|
'content' => $body,
|
|
'timeout' => 20,
|
|
'follow_location' => true,
|
|
'max_redirects' => 3,
|
|
]]);
|
|
$r = @file_get_contents($url, false, $ctx);
|
|
if ($r === false) {
|
|
$this->lastError = 'file_get_contents failed';
|
|
$r = '';
|
|
}
|
|
$this->lastRaw = (string) $r;
|
|
return (string) $r;
|
|
}
|
|
public function getLastHttpCode() { return $this->lastHttpCode; }
|
|
public function getLastRaw() { return $this->lastRaw; }
|
|
public function getLastError() { return $this->lastError; }
|
|
}
|