微信分账
此功能基于yansongda插件
详细文档参阅: https://pay.yansongda.cn/docs/v3/
use addons\epay\library\Service;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Plugin\Wechat\V3\Extend\ProfitSharing\AddReceiverPlugin;
use Yansongda\Pay\Plugin\Wechat\V3\Extend\ProfitSharing\DeleteReceiverPlugin;
use Yansongda\Pay\Plugin\Wechat\V3\Extend\ProfitSharing\CreatePlugin;
use Yansongda\Pay\Plugin\Wechat\V3\Extend\ProfitSharing\UnfreezePlugin;
use Yansongda\Pay\Plugin\Wechat\V3\Extend\ProfitSharing\QueryPlugin;
// 微信支付相关
class WxPay(){
const MINIAPPID = 'wxxxxx'; // 小程序ID
/**
* 添加分账接收方
* @return void
*/
public function addReceiverPlugin($openid) {
$config = Service::getConfig("wechat");
Pay::config($config);
$list = [
"appid" => self::MINIAPPID,
"type" => "PERSONAL_OPENID",
"account" => $openid, // 用户的OPENID
"relation_type" => "USER",
"custom_relation" => "用户"
];
$allPlugins = Pay::wechat()->mergeCommonPlugins([AddReceiverPlugin::class]);
$result = Pay::wechat()->pay($allPlugins, $list)->toArray();
}
/**
* 删除分账接收方
* @return void
*/
public function delReceiverPlugin() {
$config = Service::getConfig("wechat");
Pay::config($config);
$list = [
"appid" => self::MINIAPPID,
"type" => "PERSONAL_OPENID",
"account" => $openid,
];
$allPlugins = Pay::wechat()->mergeCommonPlugins([DeleteReceiverPlugin::class]);
$result = Pay::wechat()->pay($allPlugins, $list)->toArray();
}
/**
* 执行分账
* @return void
*/
public function createPlugin($sn) {
$orderInfo = Db::name('recharge')->where('sn', $sn)->find();
$config = Service::getConfig("wechat");
Pay::config($config);
$receivers = [
[
"type" => "PERSONAL_OPENID",
"account" => "oTGw91ydkvD8-kny1nVzt4JEPV-M",
"amount" => intval($orderInfo['amount'] * 0.08),
"description" => "分给浩浩-8%"
],
[
"type" => "PERSONAL_OPENID",
"account" => "oTGw919vumgdtNR201D9HcfSuv3E",
"amount" => intval($orderInfo['amount'] * 0.06),
"description" => "分给晶晶-6%"
]
];
$receivers[] = [
"type" => "PERSONAL_OPENID",
"account" => $orderInfo['openid'],
"amount" => intval($orderInfo['amount'] * 0.12),
"description" => "用户支付返还-12%"
];
$req = [
'transaction_id' => $orderInfo['transaction_id'],
'out_order_no' => $orderInfo['sn'],
"receivers" => $receivers,
'unfreeze_unsplit' => true,
];
$allPlugins = Pay::wechat()->mergeCommonPlugins([CreatePlugin::class]);
$result = Pay::wechat()->pay($allPlugins, $req)->toArray();
// 订单维度记录分账详情
$log[0]['request'] = $req;
Db::name('recharge')->where('sn', $orderInfo['sn'])->update([
'share_detail' => json_encode($log, 512)
]);
// 人员维度 记录分账人
foreach ($receivers as $v) {
$insert = [
'sn' => $orderInfo['sn'],
'transaction_id' => $orderInfo['transaction_id'],
'session' => 1,
'account' => $v['account'],
'account_type' => $v['type'],
'amount' => $v['amount'],
'description' => $v['description'],
];
Db::name('sharing_log')->insert($insert, true);
}
\think\Log::record("发起分账:");
\think\Log::record($result);
}
/**
* 获取分账结果
* @return void
*/
public function queryPlugin($sn) {
$orderInfo = Db::name('recharge')->where('sn', $sn)->find();
$config = Service::getConfig("wechat");
Pay::config($config);
$requset = [
'transaction_id' => $orderInfo['transaction_id'],
'out_order_no' => $orderInfo['sn'], // 首次分账即业务单号 二次分账为首次返回的 order_id
];
$allPlugins = Pay::wechat()->mergeCommonPlugins([QueryPlugin::class]);
$result = Pay::wechat()->pay($allPlugins, $requset)->toArray();
\think\Log::record("获取分账:");
\think\Log::record($result);
foreach ($result['receivers'] as $v) {
$insert = [
'sn' => $orderInfo['sn'],
'transaction_id' => $orderInfo['transaction_id'],
'session' => 1,
'account' => $v['account'],
'account_type' => $v['type'],
'amount' => $v['amount'],
'description' => $v['description'],
'detail_id' => $v['detail_id'],
'finish_time' => date('Y-m-d H:i:s', strtotime($v['finish_time'])),
'result' => $v['result'],
];
// 替换式更新
Db::name('sharing_log')->insert($insert, true);
}
$log = json_decode($orderInfo['share_detail'], true);
$log[0]['response'] = $result;
Db::name('recharge')->where('sn', $orderInfo['sn'])->update([
'share_detail' => json_encode($log, 512)
]);
}
/**
* 查询支付订单详情
* @return void
*/
public function findOrder() {
$config = Service::getConfig("wechat");
Pay::config($config);
$order = [
'out_trade_no' => 'SN202509301747346676'
];
$result = Pay::wechat()->query($order)->toArray();
}
/**
* 发起支付
* @return void
*/
public function pay() {
$user_id = $this->auth->id;
$openId = $this->auth->username;
$sn = "SN" . date("YmdHis") . mt_rand(1000, 9999);
$orderInfo = [
"user_id" => $user_id,
"openid" => $openId,
"sn" => $sn,
"amount" => mt_rand(100, 1000),
"status" => "to_pay"
];
Db::name('recharge')->insert($orderInfo);
$notifyurl = $this->request->root(true) . '/addons/exam/question/callbackV3';
$returnurl = $this->request->root(true);
$order = [
'amount' => $orderInfo['amount'] / 100,
'orderid' => $orderInfo['sn'],
'type' => "wechat",
'title' => "普通充值-无分账",
'notifyurl' => $notifyurl,
'returnurl' => $returnurl,
'method' => "miniapp",
'openid' => $openId
];
$pay = \addons\epay\library\Service::submitOrder($order);
Db::name('recharge')->where('sn', $sn)->update([
'req_detail' => json_encode($order)
]);
$this->success('成功', $pay);
}
/**
* 支付回调
*/
public function callbackV3() {
$insert = [
'sn' => '',
'log' => json_encode($this->request->param(), 512),
];
Db::name('log')->insert($insert);
$paytype = 'wechat';
$pay = Service::checkNotify($paytype);
$data = $pay->callback();
try {
//微信支付V3返回和V2不同
if (Service::isVersionV3() && $paytype === 'wechat') {
$data = $data['resource']['ciphertext'];
$data['total_fee'] = $data['amount']['total'];
}
\think\Log::record($data);
//获取支付金额、订单号
$payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
$out_trade_no = $data['out_trade_no'];
\think\Log::record("回调成功,订单号:{$out_trade_no},金额:{$payamount}");
//你可以在此编写订单逻辑
$orderInfo = Db::name('recharge')->where('sn', $out_trade_no)->find();
if ($orderInfo['status'] == 'to_pay') {
$insert['sn'] = $orderInfo['sn'];
Db::name('log')->insert($insert);
Db::name('recharge')->where('sn', $out_trade_no)->update([
'status' => 'paid',
'transaction_id' => $data['transaction_id'],
'resp_detail' => json_encode($data)
]);
}
} catch (Exception $e) {
\think\Log::record("回调逻辑处理错误:" . $e->getMessage(), "error");
}
//下面这句必须要执行,且在此之前不能有任何输出
if (Service::isVersionV3()) {
return $pay->success()->getBody()->getContents();
} else {
return $pay->success()->send();
}
}
}