支付宝记账本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

221 lines
5.7 KiB

<?php
namespace App\Services;
use App\Libs\AppException;
use App\Models\MchApp;
class OutService
{
/**
* 生成签名
* @param array $params
* @param string $secretKey
* @return string
*/
private function makeSign(array $params, string $secretKey): string
{
ksort($params);
$signStr = '';
foreach ($params as $key => $value) {
if ($value === null || $value === '' || $key === 'sign') {
continue;
}
if ($signStr) {
$signStr .= '&';
}
$signStr .= $key.'='.$value;
}
$signStr .= '&key='.$secretKey;
$sign = md5($signStr);
return strtoupper($sign);
}
/**
* 时间戳偏差校验
* @throws AppException
*/
private function checkRequestTime(int $requestTime): void
{
if (abs(time() - $requestTime / 1000) > 300) {
throw new AppException('时间戳相差大于300秒');
}
}
/**
* 渠道编码校验
* @throws AppException
*/
private function checkIfCode(string $ifCode): void
{
if ($ifCode !== 'alipay') {
throw new AppException('渠道编码固定为:alipay');
}
}
/**
* 接口版本号校验
* @throws AppException
*/
private function checkVersion(string $version): void
{
if ($version !== '1.0') {
throw new AppException('接口版本号固定为:1.0');
}
}
/**
* 签名类型校验
* @throws AppException
*/
private function checkSignType(string $signType): void
{
if ($signType !== 'MD5') {
throw new AppException('签名类型固定为:MD5');
}
}
/**
* 校验签名
* @throws AppException
*/
private function checkSign(array $params, string $secretKey): void
{
if (empty($params['sign'])) {
throw new AppException('签名缺失');
}
$checkSign = $this->makeSign($params, $secretKey);
if ($checkSign !== $params['sign']) {
throw new AppException('签名不匹配');
}
}
/**
* 根据商户号和应用ID获取应用
* @throws AppException
*/
private function getMchApp(string $mchNo, string $appId): MchApp
{
$app = MchApp::query()
->where('mch_no', $mchNo)
->where('app_id', $appId)
->first();
if (empty($app)) {
throw new AppException('应用不存在');
}
if (empty($app->account_book_id)) {
throw new AppException('还未开通记账本');
}
return $app;
}
/**
* 查询记账本余额
* @param array $params
* @return array
* @throws AppException
*/
public function queryBalance(array $params): array
{
$this->checkRequestTime($params['reqTime']);
$this->checkIfCode($params['ifCode']);
$this->checkVersion($params['version']);
$this->checkSignType($params['signType']);
$mchApp = $this->getMchApp($params['mchNo'], $params['appId']);
$this->checkSign($params, $mchApp->secret_key);
// TODO mock
$data = [
'availableAmount' => 700,
];
$sign = $this->makeSign($data, $mchApp->secret_key);
return [$data, $sign];
}
/**
* 单笔转账
* @param array $params
* @return array
* @throws AppException
*/
public function transferOrder(array $params): array
{
$this->checkRequestTime($params['reqTime']);
$this->checkIfCode($params['ifCode']);
$this->checkVersion($params['version']);
$this->checkSignType($params['signType']);
$mchApp = $this->getMchApp($params['mchNo'], $params['appId']);
$this->checkSign($params, $mchApp->secret_key);
// TODO mock
$data = [
'accountName' => '广西拉米信息科技有限公司',
'accountNo' => '3858074971@qq.com',
'amount' => 300,
'channelOrderNo' => '20250825020070011530820074021763',
'mchOrderNo' => 'P00000000000000000010',
'state' => 1,
'transferId' => 'T1708316875559008'
];
$sign = $this->makeSign($data, $mchApp->secret_key);
return [$data, $sign];
}
/**
* 转账查询
* @param array $params
* @return array
* @throws AppException
*/
public function transferQuery(array $params): array
{
$this->checkRequestTime($params['reqTime']);
$this->checkVersion($params['version']);
$this->checkSignType($params['signType']);
$mchApp = $this->getMchApp($params['mchNo'], $params['appId']);
$this->checkSign($params, $mchApp->secret_key);
// TODO mock
$data = [
'accountName' => '广西拉米信息科技有限公司',
'accountNo' => '3858074971@qq.com',
'amount' => 300,
'appId' => '664714f9e4b078d6ee5d0007',
'channelOrderNo' => '20250825020070011530820074021763',
'createdAt' => 1756092887724,
'currency' => 'cny',
'entryType' => 'ALIPAY_CASH',
'ifCode' => 'alipay',
'mchNo' => 'M1715934457',
'mchOrderNo' => 'P00000000000000000010',
'state' => 2,
'successTime' => 1756092888000,
'transferDesc' => '提现到账3.00元',
'transferId' => 'T1708316875559008'
];
$sign = $this->makeSign($data, $mchApp->secret_key);
return [$data, $sign];
}
}