custom->logs('wechat_notify', $wechat_post); 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['trade_no'] = $message['transaction_id']; $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){ $logPath = $this->getLogPath('error'); FileHelper::writeLog($logPath, json_encode([ 'post' => $wechat_post, '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); Yii::$app->custom->logs('wechatmp_notify', $wechat_post); 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 = Yii::$app->services->pay->getWechatConfig($trade->mall_id); $config['app_id'] = $config['mini_program_app_id']; \Yii::$app->params['wechatMiniProgramConfig'] = [ 'app_id' => $config['mini_program_app_id'] ?? '', 'secret' => $config['mini_program_secret'] ?? '', 'mch_id' => $config['wechat_mch_id'] ?? '', 'key' => $config['wechat_pay_secret'], 'cert_path' => dirname(Yii::$app->basePath).'/'.$config['wechat_cert_pem_file'], 'key_path' => dirname(Yii::$app->basePath).'/'.$config['wechat_key_pem_file'], ]; // Yii::$app->params['wechatPaymentConfig'] = $config; // $response = Yii::$app->wechat->payment->handlePaidNotify(function ($message, $fail) { $payment = Factory::payment(Yii::$app->params['wechatMiniProgramConfig']); $response = $payment->handlePaidNotify(function ($message, $fail) { $logPath = $this->getLogPath('wechat-mp'); FileHelper::writeLog($logPath, Json::encode(ArrayHelper::toArray($message))); if ($message['return_code'] === 'SUCCESS') { $message['trade_no'] = $message['transaction_id']; $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']; Yii::$app->custom->logs('alipay', $out_trade_no); if (!$out_trade_no) { die('操作失败'); } $trade = Yii::$app->services->pay->getByTradeNo(trim($out_trade_no)); if(empty($trade)){ die('操作失败'); } try { switch ($trade->trade_type) { case AliPay::JS: $config = Yii::$app->services->pay->getAlipayConfig($trade); break; default: $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); Yii::$app->custom->logs('joinpay', $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, json_encode([ 'post' => $params, 'error' => $e->getMessage(), ])); die('操作失败'); // 通知响应 } } /** * 公用支付回调 - 汇聚快捷支付 * @return string */ public function actionJoinpayFastPay() { try{ $post = \Yii::$app->request->post(); Yii::$app->custom->logs('joinpayfastpay', $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, json_encode([ 'post' => $post, 'error' => $e->getMessage(), ])); die('操作失败'); // 通知响应 } } public function actionSandpayFastPay() { try{ $post = \Yii::$app->request->post(); Yii::error("actionSandpayFastPay post: " , var_export($post, true)); if(empty($post) || empty($post['data'])){ die('操作失败'); // 通知响应 } $data = json_decode($post['data'],true); // $trade = PaymentTrade::findOne(['out_trade_no' => $data['body']['orderCode'] ?? '']); $trade = Yii::$app->services->pay->getByTradeNo($data['body']['orderCode']); if (empty($trade)) die("交易不存在: {$data['body']['orderCode']}"); //获取对应支付配置 $config = Yii::$app->services->pay->getConfig($trade->mall_id,'sandpay_fast'); $pay = Yii::$app->payment->sandpayFastPay($config); $message = $pay->notify($post); if ($this->pay($message,PayTypeEnum::SANDPAY_FAST_PAY)) { die('操作成功'); } }catch(\Exception $e){ // 记录报错日志 $logPath = $this->getLogPath('error'); FileHelper::writeLog($logPath, json_encode([ 'post' => $post, 'error' => $e->getMessage(), ])); die('操作失败'); // 通知响应 } } /** * 公用支付回调 - 汇聚分账支付 * * @return void */ public function actionHuiju_bill() { try { $post = Yii::$app->request->post(); if (empty($post)) { throw new Exception('参数不存在'); } // 查询流水订单 $trade = Yii::$app->services->pay->getByTradeNo(trim($post['order_no'])); if (empty($trade)) { FileHelper::writeLog($this->getLogPath('error'), 12223423432234); throw new Exception('流水订单不存在'); } // 支付配置 $config = Yii::$app->services->setting->addons->get($trade->mall_id, AddonsEnum::ADDONS_NAME_HUIJU_BILL, 'basic'); $pay = Yii::$app->payment->huijuBill($config); if (empty($pay)) { throw new Exception('支付类不存在'); } // 查询支付订单 $order = OrderModel::findOne(['trade_id' => $trade->id]); // 支付回调 $res = $pay->notify($post, $trade); if ($res === true) { $post['out_trade_no'] = $post['order_no']; $post['pay_fee'] = $post['amount']; $this->pay($post, PayTypeEnum::HUIJU_BILL, function () use ($order) { $order->success(); }); }else{ exit('notify_error'); } } catch (Exception $e) { 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(), ]))); exit('error'.$e->getMessage()); } exit('success'); } /** * 公用支付回调 - 汇聚分账支付退款回调 * * @return void */ public function actionHuiju_bill_refund() { try { $post = Yii::$app->request->post(); if (empty($post)) { throw new Exception('参数不存在'); } // 是否返回退款订单号 if (empty($post['refund_order_no'])) { throw new Exception('退款失败,未返回订单号'); } // 查询退款订单 $refund_order = OrderRefundModel::findOne(['refund_order_no' => $post['refund_order_no']]); if (empty($refund_order)) { throw new Exception("退款失败,订单{$post['refund_order_no']}订单号不存在"); } // 查询中台订单 $config = Yii::$app->services->setting->addons->get($refund_order->mall_id, AddonsEnum::ADDONS_NAME_HUIJU_BILL, 'basic'); $pay = Yii::$app->payment->huijuBill($config); $res = $pay->refund_notify($post, $refund_order); // 设置订单失败或成功 $res ? $refund_order->success() : $refund_order->fail(); } catch (Exception $e) { FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([ 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => method_exists($e, 'getFile') ? $e->getFile() : '', ]))); } exit('success'); } /** * 支付公用方法 * @param $message * @param int $pay_type 支付类型 * @param callback $call_back 回调函数 * @return bool */ protected function pay($message, $pay_type, $call_back = null) { $transaction = Yii::$app->db->beginTransaction(); try { /** * @var PaymentTrade $payLog */ 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->getOnlinePayFee()) !== 0){ throw new Exception('支付金额不一致'); } $payLog->setOnlinePayType($pay_type); $payLog->isMixedPay() && $payLog->setOnlinePaySuccess(); $payLog->is_pay = 1; $payLog->pay_time = time(); $payLog->third_trade_no = $message['trade_no'] ?? ''; if (!empty($message['trade_type'])) { $payLog->trade_type = $message['trade_type']; } if (!$payLog->save()) { throw new Exception('日志修改失败'); } // 业务回调 $orders = Yii::$app->services->pay->changePaymentTradeOrder($payLog,$pay_type); // 回调函数 if (is_callable($call_back)) { call_user_func($call_back); } $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'; } /** * 中金支付异步回调 */ public function actionSicpay(){ $mall_id = $this->request->get('mall_id'); $data = $this->request->post(); Yii::error("---notify-sicpay---{$mall_id}"); Yii::error($data); try { $pay_service = new \addons\Sicpay\common\services\PayService(); $res = $pay_service->notifyHandle($mall_id,$data); Yii::error(json_encode($res)); Yii::getLogger()->flush(true); if(is_array($res)){ // 成功 $res = $this->pay($res,PayTypeEnum::SIC_PAY); if($res) { return 'success'; } } return 'error'; } catch (Exception $e) { FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([ 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => method_exists($e, 'getFile') ? $e->getFile() : '', ]))); return 'error'; } } /** * 单笔代付回调 */ public function actionJoinpaySingle() { try{ $post = \Yii::$app->request->post(); \Yii::error('JoinpaySinglePay post:'.json_encode($post)); $merchantOrderNo = $post['merchantOrderNo'] ?? ''; if(!$post || !$merchantOrderNo){ throw new Exception('invalid param'); } $log = PaidSinglePayLog::findOne(['merchant_order_no' => $merchantOrderNo]); if(!$log){ throw new Exception('invalid param'); } //验签 //获取对应支付配置 $config = \Yii::$app->services->setting->addons->get($log->mall_id, AddonsEnum::ADDONS_NAME_JOIN_PAY, 'basic'); $params['status'] = $post['status']; $params['errorCode'] = $post['errorCode']; $params['errorCodeDesc'] = $post['errorCodeDesc']; $params['userNo'] = $post['userNo']; if(isset($post['tradeMerchantNo'])){ $params['tradeMerchantNo'] = $post['tradeMerchantNo']; } $params['merchantOrderNo'] = $post['merchantOrderNo']; $params['platformSerialNo'] = $post['platformSerialNo']; $params['receiverAccountNoEnc'] = $post['receiverAccountNoEnc']; $params['receiverNameEnc'] = $post['receiverNameEnc']; $params['paidAmount'] = sprintf("%.2f", $post['paidAmount']); $params['fee'] = sprintf("%.2f", $post['fee']); //验证签名 $hmac = $post['hmac']; $hmacVal = urlencode(RequestUtil::hmacRequest($params, $config['joinpay_merchant_secret'])); if ($hmacVal !== $hmac) { throw new Exception('invalid sign'); } $pay = new AlternativePay($config, $log->mall_id); $res = $pay->queryAlternativeOrder($log->merchant_order_no); if (!empty($res)) { $trans = \Yii::$app->db->beginTransaction(); try { $pay->updateSinglePayStatus($log,$res); $trans->commit(); } catch (\Exception $e) { $trans->rollBack(); \Yii::error('修改汇聚代付失败,获取结果:' . json_encode($res)); throw new Exception('save error'); } } echo json_encode(['statusCode' => '2001','message' => '成功']); exit; }catch(\Exception $e){ \Yii::error('actionJoinpaySingle error:' . $e->getMessage()); echo json_encode(['statusCode' => '2002','message' => $e->getMessage()]); exit; } } /** * 汇聚退款回调 * @author zmz */ public function actionJoinpayRefund() { try { $post = Yii::$app->request->post(); if (empty($post)) { throw new Exception('参数不存在'); } // 是否返回退款订单号 if (empty($post['r2_OrderNo'])) { throw new Exception('退款失败,商户订单号'); } if (empty($post['r3_RefundOrderNo'])) { throw new Exception('退款失败,商户退款订单号'); } // 查询退款订单 $payment_refund = PaymentRefund::findOne(['order_no' => $post['r3_RefundOrderNo'],'is_pay' => 0,'pay_type' => PayTypeEnum::JOINPAY]); if (empty($payment_refund)) { throw new Exception("退款失败,订单{$post['r3_RefundOrderNo']}订单号不存在"); } Yii::$app->services->pay->refundNotify($payment_refund); } catch (Exception $e) { FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([ 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => method_exists($e, 'getFile') ? $e->getFile() : '', ]))); } exit('success'); } /** * 汇聚退款回调 * @author zmz */ public function actionJoinpayFastRefund() { try { $post = Yii::$app->request->post(); \Yii::error('JoinpayFastRefund post:'.json_encode($post)); if(empty($post) || empty($post['data'])){ die('操作失败'); // 通知响应 } $data = json_decode($post['data'],true); // 查询退款订单 $payment_refund = PaymentRefund::findOne(['order_no' => $data['refund_order_no'],'is_pay' => 0,'pay_type' => PayTypeEnum::JOINPAY_FAST_PAY]); if (empty($payment_refund)) { throw new Exception("汇聚快捷支付退款失败,订单{$data['refund_order_no']}订单号不存在"); } //验签 $config = Yii::$app->services->pay->getConfig($payment_refund->mall_id,'joinpay_fast'); if(!$config){ throw new Exception("汇聚快捷支付退款失败,查询不到配置"); } $pay = \Yii::$app->payment->joinpayFastPay($config); $pay->signature_verify($post); if($data['refund_status'] == '100'){ //退款成功 Yii::$app->services->pay->refundNotify($payment_refund); } exit('success'); } catch (Exception $e) { FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([ 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => method_exists($e, 'getFile') ? $e->getFile() : '', ]))); exit('fail'); } //exit('success'); } /** * 汇聚退款回调 * @author zmz */ public function actionSandpayFastRefund() { try { $post = Yii::$app->request->post(); \Yii::error('SandpayFastRefund post:'.json_encode($post)); if(empty($post) || empty($post['data'])){ die('操作失败'); // 通知响应 } $data = json_decode($post['data'],true); // 查询退款订单 $payment_refund = PaymentRefund::findOne(['order_no' => $data['body']['oriOrderCode'],'is_pay' => 0,'pay_type' => PayTypeEnum::SANDPAY_FAST_PAY]); if (empty($payment_refund)) { throw new Exception("杉德快捷支付退款失败,订单 {$data['body']['oriOrderCode']} 订单号不存在"); } //验签 $config = Yii::$app->services->pay->getConfig($payment_refund->mall_id,'sandpay_fast'); if(!$config){ throw new Exception("汇聚快捷支付退款失败,查询不到配置"); } $pay = \Yii::$app->payment->sandpayFastPay($config); $pay->client->verify($config, $post['data'], $post['sign']); if($data['body']['orderStatus'] == 1){ //退款成功 Yii::$app->services->pay->refundNotify($payment_refund); } exit('success'); } catch (Exception $e) { FileHelper::writeLog($this->getLogPath('error'), json_encode(ArrayHelper::toArray([ 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => method_exists($e, 'getFile') ? $e->getFile() : '', ]))); exit('fail'); } //exit('success'); } /** * 微信商家转账回调 */ public function actionWechatTransfer($appKey) { try { $data = Yii::$app->request->post(); if (empty($data)) { $file = file_get_contents("php://input"); $data = json_decode($file, true); } // 存储回调过来的数据 Yii::$app->custom->logs('微信商家转账回调数据:' . $appKey, json_encode($data)); if (empty($data)) { return json_encode(['code' => 'FAIL', 'message' => '参数错误']); } $res = new WithdrawTransferService(); $res = $res->notify($data, $appKey); if (!$res) { return json_encode(['code' => 'FAIL', 'message' => '参数错误']); } return json_encode(['code' => 'SUCCESS', 'message' => '操作成功']); } catch (Exception $e) { return json_encode(['code' => 'FAIL', 'message' => '参数错误']); } } }