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