276 lines
10 KiB
PHP
276 lines
10 KiB
PHP
<?php
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: HIAPAD
|
||
* Date: 2018/9/25
|
||
* Time: 10:48
|
||
*/
|
||
|
||
namespace app\common\service;
|
||
use app\exceptions\PayException;
|
||
use think\Db;
|
||
use think\Exception;
|
||
use think\facade\Config;
|
||
use think\facade\Log;
|
||
use wxpayNew\lib\WxPayApi;
|
||
use wxpayNew\WxPayConfig;
|
||
|
||
class PayService
|
||
{
|
||
/**
|
||
* 支付宝支付
|
||
*/
|
||
public static function aliPayInfo($orderInfo)
|
||
{
|
||
$timeout_express = ceil((strtotime($orderInfo['deadline_time']) - time()) / 60);
|
||
$bodyData = [
|
||
'subject' => '支付宝订单',
|
||
'timeout_express' => $timeout_express.'m',
|
||
'product_code' => 'QUICK_MSECURITY_PAY',
|
||
'total_amount' => floatval($orderInfo['total_amount']),
|
||
'out_trade_no' => $orderInfo['order_sn'],
|
||
];
|
||
//构造参数
|
||
$path = realpath(dirname(__FILE__).'/../../../extend/alipay');
|
||
require_once($path . '/AopSdk.php');
|
||
$config = Config::pull('alipay');
|
||
$aop = new \AopClient ();
|
||
|
||
$aop->gatewayUrl = $config['gatewayUrl'];
|
||
//实际上线app id需真实的
|
||
$aop->appId = $config['app_id'];
|
||
$aop->rsaPrivateKey = $config['merchant_private_key'];
|
||
$aop->format = $config['format'];
|
||
$aop->charset = $config['charset'];
|
||
$aop->signType = $config['sign_type'];
|
||
$aop->alipayrsaPublicKey = $config['alipay_public_key'];
|
||
|
||
$request = new \AlipayTradeAppPayRequest();
|
||
$request->setNotifyUrl($config['notify_url']);
|
||
$request->setBizContent(json_encode($bodyData));
|
||
$response = $aop->sdkExecute($request);
|
||
return $response;
|
||
}
|
||
|
||
/**
|
||
* 支付宝回调
|
||
* @param $param
|
||
* @throws Exception
|
||
*/
|
||
public static function aliPayCallback($param)
|
||
{
|
||
Log::record('进入支付宝订单支付回调');
|
||
$path = realpath(dirname(__FILE__).'/../../../extend/alipay');
|
||
require_once ($path . '/pagepay'.'/service/AlipayTradeService.php');
|
||
$config = Config::pull('alipay');
|
||
$arr=$param;
|
||
$alipaySevice = new \AlipayTradeService($config);
|
||
$alipaySevice->writeLog(var_export($param,true));
|
||
$result = $alipaySevice->check($arr);
|
||
/* 实际验证过程建议商户添加以下校验。
|
||
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
|
||
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
|
||
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
|
||
4、验证app_id是否为该商户本身。
|
||
*/
|
||
if($result) {//验证成功
|
||
//请在这里加上商户的业务逻辑程序代
|
||
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
|
||
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
|
||
//商户订单号
|
||
$out_trade_no = $param['out_trade_no'];
|
||
//支付宝交易号
|
||
$trade_no = $param['trade_no'];
|
||
//交易状态
|
||
$trade_status = $param['trade_status'];
|
||
//接受订单支付金额
|
||
$money = $param['total_amount'];
|
||
//支付宝返回的seller_id
|
||
$seller_id = $param['seller_id'];
|
||
//支付宝返回的app_id
|
||
$app_id = $param['app_id'];
|
||
//如果支付出错,则做退款信息返回
|
||
$returnData = [];
|
||
$returnData['out_trade_no'] = $out_trade_no;
|
||
$returnData['trade_no'] = $trade_no;
|
||
$returnData['money'] = $money;
|
||
if($trade_status == 'TRADE_FINISHED') {
|
||
//判断该笔订单是否在商户网站中已经做过处理
|
||
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
|
||
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
|
||
//如果有做过处理,不执行商户的业务程序
|
||
//注意:
|
||
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
|
||
} else if ($trade_status == 'TRADE_SUCCESS') {
|
||
//通过商户订单号out_trade_no获取订单详情
|
||
$orderInfo = Db::name('order_info')->where('order_sn',$out_trade_no)->find();
|
||
if(!$orderInfo){
|
||
//验证失败
|
||
throw new PayException('订单验证失败', 0, null, $returnData);
|
||
}
|
||
Log::record('订单支付开始:'.$orderInfo['order_id']);
|
||
if($orderInfo['total_amount'] * 100 != $money * 100){
|
||
//TODO 如果订单现金支付金额不符 做退款取消订单处理
|
||
throw new PayException('订单金额不符', 0, null, $returnData);
|
||
}
|
||
|
||
if($seller_id != $config['seller_id'])
|
||
{
|
||
//TODO 如果订单seller_id不符 做退款取消订单处理
|
||
throw new PayException('订单seller_id不符', 0, null, $returnData);
|
||
}
|
||
|
||
|
||
if($app_id != $config['app_id'])
|
||
{
|
||
//TODO 如果订单app_id不符 做退款取消订单处理
|
||
throw new PayException('订单app_id不符', 0, null, $returnData);
|
||
}
|
||
|
||
if($orderInfo['status'] != 0){
|
||
//TODO 如果订单状态不符 做退款取消订单处理
|
||
throw new PayException('订单状态验证失败', 0, null, $returnData);
|
||
}
|
||
//判断该笔订单是否在商户网站中已经做过处理
|
||
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
|
||
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
|
||
//如果有做过处理,不执行商户的业务程序
|
||
//注意:
|
||
//付款完成后,支付宝系统发送该交易状态通知
|
||
//订单支付方式
|
||
$o['pay_type'] = 5;
|
||
$o['pay_status'] = 1;
|
||
$o['status'] = 6;
|
||
$o['pay_time'] = date('Y-m-d H:i:s',time());
|
||
try{
|
||
Db::name('order_info')->where('order_sn',$out_trade_no)->update($o);
|
||
}catch (Exception $exception){
|
||
throw new \app\exceptions\Exception('订单状态修改失败', 0, null, $returnData);
|
||
}
|
||
}
|
||
Log::record('支付宝订单支付回调成功:'.$orderInfo['order_id']);
|
||
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
|
||
return true; //请不要修改或删除
|
||
}else {
|
||
//验证失败
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 支付宝退款
|
||
* @throws \Exception
|
||
*/
|
||
public static function aliPayRefund($returnData)
|
||
{
|
||
if($returnData['money'] > 0){
|
||
$path = realpath(dirname(__FILE__).'/../../../extend/alipay/pagepay');
|
||
require_once $path.'/service/AlipayTradeService.php';
|
||
require_once $path.'/buildermodel/AlipayTradeRefundContentBuilder.php';
|
||
//获取阿里支付配置
|
||
$config = Config::pull('alipay');
|
||
//构造参数
|
||
$refundRequestBuilder = new \AlipayTradeRefundContentBuilder();
|
||
$refundRequestBuilder->setOutTradeNo($returnData['out_trade_no']);
|
||
$refundRequestBuilder->setTradeNo($returnData['trade_no'] );
|
||
$refundRequestBuilder->setRefundAmount(number_format($returnData['money'],2,'.',''));
|
||
$refundRequestBuilder->setRefundReason('订单退款');
|
||
$aop = new \AlipayTradeService($config);
|
||
$response = $aop->Refund($refundRequestBuilder);
|
||
return $response;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 微信支付
|
||
* @throws \Exception
|
||
*/
|
||
public static function wxPayInfo($orderInfo) {
|
||
$config = Config::pull('wxpay');
|
||
$config['noncestr'] = strtoupper(md5(uniqid(rand(10000, 99999))));
|
||
$timeout_express = ceil((strtotime($orderInfo['create_time']) + 86400 - time()) / 60);
|
||
if($timeout_express < 0)
|
||
{
|
||
throw new Exception('订单已过期');
|
||
}
|
||
$param = [
|
||
'body' => '金壶订单',
|
||
'attach' => '支付订单',
|
||
'out_trade_no' => $orderInfo['order_sn'],
|
||
'total_fee' => $orderInfo['total_amount'] * 100,
|
||
'spbill_create_ip' => "0.0.0.0",
|
||
'notify_url' => $config['NOTIFYURL'],
|
||
'trade_type' => 'APP',
|
||
'time_expire' => $timeout_express
|
||
];
|
||
$wxpay=new WxPayService();
|
||
$wxpay->setWxpayOrderData($param);
|
||
return $wxpay->unifiedOrder();
|
||
}
|
||
|
||
/**
|
||
* 微信回调
|
||
* @throws \Exception
|
||
*/
|
||
public static function wxPayCallback($returnData) {
|
||
$orderInfo = Db::name('order_info')->where('order_sn',$returnData['out_trade_no'])->find();
|
||
if(!$orderInfo){
|
||
//验证失败
|
||
throw new PayException('订单验证失败', 0, null, $returnData);
|
||
}
|
||
Log::record('订单支付开始:'.$orderInfo['order_id']);
|
||
if($orderInfo['total_amount'] * 100 != $returnData['money'] * 100){
|
||
//TODO 如果订单现金支付金额不符 做退款取消订单处理
|
||
throw new PayException('订单金额不符', 0, null, $returnData);
|
||
}
|
||
if($orderInfo['status'] != 0){
|
||
//TODO 如果订单状态不符 做退款取消订单处理
|
||
throw new PayException('订单状态验证失败', 0, null, $returnData);
|
||
}
|
||
$orderInfo['pay_type'] = 4;
|
||
$orderInfo['pay_status'] = 1;
|
||
$orderInfo['status'] = 6;
|
||
$orderInfo['pay_time'] = date('Y-m-d H:i:s',time());
|
||
try{
|
||
Db::name('order_info')->where('order_sn',$returnData['out_trade_no'])->update($orderInfo);
|
||
}catch (Exception $exception){
|
||
throw new \app\exceptions\Exception('订单状态修改失败', 0, null, $returnData);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 微信退款
|
||
* @throws \Exception
|
||
*/
|
||
public static function wxPayRefund($returnData) {
|
||
$config = Config::pull('wxpay');
|
||
$wxPayConfig = new WxPayConfig($config);
|
||
try {
|
||
$wxPayFound = new \WxPayRefund();
|
||
$wxPayFound->SetTransaction_id($returnData['trade_no']);
|
||
$wxPayFound->SetTotal_fee($returnData['money']);
|
||
$wxPayFound->SetRefund_fee($returnData['money']);
|
||
$wxPayFound->SetOut_refund_no("sdkphp" . date("YmdHis"));
|
||
$wxPayFound->SetOp_user_id($wxPayConfig->GetMerchantId());
|
||
$res=WxPayApi::refund($wxPayConfig,$wxPayFound);
|
||
//返回结果处理
|
||
if(isset($res['return_code'])){
|
||
if($res['return_code']=='FAIL'){
|
||
throw new Exception("退款申请失败,原因:".$res['return_msg']);
|
||
}
|
||
if($res['return_code']=='SUCCESS'){
|
||
if($res['result_code']=='FAIL'){
|
||
throw new Exception("退款申请失败,原因:".$res['err_code_des']);
|
||
}
|
||
if($res['result_code']=='SUCCESS'){
|
||
return $res;//申请成功
|
||
}
|
||
}
|
||
}
|
||
throw new Exception('退款申请失败,原因:未知');
|
||
}catch (Exception $e) {
|
||
throw new Exception( $e->getMessage());
|
||
}
|
||
}
|
||
} |