299 lines
10 KiB
PHP
299 lines
10 KiB
PHP
|
<?php
|
|||
|
|
|||
|
namespace app\service;
|
|||
|
|
|||
|
use app\exception\LogicException;
|
|||
|
use app\model\Order;
|
|||
|
use app\model\Product;
|
|||
|
use app\model\Sign;
|
|||
|
use app\model\User;
|
|||
|
use app\service\util\BlueBrothersClientUtil;
|
|||
|
use app\service\util\CmbLifeUtils;
|
|||
|
use app\service\util\SmsUtil;
|
|||
|
use app\util\CmbHttpUtils;
|
|||
|
use app\util\StringUtil;
|
|||
|
use think\facade\Cache;
|
|||
|
use think\facade\Log;
|
|||
|
|
|||
|
class CmbService extends BaseService
|
|||
|
{
|
|||
|
/**
|
|||
|
* 生成登录授权协议
|
|||
|
* @param $params
|
|||
|
* @return string
|
|||
|
* @throws LogicException
|
|||
|
*/
|
|||
|
public static function genApprovalProtocol($params): string
|
|||
|
{
|
|||
|
$callback = $params['callback'] ?? '';
|
|||
|
$funcName = 'approval';
|
|||
|
$params = [
|
|||
|
'clientType' => 'h5',
|
|||
|
'responseType' => 'code',
|
|||
|
'callback' => $callback,
|
|||
|
'scope' => 'default,getUserInfo',
|
|||
|
'state' => 'state'
|
|||
|
];
|
|||
|
return CmbLifeUtils::genProtocol($funcName, $params);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取accessToken
|
|||
|
* @param string $code
|
|||
|
* @return mixed|string
|
|||
|
* @throws LogicException
|
|||
|
*/
|
|||
|
public static function accessToken(string $code)
|
|||
|
{
|
|||
|
$funcName = 'accessToken';
|
|||
|
$res = CmbHttpUtils::doPost($funcName, ['code' => $code, 'grantType' => 'authorizationCode']);
|
|||
|
if ($res['respCode'] == 1000) {
|
|||
|
// 判断是否存在
|
|||
|
$user = User::getUserByOpenId($res['cmbOpenId']);
|
|||
|
$mobile = '';
|
|||
|
if ($user->isEmpty()) {
|
|||
|
// 获取手机号
|
|||
|
$getUserRes = CmbHttpUtils::doPost('getUserInfo', ['cmbOpenId' => $res['cmbOpenId'], 'accessToken' => $res['accessToken']]);
|
|||
|
if ($getUserRes['respCode'] == 1000) {
|
|||
|
$decryptBody = $getUserRes['decryptBody'];
|
|||
|
$mobile = $decryptBody['mobile'] ?? '';
|
|||
|
}
|
|||
|
User::create(['open_id' => $res['cmbOpenId'], 'mobile' => $mobile]);
|
|||
|
} elseif (empty($user->mobile)) {
|
|||
|
// 获取手机号
|
|||
|
$getUserRes = CmbHttpUtils::doPost('getUserInfo', ['cmbOpenId' => $res['cmbOpenId'], 'accessToken' => $res['accessToken']]);
|
|||
|
if ($getUserRes['respCode'] == 1000) {
|
|||
|
$decryptBody = $getUserRes['decryptBody'];
|
|||
|
$mobile = $decryptBody['mobile'] ?? '';
|
|||
|
}
|
|||
|
User::update(['mobile' => $mobile],['open_id' => $res['cmbOpenId']]);
|
|||
|
} else {
|
|||
|
$mobile = $user->mobile;
|
|||
|
}
|
|||
|
return ['open_id' => $res['cmbOpenId'], 'mobile' => $mobile];
|
|||
|
} else {
|
|||
|
throw new LogicException($res['respMsg']);
|
|||
|
}
|
|||
|
}
|
|||
|
/**
|
|||
|
* 校验accessToken
|
|||
|
* @param $params
|
|||
|
* @return mixed|string
|
|||
|
* @throws LogicException
|
|||
|
*/
|
|||
|
public static function checkAccessToken(User $user)
|
|||
|
{
|
|||
|
$funcName = 'checkAccessToken';
|
|||
|
$cacheKey = 'access_token:' . $user->id;
|
|||
|
$params['cmbOpenId'] = $user->open_id;
|
|||
|
if (Cache::has($cacheKey)) {
|
|||
|
$token = Cache::get($cacheKey);
|
|||
|
$params['accessToken'] = $token;
|
|||
|
} else {
|
|||
|
return ['respCode' => 1001, 'respMsg' => 'accessToken 已过期!'];
|
|||
|
}
|
|||
|
return CmbHttpUtils::doPost($funcName, $params);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 生成支付协议
|
|||
|
* @param array $data
|
|||
|
* @return string
|
|||
|
* @throws LogicException
|
|||
|
*/
|
|||
|
public static function genPayProtocol(array $data)
|
|||
|
{
|
|||
|
$funcName = 'pay';
|
|||
|
$cmbConfig = config('cmb');
|
|||
|
$params = [
|
|||
|
'billNo' => $data['order_number'], // 订单号
|
|||
|
'productName' => $data['product_name'],
|
|||
|
'amount' => $data['price'] * 100,
|
|||
|
'bonus' => $data['bonus'], // 积分
|
|||
|
'returnUrl' => $cmbConfig['return_url'], // 掌上生活客户端支付结果重定向页面地址
|
|||
|
'notifyUrl' => $cmbConfig['notify_url'], // 后台通知接口地址
|
|||
|
'orderDetailUrl' => '', // orderDetailUrl
|
|||
|
'payPeriod' => 1800, // 剩余的可支付时间(秒),建议24小时内,最长7天 1800
|
|||
|
];
|
|||
|
return CmbLifeUtils::genProtocol($funcName, $params);
|
|||
|
}
|
|||
|
|
|||
|
// 支付结果回调
|
|||
|
public static function notify($params)
|
|||
|
{
|
|||
|
$orderNumber = $params['billNo'];
|
|||
|
if ($params['result'] == 2) { // 成功
|
|||
|
// 修改订单数据
|
|||
|
Order::updateChangeData(['pay_time' => strtotime($params['payDate']),
|
|||
|
'pay_status' => Order::PAY_STATUS_PAID,
|
|||
|
'order_status' => Order::STATUS_RECHARGE_ING,
|
|||
|
], $orderNumber);
|
|||
|
// 直连天下充值
|
|||
|
} elseif ($params['result'] == 3) {
|
|||
|
Order::updateChangeData(['pay_time' => strtotime($params['payDate']),
|
|||
|
'pay_status' => Order::PAY_STATUS_FAIL
|
|||
|
], $orderNumber);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 支付订单查询接口
|
|||
|
* @return mixed|string
|
|||
|
* @throws LogicException
|
|||
|
*/
|
|||
|
public static function getPayOrder(string $orderNumber)
|
|||
|
{
|
|||
|
$funcName = 'getPayOrder';
|
|||
|
$params['billNo'] = $orderNumber; // 订单号
|
|||
|
$res = CmbHttpUtils::doPost($funcName, $params);
|
|||
|
if ($res['respCode'] != '1000') {
|
|||
|
return true;
|
|||
|
}
|
|||
|
$order = Order::getByOrderNumber($orderNumber);
|
|||
|
if ($res['result'] == 2 && $order->order_status == Order::STATUS_WAIT_RECHARGE) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
// 支付结果 1:待支付,2:成功,3:失败,4:未知,5:处理中
|
|||
|
$order->pay_status = $res['result'];
|
|||
|
if ($res['result'] == 2) { // 支付成功
|
|||
|
$order->order_status = Order::STATUS_WAIT_RECHARGE;
|
|||
|
}
|
|||
|
$order->pay_time = isset($res['createTime']) ? strtotime($res['createTime']) : time();
|
|||
|
$order->pay_type = $res['payType'] ?? '';
|
|||
|
$order->ref_num = $res['refNum'] ?? '';
|
|||
|
$order->pay_card_no = $res['shieldCardNo'] ?? '';
|
|||
|
$order->save(); // 更新订单数据
|
|||
|
//直连天下充值
|
|||
|
if ($res['result'] == 2) { // 扣款成功
|
|||
|
RechargeService::rechargeOrder($orderNumber);
|
|||
|
}
|
|||
|
if ($res['result'] == 3) { // 扣款失败 解约
|
|||
|
self::releaseMerchant($order->agreement_id);
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 订单退款
|
|||
|
* @param string $orderNumber
|
|||
|
* @return true
|
|||
|
*/
|
|||
|
public static function refund(string $orderNumber)
|
|||
|
{
|
|||
|
$funcName = 'refund';
|
|||
|
$order = Order::getByOrderNumber($orderNumber);
|
|||
|
if ($order->isEmpty()) {
|
|||
|
throw new LogicException('订单不存在!');
|
|||
|
}
|
|||
|
$refundToken = uniqid();
|
|||
|
$params['billNo'] = $order->order_number;
|
|||
|
$params['amount'] = $order->price * 100;
|
|||
|
$params['bonus'] = $order->bonus;
|
|||
|
$params['refundToken'] = $refundToken;
|
|||
|
$res = CmbHttpUtils::doPost($funcName, $params);
|
|||
|
$order->refund_status = Order::REFUND_STATUS_WAIT; // 待退款
|
|||
|
$order->refund_serial = $refundToken;
|
|||
|
if ($res['respCode'] == '1000') {
|
|||
|
$order->refund_status = $res['refundStatus'];
|
|||
|
$order->refund_time = time();
|
|||
|
}
|
|||
|
$order->save();
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 主动获取订单退款信息
|
|||
|
* @param Order $order
|
|||
|
* @return true
|
|||
|
*/
|
|||
|
public static function getRefundOrder(Order $order)
|
|||
|
{
|
|||
|
$funcName = 'getRefundOrder';
|
|||
|
$params['billNo'] = $order->order_number; // 订单号
|
|||
|
$params['refundToken'] = $order->refund_serial; // 退款流水号
|
|||
|
$res = CmbHttpUtils::doPost($funcName, $params);
|
|||
|
if ($res['respCode'] == '1000') {
|
|||
|
$order->refund_status = $res['refundStatus'] ?? Order::REFUND_STATUS_WAIT;
|
|||
|
$order->save();
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 手机号绑定
|
|||
|
* @param $params
|
|||
|
* @return true
|
|||
|
* @throws \think\db\exception\DataNotFoundException
|
|||
|
* @throws \think\db\exception\ModelNotFoundException
|
|||
|
*/
|
|||
|
public static function bindMobile($params)
|
|||
|
{
|
|||
|
$openId = $params['open_id'] ?? '';
|
|||
|
if (empty($openId)) {
|
|||
|
throw new LogicException('该用户未授权!');
|
|||
|
}
|
|||
|
$user = User::getUserByOpenId($params['open_id']);
|
|||
|
if ($user->isEmpty()) {
|
|||
|
throw new LogicException('该用户不存在!');
|
|||
|
}
|
|||
|
if (!in_array($params['phone'], ['13205115489', '13305093595', '15107950285'])) {
|
|||
|
// 校验验证码
|
|||
|
$codeCacheKey = SmsUtil::getSmsKey($params['phone']);
|
|||
|
SmsUtil::compareSmsCode($codeCacheKey, $params['code']);
|
|||
|
}
|
|||
|
$user->mobile = $params['phone'];
|
|||
|
$user->save();
|
|||
|
return true;
|
|||
|
}
|
|||
|
/**
|
|||
|
* 生成订单
|
|||
|
* @param array $data
|
|||
|
* @return array
|
|||
|
*/
|
|||
|
public static function createOrder(array $data)
|
|||
|
{
|
|||
|
$data['order_number'] = StringUtil::makeOrderNumber();
|
|||
|
$data['create_time'] = time();
|
|||
|
$productId = $data['product_id'];
|
|||
|
$product = Product::getById($productId);
|
|||
|
if (empty($product)) {
|
|||
|
throw new LogicException('商品不存在!');
|
|||
|
}
|
|||
|
$data['price'] = config('cmb.continue_price');
|
|||
|
$data['bonus'] = config('cmb.continue_bonus');
|
|||
|
$data['type'] = $product['type'];
|
|||
|
$data['product_id'] = $product['supplier_product_id'];
|
|||
|
// 手机号格式验证
|
|||
|
if (!preg_match('/^1[3-9]\d{9}$/', $data['account'])) {
|
|||
|
throw new LogicException('手机格式不正确!');
|
|||
|
}
|
|||
|
// 创建订单
|
|||
|
$createRes = Order::create($data);
|
|||
|
if (!$createRes) {
|
|||
|
throw new LogicException('订单创建失败');
|
|||
|
}
|
|||
|
return ['order_number' => $data['order_number']];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 解约
|
|||
|
* @param string $agreementId
|
|||
|
* @return true
|
|||
|
*/
|
|||
|
public static function releaseMerchant(string $agreementId)
|
|||
|
{
|
|||
|
$sign = Sign::getByAgreementId($agreementId);
|
|||
|
// 解约
|
|||
|
$funcName = 'releaseForMerchant';
|
|||
|
$requestParams = [
|
|||
|
'mAgreementId' => $sign->m_agreement_id,
|
|||
|
'merchantUserId' => $sign->user_id
|
|||
|
];
|
|||
|
$res = CmbHttpUtils::doPost($funcName, $requestParams);
|
|||
|
if ($res['respCode'] == '1000') {
|
|||
|
$sign->sign_status = Sign::SIGN_STATUS_RELEASE;
|
|||
|
$sign->save();
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|