转账功能优化
This commit is contained in:
@@ -10,18 +10,22 @@ use app\common\service\AccountWithdrawService;
|
||||
use app\common\service\CategoryService;
|
||||
use app\common\service\DemandBiddingService;
|
||||
use app\common\service\DemandService;
|
||||
use app\common\service\EasyWeChatService;
|
||||
use app\common\service\GoodsService;
|
||||
use app\common\model\Category;
|
||||
use app\common\service\OrderService;
|
||||
use app\common\service\TransferAuthorizationService;
|
||||
use app\common\service\UserService;
|
||||
use EasyWeChat\Pay\Message as PayMessage;
|
||||
use fast\Tree;
|
||||
use think\Exception;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Log;
|
||||
use think\Validate;
|
||||
|
||||
class Account extends Api
|
||||
{
|
||||
protected $noNeedLogin = [];
|
||||
protected $noNeedLogin = ['transferAuthorizationNotify'];
|
||||
protected $noNeedRight = ['*'];
|
||||
|
||||
public function logs()
|
||||
@@ -94,4 +98,65 @@ class Account extends Api
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 免确认收款授权(发起/查询),供前端 wx.requestMerchantTransfer 拉起授权页
|
||||
* @ApiMethod (POST)
|
||||
*/
|
||||
public function transferAuthorization()
|
||||
{
|
||||
try {
|
||||
$user_id = $this->auth->id ?? 0;
|
||||
if (!$user_id) {
|
||||
throw new \Exception('请先登录');
|
||||
}
|
||||
$user = UserService::get($user_id);
|
||||
if (!$user) {
|
||||
throw new \Exception('用户不存在');
|
||||
}
|
||||
//授权详情展示账号名:优先微信实名(提现填写的姓名),其次昵称
|
||||
$displayName = $user->username ?: ($user->nickname ?: '');
|
||||
$res = TransferAuthorizationService::apply($user, $displayName);
|
||||
|
||||
$this->success('', $res);
|
||||
} catch (\Exception $e) {
|
||||
if ($e instanceof HttpResponseException) {
|
||||
throw $e;
|
||||
}
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 免确认收款授权结果回调(微信异步通知,已加入 noNeedLogin)
|
||||
* @return void
|
||||
*/
|
||||
public function transferAuthorizationNotify()
|
||||
{
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
try {
|
||||
// PSR-7 响应(SDK 已完成验签/解密,业务失败返回 500 由微信重试)
|
||||
$response = (new EasyWeChatService())->handleTransferAuthorizationNotify(
|
||||
function (PayMessage $message) {
|
||||
TransferAuthorizationService::handleAuthorizationNotify($message->toArray());
|
||||
}
|
||||
);
|
||||
http_response_code($response->getStatusCode());
|
||||
foreach ($response->getHeaders() as $name => $values) {
|
||||
header($name . ': ' . implode(', ', $values));
|
||||
}
|
||||
$body = $response->getBody()->getContents();
|
||||
Log::info('免确认收款授权回调[应答] http_code=' . $response->getStatusCode() . ' body=' . $body);
|
||||
echo $body;
|
||||
exit;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('免确认收款授权回调[异常]:' . json_encode([
|
||||
'msg' => $e->getMessage(),
|
||||
'file' => $e->getFile() . ':' . $e->getLine(),
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
http_response_code(500);
|
||||
echo json_encode(['code' => 'FAIL', 'message' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model\account;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* 免确认收款授权记录
|
||||
* 一个用户对应唯一一个生效中的授权(微信侧限制同一用户同一场景最多 5 个生效授权)
|
||||
*/
|
||||
class TransferAuthorizations extends Model
|
||||
{
|
||||
// 表名
|
||||
protected $name = 'transfer_authorizations';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $deleteTime = false;
|
||||
}
|
||||
@@ -163,13 +163,19 @@ class AccountWithdrawService
|
||||
AccountService::updateData($userId, 0, -$amount, 0,0, $log_res->id);
|
||||
|
||||
if($type == AccountWithdrawService::TYPE_WECHAT){
|
||||
//发起微信商家转账到用户零钱(v3,原 v2 企业付款已停用)
|
||||
$payRes = (new EasyWeChatService())->mchPay($withdraw_record->apply_sn, $user->openid, $user->username, $amount);
|
||||
if (empty($payRes['batch_id'])) {
|
||||
//免确认收款授权校验:未授权无法以授权单发起转账
|
||||
$auth = TransferAuthorizationService::getByUserId($userId);
|
||||
if (!TransferAuthorizationService::isAuthorized($userId)) {
|
||||
throw new \Exception('该用户未完成免确认收款授权,无法发起转账,请通知用户在小程序余额页完成授权后重新审核');
|
||||
}
|
||||
//发起微信商家转账到用户零钱(v3授权转账:以授权单定位收款人,免用户确认收款)
|
||||
$payRes = (new EasyWeChatService())->mchPay($withdraw_record->apply_sn, $user->username, $amount, $auth->out_authorization_no);
|
||||
//以 transfer_bill_no(微信转账单号) 判断单据是否创建成功
|
||||
if (empty($payRes['transfer_bill_no'])) {
|
||||
throw new \Exception($payRes['message'] ?? '商家转账发起失败');
|
||||
}
|
||||
//批次受理成功(资金到账以微信侧为准,可通过 queryBalance 查询批次状态)
|
||||
$withdraw_record->result_status = 'SUCCESS';
|
||||
//授权转账免用户确认,状态记为微信返回的 state,最终以回调/查单为准
|
||||
$withdraw_record->result_status = $payRes['state'] ?? '';
|
||||
$withdraw_record->save();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -138,60 +138,191 @@ class EasyWeChatService
|
||||
}
|
||||
|
||||
/**
|
||||
* 商家转账到零钱(v3, 原 v2 企业付款已停用)
|
||||
* 需在商户平台开通「商家转账」产品权限
|
||||
* @param string $order_sn 提现单号(字母或数字)
|
||||
* @param string $openid
|
||||
* @param string $name 收款用户姓名(商家转账不校验时可留空)
|
||||
* 免确认收款转账(商家转账-用户已授权模式)
|
||||
* 接口:POST /v3/fund-app/mch-transfer/transfer-bills/transfer
|
||||
* 前置:用户需先通过 /v3/fund-app/mch-transfer/user-confirm-authorization 完成授权,
|
||||
* 转账时以授权单(out_authorization_no / authorization_id 二选一)定位收款人
|
||||
* 文档:https://pay.weixin.qq.com/doc/v3/merchant/4014399371
|
||||
* @param string $order_sn 提现单号(out_bill_no, 字母或数字)
|
||||
* @param string $name 收款用户姓名(金额>=2000元时必须传,需加密)
|
||||
* @param float $amount 金额(单位:元)
|
||||
* @param string $desc
|
||||
* @return array {out_batch_no, batch_id, create_time};失败时含 message
|
||||
* @param string $out_authorization_no 商户侧授权单号
|
||||
* @param string $desc 转账备注(≤32 字符)
|
||||
* @return array {out_bill_no, transfer_bill_no, state, transfer_amount, ...};失败时含 message
|
||||
*/
|
||||
public function mchPay($order_sn, $openid, $name, $amount, $desc = '用户提现')
|
||||
public function mchPay($order_sn, $name, $amount, $out_authorization_no, $desc = '用户提现')
|
||||
{
|
||||
$params = [
|
||||
'appid' => $this->config['app_id'],
|
||||
'out_batch_no' => $order_sn,
|
||||
'batch_name' => '用户提现',
|
||||
'batch_remark' => $desc,
|
||||
'total_amount' => (int)round($amount * 100), // 转为分
|
||||
'total_num' => 1,
|
||||
'transfer_detail_list' => [
|
||||
[
|
||||
'out_detail_no' => $order_sn . 'D1', // 明细单号(字母数字,保持唯一)
|
||||
'transfer_amount' => (int)round($amount * 100),
|
||||
'transfer_remark' => $desc,
|
||||
'openid' => $openid,
|
||||
try {
|
||||
$params = [
|
||||
'appid' => $this->config['app_id'],
|
||||
'out_bill_no' => $order_sn,
|
||||
'transfer_scene_id' => $this->config['transfer_scene_id'] ?? '',
|
||||
'transfer_amount' => (int)round($amount * 100), // 转为分
|
||||
'transfer_remark' => mb_substr($desc, 0, 32), // 最多 32 字符
|
||||
//授权转账:以授权单定位收款人,不再传 openid
|
||||
'out_authorization_no' => $out_authorization_no,
|
||||
//必须传转账场景报备信息,需按商户平台申请的场景准确填写
|
||||
'transfer_scene_report_infos' => [
|
||||
[
|
||||
'info_type' => '活动名称',
|
||||
'info_content' => mb_substr($desc ?: '佣金报酬', 0, 32),
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
Log::info('商家转账-params' . json_encode($params, JSON_UNESCAPED_UNICODE));
|
||||
$response = $this->payApp->getClient()->postJson('v3/transfer/batches', $params);
|
||||
$res = $response->toArray(false);
|
||||
Log::info('商家转账-res' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
];
|
||||
//规则:转账金额 >= 2,000 元时必须传入收款人姓名(加密)
|
||||
if ($amount >= 2000 && $name !== '') {
|
||||
$params['user_name'] = $this->encryptSensitive($name);
|
||||
}
|
||||
//含敏感字段加密时须带 Wechatpay-Serial(微信支付公钥ID/平台证书序列号)
|
||||
$client = $this->payApp->getClient();
|
||||
$platformCerts = $this->config['platform_certs'] ?? [];
|
||||
if ($platformCerts) {
|
||||
$client = $client->withHeader('Wechatpay-Serial', (string)array_key_first($platformCerts));
|
||||
}
|
||||
Log::info('商家转账-params' . json_encode($params, JSON_UNESCAPED_UNICODE));
|
||||
$response = $client->postJson('v3/fund-app/mch-transfer/transfer-bills/transfer', $params);
|
||||
$res = $response->toArray(false);
|
||||
Log::info('商家转账-res' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return $res;
|
||||
return $res;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('商家转账请求异常:' . $e->getMessage());
|
||||
return [
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商家转账批次状态
|
||||
* @param string $apply_sn 商家转账单号(out_batch_no)
|
||||
* @return array 转账批次状态及明细
|
||||
* 发起免确认收款授权(用户确认模式的前置授权)
|
||||
* 接口:POST /v3/fund-app/mch-transfer/user-confirm-authorization
|
||||
* 返回 package_info 供前端 wx.requestMerchantTransfer 拉起授权页
|
||||
* 文档:https://pay.weixin.qq.com/doc/v3/merchant/4015901167
|
||||
* @param string $out_authorization_no 商户侧授权单号(每用户唯一,未确认单30天后单号可复用)
|
||||
* @param string $openid 收款用户 openid
|
||||
* @param string $display_name 授权详情展示的开通账号名称(≤32字符)
|
||||
* @return array {out_authorization_no, state, create_time, package_info};失败时含 message
|
||||
*/
|
||||
public function applyTransferAuthorization($out_authorization_no, $openid, $display_name)
|
||||
{
|
||||
try {
|
||||
$params = [
|
||||
'appid' => $this->config['app_id'],
|
||||
'out_authorization_no' => $out_authorization_no,
|
||||
'openid' => $openid,
|
||||
'transfer_scene_id' => $this->config['transfer_scene_id'] ?? '',
|
||||
'user_display_name' => mb_substr($display_name, 0, 32),
|
||||
'authorization_notify_url' => $this->config['transfer_authorization_notify_url'] ?? '',
|
||||
];
|
||||
Log::info('免确认收款授权-params' . json_encode($params, JSON_UNESCAPED_UNICODE));
|
||||
$response = $this->payApp->getClient()->postJson('v3/fund-app/mch-transfer/user-confirm-authorization', $params);
|
||||
$res = $response->toArray(false);
|
||||
Log::info('免确认收款授权-res' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return $res;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('免确认收款授权请求异常:' . $e->getMessage());
|
||||
return [
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理免确认收款授权结果回调(验签+解密),返回 PSR-7 响应
|
||||
* 注意:handlePaid 只处理 TRANSACTION.SUCCESS,授权回调须用通用管道
|
||||
* @param \Closure $handler function(PayMessage $message){ 业务处理;异常时抛出则返回失败 }
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function handleTransferAuthorizationNotify(\Closure $handler)
|
||||
{
|
||||
$traceId = date('YmdHis') . substr(md5(uniqid('', true)), 0, 6);
|
||||
Log::info('免确认收款授权回调[收到请求] trace=' . $traceId . ' ' . json_encode([
|
||||
'body' => (string)$this->payApp->getRequest()->getBody(),
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$server = $this->payApp->getServer();
|
||||
$server->with(function (PayMessage $message, \Closure $next) use ($handler, $traceId) {
|
||||
Log::info('免确认收款授权回调[解密数据] trace=' . $traceId . ' ' . json_encode($message->toArray(), JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//回调签名验证(失败抛异常 -> serve 返回失败,微信将重试)
|
||||
$this->payApp->getValidator()->validate($this->payApp->getRequest());
|
||||
|
||||
$handler($message, $traceId);
|
||||
|
||||
return $next($message);
|
||||
});
|
||||
|
||||
return $server->serve();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询新版商家转账单状态
|
||||
* @param string $out_bill_no 商户单号
|
||||
* @return array 转账单状态及明细
|
||||
*/
|
||||
public function queryTransferBill($out_bill_no)
|
||||
{
|
||||
try {
|
||||
$response = $this->payApp->getClient()->get(
|
||||
"v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{$out_bill_no}"
|
||||
);
|
||||
$res = $response->toArray(false);
|
||||
Log::info('查询商家转账单-res' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return $res;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('查询商家转账单异常:' . $e->getMessage());
|
||||
return [
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 敏感信息加密:新版商家转账的收款人姓名需使用微信支付公钥加密(RSA-OAEP)
|
||||
* @param string $plaintext
|
||||
* @return string base64 密文
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function encryptSensitive(string $plaintext): string
|
||||
{
|
||||
if ($plaintext === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$platformCerts = $this->config['platform_certs'] ?? [];
|
||||
if (!$platformCerts) {
|
||||
throw new \Exception('未配置微信支付公钥(platform_certs),无法加密收款人姓名');
|
||||
}
|
||||
//取第一个可用公钥(微信支付公钥ID -> 公钥文件)
|
||||
$certFile = reset($platformCerts);
|
||||
if (!is_file($certFile)) {
|
||||
throw new \Exception('微信支付公钥文件不存在:' . $certFile);
|
||||
}
|
||||
|
||||
$publicKey = openssl_pkey_get_public(file_get_contents($certFile));
|
||||
if (!$publicKey) {
|
||||
throw new \Exception('微信支付公钥解析失败');
|
||||
}
|
||||
|
||||
$encrypted = '';
|
||||
if (!openssl_public_encrypt($plaintext, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING)) {
|
||||
throw new \Exception('收款人姓名加密失败');
|
||||
}
|
||||
|
||||
return base64_encode($encrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商家转账单状态(提现已改用新版接口,统一走新版查询)
|
||||
* @param string $apply_sn 提现单号(out_bill_no)
|
||||
* @return array 转账单状态及明细
|
||||
*/
|
||||
public function queryBalance($apply_sn)
|
||||
{
|
||||
$response = $this->payApp->getClient()->get("v3/transfer/batches/out-batch-no/{$apply_sn}", [
|
||||
'query' => [
|
||||
'need_query_detail' => 'true',
|
||||
'offset' => 0,
|
||||
'limit' => 20,
|
||||
'detail_status' => 'ALL',
|
||||
],
|
||||
]);
|
||||
$res = $response->toArray(false);
|
||||
Log::info('商家转账查询-res' . json_encode(['apply_sn' => $apply_sn, 'res' => $res], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return $res;
|
||||
//提现单已改用新版商家转账接口创建,查询统一走新版,避免查不到单据
|
||||
return $this->queryTransferBill($apply_sn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\model\account\TransferAuthorizations;
|
||||
use app\common\traits\ServiceTrait;
|
||||
use think\Log;
|
||||
|
||||
/**
|
||||
* 免确认收款授权(商家转账-用户确认模式的前置授权)
|
||||
* 流程:
|
||||
* 1. 用户发起提现时,前端调本服务 apply() 发起授权申请,
|
||||
* 拿到 package_info 后用 wx.requestMerchantTransfer 拉起授权页;
|
||||
* 2. 用户授权成功后,微信异步回调 transferAuthorizationNotify,
|
||||
* 本服务记录 authorization_id 并将状态置为 TAKING_EFFECT;
|
||||
* 3. 后台审核提现时,校验授权为 TAKING_EFFECT 后走
|
||||
* /v3/fund-app/mch-transfer/transfer-bills/transfer 完成免确认转账。
|
||||
* 文档:https://pay.weixin.qq.com/doc/v3/merchant/4015901167
|
||||
*/
|
||||
class TransferAuthorizationService
|
||||
{
|
||||
use ServiceTrait;
|
||||
|
||||
/** @var TransferAuthorizations */
|
||||
public static $Model = TransferAuthorizations::class;
|
||||
|
||||
// 授权状态
|
||||
const STATE_WAIT_USER_CONFIRM = 'WAIT_USER_CONFIRM'; //已受理,待用户确认
|
||||
const STATE_TAKING_EFFECT = 'TAKING_EFFECT'; //已授权,生效中(长期有效,直至主动解除)
|
||||
|
||||
/**
|
||||
* 生成商户侧授权单号:一个用户固定一个单号。
|
||||
* 微信规则:未确认的授权单 30 天后单号可复用重新发起,因此复用同一单号即可
|
||||
* @param int $userId
|
||||
* @return string 仅含字母数字,最长 32 位
|
||||
*/
|
||||
public static function generateAuthNo($userId): string
|
||||
{
|
||||
return 'TXAUTH' . str_pad((string)intval($userId), 10, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的授权记录
|
||||
* @param int $userId
|
||||
* @return TransferAuthorizations|null
|
||||
*/
|
||||
public static function getByUserId($userId)
|
||||
{
|
||||
return self::getOne(['user_id' => $userId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否已完成免确认收款授权
|
||||
* @param int $userId
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAuthorized($userId): bool
|
||||
{
|
||||
$record = self::getByUserId($userId);
|
||||
|
||||
return $record
|
||||
&& $record->state == self::STATE_TAKING_EFFECT
|
||||
&& $record->authorization_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起/获取免确认收款授权,供前端拉起授权页
|
||||
* @param \app\common\model\Users $user 用户(需含 openid)
|
||||
* @param string $displayName 授权详情中展示的开通账号名称
|
||||
* @return array {authorized: bool, state, package_info?, mch_id?, app_id?}
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function apply($user, string $displayName = ''): array
|
||||
{
|
||||
$userId = $user->id;
|
||||
if (empty($user->openid)) {
|
||||
throw new \Exception('无法获取用户微信身份,请先登录小程序');
|
||||
}
|
||||
|
||||
//已授权的用户直接返回,不再重复发起
|
||||
$record = self::getByUserId($userId);
|
||||
if ($record && self::isAuthorized($userId)) {
|
||||
return [
|
||||
'authorized' => true,
|
||||
'state' => $record->state,
|
||||
];
|
||||
}
|
||||
|
||||
//发起授权申请(授权单号固定,复用同一单号可重新发起)
|
||||
$authNo = self::generateAuthNo($userId);
|
||||
$wechat = new EasyWeChatService();
|
||||
$displayName = mb_substr($displayName ?: ($user->nickname ?: ('用户' . $userId)), 0, 32);
|
||||
$res = $wechat->applyTransferAuthorization($authNo, $user->openid, $displayName);
|
||||
|
||||
if (empty($res['package_info'])) {
|
||||
throw new \Exception($res['message'] ?? '发起免确认收款授权失败');
|
||||
}
|
||||
|
||||
//保存/更新授权记录(package_info 用于前端拉起授权页,state 当前为待用户确认)
|
||||
$data = [
|
||||
'state' => $res['state'] ?? self::STATE_WAIT_USER_CONFIRM,
|
||||
'package_info' => $res['package_info'],
|
||||
];
|
||||
if ($record) {
|
||||
$record->save($data);
|
||||
} else {
|
||||
self::create(array_merge([
|
||||
'user_id' => $userId,
|
||||
'out_authorization_no' => $authNo,
|
||||
'authorization_id' => '',
|
||||
], $data));
|
||||
}
|
||||
|
||||
return [
|
||||
'authorized' => false,
|
||||
'state' => $data['state'],
|
||||
'package_info' => $res['package_info'],
|
||||
//前端 wx.requestMerchantTransfer 需要:商户号 + AppID + package
|
||||
'mch_id' => (string)$wechat->payApp->getMerchant()->getMerchantId(),
|
||||
'app_id' => $wechat->config['app_id'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理免确认收款授权结果回调(用户授权成功后微信异步通知)
|
||||
* @param array $message 解密后的授权结果,含 out_authorization_no / authorization_id / state
|
||||
* @return bool
|
||||
*/
|
||||
public static function handleAuthorizationNotify(array $message): bool
|
||||
{
|
||||
$outAuthNo = trim((string)($message['out_authorization_no'] ?? ''));
|
||||
$authorizationId = trim((string)($message['authorization_id'] ?? ''));
|
||||
$state = trim((string)($message['state'] ?? ''));
|
||||
if (!$outAuthNo || !$authorizationId) {
|
||||
Log::error('免确认收款授权回调参数缺失:' . json_encode($message, JSON_UNESCAPED_UNICODE));
|
||||
return false;
|
||||
}
|
||||
|
||||
$record = self::getOne(['out_authorization_no' => $outAuthNo]);
|
||||
if (!$record) {
|
||||
Log::error('免确认收款授权回调找不到授权记录:' . $outAuthNo);
|
||||
return false;
|
||||
}
|
||||
|
||||
//记录微信侧授权单号,标记授权生效(授权长期有效,直至用户或商户主动解除)
|
||||
$record->authorization_id = $authorizationId;
|
||||
$record->state = $state ?: self::STATE_TAKING_EFFECT;
|
||||
$record->save();
|
||||
Log::info('免确认收款授权生效:' . json_encode([
|
||||
'user_id' => $record->user_id,
|
||||
'state' => $record->state,
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,11 @@ return [
|
||||
: [],
|
||||
// 支付结果通知地址(也可在下单时单独覆盖)
|
||||
'notify_url' => Env::get('app.url') . '/api/order/payNotify',
|
||||
// 新版商家转账(用户确认模式)转账场景ID:1005=佣金报酬
|
||||
'transfer_scene_id' => Env::get('wechat.transfer_scene_id', '1005'),
|
||||
// 新版商家转账结果回调地址(公网可访问、HTTPS、不带参数)
|
||||
'transfer_notify_url' => Env::get('app.url') . '/api/account/transferNotify',
|
||||
// 免确认收款授权结果回调地址(公网可访问、HTTPS、不带参数)
|
||||
'transfer_authorization_notify_url' => Env::get('app.url') . '/api/account/transferAuthorizationNotify',
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user