jh-admin/addon/cypay/model/Pay.php

496 lines
19 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}