You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
payment/app/Service/PaymentService.php

312 lines
10 KiB
PHTML

2 years ago
<?php
declare(strict_types=1);
namespace App\Service;
2 years ago
use App\Exception\BusinessException;
use App\Helper\Efps\Api;
2 years ago
use App\Helper\Efps\Result;
2 years ago
use App\Helper\Redis;
use App\Helper\RedisKey;
use App\Model\App;
2 years ago
use App\Model\BankCard;
2 years ago
use App\Model\Order;
2 years ago
use App\Model\RefundOrder;
2 years ago
use App\Model\User;
use App\Request\BindCardConfirmRequest;
use App\Request\BindCardRequest;
use App\Request\PaymentQueryRequest;
2 years ago
use App\Request\ProtocolPayConfirmRequest;
use App\Request\ProtocolPayPreRequest;
2 years ago
use App\Request\RefundQueryRequest;
use App\Request\RefundRequest;
use App\Request\UnBindCardRequest;
2 years ago
class PaymentService extends AbstractService
{
2 years ago
public function generateMemberId($appKey, $cardNo) {
return md5($appKey . '-' . $cardNo);
}
2 years ago
public function createOrder(App $app, array $params) {
$order = new Order();
$order->app_id = $app->app_id;
2 years ago
$order->out_order_no = $params['outTradeNo'] ?? '';
$order->amount = $params['payAmount'] ?? 0;
$order->notify_url = $params['notifyUrl'] ?? '';
$order->order_info = json_encode($params['orderInfo'] ?? [], JSON_UNESCAPED_UNICODE);
2 years ago
return $order;
}
2 years ago
public function handlePayResult(Result $result, Order $order) {
if ($result->get('payState') === '00') {
$order->status = Order::STATUS_PAYED;
$order->fee = $result->get('procedureFee', 0);
$order->pay_order_no = $result->get('transactionNo', '');
$order->channel_order_no = $result->get('channelOrder', '');
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
} elseif ($result->get('payState') === '01') {
$order->status = Order::STATUS_FAILED;
$order->error_code = '01';
$order->error_msg = '支付失败';
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
}
}
2 years ago
public function handleRefundResult(Result $result, RefundOrder $order) {
if ($result->get('refundState') === '00') {
$order->status = RefundOrder::STATUS_REFUND_SUCCESS;
$order->fee = $result->get('procedureFee', 0);
$order->refunded_at = date('Y-m-d H:i:s');
$order->save();
} elseif ($result->get('refundState') === '01') {
$order->status = RefundOrder::STATUS_REFUND_FAILED;
$order->error_code = '01';
$order->error_msg = '处理失败';
$order->refunded_at = date('Y-m-d H:i:s');
$order->save();
}
}
2 years ago
private function generateOrderNo() {
$now = time();
$key = RedisKey::getGenerateOrderNoKey($now);
$incrId = Redis::incr($key);
$incrId = '' . $incrId;
Redis::expire($key, 5*60);
$padLength = 6 - strlen($incrId);
$incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT);
return date('YmdHis', $now) . $incrId;
}
2 years ago
public function protocolPayPreRequest($params)
{
$req = new ProtocolPayPreRequest($params);
$app = $req->getApp();
$data = $req->getData();
$result = Api::protocolPayPre($data);
$order = $this->createOrder($app, $data);
if (!$result->isSuccess()) {
$order->status = Order::STATUS_APPLY_FAIL;
$order->save();
throw new BusinessException($result->getMessage());
}
$order->token = $result->get('token', '');
$order->protocol = $result->get('protocol', '');
$order->status = Order::STATUS_WAIT_PAY;
$order->save();
return $result->getData();
}
public function protocolPayConfirm($params)
{
$req = new ProtocolPayConfirmRequest($params);
$app = $req->getApp();
$data = $req->getData();
$order = Order::where('app_id', $app->app_id)
->where('token', $data['token'])
->where('protocol', $data['protocol'])
->first();
if (!$order) {
throw new BusinessException('订单不存在');
}
$result = Api::protocolPayConfirm($req->getData());
if (!$result->isSuccess()) {
$order->status = Order::STATUS_FAILED;
$order->error_code = $result->getCode();
$order->error_msg = $result->getMessage();
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
throw new BusinessException($result->getMessage());
}
// 00 01 03
$this->handlePayResult($result, $order);
return $result->getData();
}
2 years ago
public function bindCard($params) {
$req = new BindCardRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$memberId = $this->generateMemberId($app->app_key, $reqData['certificatesNo']);
$reqData['memberId'] = $memberId;
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $memberId)
->where('bank_card_no', $reqData['bankCardNo'])
->where('status', BankCard::STATUS_ACTIVE)
->first();
if ($bankCard) {
throw new BusinessException('该卡已绑定');
}
$result = Api::bindCard($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$user = User::where('member_id', $memberId)->first();
if (!$user) {
$user = new User();
$user->member_id = $memberId;
$user->app_id = $app->app_id;
$user->real_name = $reqData['userName'];
$user->card_no = $reqData['certificatesNo'];
$user->mobile = $reqData['phoneNum'];
$user->save();
}
$bankCard = new BankCard();
$bankCard->member_id = $memberId;
$bankCard->app_id = $app->app_id;
$bankCard->real_name = $reqData['userName'];
$bankCard->card_no = $reqData['certificatesNo'];
$bankCard->mobile = $reqData['phoneNum'];
$bankCard->sms_no = $result->get('smsNo', '');
$bankCard->bank_card_no = $reqData['bankCardNo'];
$bankCard->bank_card_type = $reqData['bankCardType'];
$bankCard->protocol = $result->get('protocol', '');
$bankCard->expired = $reqData['expired'] ?? '';
$bankCard->cvn = $reqData['cvn'] ?? '';
$bankCard->status = BankCard::STATUS_WAIT_CONFIRM;
$bankCard->save();
return array_merge($result->getData(), ['memberId' => $memberId]);
}
public function bindCardConfirm($params)
{
$req = new BindCardConfirmRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $reqData['memberId'])
->where('sms_no', $reqData['smsNo'])
->where('status', BankCard::STATUS_WAIT_CONFIRM)
->first();
if (!$bankCard) {
throw new BusinessException('绑卡申请不存在');
}
$result = Api::bindCardConfirm($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$bankCard->status = BankCard::STATUS_ACTIVE;
$bankCard->protocol = $result->get('protocol', '');
$bankCard->save();
return $result->getData();
}
public function refundQuery($params)
{
$req = new RefundQueryRequest($params);
$data = $req->getData();
$result = Api::refundQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = RefundOrder::where('out_refund_order_no', $result->get('outRefundNo'))
->where('status', RefundOrder::STATUS_APPLY_SUCCESS)
->first();
if ($order) {
$this->handleRefundResult($result, $order);
}
return $result->getData([
'outRefundNo',
'transactionNo',
'amount',
'refundAmount',
'refundState'
]);
}
public function paymentQuery($params)
{
$req = new PaymentQueryRequest($params);
$data = $req->getData();
$result = Api::paymentQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = Order::where('out_order_no', $result->get('outTradeNo'))
->where('status', Order::STATUS_WAIT_PAY)
->first();
if ($order) {
$this->handlePayResult($result, $order);
}
return $result->getData([
'outTradeNo',
'transactionNo',
'payState',
'procedureFee',
'amount'
]);
}
public function unBindCard($params)
{
$req = new UnBindCardRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $reqData['memberId'])
->where('protocol', $reqData['protocol'])
->where('status', BankCard::STATUS_ACTIVE)
->first();
if (!$bankCard) {
throw new BusinessException('绑卡不存在');
}
$result = Api::unBindCard($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$bankCard->status = BankCard::STATUS_UNBIND;
$bankCard->save();
return $result->getData();
}
public function refund($params)
{
$req = new RefundRequest($params);
$app = $req->getApp();
$data = $req->getData();
$refundOrder = new RefundOrder();
$refundOrder->app_id = $app->app_id;
$refundOrder->out_order_no = $data['outTradeNo'] ?: '';
$refundOrder->out_refund_order_no = $data['outRefundNo'] ?: '';
$refundOrder->order_amount = $data['amount'] ?: '';
$refundOrder->refund_amount = $data['refundAmount'] ?: '';
$refundOrder->remark = $data['remark'] ?: '';
$refundOrder->notify_url = $data['notifyUrl'] ?: '';
$result = Api::refund($data);
if (!$result->isSuccess()) {
$refundOrder->status = RefundOrder::STATUS_APPLY_FAILED;
$refundOrder->error_code = $result->getCode();
$refundOrder->error_msg = $result->getMessage();
$refundOrder->save();
throw new BusinessException($result->getMessage());
}
$refundOrder->status = RefundOrder::STATUS_APPLY_SUCCESS;
$refundOrder->save();
return $result->getData();
}
2 years ago
}