496 lines
19 KiB
PHP
496 lines
19 KiB
PHP
<?php
|
||
/**
|
||
* SaaSMall商城系统 - 团队十年电商经验汇集巨献!
|
||
* =========================================================
|
||
* Copy right 2019-2029 成都SAAS云科技有限公司, 保留所有权利。
|
||
* ----------------------------------------------
|
||
* 官方网址: https://www.gobuysaas.com
|
||
* =========================================================
|
||
*/
|
||
|
||
namespace addon\cypay\model;
|
||
|
||
use addon\weapp\model\Config as WeappConfig;
|
||
use addon\wechat\model\Config as WechatConfig;
|
||
use app\model\BaseModel;
|
||
use app\model\system\Pay as PayCommon;
|
||
use addon\cypay\sdk\AopClient;
|
||
use addon\cypay\sdk\request\TradeRefundRequest;
|
||
use addon\cypay\sdk\request\TradeCreateRequest;
|
||
use addon\cypay\sdk\request\TradeCloseRequest;
|
||
use addon\cypay\sdk\request\TradeBingAccountsRequest;
|
||
use addon\cypay\sdk\request\TradeWapPayRequest;
|
||
use addon\cypay\sdk\request\TradeQueryRequest;
|
||
use addon\cypay\sdk\request\TradePrecreateRequest;
|
||
use think\facade\Log;
|
||
|
||
/**
|
||
* 支付宝支付配置
|
||
*/
|
||
class Pay extends BaseModel
|
||
{
|
||
public $config;
|
||
public $site_id;
|
||
|
||
function __construct($site_id, $config = [])
|
||
{
|
||
try {
|
||
// 获取支付宝支付参数(统一支付到平台账户)
|
||
$this->site_id = $site_id;
|
||
$config_model = new Config();
|
||
$config_result = $config_model->getPayConfig($site_id);
|
||
$config = $config_result["data"]['value'];
|
||
$this->config = $config;
|
||
$this->aop = new AopClient();
|
||
if ($this->config['is_isp'] == 1) {
|
||
$this->aop->is_isp = 1;
|
||
$this->aop->gatewayUrl = 'https://pay.chanpay.com/merchant/gateway';
|
||
} else {
|
||
$this->aop->publicKey = $config_info['public_key'] ?? ""; //应用公钥
|
||
$this->aop->cjRsaPublicKey = $config_info['cj_public_key'] ?? "";
|
||
$this->aop->rsaPrivateKey = $config_info['private_key'] ?? ""; //应用私钥
|
||
$this->aop->gatewayUrl = 'https://pay.chanpay.com/ugtw/gateway';
|
||
}
|
||
$this->aop->apiVersion = '1.0';
|
||
$this->aop->signType = 'RSA2';
|
||
$this->aop->postCharset = 'UTF-8';
|
||
$this->aop->format = 'JSON';
|
||
} catch (\Exception $e) {
|
||
exit(json_encode($this->error('', '配置错误')));
|
||
}
|
||
}
|
||
|
||
// 根据支付类型 获取对应的支付参数
|
||
|
||
// 根据支付类型 获取对应的支付参数
|
||
public function pay($params)
|
||
{
|
||
//构造要请求的参数数组,无需改动
|
||
$outTradeNo = $params['out_trade_no'] ?? '';
|
||
$parameter = array(
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $outTradeNo,
|
||
"body" => str_sub($params["pay_body"], 60),
|
||
"attach" => $outTradeNo,
|
||
'total_amount' => (int)sprintf("%.0f", $params['pay_money'] * 100),
|
||
'mch_create_ip' => request()->ip()
|
||
);
|
||
$mch_info = $params['mch_info'];
|
||
if ($mch_info) {
|
||
$mch_info = json_decode($mch_info, true);
|
||
if (isset($mch_info['proxy_pay']) && $mch_info['proxy_pay'] == 1) {
|
||
$parameter['merchant_id'] = $mch_info['mch_id'];
|
||
}
|
||
}
|
||
$attach = [
|
||
'out_trade_no' => $outTradeNo,
|
||
'endDivide' => 0,
|
||
];
|
||
$res = event('checkAccountsAuth', ['site_id' => $this->site_id, 'pay_type' => 'cypay', 'out_trade_no' => $params["out_trade_no"]], true);
|
||
if ($res && $res['isDivide']) {
|
||
$attach['endDivide'] = 0;
|
||
} else {
|
||
$attach['endDivide'] = 1;
|
||
}
|
||
$parameter['attach'] = json_encode($attach);
|
||
if ($params["pay_type"] == 'cywechatpay') {
|
||
if ($params["app_type"] == 'h5' || $params["app_type"] == 'wechat') {
|
||
$wechat_config = (new WechatConfig())->getWechatConfig($this->site_id)['data']['value'];
|
||
$this->config['app_id'] = $wechat_config['appid'] ?? '';
|
||
} else {
|
||
$weapp_config = (new WeappConfig())->getWeappConfig($this->site_id)['data']['value'];
|
||
$this->config['app_id'] = $weapp_config['appid'] ?? '';
|
||
}
|
||
} else if ($params["pay_type"] == 'cyalipay') {
|
||
|
||
}
|
||
try {
|
||
switch ($params["app_type"]) {
|
||
case "pc":
|
||
case 'cashier':
|
||
case "h5":
|
||
$request = new TradeWapPayRequest();
|
||
$request->setMethodName('chanpay.merchanttrade.aggregate.precreate');
|
||
$request->setFunctionCode('1000110001');
|
||
break;
|
||
case "app":
|
||
break;
|
||
// 微信小程序支付
|
||
case 'weapp':
|
||
$parameter['sub_openid'] = model('member')->getValue(['member_id' => $params['member_id']], 'weapp_openid');
|
||
$request = new TradeCreateRequest();
|
||
if ($this->config['is_cashier'] == 1) {
|
||
$request->setMethodName('chanpay.merchanttrade.appletpay.cashier');
|
||
$request->setFunctionCode('1000160001');
|
||
} else {
|
||
$request->setFunctionCode($params["trade_type"]);
|
||
}
|
||
break;
|
||
case 'wechat':
|
||
$parameter['sub_appid'] = $this->config['app_id'];
|
||
$parameter['sub_openid'] = model('member')->getValue(['member_id' => $params['member_id']], 'wx_openid');
|
||
$request = new TradeWapPayRequest();
|
||
$request->setMethodName('chanpay.merchanttrade.weixin.jspay');
|
||
$request->setFunctionCode('1000120004');
|
||
break;
|
||
case "aliapp":
|
||
$request = new TradeWapPayRequest();
|
||
$request->setMethodName('chanpay.merchanttrade.alipay.jspay');
|
||
$request->setFunctionCode('1000120002');
|
||
break;
|
||
|
||
}
|
||
if ($this->config['is_cashier'] == 1) {
|
||
$parameter['notify_url'] = $params["notify_url"];
|
||
unset($parameter['mch_create_ip']);
|
||
$paydata = base64_encode(json_encode($parameter));
|
||
$path = urlencode('/pages_tool/pay/result?code=' . $outTradeNo);
|
||
$data = [
|
||
"pay_type" => $params["pay_type"],
|
||
'is_cashier' => 1,
|
||
'appId' => $this->config['app_id'],
|
||
"cashier" => "jsapi",
|
||
"cashier_appid" => "wx1eac96cd7bac0ade",
|
||
"envVersion" => "release",//开发develop ,测试trial,正式release
|
||
"path" => "pages/pay/mp?paydata={$paydata}&appId={$this->config['app_id']}&path={$path}",
|
||
];
|
||
return $this->success($data);
|
||
}
|
||
$request->setBizContent($parameter);
|
||
$request->SetNotifyUrl($params["notify_url"]);
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
if ($params["app_type"] == 'cashier') {
|
||
return $this->success([
|
||
'type' => 'qrcode',
|
||
'data' => [
|
||
// 'qrcode' => $result->$responseNode->qr_code
|
||
]
|
||
]);
|
||
}
|
||
$data = [];
|
||
if ($params["app_type"] == 'weapp' && $this->config['is_cashier'] == 1) {
|
||
$result['content']['is_cashier'] = 1;
|
||
$data = $result['content'];
|
||
}
|
||
if ($params["app_type"] == 'h5' || $params["app_type"] == 'wechat') {
|
||
$data = [
|
||
"type" => "jsapi",
|
||
"data" => json_decode($result['content']['pay_info'], true)
|
||
];
|
||
}
|
||
return $this->success($data);
|
||
} else {
|
||
return $this->error("", $result['sub_msg']);
|
||
}
|
||
return $result;
|
||
} catch (\Exception $e) {
|
||
return $this->error("", $e->getMessage());
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 支付关闭
|
||
* @param unknown $orderNumber
|
||
* @return multitype:number string |multitype:number mixed
|
||
*/
|
||
public function close($param)
|
||
{
|
||
$parameter = array(
|
||
"out_trade_no" => $param["pay_no"]
|
||
);
|
||
// 建立请求
|
||
$request = new TradeCloseRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode($param['pay_addon']);
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error("", $result['sub_msg']);
|
||
}
|
||
return $this->success();
|
||
}
|
||
|
||
/**
|
||
* 支付宝支付原路返回
|
||
* @param unknown $param 支付参数
|
||
*/
|
||
public function refund($param)
|
||
{
|
||
$pay_info = $param["pay_info"];
|
||
$refund_no = $param["refund_no"];
|
||
$out_trade_no = $pay_info["pay_no"] ?? '';
|
||
$refund_fee = $param["refund_fee"];
|
||
$parameter = array(
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $out_trade_no,
|
||
'total_amount' => $pay_info['pay_money'] * 100,
|
||
'refund_amount' => $refund_fee * 100,
|
||
'out_refund_no' => $refund_no
|
||
);
|
||
if ($param["refund_desc"]) {
|
||
$parameter['refund_desc'] = $$param["refund_desc"];
|
||
}
|
||
// 建立请求
|
||
$request = new TradeRefundRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode($pay_info['pay_addon']);
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error($pay_info["pay_type"], $result['sub_msg']);
|
||
}
|
||
}
|
||
|
||
|
||
// 支付异步通知处理
|
||
public function payNotify($param)
|
||
{
|
||
try {
|
||
$res = $this->aop->rsaCheckV1(request()->post());
|
||
if ($res) { // 验证成功
|
||
$bizContent = $this->aop->rsaDecrypt($param['biz_content']);
|
||
$outTradeNo = substr($bizContent['out_trade_no'], 0, -3);
|
||
$payInfo = (new PayCommon())->getPayInfo($outTradeNo);
|
||
$payInfo = $payInfo['data'] ?? null;
|
||
$pay_result = $bizContent['pay_result'];
|
||
if (empty($payInfo)) {
|
||
$returnData = ['return_code' => 'FAIL', 'return_msg' => '订单不存在'];
|
||
} else if ($pay_result == 0) {
|
||
$pay_no = $bizContent['out_trade_no'];
|
||
$pay_voucher = $bizContent['chanpay_trade_no'];
|
||
$attach = json_decode($bizContent['attach'], true);
|
||
$josn = json_encode([
|
||
'attach' => $attach,
|
||
'pay_result' => $pay_result,
|
||
'channel_transaction_id' => $bizContent['channel_transaction_id'],
|
||
'trade_type' => $bizContent['trade_type'],
|
||
]);
|
||
(new PayCommon())->onlinePay($outTradeNo, $param['paytype'], $bizContent['transaction_id'], $param['function_code'], [], $pay_no, $pay_voucher, $josn);
|
||
$returnData = ['return_code' => 'SUCCESS', 'return_msg' => 'OK'];
|
||
if (empty($attach) || (!empty($attach['endDivide']) && $attach['endDivide'] == 1)) {
|
||
$this->profitsharingFinish($pay_no, $outTradeNo); //解除分账
|
||
}
|
||
} else {
|
||
$returnData = ['return_code' => 'FAIL', 'return_msg' => '支付失败'];
|
||
}
|
||
}
|
||
} catch (\Exception $e) {
|
||
$returnData = ['return_code' => 'FAIL', 'return_msg' => $e->getMessage()];
|
||
}
|
||
// 验签失败 or 处理失败
|
||
echo json_encode($returnData, JSON_UNESCAPED_UNICODE);
|
||
}
|
||
|
||
|
||
/***
|
||
* 绑定分账收款账号
|
||
* @param $out_order_no
|
||
* @param $receiver_list
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public function relationBindAccounts($out_order_no, $receiver_list)
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_order_no' => $out_order_no,
|
||
'receiver_list' => $receiver_list,
|
||
];
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
$sub_msg = $result['sub_msg'];
|
||
if (!empty($resultCode) && $resultCode == 0000 && strpos($sub_msg, '绑定关系已存在') !== false) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error('', $result['sub_msg']);
|
||
}
|
||
}
|
||
|
||
/***
|
||
* 分账查询
|
||
* @param $out_order_no
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public function relationQuery($out_order_no)
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_order_no' => $out_order_no,
|
||
];
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchant.profitsharing.relation.query');
|
||
$result = $this->aop->execute($request);
|
||
return $result;
|
||
}
|
||
|
||
|
||
/***
|
||
* 提交分账
|
||
* @param $out_order_no 商家订单号
|
||
* @param $out_order_id 请求编号
|
||
* @param $trans_out_amount 分账金额
|
||
* @param $receiver_list 分账列表
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public function profitsharing($out_order_no, $out_order_id, $receiver_list, $unfreeze_unsplit = true)
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $out_order_no,
|
||
'out_order_no' => $out_order_id,
|
||
'trans_out_amount' => array_sum(array_column($receiver_list, 'amount')),
|
||
'royalty_parameters' => $receiver_list,
|
||
];
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchanttrade.profitsharing');
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
$content = $result['content'];
|
||
$trade_state = $content['trade_state'];
|
||
if ($trade_state == 'FINISHED') {
|
||
if ($unfreeze_unsplit) {
|
||
$this->profitsharingFinish($out_order_no, $out_order_id);
|
||
}
|
||
return $this->success();
|
||
} else {
|
||
return $this->error('', $content['trade_state_desc']);
|
||
}
|
||
} else {
|
||
if ($result['sub_msg'] == '该订单已分账') {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error('', $result['sub_msg']);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/***
|
||
* 标记分账完成
|
||
* @param $out_order_no
|
||
* @param $out_order_id
|
||
* @param $description
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public function profitsharingFinish($out_order_no, $out_order_id, $description = '')
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $out_order_no,
|
||
'out_order_no' => $out_order_id
|
||
];
|
||
if ($description) {
|
||
$parameter['description'] = $description;
|
||
}
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchanttrade.profitsharing.finish');
|
||
$result = $this->aop->execute($request);
|
||
$resultCode = $result['code'];
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error('', $result['sub_msg']);
|
||
}
|
||
}
|
||
|
||
|
||
/***
|
||
* 分账查询
|
||
* @param $out_order_no
|
||
* @param $out_order_id
|
||
* @return mixed|string
|
||
* @throws \Exception
|
||
*/
|
||
public function profitsharingQuery($out_order_no, $out_order_id)
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $out_order_no,
|
||
'out_order_no' => $out_order_id
|
||
];
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchanttrade.profitsharing.query');
|
||
$result = $this->aop->execute($request);
|
||
return $result;
|
||
}
|
||
|
||
|
||
/***
|
||
* 发起回退
|
||
* @param $out_order_no
|
||
* @param $out_return_no
|
||
* @param $out_order_id
|
||
* @param $return_account
|
||
* @param $description
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public function profitsharingReturn($out_order_no, $out_return_no, $out_order_id, $return_account, $description = '')
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_return_no' => $out_return_no,
|
||
'out_order_no' => $out_order_id,
|
||
'return_account' => $return_account,
|
||
'description' => '分账回退',
|
||
];
|
||
if ($description) {
|
||
$parameter['description'] = $description;
|
||
}
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchanttrade.profitsharing.return');
|
||
$result = $this->aop->execute($request);
|
||
if (!empty($resultCode) && $resultCode == 0000) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error('', $result['sub_msg']);
|
||
}
|
||
}
|
||
|
||
/***
|
||
* 查询回退
|
||
* @param $out_order_no
|
||
* @param $out_order_id
|
||
* @return mixed|string
|
||
* @throws \Exception
|
||
*/
|
||
public function profitsharingReturnQuery($out_order_no, $out_order_id)
|
||
{
|
||
$request = new TradeBingAccountsRequest();
|
||
$parameter = [
|
||
'merchant_id' => $this->config['mch_id'],
|
||
'out_trade_no' => $out_order_no,
|
||
'out_order_no' => $out_order_id
|
||
];
|
||
$request->setBizContent(json_encode($parameter));
|
||
$request->setFunctionCode('1000100001');
|
||
$request->setMethodName('chanpay.merchanttrade.profitsharing.return.query');
|
||
$result = $this->aop->execute($request);
|
||
return $result;
|
||
}
|
||
}
|