486 lines
19 KiB
PHP
486 lines
19 KiB
PHP
<?php
|
||
/**
|
||
|
||
|
||
|
||
|
||
|
||
|
||
*/
|
||
|
||
namespace addon\alipay\model;
|
||
|
||
use addon\alipay\data\sdk\AopClient;
|
||
use addon\alipay\data\sdk\request\AlipayFundTransToaccountTransferRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeAppPayRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeCloseRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeCreateRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradePagePayRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeRefundRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeWapPayRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradePrecreateRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradePayRequest;
|
||
use addon\alipay\data\sdk\request\AlipayTradeQueryRequest;
|
||
use app\model\BaseModel;
|
||
use app\model\system\Cron;
|
||
use app\model\system\Pay as PayCommon;
|
||
use addon\alipay\data\sdk\request\AlipayFundTransUniTransferRequest;
|
||
use addon\alipay\data\sdk\AopCertClient;
|
||
use app\model\system\Pay as PayModel;
|
||
use addon\aliapp\model\Config as AliappConfig;
|
||
use think\facade\Log;
|
||
|
||
/**
|
||
* 支付宝支付配置
|
||
*/
|
||
class Pay extends BaseModel
|
||
{
|
||
|
||
public $aop;
|
||
|
||
private $is_aliapp = 0;
|
||
|
||
/**
|
||
*
|
||
* @param $site_id
|
||
* @param int $is_aliapp 是否是小程序
|
||
*/
|
||
function __construct($site_id, $is_aliapp = 0)
|
||
{
|
||
$this->is_aliapp = $is_aliapp;
|
||
|
||
try {
|
||
// 获取支付宝支付参数(统一支付到平台账户)
|
||
if ($is_aliapp) {
|
||
$config_info = ( new AliappConfig() )->getAliappConfig($site_id)[ 'data' ][ 'value' ];
|
||
} else {
|
||
$config_info = ( new Config() )->getPayConfig($site_id)[ 'data' ][ 'value' ];
|
||
}
|
||
|
||
if (!empty($config_info)) {
|
||
$countersign_type = $config_info[ 'countersign_type' ] ?? 0;
|
||
|
||
if ($countersign_type == 1) {
|
||
$appCertPath = $config_info[ "public_key_crt" ] ?? "";
|
||
$alipayCertPath = $config_info[ "alipay_public_key_crt" ] ?? "";
|
||
$rootCertPath = $config_info[ "alipay_with_crt" ] ?? "";
|
||
|
||
$this->aop = new AopCertClient();
|
||
//调用getPublicKey从支付宝公钥证书中提取公钥
|
||
$this->aop->alipayrsaPublicKey = $this->aop->getPublicKey($alipayCertPath);
|
||
//是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内
|
||
$this->aop->isCheckAlipayPublicCert = false;
|
||
//调用getCertSN获取证书序列号
|
||
$this->aop->appCertSN = $this->aop->getCertSN($appCertPath);
|
||
//调用getRootCertSN获取支付宝根证书序列号
|
||
$this->aop->alipayRootCertSN = $this->aop->getRootCertSN($rootCertPath);
|
||
|
||
} else {
|
||
// 获取支付宝支付参数(统一支付到平台账户)
|
||
$this->aop = new AopClient();
|
||
$this->aop->alipayrsaPublicKey = $config_info[ 'public_key' ] ?? "";
|
||
$this->aop->alipayPublicKey = $config_info[ 'alipay_public_key' ] ?? "";
|
||
}
|
||
$this->aop->appId = $config_info[ "app_id" ] ?? "";
|
||
$this->aop->rsaPrivateKey = $config_info[ 'private_key' ] ?? "";
|
||
$this->aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
|
||
$this->aop->apiVersion = '1.0';
|
||
$this->aop->signType = 'RSA2';
|
||
$this->aop->postCharset = 'UTF-8';
|
||
$this->aop->format = 'json';
|
||
|
||
}
|
||
// else{
|
||
// return $this->error('', '支付宝支付未配置');
|
||
// }
|
||
|
||
} catch (\Exception $e) {
|
||
return $this->error('', '支付宝配置错误');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成支付
|
||
* @param $param
|
||
* @return array
|
||
*/
|
||
public function pay($param)
|
||
{
|
||
//构造要请求的参数数组,无需改动
|
||
$parameter = array (
|
||
"out_trade_no" => $param[ "out_trade_no" ],
|
||
"subject" => str_sub($param[ "pay_body" ], 15),
|
||
"total_amount" => (float) $param[ "pay_money" ],
|
||
"body" => str_sub($param[ "pay_body" ], 60),
|
||
"product_code" => 'FAST_INSTANT_TRADE_PAY',
|
||
);
|
||
|
||
switch ( $param[ "app_type" ] ) {
|
||
case "h5":
|
||
$request = new AlipayTradeWapPayRequest();
|
||
break;
|
||
case "pc":
|
||
$request = new AlipayTradePagePayRequest();
|
||
break;
|
||
case "app":
|
||
$request = new AlipayTradeAppPayRequest();
|
||
break;
|
||
case 'wechat':
|
||
$request = new AlipayTradeWapPayRequest();
|
||
break;
|
||
case 'cashier':
|
||
$request = new AlipayTradePrecreateRequest();
|
||
break;
|
||
case 'aliapp':
|
||
$parameter[ 'product_code' ] = 'FACE_TO_FACE_PAYMENT';
|
||
|
||
$member_info = model('member')->getInfo([ [ "member_id", "=", $param[ "member_id" ] ] ], 'ali_openid');
|
||
if (empty($member_info)) return $this->error(-1, '未获取到会员信息');
|
||
|
||
$parameter[ 'buyer_id' ] = $member_info[ 'ali_openid' ];
|
||
$request = new AlipayTradeCreateRequest();
|
||
break;
|
||
}
|
||
|
||
$parameter = json_encode($parameter);
|
||
$request->setBizContent($parameter);
|
||
$request->SetReturnUrl($param[ "return_url" ]);
|
||
$request->SetNotifyUrl($param[ "notify_url" ]);
|
||
|
||
///绑定商户数据
|
||
$pay_model = new PayModel();
|
||
$pay_model->bindMchPay($param[ "out_trade_no" ], [ "is_aliapp" => $this->is_aliapp ]);
|
||
|
||
try {
|
||
if ($param[ "app_type" ] == 'h5' || $param[ "app_type" ] == 'wechat' || $param[ "app_type" ] == 'pc') {
|
||
$result = $this->aop->pageExecute($request, 'get');
|
||
return $this->success([
|
||
'type' => 'url',
|
||
'data' => $result
|
||
]);
|
||
} elseif ($param[ "app_type" ] == 'app') {
|
||
$result = $this->aop->sdkExecute($request);
|
||
if (strpos(get_class($this->aop), 'AopClient') !== false) {
|
||
return $this->success([
|
||
'type' => 'url',
|
||
'data' => $result
|
||
]);
|
||
}
|
||
} else {
|
||
$result = $this->aop->execute($request);
|
||
}
|
||
if ($result === false) return $this->error('', '支付宝发起支付失败');
|
||
} catch (\Exception $e) {
|
||
return $this->error('', $e->getMessage());
|
||
}
|
||
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
switch ( $param[ "app_type" ] ) {
|
||
case 'cashier':
|
||
return $this->success([
|
||
'type' => 'qrcode',
|
||
'data' => [
|
||
'qrcode' => $result->$responseNode->qr_code
|
||
]
|
||
]);
|
||
break;
|
||
case 'aliapp':
|
||
return $this->success([
|
||
'type' => 'data',
|
||
'data' => [
|
||
'orderInfo' => $result->$responseNode->trade_no
|
||
]
|
||
]);
|
||
break;
|
||
default:
|
||
return $this->success();
|
||
}
|
||
} else {
|
||
return $this->error("", $result->$responseNode->sub_msg);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 支付关闭
|
||
* @param $param
|
||
* @return array
|
||
* @throws \think\Exception
|
||
*/
|
||
public function close($param)
|
||
{
|
||
$parameter = array (
|
||
"out_trade_no" => $param[ "out_trade_no" ]
|
||
);
|
||
// 建立请求
|
||
$request = new AlipayTradeCloseRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
return $this->success();
|
||
} else {
|
||
$sub_code = $result->$responseNode->sub_code;
|
||
$data = [];
|
||
if(in_array($sub_code, ['ACQ.TRADE_STATUS_ERROR', 'ACQ.REASON_TRADE_STATUS_INVALID', 'ACQ.REASON_ILLEGAL_STATUS'])){
|
||
$pay_order_result = $this->get($param[ "out_trade_no" ]);
|
||
if(!empty($pay_order_result) && $pay_order_result['code'] >= 0){
|
||
if($pay_order_result['data']['trade_status'] == 'TRADE_SUCCESS' || $pay_order_result['data']['trade_status'] == 'TRADE_FINISHED'){
|
||
$data['is_paid'] = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
return $this->error($data, $result->$responseNode->sub_msg);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 支付宝支付原路返回
|
||
* @param array $param 支付参数
|
||
* @return array
|
||
* @throws \think\Exception
|
||
*/
|
||
public function refund($param)
|
||
{
|
||
$pay_info = $param[ "pay_info" ];
|
||
$refund_no = $param[ "refund_no" ];
|
||
$out_trade_no = $pay_info[ "trade_no" ] ?? '';
|
||
$refund_fee = $param[ "refund_fee" ];
|
||
$parameter = array (
|
||
'trade_no' => $out_trade_no,
|
||
'refund_amount' => sprintf("%.2f", $refund_fee),
|
||
'out_request_no' => $refund_no
|
||
);
|
||
// 建立请求
|
||
$request = new AlipayTradeRefundRequest ();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
return $this->success();
|
||
} else {
|
||
return $this->error("", $result->$responseNode->sub_msg);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 支付宝转账
|
||
* @param $param
|
||
* @return array
|
||
*/
|
||
public function payTransfer($param)
|
||
{
|
||
try {
|
||
$config_model = new Config();
|
||
$config_result = $config_model->getPayConfig($param[ 'site_id' ]);
|
||
if ($config_result[ 'code' ] < 0) return $config_result;
|
||
$config = $config_result[ 'data' ][ 'value' ];
|
||
if (empty($config)) return $this->error([], '未配置支付宝支付');
|
||
if (!$config[ 'transfer_status' ]) return $this->error([], '未启用支付宝转账');
|
||
|
||
$parameter = [
|
||
'out_biz_no' => $param[ 'out_trade_no' ],
|
||
'payee_type' => 'ALIPAY_LOGONID',
|
||
'payee_account' => $param[ "account_number" ],
|
||
'amount' => sprintf("%.2f", $param[ 'amount' ]),
|
||
'payee_real_name' => $param[ "real_name" ],
|
||
'remark' => $param[ "desc" ]
|
||
];
|
||
// 建立请求
|
||
$request = new AlipayFundTransToaccountTransferRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
return $this->success([
|
||
'out_trade_no' => $result->$responseNode->out_biz_no, // 商户交易号
|
||
'payment_no' => $result->$responseNode->order_id, // 微信付款单号
|
||
'payment_time' => date_to_time($result->$responseNode->pay_date) // 付款成功时间
|
||
]);
|
||
} else {
|
||
return $this->error([], $result->$responseNode->sub_msg);
|
||
}
|
||
} catch (\Exception $e) {
|
||
return $this->error([], $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 异步完成支付
|
||
* @param $param
|
||
*/
|
||
public function payNotify()
|
||
{
|
||
|
||
// Log::write('pay_notifiy_log:alipay:'.json_encode(input()), 'notice');
|
||
try {
|
||
$res = $this->aop->rsaCheckV1($_POST, $this->aop->alipayrsaPublicKey, $this->aop->signType);
|
||
if ($res) { // 验证成功
|
||
$out_trade_no = $_POST[ 'out_trade_no' ];
|
||
// 支付宝交易号
|
||
$trade_no = $_POST[ 'trade_no' ];
|
||
// 交易状态
|
||
$trade_status = $_POST[ 'trade_status' ];
|
||
$pay_common = new PayCommon();
|
||
if ($trade_status == "TRADE_SUCCESS") {
|
||
$retval = $pay_common->onlinePay($out_trade_no, "alipay", $trade_no, "alipay");
|
||
}
|
||
echo "success";
|
||
} else {
|
||
// 验证失败
|
||
echo "fail";
|
||
}
|
||
} catch (\Exception $e) {
|
||
echo "fail";
|
||
}
|
||
}
|
||
|
||
public function payNewTransfer($param)
|
||
{
|
||
try {
|
||
$config_model = new Config();
|
||
$config_result = $config_model->getPayConfig($param[ 'site_id' ]);
|
||
if ($config_result[ 'code' ] < 0) return $config_result;
|
||
$config = $config_result[ 'data' ][ 'value' ];
|
||
if (empty($config)) return $this->error([], '未配置支付宝支付');
|
||
if (!$config[ 'transfer_status' ]) return $this->error([], '未启用支付宝转账');
|
||
|
||
$parameter = [
|
||
'out_biz_no' => $param[ 'out_trade_no' ],
|
||
'trans_amount' => sprintf("%.2f", $param[ 'amount' ]),
|
||
'product_code' => 'TRANS_ACCOUNT_NO_PWD',
|
||
'biz_scene' => 'DIRECT_TRANSFER',
|
||
'order_title' => '支付宝转账',
|
||
'remark' => $param[ "desc" ],
|
||
'payee_info' => [
|
||
'identity' => $param[ "account_number" ],
|
||
'identity_type' => "ALIPAY_LOGON_ID",
|
||
'name' => $param[ "real_name" ]
|
||
]
|
||
];
|
||
|
||
// 建立请求
|
||
$request = new AlipayFundTransUniTransferRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
return $this->success([
|
||
'out_trade_no' => $result->$responseNode->out_biz_no, // 商户交易号
|
||
'payment_no' => $result->$responseNode->order_id, // 微信付款单号
|
||
'payment_time' => date_to_time($result->$responseNode->trans_date) // 付款成功时间
|
||
]);
|
||
} else {
|
||
return $this->error([], $result->$responseNode->sub_msg);
|
||
}
|
||
} catch (\Exception $e) {
|
||
return $this->error([], $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 付款码支付
|
||
* @param $param
|
||
* @return array|mixed|void
|
||
*/
|
||
public function micropay($param)
|
||
{
|
||
try {
|
||
//构造要请求的参数数组,无需改动
|
||
$parameter = array (
|
||
"out_trade_no" => $param[ "out_trade_no" ],
|
||
"subject" => str_sub($param[ "pay_body" ], 15),
|
||
"total_amount" => (float) $param[ "pay_money" ],
|
||
"scene" => "bar_code",
|
||
"auth_code" => $param[ 'auth_code' ],
|
||
);
|
||
$parameter = json_encode($parameter);
|
||
$request = new AlipayTradePayRequest();
|
||
$request->setBizContent($parameter);
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
Log::write('支付宝—付款码支付,result:' . json_encode($result));
|
||
Log::write('支付宝—付款码支付,resultCode:' . json_encode($resultCode));
|
||
if (!empty($resultCode)) {
|
||
if ($resultCode == 10000) {
|
||
$pay_common = new PayModel();
|
||
return $res = $pay_common->onlinePay($param[ 'out_trade_no' ], 'alipay', $result->$responseNode->trade_no, 'alipay');
|
||
} else if ($resultCode == 10003) {
|
||
// 等待用户付款
|
||
( new Cron() )->addCron(1, 0, "查询付款码支付结果", "PayOrderQuery", time() + 3, $param[ 'id' ]);
|
||
}
|
||
} else {
|
||
return $this->error([], $result->$responseNode->sub_msg);
|
||
}
|
||
} catch (\Exception $e) {
|
||
return $this->error([], $e->getMessage());
|
||
}
|
||
}
|
||
|
||
// todo 查询交易信息【AlipayTradeQueryRequest】 https://opendocs.alipay.com/open/194/106039?pathHash=5b8cf9e6
|
||
public function orderQuery($param)
|
||
{
|
||
try {
|
||
//构造要请求的参数数组,无需改动
|
||
$parameter = array (
|
||
"out_trade_no" => $param[ "out_trade_no" ],
|
||
);
|
||
$parameter = json_encode($parameter);
|
||
$request = new AlipayTradeQueryRequest();
|
||
$request->setBizContent($parameter);
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
Log::write('alipay_orderQuery' . json_encode($result));
|
||
Log::write('alipay_orderQuery_$resultCode' . json_encode($resultCode));
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
if ($result->$responseNode->trade_status == 'TRADE_SUCCESS') {
|
||
$pay_common = new PayModel();
|
||
return $res = $pay_common->onlinePay($param[ 'out_trade_no' ], 'alipay', $result->$responseNode->trade_no, 'alipay');
|
||
} else {
|
||
( new Cron() )->addCron(1, 0, "查询付款码支付结果", "PayOrderQuery", time() + 3, $param[ 'id' ]);
|
||
}
|
||
|
||
} else {
|
||
return $this->error([], $result->$responseNode->sub_msg);
|
||
}
|
||
} catch (\Exception $e) {
|
||
return $this->error([], $e->getMessage());
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 查询订单信息
|
||
* @param $out_trade_no
|
||
* @return array
|
||
* @throws \think\Exception
|
||
*/
|
||
public function get($out_trade_no)
|
||
{
|
||
$parameter = array (
|
||
"out_trade_no" => $out_trade_no
|
||
);
|
||
// 建立请求
|
||
$request = new AlipayTradeQueryRequest();
|
||
$request->setBizContent(json_encode($parameter));
|
||
$result = $this->aop->execute($request);
|
||
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
|
||
$resultCode = $result->$responseNode->code;
|
||
|
||
|
||
if (!empty($resultCode) && $resultCode == 10000) {
|
||
return $this->success(json_decode(json_encode($result->$responseNode), true));
|
||
} else {
|
||
return $this->error([], $result->$responseNode->sub_msg);
|
||
}
|
||
}
|
||
} |