Browse Source

feat: 异步回调与转发回调功能

wechat_public_accounts
ww519441258 5 years ago
parent
commit
0901cd9814
  1. 1
      api/config/main.php
  2. 16
      api/controllers/WxPaymentController.php
  3. 145
      api/logic/WxPaymentLogic.php
  4. 3
      backend/modules/shop/models/ars/PaymentLog.php

1
api/config/main.php

@ -96,6 +96,7 @@ return [
'extraPatterns' => [
'GET web' => 'web',
'POST notify' => 'notify',
'POST test' => 'test',
]
],
],

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

145
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();
}
}

3
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}
*/

Loading…
Cancel
Save