643 lines
31 KiB
PHP
643 lines
31 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @author Any
|
||
* @description KISS
|
||
* @date 2021年6月11日
|
||
* @version 1.0.0
|
||
*
|
||
* _____LOG_____
|
||
*
|
||
*/
|
||
namespace app\models\common\payment;
|
||
|
||
|
||
use app\models\common\notify\payment\PaymentNotify;
|
||
use app\models\UniqueOrderNo;
|
||
use app\models\Model;
|
||
use app\models\Order;
|
||
use app\models\integral\Integral;
|
||
use app\models\Balance;
|
||
use app\models\PaymentOrderUnion;
|
||
use app\components\SysConst;
|
||
use app\components\SysErrCode;
|
||
use app\models\PaymentTypes;
|
||
use app\models\PaymentConfig;
|
||
use app\models\PaymentOrder;
|
||
|
||
class Payment
|
||
{
|
||
|
||
/**
|
||
* @param PaymentOrder|PaymentOrder[] $paymentOrders 支付订单数据,支持单个或多个订单
|
||
* @param integer $cx_mch_id 平台商户ID
|
||
* @return array
|
||
*/
|
||
public function createOrder($paymentOrders, $cx_mch_id = 0)
|
||
{
|
||
if (!is_array($paymentOrders)) {
|
||
if ($paymentOrders instanceof PaymentOrder) {
|
||
$paymentOrders = [$paymentOrders];
|
||
} else {
|
||
return Model::asReturnError("`$paymentOrders`不是有效的PaymentOrder对象。");
|
||
}
|
||
}
|
||
if (!count($paymentOrders)) {
|
||
return Model::asReturnError("`$paymentOrders`不能为空。");
|
||
}
|
||
|
||
/** @var User $user */
|
||
$user = \Yii::$app->user->identity;
|
||
|
||
$orderNos = [];
|
||
$amount = 0;
|
||
$title = '';
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$orderNos[] = $paymentOrder->orderNo;
|
||
$amount = $amount + $paymentOrder->amount;
|
||
$title = $title . str_replace(';', '', $paymentOrder->title) . ';';
|
||
}
|
||
sort($orderNos);
|
||
$orderNos[] = $amount;
|
||
$unionOrderNo = UniqueOrderNo::generate(UniqueOrderNo::ORDER_TYPE_PAYMENT_ORDER_UNION, "\\app\\models\\PaymentOrderUnion");
|
||
$title = mb_substr($title, 0, 32);
|
||
$paymentOrderUnion = new PaymentOrderUnion();
|
||
$paymentOrderUnion->cx_mch_id = $cx_mch_id;
|
||
$paymentOrderUnion->user_id = $user->id;
|
||
$paymentOrderUnion->order_no = $unionOrderNo;
|
||
$paymentOrderUnion->out_trade_no = $unionOrderNo;
|
||
$paymentOrderUnion->amount = $amount;
|
||
$paymentOrderUnion->title = $title;
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$supportPayTypes = $paymentOrder->supportPayTypes;
|
||
if ($supportPayTypes) {
|
||
$supportPayTypes = (array)$supportPayTypes;
|
||
}
|
||
}
|
||
if (!empty($supportPayTypes) && is_array($supportPayTypes)) {
|
||
$appendPayTypes = [];
|
||
foreach ($supportPayTypes as $index => $payType) {
|
||
if ($payType == 'online_pay') {
|
||
$appendPayTypes[] = SysConst::$cxPayTypeEnWxpay;
|
||
$appendPayTypes[] = SysConst::$cxPayTypeEnAlipay;
|
||
unset($supportPayTypes[$index]);
|
||
break;
|
||
}
|
||
}
|
||
$supportPayTypes = array_merge($supportPayTypes, $appendPayTypes);
|
||
}
|
||
|
||
$paymentOrderUnion->support_pay_types = $paymentOrderUnion->encodeSupportPayTypes($supportPayTypes);
|
||
$t = \Yii::$app->db->beginTransaction();
|
||
try {
|
||
if (!$paymentOrderUnion->save()) {
|
||
return (new Model())->getModelError($paymentOrderUnion);
|
||
}
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$model = new \app\models\PaymentOrder();
|
||
$model->payment_order_union_id = $paymentOrderUnion->id;
|
||
$model->order_no = $paymentOrder->orderNo;
|
||
$model->amount = $paymentOrder->amount;
|
||
$model->title = $paymentOrder->title;
|
||
$model->notify_class = $paymentOrder->notifyClass;
|
||
$model->notify_status = 0;
|
||
if (!$model->save()) {
|
||
return (new Model())->getModelError($model);
|
||
}
|
||
}
|
||
$t->commit();
|
||
} catch (\Exception $e) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($e->getMessage());
|
||
}
|
||
return Model::asReturnSuccess('ok',['pay_id' => $paymentOrderUnion->id]);
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取支付数据
|
||
* @param integer $id 合并支付ID
|
||
* @param string $payType 支付类型
|
||
* @param integer $cx_mch_id 平台商户ID,默认0
|
||
* @param string $platform 平台类型,默认微信小程序(wxmp)
|
||
* return array
|
||
*/
|
||
public function getPayData($id, $payType, $cx_mch_id = 0, $openid = '',$platform = 'wxmp')
|
||
{
|
||
if (\Yii::$app->user->isGuest) {
|
||
return Model::asReturnError('用户未登录。');
|
||
}
|
||
/** @var User $user */
|
||
$user = \Yii::$app->user->identity;
|
||
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['id' => $id, 'user_id' => $user->id]);
|
||
if (!$paymentOrderUnion) {
|
||
return Model::asReturnError('待支付订单不存在。');
|
||
}
|
||
|
||
if ($paymentOrderUnion->is_pay == 1) {
|
||
return Model::asReturnError('订单已经支付。');
|
||
}
|
||
|
||
$supportPayTypes = (array)$paymentOrderUnion->decodeSupportPayTypes($paymentOrderUnion->support_pay_types);
|
||
if (!empty($supportPayTypes)
|
||
&& is_array($supportPayTypes)
|
||
&& !in_array($payType, $supportPayTypes)) {
|
||
if ($paymentOrderUnion->amount != 0) { // 订单金额为0时使用余额支付
|
||
return Model::asReturnError('该订单不支持此支付方式。');
|
||
}
|
||
}
|
||
|
||
//订单金额为0时,使用余额支付
|
||
if($paymentOrderUnion->amount == 0 && $payType != SysConst::$cxPayTypeEnBalance){
|
||
return Model::asReturnError('该订单只支持余额支付');
|
||
}
|
||
|
||
|
||
|
||
switch ($payType) {
|
||
case SysConst::$cxPayTypeEnBalance:
|
||
$data = [
|
||
'pay_type' => $payType,
|
||
'id' => $paymentOrderUnion->id,
|
||
'balance_amount' => $user->balance ? $user->balance->account_balance : 0.00,
|
||
'order_amount' => $paymentOrderUnion->amount,
|
||
];
|
||
break;
|
||
case SysConst::$cxPayTypeEnWxpay:
|
||
$plugin = new \app\models\common\PluginService();
|
||
if($user->bindWxmp){
|
||
if(!empty($openid)){
|
||
$params['openid'] = $openid;
|
||
}else{
|
||
$params['openid'] = $user->bindWxmp->openid;
|
||
}
|
||
$wxmpService = $plugin->getWxmpService($cx_mch_id);
|
||
$res = $wxmpService->pay->unifiedOrder(array_merge([
|
||
'body' => $paymentOrderUnion->title,
|
||
'out_trade_no' => $paymentOrderUnion->order_no,
|
||
'total_fee' => $paymentOrderUnion->amount * 100,
|
||
'notify_url' => $this->getNotifyUrl(SysConst::$cxPayTypeEnWxpay),
|
||
'trade_type' => 'JSAPI',
|
||
],$params));
|
||
$appPayData = [
|
||
'appId' => $wxmpService->appId,
|
||
'timeStamp' => (string)time(),
|
||
'nonceStr' => md5(uniqid()),
|
||
'package' => 'prepay_id=' . $res['prepay_id'],
|
||
'signType' => 'MD5',
|
||
];
|
||
$appPayData['paySign'] = $wxmpService->pay->makeSign($appPayData);
|
||
} else {
|
||
return Model::asReturnError('账户尚未绑定微信,该订单不支持此付款方式');
|
||
}
|
||
|
||
$data = array_merge([
|
||
'pay_type' => $payType,
|
||
'id' => $paymentOrderUnion->id,
|
||
],$appPayData);
|
||
break;
|
||
case SysConst::$cxPayTypeEnUnionpay:
|
||
$plugin = new \app\models\common\PluginService();
|
||
$updcService = $plugin->getUpdcService($cx_mch_id);
|
||
if($paymentOrderUnion->out_trade_no == $paymentOrderUnion->order_no){
|
||
$merOrderNo = $updcService->getMerOrderNo($cx_mch_id);
|
||
$paymentOrderUnion->out_trade_no = $merOrderNo;
|
||
if (!$paymentOrderUnion->save()) {
|
||
return (new Model())->getModelError($paymentOrderUnion);
|
||
}
|
||
}
|
||
$merOrderNo = $paymentOrderUnion->out_trade_no;
|
||
|
||
if($platform == SysConst::$cxPlatformWxmp){
|
||
|
||
$appPayData = [];
|
||
//银联微信小程序支付
|
||
if($user->bindWxmp){
|
||
|
||
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeUnionpay;
|
||
$paymentOrderUnion->updated_at = time();
|
||
$chnlMerOrdrNo = 0;
|
||
$paymentOrderUnion->transaction_id = $chnlMerOrdrNo;
|
||
if ($paymentOrderUnion->save()) {
|
||
//支付完成之后,相关的操作
|
||
$form = new PaymentNotify();
|
||
$resp = $form->notify($paymentOrderUnion);
|
||
if($resp['code'] != 0){
|
||
//记录错误
|
||
return Model::asReturnError($resp['msg']);
|
||
}
|
||
}
|
||
return Model::asReturnSuccess('ok',[]);
|
||
|
||
|
||
$wxmpService = $plugin->getWxmpService();
|
||
$openid = $user->bindWxmp->openid;
|
||
|
||
try{
|
||
$args = [
|
||
'method' => 'gnete.upbc.code.trade',
|
||
'method_name' => 'create'
|
||
];
|
||
|
||
$remark = $paymentOrderUnion->order_no;
|
||
|
||
$msgBody = [];
|
||
$msgBody['merOrdrNo'] = $merOrderNo; //商户交易订单号,需保证在商户端不重复;格式:15 位商户号+8 位交易日期+9 位序数字列号
|
||
$msgBody['busiId'] = '00250007';//商户开通的业务 ID,00250007:小程序
|
||
$msgBody['bizFunc'] = '111011'; //业务功能,交易-111011
|
||
$msgBody['notifyUrl'] = $this->getNotifyUrl(SysConst::$cxPayTypeEnUnionpay);
|
||
$msgBody['trxTtlAmt'] = $paymentOrderUnion->amount * 100;//交易总金额/订单总金额,单位分;【订单总金额】=【可打折金额】+【不可打折金额】
|
||
$msgBody['trxTtlAmt'] = (string)$msgBody['trxTtlAmt'];
|
||
$subject = $paymentOrderUnion->title;
|
||
$subject = $updcService->filterSpecialChar($subject);
|
||
$msgBody['subject'] = $subject;//订单标题
|
||
$ordrDesc = $subject;
|
||
$msgBody['ordrDesc'] = $ordrDesc;//订单描述
|
||
$msgBody['timeoutExpress'] = \Yii::$app->params['payTimeoutExpress'];//允许的最晚付款时间,逾期将关闭交易。取值范围:1m~24h。m-分钟,h-小时。
|
||
$msgBody['isMinipg'] = '1';//是否小程序支付。1-表示小程序支付;不传或值不为 1,表示公众账号内支付
|
||
|
||
/**
|
||
* 交易类型
|
||
* JSAPI 微信公众号支付/微信小程序支付/支付宝服务窗/
|
||
* 云闪付支付
|
||
* NATIVE 扫码支付
|
||
* APP APP 支付(支持:微信 APP 支付)
|
||
* MWEB H5 支付(支持:云闪付 H5、支付宝 H5)
|
||
* APP-MINI APP 跳转小程序支付(支持:云闪付 APP、支
|
||
* 付宝 APP)
|
||
* 商户 APP 支付场景使用交易类型说明:调用微信:APP,
|
||
* 调用支付宝:APP-MINI,调用云闪付:APP-MINI。
|
||
*/
|
||
$msgBody['trxType'] = 'JSAPI';
|
||
|
||
/**
|
||
* 买家信息
|
||
*/
|
||
$msgBody['buyerInf'] = [
|
||
//付款方银行代码,支持 3 位或 8 位银行代码,或金融机构编码;支付宝上送:00070707,微信上送:00060606,云闪付上送:00050505,公众号,小程序要必填
|
||
'bankCode' => '00060606',
|
||
//用于微信支付,openId 为用户在主商户 appId 下的唯一标识(这里的 appId是我司的,openId 是用户静默授权给我司的)。openId 和 subOpenId 可以选传其中之一(商户一般会选择上送 subOpenId)。
|
||
//'openId' => '',
|
||
//用于微信支付 subOpenId 为用户在主商户 subAppId 下的唯一标识(这里 的 subAppId 是商户的,具体参照下面 subAppId 字段的描 述。 subOpenId 是用户静默授权给商户的)。 openId 和 subOpenId 可以选传其中之一(商户一般会选择 上送 subOpenId),如果选择传 subOpenId,则必须同时传 subAppId。
|
||
'subOpenId' => $openid,
|
||
//用于微信支付 如果是公众号支付,subAppId 对应商户的公众号的 appId; 如果是小程序支付,subAppId 对应商户小程序的 appId;; 如果是 APP 支付,subAppId 对应商户微信开放平台的应用appId;
|
||
'subAppId' => $wxmpService->appId,
|
||
];
|
||
$goodsDtl = [];
|
||
foreach ($paymentOrderUnion->paymentOrder as $index => $paymentOrder){
|
||
$goodsDtlItem = [];
|
||
$goodsDtlItem['gdsId'] = $paymentOrder->id;
|
||
$goodsDtlItem['gdsNm'] = $paymentOrder->title;
|
||
$goodsDtlItem['gdsCnt'] = 1;
|
||
$goodsDtlItem['gdsPrice'] = $paymentOrder->amount * 100;
|
||
$goodsDtlItem['gdsPrice'] = (string)$goodsDtlItem['gdsPrice'];
|
||
$goodsDtl[] = $goodsDtlItem;
|
||
}
|
||
$msgBody['goodsDtl'] = $goodsDtl;//商品详情
|
||
$msgBody['remark'] = $remark;
|
||
|
||
$biz_content = [];
|
||
$biz_content['sndDt'] = date('YmdHis', time());
|
||
$biz_content['busiMerNo'] = $updcService->mchId;
|
||
$biz_content['notifyUrl'] = $this->getNotifyUrl(SysConst::$cxPayTypeEnUnionpay);
|
||
$biz_content['merOrderNo'] = $merOrderNo;
|
||
$biz_content['msgBody'] = $msgBody;
|
||
$biz_content['remark'] = $remark;
|
||
|
||
\Yii::info('[UpdcRequest]'.json_encode($biz_content,JSON_UNESCAPED_UNICODE),'PaymentUpdc');
|
||
|
||
$biz_content = json_encode($biz_content);
|
||
$args['biz_content'] = $biz_content;
|
||
$res = $updcService->apiRequest($args);
|
||
if(!isset($res['wcPayData']) || empty($res['wcPayData'])){
|
||
throw new \Exception('[60101]系统内部错误');
|
||
}
|
||
$appPayData = $res['wcPayData'];
|
||
} catch (\Exception $ex){
|
||
return Model::asReturnError($ex->getMessage());
|
||
}
|
||
} else {
|
||
return Model::asReturnError('账户尚未绑定微信,该订单不支持此付款方式');
|
||
}
|
||
$data = array_merge([
|
||
'pay_type' => $payType,
|
||
'id' => $paymentOrderUnion->id,
|
||
],$appPayData);
|
||
} else {
|
||
return $this->throwNotSupport($payType, $platform);
|
||
}
|
||
break;
|
||
default:
|
||
return Model::asReturnError('未知的`payType`。');
|
||
break;
|
||
}
|
||
return Model::asReturnSuccess('ok',$data);
|
||
}
|
||
|
||
private function throwNotSupport($pay_type, $platform)
|
||
{
|
||
$pay_type_cn = PaymentTypes::getPayType($pay_type);
|
||
$platform_cn = SysConst::getPlatformByKey($platform);
|
||
$msg = "{$platform_cn}暂不支持{$pay_type_cn}";
|
||
return Model::asReturnError($msg);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @param $id
|
||
* @return array
|
||
*/
|
||
public function payBuyBalance($id)
|
||
{
|
||
if (\Yii::$app->user->isGuest) {
|
||
return Model::asReturnError('用户未登录。');
|
||
}
|
||
$user = \Yii::$app->user->identity;
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['id' => $id, 'user_id' => $user->id]);
|
||
if (!$paymentOrderUnion) {
|
||
return Model::asReturnError('待支付订单不存在。');
|
||
}
|
||
if (intval($paymentOrderUnion->is_pay) === 1) {
|
||
return Model::asReturnError('订单已支付。');
|
||
}
|
||
$supportPayTypes = (array)$paymentOrderUnion->decodeSupportPayTypes($paymentOrderUnion->support_pay_types);
|
||
if (!empty($supportPayTypes)
|
||
&& is_array($supportPayTypes)
|
||
&& !in_array(SysConst::$cxPayTypeEnBalance, $supportPayTypes)) {
|
||
if ($paymentOrderUnion->amount != 0) { // 订单金额为0时可以使用余额支付
|
||
return Model::asReturnError('暂不支持余额支付。');
|
||
}
|
||
}
|
||
$t = \Yii::$app->db->beginTransaction();
|
||
try {
|
||
/** @var \app\models\PaymentOrder[] $paymentOrders */
|
||
$paymentOrders = \app\models\PaymentOrder::find()
|
||
->where(['payment_order_union_id' => $paymentOrderUnion->id,])
|
||
->all();
|
||
$totalAmount = 0;
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$totalAmount += $paymentOrder->amount;
|
||
}
|
||
$balanceAmount = $user->balance ? $user->balance->account_balance : 0.00;
|
||
if ($balanceAmount < $totalAmount) {
|
||
$t->rollBack();
|
||
return Model::asReturnError('账户余额不足。');
|
||
}
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeBalance;
|
||
if (!$paymentOrderUnion->save()) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($paymentOrderUnion->getFirstErrors());
|
||
}
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$paymentOrder->is_pay = 1;
|
||
$paymentOrder->pay_type = SysConst::$cxPayTypeBalance;
|
||
if (!$paymentOrder->save()) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($paymentOrder->getFirstErrors());
|
||
}
|
||
|
||
$po = new PaymentOrder([
|
||
'orderNo' => $paymentOrder->order_no,
|
||
'amount' => (float)$paymentOrder->amount,
|
||
'title' => $paymentOrder->title,
|
||
'notifyClass' => $paymentOrder->notify_class,
|
||
'payType' => SysConst::$cxPayTypeEnBalance,
|
||
]);
|
||
if ($po->amount > 0) {
|
||
//账户余额变动
|
||
$order_type = UniqueOrderNo::getOrderTypeByOrderNo($po->orderNo);
|
||
$ext = "";
|
||
$res = Balance::userWalletLog($user->id, Balance::TYPE_PAY, $po->amount, $po->title, $order_type, $po->orderNo, $ext, $paymentOrderUnion->cx_mch_id);
|
||
if($res['code'] != SysErrCode::$apiReturnSuccess){
|
||
$t->rollBack();
|
||
return Model::asReturnError($res['msg']);
|
||
}
|
||
}
|
||
$NotifyClass = $paymentOrder->notify_class;
|
||
if(class_exists($NotifyClass)){
|
||
/** @var PaymentNotify $notifyObject */
|
||
$notifyObject = new $NotifyClass();
|
||
try {
|
||
$resp = $notifyObject->notify($po);
|
||
if($resp['code'] != 0){
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$resp['msg']}";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
} catch (\Exception $exception) {
|
||
$exp_err = $exception->getMessage();
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$exp_err}";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
} else {
|
||
//记录错误
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$paymentOrder->notify_class}不存在";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
}
|
||
$t->commit();
|
||
} catch (\Exception $e) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($e->getMessage());
|
||
}
|
||
return Model::asReturnSuccess();
|
||
}
|
||
|
||
|
||
/**
|
||
* 积分支付
|
||
* @param $id
|
||
* @return array
|
||
*/
|
||
public function payBuyIntegral($id)
|
||
{
|
||
if (\Yii::$app->user->isGuest) {
|
||
return Model::asReturnError('用户未登录。');
|
||
}
|
||
$user = \Yii::$app->user->identity;
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['id' => $id, 'user_id' => $user->id]);
|
||
if (!$paymentOrderUnion) {
|
||
return Model::asReturnError('待支付订单不存在。');
|
||
}
|
||
if (intval($paymentOrderUnion->is_pay) === 1) {
|
||
return Model::asReturnError('订单已支付。');
|
||
}
|
||
$supportPayTypes = (array)$paymentOrderUnion->decodeSupportPayTypes($paymentOrderUnion->support_pay_types);
|
||
if (!empty($supportPayTypes)
|
||
&& is_array($supportPayTypes)
|
||
&& !in_array(SysConst::$cxPayTypeEnIntegral, $supportPayTypes)) {
|
||
if ($paymentOrderUnion->amount != 0) { // 订单金额为0时可以使用积分支付
|
||
return Model::asReturnError('暂不支持积分支付。');
|
||
}
|
||
}
|
||
$t = \Yii::$app->db->beginTransaction();
|
||
try {
|
||
/** @var \app\models\PaymentOrder[] $paymentOrders */
|
||
$paymentOrders = \app\models\PaymentOrder::find()
|
||
->where(['payment_order_union_id' => $paymentOrderUnion->id,])
|
||
->all();
|
||
$totalAmount = 0;
|
||
$totalIntegral = 0;
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$totalAmount += $paymentOrder->amount;
|
||
$order = Order::findOne(['order_no' => $paymentOrder->order_no]);
|
||
if($order == null){
|
||
$t->rollBack();
|
||
return Model::asReturnError('订单不存在');
|
||
}
|
||
$totalIntegral += $order->integralMallOrder->integral_num;
|
||
}
|
||
$balanceAmount = $user->balance ? $user->balance->account_balance : 0.00;
|
||
if ($balanceAmount < $totalAmount) {
|
||
$t->rollBack();
|
||
return Model::asReturnError('账户余额不足。');
|
||
}
|
||
$accountIntegral = $user->integral ? $user->integral->account_integral : 0;
|
||
if($accountIntegral < $totalIntegral){
|
||
$t->rollBack();
|
||
return Model::asReturnError('账户积分不足。');
|
||
}
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeIntegral;
|
||
if (!$paymentOrderUnion->save()) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($paymentOrderUnion->getFirstErrors());
|
||
}
|
||
foreach ($paymentOrders as $paymentOrder) {
|
||
$paymentOrder->is_pay = 1;
|
||
$paymentOrder->pay_type = SysConst::$cxPayTypeIntegral;
|
||
if (!$paymentOrder->save()) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($paymentOrder->getFirstErrors());
|
||
}
|
||
|
||
$po = new PaymentOrder([
|
||
'orderNo' => $paymentOrder->order_no,
|
||
'amount' => (float)$paymentOrder->amount,
|
||
'title' => $paymentOrder->title,
|
||
'notifyClass' => $paymentOrder->notify_class,
|
||
'payType' => SysConst::$cxPayTypeEnBalance,
|
||
]);
|
||
if ($po->amount > 0) {
|
||
//账户余额变动
|
||
$order_type = UniqueOrderNo::getOrderTypeByOrderNo($po->orderNo);
|
||
$ext = "";
|
||
$res = Balance::userWalletLog($user->id, Balance::TYPE_PAY, $po->amount, $po->title, $order_type, $po->orderNo, $ext, $paymentOrderUnion->cx_mch_id);
|
||
if($res['code'] != SysErrCode::$apiReturnSuccess){
|
||
$t->rollBack();
|
||
return Model::asReturnError($res['msg']);
|
||
}
|
||
}
|
||
$order = Order::findOne(['order_no' => $paymentOrder->order_no]);
|
||
if($order->integralMallOrder->integral_num > 0){
|
||
//积分账户变动
|
||
$order_type = UniqueOrderNo::getOrderTypeByOrderNo($order->order_no);
|
||
$ext = "";
|
||
$res = Integral::userIntegralWalletLog($user->id, Integral::TYPE_PAY, $order->integralMallOrder->integral_num, $po->title, $order_type, $order->order_no, $ext, $order->cx_mch_id);
|
||
if($res['code'] != SysErrCode::$apiReturnSuccess){
|
||
$t->rollBack();
|
||
return Model::asReturnError($res['msg']);
|
||
}
|
||
}
|
||
$NotifyClass = $paymentOrder->notify_class;
|
||
if(class_exists($NotifyClass)){
|
||
/** @var PaymentNotify $notifyObject */
|
||
$notifyObject = new $NotifyClass();
|
||
try {
|
||
$resp = $notifyObject->notify($po);
|
||
if($resp['code'] != 0){
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$resp['msg']}";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
} catch (\Exception $exception) {
|
||
$exp_err = $exception->getMessage();
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$exp_err}";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
} else {
|
||
//记录错误
|
||
$msg = "[ORDER_NO:{$paymentOrder->order_no}] ERR_MSG:{$paymentOrder->notify_class}不存在";
|
||
\Yii::error($msg,'NotifyPayment');
|
||
}
|
||
}
|
||
$t->commit();
|
||
} catch (\Exception $e) {
|
||
$t->rollBack();
|
||
return Model::asReturnError($e->getMessage());
|
||
}
|
||
return Model::asReturnSuccess();
|
||
}
|
||
|
||
|
||
private function getNotifyUrl($action)
|
||
{
|
||
$url = \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/notify/payment/' . $action;
|
||
return $url;
|
||
}
|
||
|
||
/**
|
||
* @param PaymentTransfer $paymentTransfer
|
||
* @return array
|
||
*/
|
||
public function transfer($paymentTransfer)
|
||
{
|
||
if (!$paymentTransfer instanceof PaymentTransfer) {
|
||
return Model::asReturnError('无效的参数,参数不是有效的payment\\PaymentTransfer对象');
|
||
}
|
||
$model = \app\models\PaymentTransfer::find()
|
||
->where([
|
||
'transfer_order_no' => $paymentTransfer->order_no,
|
||
'user_id' => $paymentTransfer->user->id,
|
||
'cx_mch_id' => $paymentTransfer->cx_mch_id
|
||
])->one();
|
||
if($model == null){
|
||
$model = new \app\models\PaymentTransfer();
|
||
$model->cx_mch_id = $paymentTransfer->cx_mch_id;
|
||
$model->user_id = $paymentTransfer->user->id;
|
||
$model->order_no = UniqueOrderNo::generate(UniqueOrderNo::ORDER_TYPE_TRANSFER, "\\app\\models\\PaymentTransfer");
|
||
$model->transfer_order_no = $paymentTransfer->order_no;
|
||
$model->amount = $paymentTransfer->amount;
|
||
$model->pay_type = $paymentTransfer->transfer_type;
|
||
$model->is_pay = 0;
|
||
$model->title = $paymentTransfer->title;
|
||
if(!$model->save())
|
||
return (new Model())->getModelError($model);
|
||
}
|
||
if($model->is_pay == 1){
|
||
return Model::asReturnError("该订单号已经打款,请勿重复操作");
|
||
}
|
||
|
||
try{
|
||
$class = $this->transferClass($model->pay_type);
|
||
if ($class->transfer($model, $paymentTransfer->user)) {
|
||
return Model::asReturnSuccess();
|
||
} else {
|
||
throw new PaymentException();
|
||
}
|
||
} catch (PaymentException $ex){
|
||
return Model::asReturnError($ex->getMessage());
|
||
}
|
||
}
|
||
|
||
private function transferClass($type)
|
||
{
|
||
switch ($type){
|
||
case PaymentTransfer::TRANSFER_TYPE_WXPAY:
|
||
$class = "app\\models\\common\\payment\\WxpayTransfer";
|
||
break;
|
||
default:
|
||
throw new PaymentException("无效的转账方式");
|
||
}
|
||
if (!class_exists($class)) {
|
||
throw new PaymentException("缺少{$class}对象");
|
||
}
|
||
|
||
return new $class();
|
||
}
|
||
}
|
||
|