diff --git a/api/config/main.php b/api/config/main.php index d7c78e0..dc9d5e6 100644 --- a/api/config/main.php +++ b/api/config/main.php @@ -96,6 +96,7 @@ return [ 'extraPatterns' => [ 'GET web' => 'web', 'POST notify' => 'notify', + 'POST test' => 'test', ] ], ], diff --git a/api/controllers/WxPaymentController.php b/api/controllers/WxPaymentController.php index 44af1a3..adefd3d 100644 --- a/api/controllers/WxPaymentController.php +++ b/api/controllers/WxPaymentController.php @@ -14,6 +14,7 @@ use yii\filters\auth\HttpBearerAuth; use yii\helpers\ArrayHelper; use yii\web\Response; use Yii; +use yii\web\BadRequestHttpException; class WxPaymentController extends CommonController { @@ -25,7 +26,7 @@ class WxPaymentController extends CommonController return ArrayHelper::merge(parent::behaviors(), [ 'authenticatior' => [ 'class' => HttpBearerAuth::className(), - 'except' => ['notify'], + 'except' => ['notify', 'test'], ] ]); } @@ -54,9 +55,22 @@ class WxPaymentController extends CommonController return $this->object->wxPayment(WxPaymentLogic::PAY_TYPE_MINI_PROGRAM); } + /** + * @return array|bool + * @throws BadRequestHttpException + * @throws \yii\base\InvalidConfigException + * @throws \yii\httpclient\Exception + * 异步回调 + */ public function actionNotify() { Yii::$app->response->format = Response::FORMAT_XML; return $this->object->notify(); } + + public function actionTest() + { + $data = Yii::$app->request->getBodyParam('notify');/*int 商品id*/ + return $data; + } } \ No newline at end of file diff --git a/api/logic/WxPaymentLogic.php b/api/logic/WxPaymentLogic.php index 00c1498..9988be7 100644 --- a/api/logic/WxPaymentLogic.php +++ b/api/logic/WxPaymentLogic.php @@ -10,14 +10,12 @@ namespace api\logic; use backend\modules\shop\models\ars\PaymentLog; use backend\modules\shop\models\ars\WxPayConfig; -use common\models\User; use Yii; -use backend\modules\shop\models\ars\Config; use EasyWeChat\Factory; -use backend\modules\shop\models\ars\Order; use yii\db\Exception; +use yii\helpers\Json; +use yii\httpclient\Client; use yii\web\BadRequestHttpException; -use yii\web\NotFoundHttpException; use yii\base\BaseObject; class WxPaymentLogic extends BaseObject @@ -33,7 +31,7 @@ class WxPaymentLogic extends BaseObject public $key; public $certPath; public $keyPath; - public $notifyUrl = 'http://baidu.com'; + public $notifyUrl; public $tradeType; public $payType; public $app; @@ -98,6 +96,7 @@ class WxPaymentLogic extends BaseObject $paymentLog->payment_amount = $paymentAmount; $paymentLog->notify_url = $notifyUrl; $paymentLog->type = $this->payType; + $paymentLog->status = PaymentLog::PAYMENT_STATUS_WAITING; if (!$paymentLog->save()) { throw new Exception(Helper::errorMessageStr($paymentLog->errors)); } @@ -127,31 +126,26 @@ class WxPaymentLogic extends BaseObject private function initObject() { $path = Yii::getAlias('@backend'); - + $wxPayConfig = WxPayConfig::find()->one(); +// $wxConfig = WxConfig::find()->one(); // switch ($this->payType) { // case self::PAY_TYPE_WEB: -// $this->appId = trim($config->wx_appId); -// $this->mchId = trim($config->wx_mchId); -// $this->key = trim($config->wx_key); -// $this->keyPath = trim($path . $config->wx_keyPath); +// $this->appId = trim($wxConfig->wx_appId); // break; // case self::PAY_TYPE_MINI_PROGRAM: -// $this->appId = trim($config->mini_program_appId); -// $this->mchId = trim($config->mini_program_mchId); -// $this->key = trim($config->mini_program_key); +// $this->appId = trim($wxConfig->mini_program_appId); // break; // } - $wxPayConfig = WxPayConfig::find()->one(); $this->mchId = $wxPayConfig->mch_id; $this->certPath = trim($path . $wxPayConfig->cert_path); $this->keyPath = trim($path . $wxPayConfig->key_path); + $this->notifyUrl = Yii::$app->request->hostInfo . '/wx-payment/notify'; } /** * @param $unifyParams * @return mixed - * @throws Exception * 统一下单 */ private function unify($unifyParams) @@ -164,60 +158,34 @@ class WxPaymentLogic extends BaseObject /** * @return array|bool * @throws BadRequestHttpException - * 支付回调 + * @throws \yii\base\InvalidConfigException + * @throws \yii\httpclient\Exception + * 微信支付回调 */ public function notify() { - $result = [ - 'appid' => 'wxdccdddaa336353e1', - 'bank_type' => 'OTHERS', - 'cash_fee' => '926', - 'fee_type' => 'CNY', - 'is_subscribe' => 'N', - 'mch_id' => '1395812402', - 'nonce_str' => '5df366a248edb', - 'openid' => 'ovT0C0UB8xQbfYHVVS2VGWMjDMhI', - 'out_trade_no' => '201912131823156640Q', - 'result_code' => 'SUCCESS', - 'return_code' => 'SUCCESS', - 'sign' => 'EA6FFD717A206D203856EAFB554F666F', - 'time_end' => '20191213182333', - 'total_fee' => '926', - 'trade_type' => 'JSAPI', - 'transaction_id' => '4200000423201912134049863433', - ]; - $xmlString = $this->arrayToXml($result); - $notifyData = json_decode(json_encode(simplexml_load_string($xmlString, 'SimpleXMLElement', LIBXML_NOCDATA))); - -// $notifyData = json_decode(json_encode(simplexml_load_string(Yii::$app->request->getRawBody(), 'SimpleXMLElement', LIBXML_NOCDATA))); -// Yii::info($notifyData, "notify"); -// if (!$this->checkSign($notifyData)) { -// throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS); -// } + $notifyData = Json::decode(Json::encode(simplexml_load_string(Yii::$app->request->getRawBody(), 'SimpleXMLElement', LIBXML_NOCDATA))); + Yii::info($notifyData, "notify"); + if (!$this->checkSign($notifyData)) { + throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS); + } $tra = Yii::$app->db->beginTransaction('SERIALIZABLE'); try { if ($notifyData->result_code != 'SUCCESS' || $notifyData->return_code != 'SUCCESS') { - throw new Exception('result_code or return_code is false'); + throw new BadRequestHttpException('result_code or return_code is false'); } - - $user = User::findOne(['wx_openid' => $notifyData->openid, 'status' => User::STATUS_ACTIVE]) - ?? User::findOne(['mini_openid' => $notifyData->openid, 'status' => User::STATUS_ACTIVE]);/*根据openid获取用户*/ - if (empty($user)) { - throw new Exception('用户不存在或已被禁用'); - } - $paymentLog = PaymentLog::findOne(['order_id' => $notifyData->out_trade_no]); - $paymentLog->mch_id = $this->mch_id; + $this->notifyUrl = Yii::$app->request->hostInfo . $paymentLog->notify_url; + $paymentLog->mch_id = $notifyData->mch_id; $paymentLog->wx_refund_id = $notifyData->transaction_id; //交易号 - $paymentLog->status = 1; + $paymentLog->status = PaymentLog::PAYMENT_STATUS_SUCCESS; if (!$paymentLog->save()) { throw new Exception(Helper::errorMessageStr($paymentLog->errors)); } - if (!$tra->commit()) { throw new Exception('保存数据失败'); } - + /*转发回调信息*/ $this->forwardNotify($notifyData, true); return ['return_code' => 'SUCCESS', 'return_msg' => 'OK'];//回传成功信息到微信服务器 @@ -226,16 +194,43 @@ class WxPaymentLogic extends BaseObject $this->forwardNotify($notifyData, false); Yii::info($e->getMessage(), 'notify'); return false; + } catch (BadRequestHttpException $e) { + Yii::info($e->getMessage(), 'notify'); + return false; } } - + /** + * @param $notifyData + * @param $status + * @return bool + * @throws \yii\base\InvalidConfigException + * @throws \yii\httpclient\Exception + * 转发异步回调信息 + */ private function forwardNotify($notifyData, $status) { - return true; - return false; + $notify = [ + 'notify' => [ + 'status' => $status, + 'notify' => $notifyData + ] + ]; + $client = new Client(); + $response = $client->createRequest() + ->setMethod('POST') + ->setUrl($this->notifyUrl) + ->addHeaders(['content-type' => 'application/json']) + ->setContent(Json::encode($notify)) + ->send(); + if ($response->isOk) { + return true; + } else { + return false; + } } + /** * @param $data * @return bool @@ -269,41 +264,5 @@ class WxPaymentLogic extends BaseObject return strtoupper(md5($queryString)); } - /** - * @param $arr - * @param null $dom - * @param null $node - * @param string $root - * @param bool $cdata - * @return string - * 数组转xml字符串 - */ - function arrayToXml($arr, $dom = null, $node = null, $root = 'xml', $cdata = false) - { - if (!$dom) { - $dom = new \DOMDocument('1.0','utf-8'); - } - if (!$node) { - $node = $dom->createElement($root); - $dom->appendChild($node); - } - foreach ($arr as $key=>$value) { - $child_node = $dom->createElement(is_string($key) ? $key : 'node'); - $node->appendChild($child_node); - if (!is_array($value)) { - if (!$cdata) { - $data = $dom->createTextNode($value); - } else { - $data = $dom->createCDATASection($value); - } - $child_node->appendChild($data); - } else { - $this->arrayToXml($value,$dom,$child_node,$root,$cdata); - } - } - return $dom->saveXML(); - } - - } \ No newline at end of file diff --git a/backend/modules/shop/models/ars/PaymentLog.php b/backend/modules/shop/models/ars/PaymentLog.php index 1841e14..9a716d7 100755 --- a/backend/modules/shop/models/ars/PaymentLog.php +++ b/backend/modules/shop/models/ars/PaymentLog.php @@ -23,6 +23,9 @@ use yii\behaviors\TimestampBehavior; */ class PaymentLog extends \yii\db\ActiveRecord { + const PAYMENT_STATUS_WAITING = 0; + const PAYMENT_STATUS_SUCCESS = 1; + /** * {@inheritdoc} */