You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zhishifufei_php/extend/service/AlipayTradeWapService.php

682 lines
26 KiB

10 months ago
<?php
// +----------------------------------------------------------------------
// | 天诚科技 [ 刘海东 17600099397赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.tczxkj.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 该系统并不是自由软件,未经许可不能去掉相关版权
// +----------------------------------------------------------------------
// | Author:甘肃天诚志信电子商务有限公司 刘海东 联系电话维系17600099397
// +----------------------------------------------------------------------
namespace service;
use app\wap\model\activity\EventSignUp;
use app\wap\model\store\StoreOrder;
use think\Log;
use think\Request;
use think\Url;
use behavior\wechat\PaymentBehavior;
use service\HookService;
use service\SystemConfigService;
use app\wap\model\topic\TestPaperOrder;
use app\wap\model\material\DataDownloadOrder;
use app\wap\model\user\UserRecharge;
use think\Db;
class AlipayTradeWapService
{
/**
* 异步通知地址
* @var string
*/
protected static $notifyUrl;
/**
* 同步跳转地址
* @var mixed
*/
protected static $returnUrl;
/**
* 支付宝公钥
* @var mixed
*/
protected static $alipayPublicKey;
/**
* 应用appid
* @var mixed
*/
protected static $alipayAppId;
/**
* 应用私钥
* @var mixed
*/
protected static $alipayPrivateKey;
/**
* 支付宝根证书
* @var mixed
*/
protected static $alipayRootCert;
/**
* 支付宝公钥证书
* @var mixed
*/
protected static $alipayCertPublicKey;
/**
* 应用公钥证书
* @var mixed
*/
protected static $appCertPublicKey;
/**
* 编码格式
* @var mixed|string
*/
protected static $charset = 'UTF-8';
/**
* 请求网管
* @var string
*/
protected static $gatewayUrl = 'https://openapi.alipay.com/gateway.do';
/**
* 加密方式
* @var mixed|string
*/
protected static $signType = 'RSA2';
/**
* 是否开启调试模式
* @var bool
*/
public static $isDeBug = true;
/**
* 获取不到配置信息错误次数
* @var int
*/
private static $ErrorCount = 0;
/**
* 获取不到配置信息错误最大次数
* @var int
*/
private static $ErrorSum = 3;
/**
* AlipayTradeWapService constructor.
* @param array $confing
* @throws \Exception
*/
public function __construct($confing = [])
{
self::$ErrorCount++;
if (self::$ErrorCount >= self::$ErrorSum) return exception('请配置支付宝公钥私钥APPID');
if ((!self::$alipayAppId || !self::$alipayPublicKey || !self::$alipayPrivateKey) && !$confing) self::confing(true);
if (isset($confing['returnUrl'])) self::$returnUrl = $confing['returnUrl'];
if (isset($confing['notifyUrl'])) self::$returnUrl = $confing['notifyUrl'];
if (isset($confing['signType'])) self::$signType = $confing['signType'];
if (isset($confing['charset'])) self::$charset = $confing['charset'];
if (isset($confing['alipay_app_id'])) self::$alipayAppId = $confing['alipay_app_id'];
if (isset($confing['alipay_public_key'])) self::$alipayPublicKey = $confing['alipay_public_key'];
if (isset($confing['alipay_private_key'])) self::$alipayPrivateKey = $confing['alipay_private_key'];
if (isset($confing['appCertPublicKey'])) self::$appCertPublicKey = $confing['appCertPublicKey'];
if (isset($confing['alipayCertPublicKey'])) self::$alipayCertPublicKey = $confing['alipayCertPublicKey'];
if (isset($confing['alipayRootCert'])) self::$alipayRootCert = $confing['alipayRootCert'];
if (!self::$alipayAppId || !self::$alipayPublicKey || !self::$alipayPrivateKey) exception('请配置支付宝公钥私钥APPID');
self::$ErrorCount = 0;
}
/**
* 设置加密方式
* @param $signType
* @return $this
*/
public function setSignType($signType)
{
self::$signType = $signType;
return $this;
}
/**
* 设置同步回调地址
* @param $returnUrl
* @return $this
*/
public function setReturnUrl($returnUrl)
{
self::$returnUrl = $returnUrl;
return $this;
}
/**
* 设置异步回调地址
* @param $notifyUrl
*/
public function setNotifyUrl($notifyUrl)
{
self::$notifyUrl = $notifyUrl;
return $this;
}
/**
* 设置业务参数
* @param array $biz_content
* @return string
*/
protected static function setBizContent(array $biz_content = [])
{
if (isset($biz_content['passback_params'])) $biz_content['passback_params'] = urlencode($biz_content['passback_params']);
if (isset($biz_content['trade_no']) && empty($biz_content['trade_no'])) unset($biz_content['trade_no']);
$bizContent = json_encode($biz_content);
//打印业务参数
self::$isDeBug && self::WriteLog($bizContent);
return $bizContent;
}
/**
* 获取同步回调地址
* @return mixed
*/
public function getReturnUrl()
{
return self::$returnUrl;
}
/**
* 获取异步回调地址
* @return mixed
*/
public function getNotifyUrl()
{
return self::$notifyUrl;
}
/**
* 读取系统配置赋值给静态变量 并加载支付宝官方支付sdk
* @param bool $isReturn
* @return AlipayTradeWapService
*/
public static function confing($isReturn = false)
{
$confing = SystemConfigService::more([
'alipay_public_key',
'alipay_app_id',
'alipay_private_key',
'appCertPublicKey',
'alipayCertPublicKey',
'alipayRootCert',
]);
self::$alipayAppId = isset($confing['alipay_app_id']) ? trim($confing['alipay_app_id']) : '';
self::$alipayPublicKey = isset($confing['alipay_public_key']) ? trim($confing['alipay_public_key']) : '';
self::$alipayPrivateKey = isset($confing['alipay_private_key']) ? trim($confing['alipay_private_key']) : '';
self::$returnUrl = SystemConfigService::get('site_url') . Url::build('wap/alipay/alipay_success_synchro');
self::$notifyUrl = SystemConfigService::get('site_url') . Url::build('wap/alipay/alipay_success_notify');
self::$alipayRootCert =$confing['alipayRootCert'] ? ROOT_PATH .'public' .$confing['alipayRootCert'] : '';
self::$alipayCertPublicKey =$confing['alipayCertPublicKey'] ? ROOT_PATH .'public' .$confing['alipayCertPublicKey'] : '';
self::$appCertPublicKey =$confing['appCertPublicKey'] ? ROOT_PATH .'public' .$confing['appCertPublicKey'] : '';
vendor('alipay.AopSdk');
if ($isReturn == false) return new self;
}
/**
* 静态调用初始化数据
* @return AlipayTradeWapService
*/
public static function init()
{
return self::confing();
}
/**
* 支付宝异步回调
*/
public static function handleNotify()
{
self::init()->AliPayNotify(function ($data, $result) {
if ($result && isset($data->out_trade_no) && $data->passback_params) {
if ($data->passback_params == 'special') {
StoreOrder::where('order_id', $data->out_trade_no)->where('type', 0)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'signup') {
EventSignUp::where('order_id', $data->out_trade_no)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'member') {
StoreOrder::where('order_id', $data->out_trade_no)->where('type', 1)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'goods') {
StoreOrder::where('order_id', $data->out_trade_no)->where('type', 2)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'testpaper') {
TestPaperOrder::where('order_id', $data->out_trade_no)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'datadownload') {
DataDownloadOrder::where('order_id', $data->out_trade_no)->update(['trade_no' => $data->trade_no]);
} elseif ($data->passback_params == 'recharge') {
UserRecharge::where('order_id', $data->out_trade_no)->update(['trade_no' => $data->trade_no]);
}
HookService::listen('wechat_pay_success', $data, null, true, PaymentBehavior::class);
}
});
}
/**
* 支付宝异步回调
* @param callable $notifyFn 闭包函数 参数1,回调返回的参数,回调结果
* @return bool
*/
protected function AliPayNotify(callable $notifyFn)
{
$post = Request::instance()->post();
$result = self::AliPaycheck($post);
if ($result) {
//商户订单号
$post['out_trade_no'] = isset($post['out_trade_no']) ? $post['out_trade_no'] : '';
//支付宝交易号
$post['trade_no'] = isset($post['trade_no']) ? $post['trade_no'] : '';
//交易状态
$post['trade_status'] = isset($post['trade_status']) ? $post['trade_status'] : '';
//备注
$post['attach'] = isset($post['passback_params']) ? urldecode($post['passback_params']) : '';
//异步回调成功执行
try {
if (is_callable($notifyFn)) $notifyFn((object)$post, $result);
} catch (\Exception $e) {
self::$isDeBug && self::WriteLog('支付宝支付成功,订单号为:' . $post['out_trade_no'] . '.回调报错:' . $e->getMessage());
}
echo 'success';
} else {
echo 'fail';
}
self::$isDeBug && self::WriteLog($result);
return true;
}
/**
* 支付宝同步回调
* @return array
*/
public function AliPayReturn()
{
//获取返回参数
$get = Request::instance()->get();
//验签成功与否
$result = self::AliPaycheck($get);
//记录日志
self::$isDeBug && self::WriteLog(compact('result', 'get'));
return compact('result', 'get');
}
/**
* 验签方法
* @param $arr 验签支付宝返回的信息,使用支付宝公钥。
* @return boolean
*/
protected static function AliPaycheck($post)
{
$aop = new \AopClient();
$aop->alipayrsaPublicKey = self::$alipayPublicKey;
return $aop->rsaCheckV1($post, self::$alipayPrivateKey, self::$signType);
}
/**
* 初始化参数
* @param $request
* @param bool $ispage
* @return mixed|\SimpleXMLElement|string|\提交表单HTML文本
* @throws \Exception
*/
protected static function AopclientRequestExecute($request, $ispage = false, $isapp = false)
{
$privateKey = self::$alipayPrivateKey;
$alipayConfig = new \AlipayConfig();
$alipayConfig->setPrivateKey($privateKey);
$alipayConfig->setServerUrl("https://openapi.alipay.com/gateway.do");
$alipayConfig->setAppId(self::$alipayAppId);
$alipayConfig->setCharset("UTF-8");
$alipayConfig->setSignType("RSA2");
$alipayConfig->setEncryptKey("");
$alipayConfig->setFormat("json");
$alipayConfig->setAppCertPath(self::$appCertPublicKey);
$alipayConfig->setAlipayPublicCertPath(self::$alipayCertPublicKey);
$alipayConfig->setRootCertPath(self::$alipayRootCert);
$aop = new \AopCertClient($alipayConfig);
// 开启页面信息输出
$aop->debugInfo = true;
if (!$isapp) {
if ($ispage) {
$result = $aop->pageExecute($request, "post");
return $result;
} else
$result = $aop->Execute($request);
} else {
$result = $aop->sdkExecute($request);
}
//打开后,将报文写入log文件
self::$isDeBug && self::WriteLog($result);
return $result;
}
/**
* alipay.trade.wap.pay 下单支付手机网站支付版本
* @param $out_trade_no 下单号
* @param $total_amount 订单金额 单位元
* @param $subject 订单标题
* @param $passback_params 订单备注 会原样返回通常用于回调监听函数
* @param $product_code 销售产品码,商家和支付宝签约的产品码
* @param $ispage 是否直接输出
* @return $response 支付宝返回的信息
*/
public function AliPayWap($out_trade_no, $total_amount, $subject, $returnUrl = '', $passback_params, $product_code = 'QUICK_MSECURITY_PAY', $ispage = true)
{
$request = new \AlipayTradeWapPayRequest();
$request->setNotifyUrl(self::$notifyUrl);
$request->setReturnUrl($returnUrl ? $returnUrl : self::$returnUrl);
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'total_amount', 'subject', 'passback_params', 'product_code')));
return self::AopclientRequestExecute($request, $ispage);
}
// 支付宝提现
public function WithdrawalQuery($extract){
if(!self::$alipayPrivateKey) return array("code"=>"400",'sub_msg'=>"请先配置支付宝提现信息");
$privateKey = self::$alipayPrivateKey;
$alipayConfig = new \AlipayConfig();
$alipayConfig->setPrivateKey($privateKey);
$alipayConfig->setServerUrl("https://openapi.alipay.com/gateway.do");
$alipayConfig->setAppId(self::$alipayAppId);
$alipayConfig->setCharset("UTF-8");
$alipayConfig->setSignType("RSA2");
$alipayConfig->setEncryptKey("");
$alipayConfig->setFormat("json");
$alipayConfig->setAppCertPath(self::$appCertPublicKey);
$alipayConfig->setAlipayPublicCertPath(self::$alipayCertPublicKey);
$alipayConfig->setRootCertPath(self::$alipayRootCert);
$alipayClient = new \AopCertClient($alipayConfig);
$alipayClient->isCheckAlipayPublicCert = true;
try {
//code...
$request = new \AlipayFundTransUniTransferRequest();
$randomNumber = "";
for ($i = 0; $i < 12; $i++) {
$randomNumber .= mt_rand(0, 9);
}
$data = array();
$data['out_biz_no'] = $randomNumber;
$data['remark'] = "发放佣金";
$data['business_params'] = array(
'payer_show_name_use_alias' => true
);
$data['biz_scene'] = "DIRECT_TRANSFER";
$data['payee_info'] = array(
'identity' => $extract['alipay_code'],
'identity_type' => "ALIPAY_LOGON_ID",
'name' => $extract['real_name']
);
$data['trans_amount'] = $extract['extract_price'];
$data['product_code'] = "TRANS_ACCOUNT_NO_PWD";
$data['order_title'] = "佣金发放";
$tosign = json_encode($data);
$request->setBizContent($tosign);
$responseResult = $alipayClient->execute($request);
$responseApiName = str_replace(".","_",$request->getApiMethodName())."_response";
$response = $responseResult->$responseApiName;
$error = json_decode(json_encode($response), TRUE);
return $error;
} catch (\Throwable $th) {
//throw $th;
var_dump($th->getMessage());
}
}
public function applyQuery($uid)
{
// f5c7072d28fe95ab632b90d357798ea4
$certify_id = Db::name('user')->where('uid',$uid)->value('certify_id');
$user = Db::name('user')->where('uid',$uid)->find();
if (!$certify_id) return array(
'status' => "N",
'cert_name' => $user['cert_name'],
'cert_no' => $user['cert_no'],
);;
if ($certify_id == "T") return array(
'status' => "Y",
'cert_name' => $user['cert_name'],
'cert_no' => $user['cert_no'],
);
$privateKey = self::$alipayPrivateKey;
$alipayConfig = new \AlipayConfig();
$alipayConfig->setPrivateKey($privateKey);
$alipayConfig->setServerUrl("https://openapi.alipay.com/gateway.do");
$alipayConfig->setAppId(self::$alipayAppId);
$alipayConfig->setCharset("UTF-8");
$alipayConfig->setSignType("RSA2");
$alipayConfig->setEncryptKey("");
$alipayConfig->setFormat("json");
$alipayConfig->setAppCertPath(self::$appCertPublicKey);
$alipayConfig->setAlipayPublicCertPath(self::$alipayCertPublicKey);
$alipayConfig->setRootCertPath(self::$alipayRootCert);
$aop = new \AopCertClient($alipayConfig);
$aop->isCheckAlipayPublicCert = true;
$request = new \AlipayUserCertifyOpenQueryRequest();
$data = array();
$data['certify_id'] = $certify_id;
$tosign = json_encode($data);
$request->setBizContent($tosign);
$result = $aop->execute($request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$error = json_decode(json_encode($result), TRUE)["alipay_user_certify_open_query_response"]["code"];
if($error == 40004){
$status = "N";
}else{
$status = json_decode(json_encode($result), TRUE)["alipay_user_certify_open_query_response"]["passed"];
}
$data = array(
'status' => $status,
'cert_name' => $user['cert_name'],
'cert_no' => $user['cert_no'],
);
return $data;
}
public function applyVerify($data)
{
//判断是从app/抖音/快手
switch ($data['type']) {
case 1:
$scheme = "adr://";
# code... //原App
break;
case 2:
$scheme = "snssdk1128://";
# code... //抖音
break;
case 3:
$scheme = "kwai://";
# code...//快手
break;
case 4:
$scheme = "https://demo.zhishi.tczxkj.com/h5/#/pages/merchant/index";
# code...//H5
break;
}
$privateKey = self::$alipayPrivateKey;
$alipayConfig = new \AlipayConfig();
$alipayConfig->setPrivateKey($privateKey);
$alipayConfig->setServerUrl("https://openapi.alipay.com/gateway.do");
$alipayConfig->setAppId(self::$alipayAppId);
$alipayConfig->setCharset("UTF-8");
$alipayConfig->setSignType("RSA2");
$alipayConfig->setEncryptKey("");
$alipayConfig->setFormat("json");
$alipayConfig->setAppCertPath(self::$appCertPublicKey);
$alipayConfig->setAlipayPublicCertPath(self::$alipayCertPublicKey);
$alipayConfig->setRootCertPath(self::$alipayRootCert);
$aop = new \AopCertClient($alipayConfig);
$aop->isCheckAlipayPublicCert = true;
$request = new \AlipayUserCertifyOpenInitializeRequest();
$newsigndata = array();
$newsigndata['outer_order_no'] = md5(time());
$newsigndata['biz_code'] = "FACE";
$newsigndata['identity_param']['identity_type'] = "CERT_INFO";
$newsigndata['identity_param']['cert_type'] = "IDENTITY_CARD";
$newsigndata['identity_param']['cert_name'] = $data['cert_name'];
$newsigndata['identity_param']['cert_no'] = $data['cert_no'];
$newsigndata['merchant_config']['return_url'] = $scheme;
$newsigndata['face_contrast_picture'] = "xydasf==";
$tosign = json_encode($newsigndata);
$request->setBizContent($tosign);
$result = $aop->execute($request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
Log::error("上面认证拿到的certify_id获取失败");
Log::error(json_encode($result));
$certify_id = json_decode(json_encode($result), TRUE)["alipay_user_certify_open_initialize_response"]["certify_id"]; // 上面认证拿到的certify_id 作为参数传入
Db::name('user')->where('uid',$data['uid'])->update([
'certify_id' => $certify_id,
'cert_name' => $data['cert_name'],
'cert_no' => $data['cert_no'],
]);
if (!empty($resultCode) && $resultCode == 10000) {
$request_start = new \AlipayUserCertifyOpenCertifyRequest();
$data = array();
$data['certify_id'] = $certify_id;
$tosignstart = json_encode($data);
$request_start->setBizContent($tosignstart);
$result_start = $aop->pageExecute($request_start);
// Log::error("实名认证接口");
// Log::error($result_start);
// var_dump($result_start);
return $result_start;
// $responseNodeStart = str_replace(".", "_", $request_start->getApiMethodName()) . "_response";
// $resultCode = $result->$responseNodeStart->code;
// if(!empty($resultCode)&&$resultCode == 10000){
// echo "成功";
// } else {
// echo "失败";
// }
} else {
echo "失败";
}
}
/**
* alipay.trade.wap.pay 下单支付手机网站支付版本
* @param $out_trade_no 下单号
* @param $total_amount 订单金额 单位元
* @param $subject 订单标题
* @param $passback_params 订单备注 会原样返回通常用于回调监听函数
* @param $product_code 销售产品码,商家和支付宝签约的产品码
* @param $ispage 是否直接输出
* @return $response 支付宝返回的信息
*/
public function AliPayApp($out_trade_no, $total_amount, $subject,$passback_params, $product_code = 'QUICK_MSECURITY_PAY', $ispage = false)
{
$request = new \AlipayTradeAppPayRequest();
$request->setNotifyUrl(self::$notifyUrl);
$request->setReturnUrl(self::$returnUrl);
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'total_amount', 'subject', 'passback_params', 'product_code')));
return self::AopclientRequestExecute($request, $ispage, true);
}
/**支付宝 当面付
* @param $out_trade_no
* @param $total_amount
* @param $subject
* @param $passback_params
* @param string $product_code
* @param bool $ispage
* @return mixed|\SimpleXMLElement|string|\提交表单HTML文本
* @throws \Exception
*/
public function AliPayNative($out_trade_no, $total_amount, $subject, $passback_params, $product_code = 'FACE_TO_FACE_PAYMENT', $ispage = false)
{
$request = new \AlipayTradePrecreateRequest();
$request->setNotifyUrl(self::$notifyUrl);
$request->setReturnUrl(self::$returnUrl);
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'total_amount', 'subject', 'passback_params', 'product_code')));
$result = self::AopclientRequestExecute($request, $ispage);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
$qr_code_url = $result->$responseNode->qr_code;
if (!empty($resultCode) && $resultCode == 10000) {
return $qr_code_url;
} else {
return '';
}
}
/**
* alipay.trade.query (统一收单线下交易查询)
* @param $out_trade_no 下单号
* @param $trade_no 支付宝订单号
* @param $passback_params 订单备注 会原样返回通常用于回调监听函数
* @return $response 支付宝返回的信息
*/
public function AliPayQuery($out_trade_no, $trade_no, $passback_params)
{
$request = new \AlipayTradeQueryRequest();
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'passback_params', 'trade_no')));
return self::AopclientRequestExecute($request);
}
/**
* alipay.trade.refund (统一收单交易退款接口)
* @param $out_trade_no 下单订单号
* @param $trade_no 支付宝订单号
* @param $refund_amount 退款金额
* @param $refund_reason 退款说明
* @param $passback_params 备注
* @return $response 支付宝返回的信息
*/
public function AliPayRefund($out_trade_no, $trade_no, $refund_amount, $refund_reason, $passback_params)
{
$request = new \AlipayTradeRefundRequest();
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'trade_no', 'refund_amount', 'refund_reason', 'passback_params')));
$result = self::AopclientRequestExecute($request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
return $resultCode;
}
/**
* alipay.trade.close (统一收单交易关闭接口)
* @param $out_trade_no 订单号
* @param $trade_no 支付宝订单号
* @return $response 支付宝返回的信息
*/
public function AliPayClose($out_trade_no, $trade_no)
{
$request = new \AlipayTradeCloseRequest();
$request->setBizContent(self::setBizContent(compact('out_trade_no', 'trade_no')));
return self::AopclientRequestExecute($request);
}
/**
* 写入日志
* @param $content string | array | object
* @return boolen
* */
public static function WriteLog($content)
{
try {
Log::init([
'type' => 'File',
'path' => LOG_PATH . 'alipay/'
]);
if (is_array($content)) $content = 'response: ' . var_export($content, true);
if (is_object($content)) $content = 'response: ' . var_export($content, true);
Log::write(date('Y-m-d H:i:s', time()) . ' ' . $content);
} catch (\Exception $e) {
}
}
}