| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- <?php
- namespace frontend\controllers;
- use common\enums\AliPayPayTypeEnum;
- use common\models\common\PaymentTradeLog;
- use yii\web\Controller;
- use Yii;
- use Exception;
- use common\helpers\WechatHelper;
- use common\helpers\FileHelper;
- use common\helpers\ArrayHelper;
- use common\enums\PayTypeEnum;
- /**
- * 支付回调
- *
- * Class NotifyController
- * @package frontend\controllers
- */
- class NotifyController extends Controller
- {
- //use PayNotify;
- /**
- * 关闭csrf
- *
- * @var bool
- */
- public $enableCsrfValidation = false;
- /**
- * 公用支付回调 - 微信
- *
- * @return bool|string
- */
- public function actionWechat()
- {
- try{
- $xml = file_get_contents('php://input');
- $wechat_post = WechatHelper::xmlToArray($xml);
- if(!$wechat_post || !$wechat_post['out_trade_no']){
- throw new Exception('参数不合法');
- }
- $trade = Yii::$app->services->pay->getByTradeNo(trim($wechat_post['out_trade_no']));
- if(empty($trade)){
- throw new Exception('交易流水号不存在:'.trim($wechat_post['out_trade_no']));
- }
- $config = Yii::$app->services->pay->getConfig($trade->mall_id,'wechat');
- //微信支付配置获取
- $wechat = Yii::$app->payment->wechat($config);
- $response = $wechat->notify();
- if ($response->isPaid()) {
- $message = $response->getRequestData();
- //日志记录回调文件
- FileHelper::writeLog($this->getLogPath('wechat'), json_encode(ArrayHelper::toArray($message)));
- ///////////// 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况,确认是已经支付 /////////////
- $message['pay_fee'] = bcdiv($message['total_fee'],100,2);
- //pay success 注意微信会发二次消息过来 需要判断是通知还是回调
- if ($this->pay($message,PayTypeEnum::WECHAT)) {
- return WechatHelper::success();
- }
- throw new Exception('pay error:'.trim($wechat_post['out_trade_no']));
- } else {
- throw new Exception('response is not Paid:'.trim($wechat_post['out_trade_no']));
- }
- }catch(Exception $e){
- FileHelper::writeLog($this->getLogPath('error'), $e->getMessage());
- return WechatHelper::fail();
- }
- }
- /**
- * 公用支付回调 - 微信小程序支付回调
- * @return bool|string|\Symfony\Component\HttpFoundation\Response
- * @throws \EasyWeChat\Kernel\Exceptions\Exception
- */
- public function actionWechatMp()
- {
- $xml = file_get_contents('php://input');
- $wechat_post = WechatHelper::xmlToArray($xml);
- if(!$wechat_post || !$wechat_post['out_trade_no']){
- return WechatHelper::fail();
- }
- $trade = Yii::$app->services->pay->getByTradeNo(trim($wechat_post['out_trade_no']));
- if(empty($trade)){
- return WechatHelper::fail();
- }
- // 微信支付参数配置
- // 设置appid
- $config = Yii::$app->services->pay->getConfig($trade->mall_id,'wechat');
- $config['app_id'] = $config['miniprogram_appid'];
- Yii::$app->params['wechatPaymentConfig'] = $config;
- $response = Yii::$app->wechat->payment->handlePaidNotify(function ($message, $fail) {
- $logPath = $this->getLogPath('wechat-mp');
- FileHelper::writeLog($logPath, Json::encode(ArrayHelper::toArray($message)));
- if ($message['return_code'] === 'SUCCESS') {
- $message['pay_fee'] = bcdiv($message['total_fee'],100,2);
- if ($this->pay($message,PayTypeEnum::WECHAT)) {
- return true;
- }
- }
- return $fail('处理失败,请稍后再通知我');
- });
- return $response;
- }
- /**
- * 公用支付回调 - 支付宝
- *
- * @throws Exception
- */
- public function actionAlipay()
- {
- $out_trade_no = $_POST['out_trade_no'];
- if (!$out_trade_no) {
- die('操作失败');
- }
- $trade = Yii::$app->services->pay->getByTradeNo(trim($out_trade_no));
- if(empty($trade)){
- die('操作失败');
- }
- try {
- $config = Yii::$app->services->pay->getConfig($trade->mall_id, 'alipay');
- $trade_log = PaymentTradeLog::find()->where(['trade_id' => $trade->id,'pay_type' => PayTypeEnum::ALI])->orderBy('id desc')->one();
- if($trade_log && $trade_log->trade_type == AliPayPayTypeEnum::JS){
- $config = Yii::$app->services->setting->mall->get($trade->mall_id, "alipay_mini");
- $config['alipay_app_id'] = $config['app_id'];
- $base_path = dirname(Yii::$app->basePath);
- $config['alipay_public_key'] = file_get_contents("$base_path/{$config['alipayCertPath']}");
- $config['alipay_private_key'] = $config['merchantPrivateKey'];
- }
- //$config = Yii::$app->services->pay->getConfig($trade->mall_id, 'alipay');
- $alipay = Yii::$app->payment->alipay($config);
- $request = $alipay->notify();
- /** @var \Omnipay\Alipay\Responses\AopCompletePurchaseResponse $response */
- $response = $request->send();
- if ($response->isPaid()) {
- $message = Yii::$app->request->post();
- $message['pay_fee'] = $message['total_amount'];
- $message['mch_id'] = $message['auth_app_id'];
- //支付宝回调内有 out_trade_no 商户订单号
- // 日志记录
- $logPath = $this->getLogPath('alipay');
- FileHelper::writeLog($logPath, json_encode(ArrayHelper::toArray($message)));
- if ($this->pay($message, PayTypeEnum::ALI)) {
- die('操作成功');
- }else{
- throw new Exception('alipay pay error:'.$out_trade_no);
- }
- }
- throw new Exception('alipay response isPaid error:'.$out_trade_no);
- } catch (\Exception $e) {
- // 记录报错日志
- FileHelper::writeLog($this->getLogPath('error'), $e->getMessage());
- die('操作失败'); // 通知响应
- }
- }
- /**
- * 公用支付回调 - 汇聚支付
- * @return string
- */
- public function actionJoinpay()
- {
- $params = \Yii::$app->request->get();
- $params = array_map('urldecode', $params);
- try{
- $my_param = !empty($params['r5_Mp']) ? json_decode($params['r5_Mp'],true) : []; //json格式
- //获取对应支付配置
- $mall_id = $my_param['mall_id'] ?? 0;
- $config = Yii::$app->services->pay->getConfig($mall_id,'joinpay');
- //调用支付类:回调方法
- $pay = Yii::$app->payment->joinpay($config);
- $message = $pay->notify();
- if ($this->pay($message,PayTypeEnum::JOINPAY)) {
- die('操作成功');
- }
- die('操作失败');
- }catch(\Exception $e){
- // 记录报错日志
- $logPath = $this->getLogPath('error');
- FileHelper::writeLog($logPath, $e->getMessage());
- die('操作失败'); // 通知响应
- }
- }
- /**
- * 公用支付回调 - 汇聚快捷支付
- * @return string
- */
- public function actionJoinpayFastPay()
- {
- try{
- $post = \Yii::$app->request->post();
- if(empty($post) || empty($post['data'])){
- die('操作失败'); // 通知响应
- }
- $data = json_decode($post['data'],true);
- $callback_param = json_decode($data['callback_param'],true);
- $mall_id = $callback_param['mall_id'] ?? 0;
- //获取对应支付配置
- $config = Yii::$app->services->pay->getConfig($mall_id,'joinpay_fast');
- $pay = Yii::$app->payment->joinpayFastPay($config);
- $message = $pay->notify($post);
- if ($this->pay($message,PayTypeEnum::JOINPAY_FAST_PAY)) {
- die('操作成功');
- }
- die('操作失败');
- }catch(\Exception $e){
- // 记录报错日志
- $logPath = $this->getLogPath('error');
- FileHelper::writeLog($logPath, $e->getMessage());
- die('操作失败'); // 通知响应
- }
- }
- /**
- * 支付公用方法
- * @param $message
- * @param int $pay_type 支付类型
- * @return bool
- */
- protected function pay($message,$pay_type)
- {
- $transaction = Yii::$app->db->beginTransaction();
- try {
- if (!($payLog = Yii::$app->services->pay->getByTradeNo($message['out_trade_no']))) {
- throw new Exception('找不到支付信息');
- }
- // 支付完成
- if ($payLog->is_pay == 1) {
- return true;
- }
- //支付金额验证
- if(bccomp($message['pay_fee'],$payLog->pay_fee) !== 0){
- throw new Exception('支付金额不一致');
- }
- $payLog->pay_type = $pay_type;
- $payLog->is_pay = 1;
- $payLog->pay_time = time();
- $payLog->third_trade_no = $message['trade_no'] ?? '';
- if (!$payLog->save()) {
- throw new Exception('日志修改失败');
- }
- // 业务回调
- $orders = Yii::$app->services->pay->changePaymentTradeOrder($payLog,$pay_type);
- $transaction->commit();
- Yii::$app->services->pay->notify($orders);
- return true;
- } catch (\Exception $e) {
- $transaction->rollBack();
- //FileHelper::writeLog($this->getLogPath('error'), $e->getMessage());
- // 记录报错日志
- FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([
- 'message' => $e->getMessage(),
- 'line' => $e->getLine(),
- 'file' => method_exists($e, 'getFile') ? $e->getFile() : '',
- 'trace' => $e->getTrace(),
- 'code' => $e->getCode(),
- ])));
- return false;
- }
- }
- /**
- * @param $type
- * @return string
- */
- protected function getLogPath($type)
- {
- return Yii::getAlias('@runtime') . "/pay-logs/" . date('Y_m_d') . '/' . $type . '.txt';
- }
- }
|