Phase1 后端核心:
- 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess)
- SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机)
- StoreOrderCreateServices 周期循环佣金计算
- StoreOrderTakeServices 佣金发放后同步冻结积分
- StoreProductServices/StoreProduct 保存 is_queue_goods
Phase2 后端接口:
- GET /api/hjf/brokerage/progress 佣金周期进度
- GET /api/hjf/assets/overview 资产总览
- HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务
- PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口
- GET /adminapi/hjf/points/release_log 积分日志接口
Phase3 前端清理:
- hjfCustom.js 路由精简(仅保留 points/log)
- hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口
- pages.json 公排→推荐佣金/佣金记录/佣金规则
Phase4-5 前端改造:
- queue/status.vue 推荐佣金进度页整体重写
- 商品详情/订单确认/支付结果页文案与逻辑改造
- 个人中心/资产页/引导页/规则页文案改造
- HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造
- 推广中心嵌入佣金进度摘要
- hjfMockData.js 全量更新(公排字段→佣金字段)
Phase6 Admin 增强:
- 用户列表新增 frozen_points/available_points 列及不考核操作按钮
- hjfPoints.js USE_MOCK=false 对接真实积分日志接口
Phase7 配置文档:
- docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单
Made-with: Cursor
340 lines
10 KiB
PHP
340 lines
10 KiB
PHP
<?php
|
||
/**
|
||
* +----------------------------------------------------------------------
|
||
* | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||
* +----------------------------------------------------------------------
|
||
* | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
|
||
* +----------------------------------------------------------------------
|
||
* | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||
* +----------------------------------------------------------------------
|
||
* | Author: CRMEB Team <admin@crmeb.com>
|
||
* +----------------------------------------------------------------------
|
||
*/
|
||
|
||
namespace crmeb\services\wechat\client\pay;
|
||
|
||
use crmeb\services\wechat\util\Helper;
|
||
use crmeb\services\wechat\util\XML;
|
||
use EasyWeChat\Kernel\HttpClient\Response;
|
||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||
use think\helper\Arr;
|
||
use EasyWeChat\Pay\Client;
|
||
use EasyWeChat\Kernel\Contracts\Config;
|
||
|
||
/**
|
||
* 创建订单
|
||
* Class OrderClient
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/26
|
||
* @package crmeb\services\wechat\client\pay
|
||
*/
|
||
class OrderClient
|
||
{
|
||
|
||
/**
|
||
* OrderClient constructor.
|
||
* @param Client $api
|
||
* @param Config $config
|
||
*/
|
||
public function __construct(protected Client $api, protected Config $config)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* 小程序创建订单
|
||
* @param array $params
|
||
* @return Response|ResponseInterface
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function createorder(array $params): ResponseInterface|Response
|
||
{
|
||
$data = [
|
||
'openid' => $params['openid'],//支付者的openid
|
||
'combine_trade_no' => $params['out_trade_no'],//商家合单支付总交易单号
|
||
'expire_time' => time() + 7000,
|
||
'sub_orders' => [
|
||
[
|
||
'mchid' => $this->config->get('mch_id'),
|
||
'amount' => (int)$params['total_fee'],
|
||
'trade_no' => $params['out_trade_no'],
|
||
'description' => $params['body'],
|
||
]
|
||
],
|
||
];
|
||
return $this->api->postJson('shop/pay/createorder', $data);
|
||
}
|
||
|
||
/**
|
||
* 小程序退款
|
||
* @param array $params
|
||
* @return Response|ResponseInterface
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function refundorder(array $params): ResponseInterface|Response
|
||
{
|
||
$data = [
|
||
'openid' => $params['openid'],
|
||
'mchid' => $this->config->get('mch_id'),
|
||
'trade_no' => $params['trade_no'],
|
||
'transaction_id' => $params['transaction_id'],
|
||
'refund_no' => $params['refund_no'],
|
||
'total_amount' => (int)$params['total_amount'],
|
||
'refund_amount' => (int)$params['refund_amount'],
|
||
];
|
||
return $this->api->postJson('shop/pay/refundorder', $data);
|
||
}
|
||
|
||
/**
|
||
* 付款码支付
|
||
* @param array $params
|
||
* @return ResponseInterface
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function pay(array $params): ResponseInterface
|
||
{
|
||
$params['appid'] = $this->config->get('app_id');
|
||
|
||
return $this->api->request('post', 'pay/micropay', $params);
|
||
}
|
||
|
||
/**
|
||
* 下单
|
||
* @param array $params
|
||
* @return ResponseInterface
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/14
|
||
*/
|
||
public function unify(array $params): ResponseInterface
|
||
{
|
||
if (empty($params['spbill_create_ip'])) {
|
||
$params['spbill_create_ip'] = request()->ip();
|
||
}
|
||
|
||
$params['notify_url'] = $params['notify_url'] ?? $this->config->get('notify_url');
|
||
|
||
return $this->request('pay/unifiedorder', $params);
|
||
}
|
||
|
||
/**
|
||
* 发起请求
|
||
* @param string $endpoint
|
||
* @param array $params
|
||
* @param string $method
|
||
* @param array $options
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/14
|
||
*/
|
||
protected function request(string $endpoint, array $params = [], string $method = 'post', array $options = []): ResponseInterface
|
||
{
|
||
$base = [
|
||
'appid' => $this->config->get('app_id'),
|
||
'mch_id' => $this->config->get('mch_id'),
|
||
'nonce_str' => uniqid(),
|
||
];
|
||
|
||
$params = array_filter(array_filter(array_merge($base, [], $params)), 'strlen');
|
||
|
||
$secretKey = $this->config->get('v2_secret_key');
|
||
|
||
$encryptMethod = Helper::getEncryptMethod(Arr::get($params, 'sign_type', 'MD5'), $secretKey);
|
||
|
||
$params['sign'] = Helper::generateSign($params, $secretKey, $encryptMethod);
|
||
|
||
$options = array_merge([
|
||
'body' => XML::build($params),
|
||
], $options);
|
||
|
||
return $this->api->request(strtoupper($method), $endpoint, $options);
|
||
}
|
||
|
||
/**
|
||
* 商户订单号退款
|
||
* @param string $number
|
||
* @param string $refundNumber
|
||
* @param int $totalFee
|
||
* @param int $refundFee
|
||
* @param array $optional
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function byOutTradeNumber(string $number, string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
|
||
{
|
||
return $this->refund($refundNumber, $totalFee, $refundFee, array_merge($optional, ['out_trade_no' => $number]));
|
||
}
|
||
|
||
/**
|
||
* 支付回执单号退款
|
||
* @param string $transactionId
|
||
* @param string $refundNumber
|
||
* @param int $totalFee
|
||
* @param int $refundFee
|
||
* @param array $optional
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function byTransactionId(string $transactionId, string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
|
||
{
|
||
return $this->refund($refundNumber, $totalFee, $refundFee, array_merge($optional, ['transaction_id' => $transactionId]));
|
||
}
|
||
|
||
/**
|
||
* 退款
|
||
* @param string $refundNumber
|
||
* @param int $totalFee
|
||
* @param int $refundFee
|
||
* @param array $optional
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
protected function refund(string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
|
||
{
|
||
$params = array_merge([
|
||
'out_refund_no' => $refundNumber,
|
||
'total_fee' => $totalFee,
|
||
'refund_fee' => $refundFee,
|
||
'appid' => $this->config->get('app_id'),
|
||
], $optional);
|
||
|
||
return $this->safeRequest('secapi/pay/refund', $params);
|
||
}
|
||
|
||
/**
|
||
* 撤销订单
|
||
* @param string $outTradeNumber
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function reverseByOutTradeNumber(string $outTradeNumber): Response
|
||
{
|
||
return $this->reverse($outTradeNumber, 'out_trade_no');
|
||
}
|
||
|
||
/**
|
||
* 撤销订单
|
||
* @param string $number
|
||
* @param string $type
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
protected function reverse(string $number, string $type): Response
|
||
{
|
||
$params = [
|
||
'appid' => $this->config->get('app_id'),
|
||
$type => $number,
|
||
];
|
||
|
||
return $this->safeRequest('secapi/pay/reverse', $params);
|
||
}
|
||
|
||
/**
|
||
* 查询退款订单
|
||
* @param string $number
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function queryByOutTradeNumber(string $number): Response
|
||
{
|
||
return $this->query([
|
||
'out_trade_no' => $number,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 查询订单
|
||
* @param array $params
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
protected function query(array $params): Response
|
||
{
|
||
$params['appid'] = $this->config->get('app_id');
|
||
|
||
return $this->request('pay/orderquery', $params);
|
||
}
|
||
|
||
/**
|
||
* 企业付款到零钱
|
||
* @param array $params
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
public function toBalance(array $params): Response
|
||
{
|
||
$base = [
|
||
'mch_id' => null,
|
||
'mchid' => $this->config->get('mch_id'),
|
||
'mch_appid' => $this->config->get('app_id'),
|
||
];
|
||
|
||
if (empty($params['spbill_create_ip'])) {
|
||
$params['spbill_create_ip'] = request()->ip();
|
||
}
|
||
|
||
return $this->safeRequest('mmpaymkttransfers/promotion/transfers', array_merge($base, $params));
|
||
}
|
||
|
||
/**
|
||
* 退款请求
|
||
* @param string $endpoint
|
||
* @param array $params
|
||
* @param string $method
|
||
* @param array $options
|
||
* @return Response
|
||
* @throws TransportExceptionInterface
|
||
* @author 等风来
|
||
* @email 136327134@qq.com
|
||
* @date 2023/9/15
|
||
*/
|
||
protected function safeRequest(string $endpoint, array $params, string $method = 'post', array $options = []): Response
|
||
{
|
||
$options = array_merge([
|
||
'cert' => $this->config->get('certificate'),
|
||
'ssl_key' => $this->config->get('private_key'),
|
||
], $options);
|
||
|
||
return $this->request($endpoint, $params, $method, $options);
|
||
}
|
||
|
||
|
||
}
|