master
elf 1 year ago
parent 464027eb37
commit 791295112f

@ -43,6 +43,8 @@ class MineCommand extends HyperfCommand
public function handle(): void public function handle(): void
{ {
$this->refundConfirm();
return;
$this->rsyncUser('4673f922e30cfd2efeeb992ff6a32ece', '202308070000001', 'ELF1990'); $this->rsyncUser('4673f922e30cfd2efeeb992ff6a32ece', '202308070000001', 'ELF1990');
$this->rsyncUser('247eda1b7de0c76603123c477f2072fa', '202308070000001', 'RLX1990'); $this->rsyncUser('247eda1b7de0c76603123c477f2072fa', '202308070000001', 'RLX1990');
$this->rsyncUser('13f366c46bb842b6cb732e6a30836a9b', '202308070000001', '30684'); $this->rsyncUser('13f366c46bb842b6cb732e6a30836a9b', '202308070000001', '30684');
@ -151,6 +153,16 @@ class MineCommand extends HyperfCommand
echo $url; echo $url;
} }
protected function unbindCard()
{
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$result = $userService->unbindCard(['userId' => 'ELF1990', 'agreementNo' => '312023080400002047764'], $this->getApp());
var_dump($result);
}
protected function payment() protected function payment()
{ {
/** /**
@ -159,7 +171,7 @@ class MineCommand extends HyperfCommand
$paymentService = $this->container->make(PaymentService::class); $paymentService = $this->container->make(PaymentService::class);
$data = [ $data = [
'userId' => 'ELF1990', 'userId' => 'ELF1990',
'agreementNo' => '312023080400002047764', 'agreementNo' => '312023081200002052866',
'notifyUrl' => 'http://www.baidu.com', 'notifyUrl' => 'http://www.baidu.com',
'returnUrl' => 'http://www.baidu.com', 'returnUrl' => 'http://www.baidu.com',
'amount' => 100, 'amount' => 100,
@ -209,4 +221,51 @@ class MineCommand extends HyperfCommand
$userId = $requestLog->getDataValue('userId'); $userId = $requestLog->getDataValue('userId');
var_dump($userId); var_dump($userId);
} }
public function getBalance()
{
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$result = $userService->getBalance('1274207');
var_dump($result);
}
public function refund()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$data = [
'userId' => 'ELF1990',
'outOrderNo' => '16918297262208',
'notifyUrl' => 'http://www.baidu.com',
'returnUrl' => 'http://www.baidu.com',
'outRefundNo' => time() . rand(1000, 9999),
'refundAmount' => 100,
'refundReason' => '不想买了',
'refundSplitInfoList' => [
]
];
$result = $paymentService->refundApply($data, $this->getApp());
var_dump($result);
}
public function refundConfirm()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$data = [
'userId' => 'ELF1990',
'outOrderNo' => '16918297262208',
'outRefundNo' => '16919422375337',
'notifyUrl' => 'http://www.baidu.com',
'refundAmount' => 100,
];
$paymentService->refundConfirm($data, $this->getApp(), $this->getToken());
}
} }

@ -104,14 +104,14 @@ class NotifyController extends AbstractController
$info = [ $info = [
'member_id' => $params['loginId'], 'member_id' => $params['loginId'],
'order_no' => $params['orderId'], 'order_no' => $params['tradeId'],
'third_order_no' => $params['tradeId'], 'third_order_no' => $params['orderId'],
'status' => $params['orderStatus'], 'status' => $params['orderStatus'],
'amount' => $params['orderMoney'], 'amount' => $params['orderMoney'],
'finished_at' => $params['finishTime'], 'finished_at' => $params['finishTime'],
'error_message' => $params['errorMsg'], 'error_message' => $params['errorMsg'],
'transaction_id' => $params['transactionId'], 'transaction_id' => $params['transactionId'] ?? '',
'out_transaction_id' => $params['outTransactionId'], 'out_transaction_id' => $params['outTransactionId'] ?? '',
]; ];
$order = $this->paymentService->updateOrder($info); $order = $this->paymentService->updateOrder($info);
if (empty($order)) { if (empty($order)) {

@ -75,8 +75,8 @@ class PaymentController extends AbstractController
public function payment(RequestInterface $request) { public function payment(RequestInterface $request) {
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class); [$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$url = $this->paymentService->payment($data, $app, $token); $this->paymentService->payment($data, $app, $token);
return $this->success(['url' => $url]); return $this->success();
} }
public function refundApply(RequestInterface $request) public function refundApply(RequestInterface $request)
@ -89,8 +89,8 @@ class PaymentController extends AbstractController
public function refundConfirm(RequestInterface $request) public function refundConfirm(RequestInterface $request)
{ {
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class); [$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->paymentService->refundApply($app, $data); $this->paymentService->refundConfirm($app, $data, $token);
return $this->success($data); return $this->success();
} }
public function refundCancel(RequestInterface $request) public function refundCancel(RequestInterface $request)

@ -375,14 +375,14 @@ class Baofu
return $this->api('profit-share-refund-apply', $data); return $this->api('profit-share-refund-apply', $data);
} }
public function profitShareRefundConfirm($params){ public function profitShareRefundConfirm($params, $token){
$data = []; $data = [];
$data['loginNo'] = $params['loginNo'] ?: '';// 匿名支付不需要传 $data['loginNo'] = $params['loginNo'] ?: '';// 匿名支付不需要传
$data['refundTradeId'] = $params['refundTradeId']; // 与退款申请中的退款请求订单号一致 $data['refundTradeId'] = $params['refundTradeId']; // 与退款申请中的退款请求订单号一致
$data['refundTradeType'] = 'REFUND_CONFIRM'; $data['refundTradeType'] = 'REFUND_CONFIRM';
$data['orgTradeId'] = $params['orgTradeId']; // 原始支付商户订单号 $data['orgTradeId'] = $params['orgTradeId']; // 原始支付商户订单号
$data['refundAmount'] = $params['refundAmount']; // 单位:分 $data['refundAmount'] = $params['refundAmount']; // 单位:分
$data['notifyUrl'] = $params['notifyUrl']; $data['notifyUrl'] = NotifyList::getNotifyUrl('confirm-split', $token);
return $this->api('profit-share-refund-confirm', $data); return $this->api('profit-share-refund-confirm', $data);
} }

@ -53,7 +53,6 @@ class SignatureUtil
$pubKey = file_get_contents($cerPath); $pubKey = file_get_contents($cerPath);
$certs = openssl_get_publickey($pubKey); $certs = openssl_get_publickey($pubKey);
$ok = openssl_verify($data, hex2bin($signature), $certs); $ok = openssl_verify($data, hex2bin($signature), $certs);
var_dump($cerPath, $signature);
if ($ok == 1) { if ($ok == 1) {
return true; return true;
} }

@ -7,6 +7,8 @@ namespace App\Model;
class Order extends Model class Order extends Model
{ {
public const STATUS_PREPARE = 'PREPARE'; public const STATUS_PREPARE = 'PREPARE';
public const STATUS_APPLY_SUCCESS = 'APPLY_SUCCESS';
public const STATUS_APPLY_FAILED = 'APPLY_FAILED';
public const STATUS_INIT = 'INIT'; public const STATUS_INIT = 'INIT';
public const STATUS_PROCESS = 'PROCESS'; public const STATUS_PROCESS = 'PROCESS';
public const STATUS_SUCCESS = 'SUCCESS'; public const STATUS_SUCCESS = 'SUCCESS';
@ -21,4 +23,9 @@ class Order extends Model
public function getExpiresIn() { public function getExpiresIn() {
return strtotime($this->expired_at) - time(); return strtotime($this->expired_at) - time();
} }
public function orderSplitInfos()
{
return $this->hasMany(OrderSplitInfo::class, 'order_no', 'order_no');
}
} }

@ -6,7 +6,11 @@ namespace App\Model;
class Refund extends Model class Refund extends Model
{ {
public const STATUS_PREPARE = 'PREPARE'; public const STATUS_PREPARE = 'PREPARE';
public const STATUS_APPLY_SUCCESS = 'APPLY_SUCCESS';
public const STATUS_APPLY_FAILED = 'APPLY_FAILED';
public const STATUS_CONFIRM_FAILED = 'CONFIRM_FAILED';
public const STATUS_INIT = 'INIT'; public const STATUS_INIT = 'INIT';
public const STATUS_PROCESS = 'PROCESS'; public const STATUS_PROCESS = 'PROCESS';
public const STATUS_SUCCESS = 'SUCCESS'; public const STATUS_SUCCESS = 'SUCCESS';
@ -14,6 +18,10 @@ class Refund extends Model
protected $table = 'refunds'; protected $table = 'refunds';
protected $casts = [
'org_refund_split_info_list' => 'array',
];
public static $shortStatusAndStatusMap = [ public static $shortStatusAndStatusMap = [
'I' => self::STATUS_INIT, 'I' => self::STATUS_INIT,
'P' => self::STATUS_PROCESS, 'P' => self::STATUS_PROCESS,

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace App\Model;
class RefundSplitInfo extends Model
{
protected $table = 'refund_split_infos';
}

@ -13,6 +13,7 @@ use App\Model\App;
use App\Model\Order; use App\Model\Order;
use App\Model\OrderSplitInfo; use App\Model\OrderSplitInfo;
use App\Model\Refund; use App\Model\Refund;
use App\Model\RefundSplitInfo;
use App\Model\User; use App\Model\User;
class PaymentService extends AbstractService class PaymentService extends AbstractService
@ -104,11 +105,11 @@ class PaymentService extends AbstractService
$order->org_split_info_list = $params['splitInfoList']; $order->org_split_info_list = $params['splitInfoList'];
$order->save(); $order->save();
$fee = floor($order->amount * 0.007); $platformAccount = User::getPlatformAccount();
$fee = $platformAccount ? floor($order->amount * 0.01) : 0;
$orderSplitInfos = []; $orderSplitInfos = [];
$splitUserIds = array_column($params['splitInfoList'], 'userId'); $splitUserIds = array_column($params['splitInfoList'], 'userId');
$users = User::where('app_id', $app->app_id)->whereIn('user_id', $splitUserIds)->get()->keyBy('user_id'); $users = User::where('app_id', $app->app_id)->whereIn('user_id', $splitUserIds)->get()->keyBy('user_id');
$platformAccount = User::getPlatformAccount();
foreach ($params['splitInfoList'] as $splitInfo) { foreach ($params['splitInfoList'] as $splitInfo) {
$splitUser = $users[$splitInfo['userId']]; $splitUser = $users[$splitInfo['userId']];
$splitAmount = $splitInfo['sellerFlag'] == 1 ? ($splitInfo['amount'] - $fee): $splitInfo['amount']; $splitAmount = $splitInfo['sellerFlag'] == 1 ? ($splitInfo['amount'] - $fee): $splitInfo['amount'];
@ -151,7 +152,7 @@ class PaymentService extends AbstractService
} }
public function updateOrder($params) { public function updateOrder($params) {
$order = Order::where('order_no', $params['order_no'])->where('status', 'APPLY_FAILED')->first(); $order = Order::where('order_no', $params['order_no'])->where('status', 'APPLY_SUCCESS')->first();
if (empty($order)) { if (empty($order)) {
return null; return null;
} }
@ -167,17 +168,17 @@ class PaymentService extends AbstractService
public function refundApply(array $data, App $app) { public function refundApply(array $data, App $app) {
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first(); $user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if ($user) { if (!$user) {
throw new BusinessException('用户存在'); throw new BusinessException('用户存在');
} }
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first(); $order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first();
if (empty($order)) { if (empty($order)) {
throw new BusinessException('订单号不存在'); throw new BusinessException('订单号不存在');
} }
if ($order->status != 'FINISH') { if ($order->status != 'SUCCESS') {
throw new BusinessException('该订单状态不能发起退款'); throw new BusinessException('该订单状态不能发起退款');
} }
$refund = Refund::where('app_id', $app->app_id)->where('refund_no', $data['refundNo'])->first(); $refund = Refund::where('app_id', $app->app_id)->where('out_refund_no', $data['outRefundNo'])->first();
if ($refund) { if ($refund) {
throw new BusinessException('该退款单已经存在'); throw new BusinessException('该退款单已经存在');
} }
@ -189,19 +190,20 @@ class PaymentService extends AbstractService
$refund->order_no = $order->order_no; $refund->order_no = $order->order_no;
$refund->out_order_no = $order->out_order_no; $refund->out_order_no = $order->out_order_no;
$refund->refund_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_REFUND); $refund->refund_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_REFUND);
$refund->out_refund_no = $data['outRefundNo'];
$refund->refund_amount = $data['refundAmount']; $refund->refund_amount = $data['refundAmount'];
$refund->refund_reason = $data['refundReason']; $refund->refund_reason = $data['refundReason'];
$refund->notify_url = $data['notifyUrl'] ?? ''; $refund->notify_url = $data['notifyUrl'] ?? '';
$refund->org_refund_split_info_list = $data['refundSplitInfoList']; $refund->org_refund_split_info_list = $data['refundSplitInfoList'] ?? [];
$refund->remark = $data['remark'] ?: ''; $refund->remark = $data['remark'] ?? '';
$refund->applied_at = date('Y-m-d H:i:s'); $refund->applied_at = date('Y-m-d H:i:s');
$refundSplitInfoList = []; $refundSplitInfoList = [];
$refundSplitInfos = []; $refundSplitInfos = [];
foreach ($order->order_split_infos as $splitInfo) { foreach ($order->orderSplitInfos as $splitInfo) {
$refundSplitInfoList[] = [ $refundSplitInfoList[] = [
'orgSubOutOrderNo' => $splitInfo->sub_order_no, 'orgSubOutOrderNo' => $splitInfo->sub_order_no,
'refundAmount' => $splitInfo->split_amount, 'refundAmount' => (string)$splitInfo->split_amount,
]; ];
$refundSplitInfos[$splitInfo->sub_order_no] = [ $refundSplitInfos[$splitInfo->sub_order_no] = [
'app_id' => $splitInfo->user_id, 'app_id' => $splitInfo->user_id,
@ -210,12 +212,14 @@ class PaymentService extends AbstractService
'user_id' => $splitInfo->user_id, 'user_id' => $splitInfo->user_id,
'split_member_id' => $splitInfo->split_member_id, 'split_member_id' => $splitInfo->split_member_id,
'split_user_id' => $splitInfo->split_user_id, 'split_user_id' => $splitInfo->split_user_id,
'refund_no' => $refund->refund_no,
'out_refund_no' => $refund->out_refund_no,
'order_no' => $splitInfo->order_no, 'order_no' => $splitInfo->order_no,
'out_order_no' => $splitInfo->out_order_no, 'out_order_no' => $splitInfo->out_order_no,
'sub_order_no' => $splitInfo->sub_order_no, 'sub_order_no' => $splitInfo->sub_order_no,
'sub_out_order_no' => $splitInfo->sub_out_order_no, 'sub_out_order_no' => $splitInfo->sub_out_order_no,
'refund_amount' => $splitInfo->split_amount, 'refund_amount' => $splitInfo->split_amount,
'status' => 'P', 'status' => Refund::STATUS_PREPARE,
'message' => '', 'message' => '',
]; ];
} }
@ -235,18 +239,69 @@ class PaymentService extends AbstractService
$refund->real_refund_amount = $result['refundAmount']; $refund->real_refund_amount = $result['refundAmount'];
foreach ($result['refundSplitResultList'] as $refundSplitResult) { foreach ($result['refundSplitResultList'] as $refundSplitResult) {
$subOrderNo = $refundSplitResult['orgSubOutOrderNo']; $subOrderNo = $refundSplitResult['orgSubOutOrderNo'];
$refundSplitResult[$subOrderNo]['status'] = $refundSplitResult['status']; $refundSplitInfos[$subOrderNo]['status'] = Refund::getStatusByShortStatus($refundSplitResult['status']);
$refundSplitResult[$subOrderNo]['message'] = $refundSplitResult['message']; $refundSplitInfos[$subOrderNo]['message'] = $refundSplitResult['message'] ?: '';
} }
RefundSplitInfo::insert($refundSplitInfos);
$refund->save();
} catch (BasicException $e) { } catch (BasicException $e) {
$refund->status = 'APPLY_FAILED'; $refund->status = 'APPLY_FAILED';
$refund->error_code = $e->getCode(); $refund->error_code = $e->getCode();
$refund->error_message = $e->getMessage(); $refund->error_message = $e->getMessage();
foreach ($refundSplitInfos as $key => $refundSplitInfo) {
$refundSplitInfos[$key]['status'] = 'APPLY_FAILED';
$refundSplitInfos[$key]['message'] = $e->getMessage();
}
RefundSplitInfo::insert($refundSplitInfos);
$refund->save();
throw $e; throw $e;
} }
}
public function refundConfirm(array $data, App $app, string $token)
{
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (!$user) {
throw new BusinessException('用户不存在');
}
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first();
if (empty($order)) {
throw new BusinessException('订单号不存在');
}
if ($order->status != 'SUCCESS') {
throw new BusinessException('该订单状态不能发起退款');
}
$refund = Refund::where('app_id', $app->app_id)->where('out_refund_no', $data['outRefundNo'])->first();
if (empty($refund)) {
throw new BusinessException('退款申请不存在');
}
if ($refund->status != Refund::STATUS_APPLY_SUCCESS || $refund->status != Refund::STATUS_CONFIRM_FAILED) {
throw new BusinessException('该退款单未申请成功');
}
try {
$baofu = new Baofu();
$result = $baofu->profitShareRefundConfirm([
'loginNo' => $user->member_id,
'refundTradeId' => $refund->refund_no,
'refundTradeType' => 'REFUND_APPLY',
'orgTradeId' => $refund->order_no,
'refundAmount' => $refund->refund_amount,
'notifyUrl' => $data['notifyUrl'],
], $token);
$refund->status = Refund::getStatusByShortStatus($result['refundStatus']);
$refund->third_refund_no = $result['refundOrderId'];
$refund->save(); $refund->save();
} catch (ApiException $e) {
$refund->status = Refund::STATUS_CONFIRM_FAILED;
$refund->error_code = $e->getCode();
$refund->error_message = $e->getMessage();
$refund->save();
throw $e;
}
} }
public function updateRefund($params) public function updateRefund($params)

@ -93,6 +93,13 @@ class UserService extends AbstractService
'loginNo' => $memberId, 'loginNo' => $memberId,
'contractNo' => $user->contract_no, 'contractNo' => $user->contract_no,
]); ]);
$oldAgreementNos = BankCard::where('member_id', $memberId)->get()->pluck('agreement_no')->toArray();
$agreementNos = array_column($bankCards, 'agreementNo');
$deletedAgreementNos = array_diff($oldAgreementNos, $agreementNos);
BankCard::where('member_id', $memberId)->whereIn('agreement_no', $deletedAgreementNos)->delete();
foreach ($bankCards as $bankCard) { foreach ($bankCards as $bankCard) {
$this->saveBankCard($bankCard, $user); $this->saveBankCard($bankCard, $user);
} }
@ -169,7 +176,7 @@ class UserService extends AbstractService
$baofu = new Baofu(); $baofu = new Baofu();
$result = $baofu->cardUnbind($user->member_id, $data['agreementNo']); $result = $baofu->cardUnbind($user->member_id, $data['agreementNo']);
if ($result && $result != 'false') { if ($result) {
$this->rsyncBankCards($user->member_id) ; $this->rsyncBankCards($user->member_id) ;
return true; return true;
} }
@ -186,7 +193,8 @@ class UserService extends AbstractService
return $baofu->pwdForget($user->member_id, $token); return $baofu->pwdForget($user->member_id, $token);
} }
public function pwdModify(array $data, App $app, $token) { public function pwdModify(array $data, App $app, $token)
{
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first(); $user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) { if (empty($user)) {
throw new BusinessException('用户不存在'); throw new BusinessException('用户不存在');
@ -195,4 +203,10 @@ class UserService extends AbstractService
$baofu = new Baofu(); $baofu = new Baofu();
return $baofu->pwdModify($user->member_id, $token); return $baofu->pwdModify($user->member_id, $token);
} }
public function getBalance($memberId)
{
$baofu = new Baofu();
return $baofu->getBalance($memberId);
}
} }

@ -168,7 +168,7 @@ CREATE TABLE `refunds` (
`out_order_no` varchar(32) NOT NULL, `out_order_no` varchar(32) NOT NULL,
`refund_no` varchar(32) NOT NULL, `refund_no` varchar(32) NOT NULL,
`out_refund_no` varchar(32) NOT NULL, `out_refund_no` varchar(32) NOT NULL,
`third_refund_no` varchar(32) NOT NULL, `third_refund_no` varchar(32) NOT NULL DEFAULT '',
`refund_amount` int(11) NOT NULL DEFAULT 0, `refund_amount` int(11) NOT NULL DEFAULT 0,
`refund_reason` varchar(255) NOT NULL DEFAULT '', `refund_reason` varchar(255) NOT NULL DEFAULT '',
`refund_type` varchar(16) NOT NULL DEFAULT '', `refund_type` varchar(16) NOT NULL DEFAULT '',
@ -200,6 +200,8 @@ CREATE TABLE `refund_split_infos` (
`out_order_no` varchar(32) NOT NULL, `out_order_no` varchar(32) NOT NULL,
`sub_order_no` varchar(32) NOT NULL, `sub_order_no` varchar(32) NOT NULL,
`sub_out_order_no` varchar(32) NOT NULL, `sub_out_order_no` varchar(32) NOT NULL,
`refund_no` varchar(32) NOT NULL,
`out_refund_no` varchar(32) NOT NULL,
`refund_amount` int(11) NOT NULL DEFAULT 0, `refund_amount` int(11) NOT NULL DEFAULT 0,
`status` varchar(16) NOT NULL DEFAULT '', `status` varchar(16) NOT NULL DEFAULT '',
`message` varchar(32) NOT NULL DEFAULT '', `message` varchar(32) NOT NULL DEFAULT '',

Loading…
Cancel
Save