291 lines
11 KiB
PHP
291 lines
11 KiB
PHP
<?php
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: zn
|
||
* Date: 2017/8/9
|
||
* Time: 11:51
|
||
*/
|
||
|
||
namespace common\modules\qixunpay;
|
||
|
||
|
||
use common\modules\achievement\AchievementUtil;
|
||
use common\modules\card\CardUtil;
|
||
use common\models\User;
|
||
use common\services\UserService;
|
||
use common\modules\rebate\RebateUtil;
|
||
use common\modules\card\vo\Card;
|
||
use common\modules\dailytask\DailyTaskUtil;
|
||
use common\modules\qixunpay\vo\Pay;
|
||
use common\modules\safe\SafeUtil;
|
||
use common\modules\systemlog\SystemLogUtil;
|
||
use common\modules\vip\VipUtil;
|
||
use common\services\GameConfigServices;
|
||
use common\services\ItemServices;
|
||
use common\services\ResultStatusServices;
|
||
use common\services\StatusException;
|
||
use common\utils\MoneyUtil;
|
||
use common\utils\RedisKeyUtil;
|
||
use common\utils\YiiComponentUtil;
|
||
use Yii;
|
||
|
||
class PayUtil
|
||
{
|
||
const PAY_STATUS_WAIT = 0;//等待支付
|
||
const PAY_STATUS_COMPLETE = 1;//支付成功
|
||
const PAY_STATUS_FAIL = 2;//支付失败
|
||
const PAY_STATUS_LIST = [
|
||
self::PAY_STATUS_WAIT,
|
||
self::PAY_STATUS_COMPLETE,
|
||
self::PAY_STATUS_FAIL,
|
||
];
|
||
|
||
const PAY_TYPE_WX_INSIDE = 0;//微信内支付
|
||
const PAY_TYPE_WX_SCAN = 1;//微信扫码支付
|
||
const PAY_TYPE_LIST = [
|
||
self::PAY_TYPE_WX_INSIDE,
|
||
self::PAY_TYPE_WX_SCAN,
|
||
];
|
||
|
||
public static function pay($userID, $rmb, $gem, $payType, $configID, $configType = 0)
|
||
{
|
||
$rmb = (float)$rmb;
|
||
$gem = (int)$gem;
|
||
|
||
if (empty($userID) || $rmb <= 0 || !in_array($payType, self::PAY_TYPE_LIST))
|
||
throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
|
||
return SafeUtil::dbOperate(function ($userID, $rmb, $gem, $payType, $configID, $configType) {
|
||
|
||
if ($configType == 1) {
|
||
//周卡月卡
|
||
$card = Card::findByUserIDAndItemID($userID, $configID);
|
||
if (!empty($card) && $card->count > 0) throw new StatusException(ResultStatusServices::RS_ITEM_CAN_NOT_BY_MORE);
|
||
|
||
$config = GameConfigServices::getParamByPath('card.' . $configID);
|
||
if (empty($config)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
} elseif($configType == 0) {
|
||
if ($gem <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
}else{
|
||
|
||
}
|
||
|
||
$orderID = OrderCreater::createOrderID();
|
||
|
||
$payData = new Pay();
|
||
$payData->user_id = $userID;
|
||
$payData->order_id = $orderID;
|
||
$payData->price = $rmb;
|
||
$payData->gem = $gem;
|
||
$payData->status = self::PAY_STATUS_WAIT;
|
||
$payData->config_id = $configID;
|
||
$payData->config_type = $configType;
|
||
|
||
if (!$payData->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR);
|
||
|
||
if ($configType == 0) {
|
||
$orderConfig = [
|
||
// 'trade_type' => 'JSAPI', // JSAPI,NATIVE,APP...
|
||
'body' => '购买钻石',
|
||
'detail' => sprintf('购买%d个钻石', $gem),
|
||
'out_trade_no' => $orderID,
|
||
'total_fee' => $rmb * 100, // 单位:分
|
||
// 'openid' => $openID, // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
|
||
];
|
||
}
|
||
elseif ($configType == 1)
|
||
{
|
||
$orderConfig = [
|
||
// 'trade_type' => 'JSAPI', // JSAPI,NATIVE,APP...
|
||
'body' => "购买{$config['name']}",
|
||
'detail' => "购买{$config['name']}",
|
||
'out_trade_no' => $orderID,
|
||
'total_fee' => $rmb * 100, // 单位:分
|
||
// 'openid' => $openID, // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
|
||
];
|
||
}else{
|
||
$orderConfig = [
|
||
// 'trade_type' => 'JSAPI', // JSAPI,NATIVE,APP...
|
||
'body' => "激活账号",
|
||
'detail' => "激活账号",
|
||
'out_trade_no' => $orderID,
|
||
'total_fee' => $rmb * 100, // 单位:分
|
||
// 'openid' => $openID, // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
|
||
];
|
||
}
|
||
return [$rmb, $orderID];
|
||
//下面是之前配置微信支付的
|
||
if ($payType == self::PAY_TYPE_WX_INSIDE) {
|
||
$wxUser = YiiComponentUtil::easywechat()->getUserInfo();
|
||
$orderConfig['trade_type'] = 'JSAPI';
|
||
$orderConfig['openid'] = $wxUser->openID;
|
||
}
|
||
if ($payType == self::PAY_TYPE_WX_SCAN) {
|
||
$orderConfig['trade_type'] = 'NATIVE';
|
||
}
|
||
|
||
$result = YiiComponentUtil::easywechat()->payApp()->order->unify($orderConfig);
|
||
|
||
Yii::warning("微信支付 " . json_encode($result));
|
||
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
|
||
$prepayId = $result['prepay_id'];
|
||
// $scanURL = $result['code_url'];
|
||
// $json = YiiComponentUtil::easywechat()->payment->configForPayment($prepayId);
|
||
|
||
$insidePayConfig = null;
|
||
if ($payType == self::PAY_TYPE_WX_INSIDE) $insidePayConfig = YiiComponentUtil::easywechat()->payApp()->jssdk->sdkConfig($prepayId);
|
||
return [$insidePayConfig, $orderID];
|
||
}
|
||
|
||
throw new StatusException(ResultStatusServices::RS_WX_PAY_ERROR, $result);
|
||
}, [$userID, $rmb, $gem, $payType, $configID, $configType]);
|
||
|
||
}
|
||
|
||
public static function payCallBack()
|
||
{
|
||
//设置时区
|
||
date_default_timezone_set('Asia/Shanghai');
|
||
//接受ISPAY通知返回的支付渠道
|
||
$Array['payChannel'] = $_POST['payChannel']; //(支付通道)
|
||
//接受ISPAY通知返回的支付金额
|
||
$Array['Money'] = $_POST['Money']; //(单位分)
|
||
//接受ISPAY通知返回的订单号
|
||
$Array['orderNumber'] = $_POST['orderNumber']; //(商户订单号)
|
||
//接受ISPAY通知返回的附加数据
|
||
$Array['attachData'] = $_POST['attachData']; //(商户自定义附加数据)
|
||
//接受ISPAY通知返回的回调签名
|
||
$Array['callbackSign'] = $_POST['callbackSign']; //(详情查看ISPAY开发文档)
|
||
file_put_contents('111111.txt',json_encode($Array));
|
||
//回调签名校验
|
||
|
||
//接受ISPAY通知返回的支付渠道
|
||
$Array['payChannel'] = 'alipay'; //(支付通道)
|
||
//接受ISPAY通知返回的支付金额
|
||
$Array['Money'] = '100'; //(单位分)
|
||
//接受ISPAY通知返回的订单号
|
||
$Array['orderNumber'] = '20190411193452562273'; //(商户订单号)
|
||
//接受ISPAY通知返回的附加数据
|
||
$Array['attachData'] = '10957'; //(商户自定义附加数据)
|
||
//接受ISPAY通知返回的回调签名
|
||
$Array['callbackSign'] = '8e8337472ca08baafe354f6969f7be58'; //(详情查看ISPAY开发文档)
|
||
if(self::callbackSignCheck($Array)){
|
||
$payData = Pay::findByOrderID($_POST['attachData']);
|
||
if (empty($payData)) return '订单不存在';
|
||
|
||
|
||
if ($payData->status != PayUtil::PAY_STATUS_WAIT) return '已经支付过';
|
||
$payData->pay_from=$_POST['payChannel'];
|
||
$payData->status = PayUtil::PAY_STATUS_COMPLETE;
|
||
if (!$payData->save()) return '保存失败';
|
||
echo "SUCCESS";
|
||
return self::doOrder($orderID);
|
||
|
||
}else{
|
||
echo "callbackSign fail!";
|
||
exit;
|
||
}
|
||
|
||
exit;
|
||
|
||
Yii::warning('支付回调');
|
||
Yii::warning(Yii::$app->request->post());
|
||
|
||
$response = YiiComponentUtil::easywechat()->payApp()->handlePaidNotify(function ($message, $fail) {
|
||
$orderID = $message['out_trade_no'];
|
||
Yii::warning('支付返回订单ID:' . $orderID);
|
||
|
||
// 用户是否支付成功
|
||
if ($message['result_code'] === 'SUCCESS') {
|
||
// 不是已经支付状态则修改为已经支付状态
|
||
|
||
return self::doOrder($orderID);
|
||
|
||
} else { // 用户支付失败
|
||
$payData = Pay::findByOrderID($orderID);
|
||
if (empty($payData)) return '订单不存在';
|
||
|
||
if ($payData->status != PayUtil::PAY_STATUS_WAIT) return '已经支付过';
|
||
|
||
$payData->status = PayUtil::PAY_STATUS_FAIL;
|
||
if (!$payData->save()) return '保存失败';
|
||
}
|
||
});
|
||
$response->send();
|
||
}
|
||
|
||
/**
|
||
* 查询订单
|
||
* @param $orderID
|
||
* @return mixed
|
||
* @throws StatusException
|
||
*/
|
||
public static function checkOrder($orderID)
|
||
{
|
||
$r = YiiComponentUtil::easywechat()->payApp()->order->queryByOutTradeNumber($orderID);
|
||
Yii::warning('支付订单查询:' . json_encode($r));
|
||
if ($r['return_code'] == 'SUCCESS' && $r['result_code'] == 'SUCCESS' && $r['trade_state'] == 'SUCCESS') {
|
||
//支付成功
|
||
return self::doOrder($orderID);
|
||
}
|
||
|
||
throw new StatusException(ResultStatusServices::RS_WX_PAY_ERROR, $r);
|
||
}
|
||
|
||
|
||
private static function callbackSignCheck($Array) {
|
||
if (self::Sign($Array) == $Array['callbackSign']) {
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
private static function Sign($Array) {
|
||
ksort($Array);
|
||
$stringA = "";
|
||
foreach ($Array as $k => $v) {
|
||
if ($k != "Sign" && $k != "callbackSign") {
|
||
$stringA .= $v;
|
||
}
|
||
}
|
||
$stringSignTemp = $stringA . 'efd7838b44c72e8a3633498581e32841';
|
||
$Sign = md5($stringSignTemp);
|
||
return $Sign;
|
||
}
|
||
private static function doOrder($orderID)
|
||
{
|
||
//支付成功
|
||
|
||
return SafeUtil::dbOperate(function ($orderID) {
|
||
return SafeUtil::redisLockOperate(function ($orderID) {
|
||
$payData = Pay::findByOrderID($orderID);
|
||
|
||
|
||
if ($payData->config_type == 0) {
|
||
$log = SystemLogUtil::get($payData->user_id, SystemLogUtil::TYPE_GEM, $payData->gem, 0, SystemLogUtil::FROM_TYPE_PAYPAL, ['order_id' => $orderID]);
|
||
MoneyUtil::checkAndModifyRes($payData->user_id, true, $payData->gem, ItemServices::ITEM_TYPE2_GEM, $log);
|
||
|
||
VipUtil::addVipExp($payData->user_id, $payData->gem);
|
||
} elseif ($payData->config_type == 1) {
|
||
//周卡月卡
|
||
CardUtil::buyCard($payData->user_id, $payData->config_id);
|
||
}else{
|
||
$userDbData = User::findById($payData->user_id);
|
||
$userDbData->isjihuo = 1;
|
||
|
||
//保存
|
||
$userDbData->save(true, ['isjihuo']);
|
||
}
|
||
//分销返点
|
||
|
||
//RebateUtil::addRebate($payData->user_id, $payData->price, RebateUtil::TYPE_BUY);
|
||
//成就
|
||
AchievementUtil::addCount($payData->user_id, AchievementUtil::ID_PAY_COUNT, 1);
|
||
DailyTaskUtil::addTaskCount($payData->user_id, DailyTaskUtil::TYPE_PAY_GEM, null, 1);
|
||
|
||
return true;
|
||
}, [$orderID], RedisKeyUtil::lockPayOrder($orderID));
|
||
|
||
}, [$orderID]);
|
||
}
|
||
} |