添加虚拟支付
This commit is contained in:
@@ -5,13 +5,14 @@ namespace app\api\controller;
|
||||
use app\common\controller\Api;
|
||||
use app\common\service\OrderService;
|
||||
use app\common\service\ToolService;
|
||||
use app\common\service\VirtualPayService;
|
||||
use think\Exception;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Log;
|
||||
|
||||
class Order extends Api
|
||||
{
|
||||
protected $noNeedLogin = ['payNotify', 'detail'];
|
||||
protected $noNeedLogin = ['payNotify', 'virtualPayNotify', 'detail'];
|
||||
protected $noNeedRight = ['*'];
|
||||
|
||||
/**
|
||||
@@ -296,6 +297,143 @@ class Order extends Api
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 虚拟支付收银台成功后确认入账
|
||||
* @ApiMethod (POST)
|
||||
*/
|
||||
public function virtualPayConfirm()
|
||||
{
|
||||
try {
|
||||
$orderNo = $this->request->post('orderNo', '');
|
||||
if (!$orderNo) {
|
||||
$this->error('订单号不能为空');
|
||||
}
|
||||
$res = OrderService::confirmVirtualPay($orderNo, $this->auth->id);
|
||||
$this->success('支付成功', $res);
|
||||
} catch (\Exception $e) {
|
||||
if ($e instanceof HttpResponseException) {
|
||||
throw $e;
|
||||
}
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 虚拟支付消息推送。MP 后台消息推送 URL 填本接口,明文模式即可
|
||||
*/
|
||||
public function virtualPayNotify()
|
||||
{
|
||||
$echostr = (string)$this->request->get('echostr', '');
|
||||
if ($echostr !== '') {
|
||||
try {
|
||||
$this->assertVirtualPaySignature();
|
||||
} catch (\Exception $e) {
|
||||
Log::error('虚拟支付消息验签失败 ' . $e->getMessage());
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
echo $echostr;
|
||||
exit;
|
||||
}
|
||||
|
||||
$raw = trim((string)$this->request->getInput());
|
||||
$asJson = strpos($raw, '{') === 0;
|
||||
Log::info('虚拟支付推送[进入] ' . $raw);
|
||||
try {
|
||||
$payload = $this->parseVirtualPayBody($raw);
|
||||
if (!empty($payload['Encrypt'])) {
|
||||
$plain = VirtualPayService::decryptMessage(
|
||||
(string)$payload['Encrypt'],
|
||||
(string)$this->request->get('msg_signature', ''),
|
||||
(string)$this->request->get('nonce', ''),
|
||||
(string)$this->request->get('timestamp', '')
|
||||
);
|
||||
$payload = $this->parseVirtualPayBody($plain);
|
||||
} else {
|
||||
$this->assertVirtualPaySignature();
|
||||
}
|
||||
$reply = VirtualPayService::handleMessage($payload);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('虚拟支付推送处理失败 ' . $e->getMessage());
|
||||
$message = $e->getMessage();
|
||||
if (strpos($message, '订单不存在') !== false || strpos($message, '获取订单数据失败') !== false) {
|
||||
$reply = ['ErrCode' => 0, 'ErrMsg' => 'success'];
|
||||
} else {
|
||||
$reply = ['ErrCode' => 1, 'ErrMsg' => $message];
|
||||
}
|
||||
}
|
||||
$this->replyVirtualPay(isset($reply) ? $reply : ['ErrCode' => 1, 'ErrMsg' => 'fail'], $asJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验消息推送签名
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function assertVirtualPaySignature()
|
||||
{
|
||||
$token = (string)config('common.virtual_pay.msg_token');
|
||||
if ($token === '') {
|
||||
throw new \Exception('未配置虚拟支付消息令牌');
|
||||
}
|
||||
$parts = [
|
||||
$token,
|
||||
(string)$this->request->get('timestamp', ''),
|
||||
(string)$this->request->get('nonce', ''),
|
||||
];
|
||||
sort($parts, SORT_STRING);
|
||||
if (sha1(implode($parts)) !== (string)$this->request->get('signature', '')) {
|
||||
throw new \Exception('消息签名校验失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $raw
|
||||
* @return array
|
||||
*/
|
||||
private function parseVirtualPayBody($raw)
|
||||
{
|
||||
$raw = trim((string)$raw);
|
||||
if ($raw === '') {
|
||||
return [];
|
||||
}
|
||||
if ($raw[0] === '{') {
|
||||
$data = json_decode($raw, true);
|
||||
return is_array($data) ? $data : [];
|
||||
}
|
||||
$xml = simplexml_load_string($raw, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NONET);
|
||||
if (!$xml) {
|
||||
return [];
|
||||
}
|
||||
$data = json_decode(json_encode($xml), true);
|
||||
|
||||
return is_array($data) ? $data : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param bool $asJson
|
||||
*/
|
||||
private function replyVirtualPay(array $data, $asJson)
|
||||
{
|
||||
if ($asJson) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
header('Content-Type: text/xml; charset=utf-8');
|
||||
$xml = '<xml>';
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_int($value) || is_float($value)) {
|
||||
$xml .= '<' . $key . '>' . $value . '</' . $key . '>';
|
||||
} else {
|
||||
$xml .= '<' . $key . '><![CDATA[' . $value . ']]></' . $key . '>';
|
||||
}
|
||||
}
|
||||
$xml .= '</xml>';
|
||||
echo $xml;
|
||||
exit;
|
||||
}
|
||||
|
||||
public function businessTime()
|
||||
{
|
||||
$res = [
|
||||
|
||||
Reference in New Issue
Block a user