|
|
@ -3,25 +3,56 @@ |
|
|
namespace plugin\piadmin\app\service\pay; |
|
|
namespace plugin\piadmin\app\service\pay; |
|
|
|
|
|
|
|
|
use plugin\piadmin\app\base\BaseService; |
|
|
use plugin\piadmin\app\base\BaseService; |
|
|
|
|
|
use plugin\piadmin\app\dao\PayOrderDao; |
|
|
|
|
|
use plugin\piadmin\app\dao\UserDao; |
|
|
|
|
|
use plugin\piadmin\app\exception\ApiException; |
|
|
use plugin\piadmin\app\utils\pay\ali\AliPay; |
|
|
use plugin\piadmin\app\utils\pay\ali\AliPay; |
|
|
use plugin\piadmin\app\utils\pay\wechat\WechatPay; |
|
|
use plugin\piadmin\app\utils\pay\wechat\WechatPay; |
|
|
|
|
|
use plugin\piadmin\app\utils\RandomUtils; |
|
|
|
|
|
use plugin\piadmin\app\utils\RequestUtils; |
|
|
|
|
|
use support\Db; |
|
|
|
|
|
|
|
|
class PayService extends BaseService |
|
|
class PayService extends BaseService |
|
|
{ |
|
|
{ |
|
|
|
|
|
protected $payOrderDao; |
|
|
|
|
|
protected $userDao; |
|
|
|
|
|
|
|
|
|
|
|
public function __construct() |
|
|
|
|
|
{ |
|
|
|
|
|
$this->payOrderDao = app()->make(PayOrderDao::class); |
|
|
|
|
|
$this->userDao = app()->make(UserDao::class); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public function getQrUrl($params) |
|
|
public function getQrUrl($params) |
|
|
{ |
|
|
{ |
|
|
|
|
|
$userInfo = RequestUtils::getUserInfo(); |
|
|
|
|
|
//创建订单记录
|
|
|
|
|
|
$order_no = $this->generateOrderNo(); |
|
|
|
|
|
$price = $params['price']; |
|
|
|
|
|
if (env('APP_DEBUG')) { |
|
|
|
|
|
$price = 0.01; |
|
|
|
|
|
} |
|
|
|
|
|
$this->payOrderDao->save([ |
|
|
|
|
|
'uid' => $userInfo['id'], |
|
|
|
|
|
'order_no' => $order_no, |
|
|
|
|
|
'desc' => '投稿点数充值', |
|
|
|
|
|
'order_time' => date('Y-m-d H:i:s'), |
|
|
|
|
|
'total_price' => $params['price'], |
|
|
|
|
|
'ip_address' => request()->getRealIp() |
|
|
|
|
|
]); |
|
|
|
|
|
//微信订单封装
|
|
|
$wechatOrder = [ |
|
|
$wechatOrder = [ |
|
|
'out_trade_no' => time().'', |
|
|
|
|
|
'description' => 'subject-测试', |
|
|
|
|
|
|
|
|
'out_trade_no' => $order_no, |
|
|
|
|
|
'description' => '投稿点数充值', |
|
|
'amount' => [ |
|
|
'amount' => [ |
|
|
'total' => $params['price'] * 100, |
|
|
|
|
|
|
|
|
'total' => $price * 100, |
|
|
], |
|
|
], |
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
//支付宝订单封装
|
|
|
$aliOrder = [ |
|
|
$aliOrder = [ |
|
|
'out_trade_no' => time(), |
|
|
|
|
|
'total_amount' => $params['price'] . '', |
|
|
|
|
|
'subject' => 'yansongda 测试 - 01', |
|
|
|
|
|
|
|
|
'out_trade_no' => $order_no, |
|
|
|
|
|
'total_amount' => $price . '', |
|
|
|
|
|
'subject' => '投稿点数充值', |
|
|
]; |
|
|
]; |
|
|
$wechatqrurl = WechatPay::getQrUrl($wechatOrder); |
|
|
$wechatqrurl = WechatPay::getQrUrl($wechatOrder); |
|
|
$aliqrurl = AliPay::getQrUrl($aliOrder); |
|
|
$aliqrurl = AliPay::getQrUrl($aliOrder); |
|
|
@ -31,4 +62,111 @@ class PayService extends BaseService |
|
|
]; |
|
|
]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public function notify($type = 'wechat') |
|
|
|
|
|
{ |
|
|
|
|
|
switch ($type) { |
|
|
|
|
|
case 'wechat': |
|
|
|
|
|
$result = WechatPay::notify(); |
|
|
|
|
|
break; |
|
|
|
|
|
case 'alipay': |
|
|
|
|
|
$result = AliPay::notify(); |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
$result = []; |
|
|
|
|
|
} |
|
|
|
|
|
return $result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 订单支付回调 |
|
|
|
|
|
* @param array $params |
|
|
|
|
|
* @return array |
|
|
|
|
|
*/ |
|
|
|
|
|
public function orderPayNotify(array $params): array |
|
|
|
|
|
{ |
|
|
|
|
|
// 查订单
|
|
|
|
|
|
$order = $this->payOrderDao->getOne([ |
|
|
|
|
|
'no' => $params['order_no'], |
|
|
|
|
|
'delete_time' => 0 |
|
|
|
|
|
]); |
|
|
|
|
|
if (empty($order)) { |
|
|
|
|
|
throw new ApiException('订单不存在'); |
|
|
|
|
|
} |
|
|
|
|
|
if ($order['status'] != 1) { |
|
|
|
|
|
throw new ApiException('订单状态不需要处理'); |
|
|
|
|
|
} |
|
|
|
|
|
// 更新订单信息
|
|
|
|
|
|
$updateOrderData = [ |
|
|
|
|
|
'payer_open_id' => $params['payer_open_id'] ?? '', |
|
|
|
|
|
'transaction_id' => $params['transaction_id'] ?? '', |
|
|
|
|
|
'pay_type' => $params['pay_type'] |
|
|
|
|
|
]; |
|
|
|
|
|
if ($params['is_paid']) { |
|
|
|
|
|
$updateOrderData['status'] = 3; |
|
|
|
|
|
$updateOrderData['pay_price'] = $params['pay_total'] / 100; |
|
|
|
|
|
$updateOrderData['pay_time'] = $params['success_time']->getTimestamp(); |
|
|
|
|
|
$updateOrderData['pay_currency'] = $params['currency']; |
|
|
|
|
|
} |
|
|
|
|
|
// 落库
|
|
|
|
|
|
Db::beginTransaction(); |
|
|
|
|
|
try { |
|
|
|
|
|
// 订单主表落库
|
|
|
|
|
|
$this->dao->update(['id' => $order['id']], $updateOrderData); |
|
|
|
|
|
//更改用户余额
|
|
|
|
|
|
$this->userDao->update(['id' => $order['uid']], [ |
|
|
|
|
|
'balance' => Db::raw('balance+' . $params['pay_total'] / 100) |
|
|
|
|
|
]); |
|
|
|
|
|
Db::commit(); |
|
|
|
|
|
} catch (\Exception $exception) { |
|
|
|
|
|
Db::rollback(); |
|
|
|
|
|
} |
|
|
|
|
|
return []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 生成唯一订单号 |
|
|
|
|
|
* |
|
|
|
|
|
* @param string $prefix 业务前缀(如支付方式、渠道标识) |
|
|
|
|
|
* @param int $length 订单号总长度(默认32位,最小16位) |
|
|
|
|
|
* @return string |
|
|
|
|
|
*/ |
|
|
|
|
|
private function generateOrderNo(string $prefix = 'GEOCN', int $length = 32): string |
|
|
|
|
|
{ |
|
|
|
|
|
// 验证参数
|
|
|
|
|
|
if ($length < 16) { |
|
|
|
|
|
throw new ApiException("订单号长度不能小于16位"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 1. 基础时间部分(14位:年月日时分秒)
|
|
|
|
|
|
$time = date('YmdHis'); |
|
|
|
|
|
|
|
|
|
|
|
// 2. 随机字符串(至少2位)
|
|
|
|
|
|
$randomLength = $length - strlen($prefix) - strlen($time) - 2; |
|
|
|
|
|
$randomLength = max($randomLength, 2); // 确保至少2位随机数
|
|
|
|
|
|
$random = RandomUtils::generateRandomString($randomLength); |
|
|
|
|
|
|
|
|
|
|
|
// 3. 进程/机器标识(2位,避免集群环境冲突)
|
|
|
|
|
|
$machineId = self::getMachineId(); |
|
|
|
|
|
|
|
|
|
|
|
// 组合订单号
|
|
|
|
|
|
$orderNo = $prefix . $time . $machineId . $random; |
|
|
|
|
|
|
|
|
|
|
|
// 截断或补位到指定长度
|
|
|
|
|
|
return substr($orderNo, 0, $length); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取机器/进程标识(2位) |
|
|
|
|
|
* |
|
|
|
|
|
* @return string |
|
|
|
|
|
*/ |
|
|
|
|
|
private function getMachineId(): string |
|
|
|
|
|
{ |
|
|
|
|
|
// 单机环境:使用进程ID的后两位
|
|
|
|
|
|
// 集群环境:可改为服务器IP最后一段的哈希值
|
|
|
|
|
|
$pid = getmypid() ?: 1; |
|
|
|
|
|
$id = $pid % 100; |
|
|
|
|
|
|
|
|
|
|
|
return str_pad((string)$id, 2, '0', STR_PAD_LEFT); |
|
|
|
|
|
} |
|
|
} |
|
|
} |