391 lines
14 KiB
PHP
391 lines
14 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @author Any
|
||
* @description KISS
|
||
* @date 2021年10月3日
|
||
* @version 1.0.0
|
||
*
|
||
* _____LOG_____
|
||
*
|
||
*/
|
||
namespace app\controllers\notify;
|
||
|
||
use app\models\Order;
|
||
use app\models\wechat\WechatApp;
|
||
use Wechat\Wechat;
|
||
use Wechat\DataConversion;
|
||
use app\controllers\Controller;
|
||
use app\models\PaymentOrder;
|
||
use app\models\PaymentOrderUnion;
|
||
use app\models\common\PluginService;
|
||
use app\components\SysConst;
|
||
use app\models\common\notify\payment\PaymentNotify;
|
||
use app\models\log\PayNotifyLog;
|
||
use app\models\Model;
|
||
|
||
class PaymentController extends Controller
|
||
{
|
||
public $enableCsrfValidation = false;
|
||
public $wechat;
|
||
|
||
//服务项目订单微信支付异步通知
|
||
public function actionWxpay()
|
||
{
|
||
$xml = file_get_contents("php://input");
|
||
$res = DataConversion::xmlToArray($xml);
|
||
if ($res && !empty($res['out_trade_no'])) { //微信支付回调
|
||
$this->handleWxpayNotify($res);
|
||
}
|
||
}
|
||
|
||
private function handleWxpayNotify($res)
|
||
{
|
||
//记录日志
|
||
if(isset($res['out_trade_no'])){
|
||
PayNotifyLog::logger($res['out_trade_no'], $res);
|
||
}
|
||
if ($res['result_code'] != 'SUCCESS' && $res['return_code'] != 'SUCCESS') {
|
||
return;
|
||
}
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['order_no' => $res['out_trade_no']]);
|
||
if($paymentOrderUnion == null){
|
||
return;
|
||
}
|
||
$plugin = new PluginService();
|
||
$wechat = $plugin->getWxmpService($paymentOrderUnion->cx_mch_id);
|
||
|
||
$sign = $wechat->pay->makeSign($res);
|
||
if ($sign != $res['sign']) {
|
||
echo "Sign 错误";
|
||
$this->handleError($paymentOrderUnion->order_no, 'Sign错误');
|
||
return;
|
||
}
|
||
if ($paymentOrderUnion->is_pay == 1) {
|
||
echo "订单已支付";
|
||
$this->handleError($paymentOrderUnion->order_no, '订单已支付');
|
||
return;
|
||
}
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeWxpay;
|
||
$paymentOrderUnion->updated_at = time();
|
||
$paymentOrderUnion->transaction_id = $res['transaction_id'];
|
||
if ($paymentOrderUnion->save()) {
|
||
//支付完成之后,相关的操作
|
||
$form = new PaymentNotify();
|
||
$resp = $form->notify($paymentOrderUnion);
|
||
if($resp['code'] != 0){
|
||
//记录错误
|
||
$this->handleError($paymentOrderUnion->order_no, $resp['msg']);
|
||
}
|
||
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
|
||
return;
|
||
} else {
|
||
echo "支付失败";
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
//银联支付回调异步通知
|
||
public function actionUnionpay()
|
||
{
|
||
$req = file_get_contents("php://input");
|
||
if(!empty($req)){
|
||
$this->handleUnionpayNotify($req);
|
||
}
|
||
}
|
||
|
||
private function handleUnionpayNotify($req)
|
||
{
|
||
$reqArr = json_decode($req,true);
|
||
//记录日志
|
||
if(isset($reqArr["response"]["msgBody"]["remark"])){
|
||
PayNotifyLog::logger($reqArr["response"]["msgBody"]["remark"], $req);
|
||
}
|
||
$plugin = new PluginService();
|
||
$updcService = $plugin->getUpdcService();
|
||
//签名原文不能使用json字符串和数组之间的转换获取,该处理过程将键值冒号前的空着除去,导致与原文不一致
|
||
$sindex=strpos($req,'"sign":');
|
||
$reqJson=substr($req,0,$sindex-1)."}";
|
||
$reqSign = $reqArr['sign'];
|
||
$r = $updcService->signature->verify($reqJson,$reqSign);
|
||
if(!$r){
|
||
echo "响应报文验签失败\n";
|
||
return;
|
||
}
|
||
//验签通过
|
||
$res = $reqArr;
|
||
if(!isset($res['code']) || $res['code'] != '00000'){
|
||
$msg = isset($res['msg']) ? "[{$res['code']}]{$res['msg']}" : "[{$res['code']}]error";
|
||
throw new \Exception($msg);
|
||
}
|
||
if(!isset($res['response'])){
|
||
echo '缺少response参数' .PHP_EOL;
|
||
return;
|
||
}
|
||
$response = $res['response'];
|
||
if(!isset($response['subCode']) || $response['subCode'] != '00000'){
|
||
$msg = isset($response['subMsg']) ? "[{$response['subCode']}]{$response['subMsg']}" : "[{$response['subCode']}]error";
|
||
echo $msg .PHP_EOL;
|
||
return;
|
||
}
|
||
if(!isset($response['msgBody'])){
|
||
echo '缺少msgBody参数' .PHP_EOL;
|
||
return;
|
||
}
|
||
$msgBody = $response['msgBody'];
|
||
if(!isset($msgBody['retCode']) || $msgBody['retCode'] != '00000'){
|
||
$msg = isset($msgBody['retMsg']) ? "[{$msgBody['retCode']}]{$msgBody['retMsg']}" : "[{$msgBody['retCode']}]error";
|
||
echo $msg .PHP_EOL;
|
||
return;
|
||
}
|
||
$out_trade_no = $msgBody['oriMerOrdrNo'];
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['out_trade_no' => $out_trade_no]);
|
||
if($paymentOrderUnion == null){
|
||
echo '支付订单不存在' .PHP_EOL;
|
||
return;
|
||
}
|
||
if ($paymentOrderUnion->is_pay == 1) {
|
||
echo "订单已支付" .PHP_EOL;
|
||
$this->handleError($paymentOrderUnion->order_no, '订单已支付');
|
||
return;
|
||
}
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeUnionpay;
|
||
$paymentOrderUnion->updated_at = time();
|
||
$chnlMerOrdrNo = isset($msgBody['chnlMerOrdrNo']) ? $msgBody['chnlMerOrdrNo'] : 0;
|
||
$paymentOrderUnion->transaction_id = $chnlMerOrdrNo;
|
||
if ($paymentOrderUnion->save()) {
|
||
//支付完成之后,相关的操作
|
||
$form = new PaymentNotify();
|
||
$resp = $form->notify($paymentOrderUnion);
|
||
if($resp['code'] != 0){
|
||
//记录错误
|
||
$this->handleError($paymentOrderUnion->order_no, $resp['msg']);
|
||
}
|
||
echo '支付成功' .PHP_EOL;
|
||
return;
|
||
} else {
|
||
echo "支付失败" .PHP_EOL;
|
||
return;
|
||
}
|
||
}
|
||
|
||
private function handleError($order_no, $err_msg)
|
||
{
|
||
$message = "ORDER_NO:{$order_no} ERR_MSG:{$err_msg}";
|
||
\Yii::error($message,'NotifyPayment');
|
||
}
|
||
|
||
//支付回调测试
|
||
public function actionTest()
|
||
{
|
||
$open = false;
|
||
if(!$open){
|
||
$data = $this->invaildRequest();
|
||
return $this->responseHandler($data);
|
||
}
|
||
$params = \Yii::$app->request->post();
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['order_no' => $params['out_trade_no']]);
|
||
if($paymentOrderUnion == null){
|
||
$data = $this->requestNotFound();
|
||
return $this->responseHandler($data);
|
||
}
|
||
$paymentOrderUnion->is_pay = 1;
|
||
$paymentOrderUnion->pay_type = SysConst::$cxPayTypeWxpay;
|
||
$paymentOrderUnion->updated_at = time();
|
||
if ($paymentOrderUnion->save()) {
|
||
//支付完成之后,相关的操作
|
||
$form = new PaymentNotify();
|
||
$resp = $form->notify($paymentOrderUnion);
|
||
if($resp['code'] != 0){
|
||
//记录错误
|
||
$this->handleError($paymentOrderUnion->order_no, $resp['msg']);
|
||
}
|
||
return $this->responseHandler($resp);
|
||
} else {
|
||
$data = (new Model())->getModelError($paymentOrderUnion);
|
||
return $this->responseHandler($data);
|
||
}
|
||
}
|
||
|
||
//微信退款回调-押金
|
||
public function actionWxpayDepositRefunds()
|
||
{
|
||
$xml = file_get_contents("php://input");
|
||
$res = DataConversion::xmlToArray($xml);
|
||
|
||
// $associatedData = $res['resource']['associated_data'];
|
||
// $nonceStr = $res['resource']['nonce'];
|
||
// $ciphertext = $res['resource']['ciphertext'];
|
||
//
|
||
// $plugin = new \app\models\common\PluginService();
|
||
// $wxmpService = $plugin->getWxmpService(0);
|
||
//
|
||
// $ctext = substr($ciphertext, 0, 16);
|
||
// $authTag = substr($ciphertext, 16);
|
||
// $res_json = openssl_decrypt($ctext, 'aes-256-gcm', $wxmpService->apiKey_three, 1, $nonceStr,$authTag, $associatedData);
|
||
// $res = json_decode($res_json,true);
|
||
|
||
if ($res && !empty($res['out_trade_no'])) { //微信支付回调
|
||
$this->handleWxpayDepositRefundsNotify($res);
|
||
}
|
||
}
|
||
|
||
//微信退款回调-押金
|
||
private function handleWxpayDepositRefundsNotify($res)
|
||
{
|
||
try {
|
||
//记录日志
|
||
if(isset($res['out_trade_no'])){
|
||
PayNotifyLog::logger($res['out_trade_no'], $res);
|
||
}
|
||
|
||
$plugin = new PluginService();
|
||
$wechat = $plugin->getWxmpService(0);
|
||
$sign = $wechat->pay->makeSign($res);
|
||
if ($sign != $res['sign']) {
|
||
echo "Sign 错误";
|
||
$this->handleError($res['out_trade_no'], 'Sign错误');
|
||
return;
|
||
}
|
||
|
||
//SUCCESS:退款成功,CLOSED:退款关闭,ABNORMAL:退款异常
|
||
if($res['refund_status'] == 'SUCCESS'){
|
||
$status = 1; //退款成功
|
||
}elseif ($res['refund_status'] == 'CLOSED'){
|
||
$status = 2; //退款关闭状态
|
||
}elseif ($res['refund_status'] == 'ABNORMAL'){
|
||
$status = 3; //退款异常
|
||
}else{
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['order_no' => $res['out_trade_no']]);
|
||
if($paymentOrderUnion == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$paymentOrder = PaymentOrder::findOne(['payment_order_union_id' => $paymentOrderUnion->id]);
|
||
if($paymentOrder == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$order = Order::findOne(['order_no' => $paymentOrder->order_no]);
|
||
if($order == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
$order->is_confirm = $status;
|
||
$order->updated_at = time();
|
||
if(!$order){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
|
||
return;
|
||
}catch (\Exception $e){
|
||
echo "ERROR";
|
||
return;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
//微信支付退款回调-订单
|
||
public function actionWxpayOrderRefunds()
|
||
{
|
||
$xml = file_get_contents("php://input");
|
||
$res = DataConversion::xmlToArray($xml);
|
||
|
||
// $associatedData = $res['resource']['associated_data'];
|
||
// $nonceStr = $res['resource']['nonce'];
|
||
// $ciphertext = $res['resource']['ciphertext'];
|
||
//
|
||
// $plugin = new \app\models\common\PluginService();
|
||
// $wxmpService = $plugin->getWxmpService(0);
|
||
//
|
||
// $ctext = substr($ciphertext, 0, 16);
|
||
// $authTag = substr($ciphertext, 16);
|
||
// $res_json = openssl_decrypt($ctext, 'aes-256-gcm', $wxmpService->apiKey_three, 1, $nonceStr,$authTag, $associatedData);
|
||
// $res = json_decode($res_json,true);
|
||
|
||
if ($res && !empty($res['out_trade_no'])) { //微信支付回调
|
||
$this->handleWxpayOrderRefundsNotify($res);
|
||
}
|
||
}
|
||
|
||
//微信支付退款回调-订单
|
||
private function handleWxpayOrderRefundsNotify($res)
|
||
{
|
||
try {
|
||
//记录日志
|
||
if(isset($res['out_trade_no'])){
|
||
PayNotifyLog::logger($res['out_trade_no'], $res);
|
||
}
|
||
|
||
if ($res['result_code'] != 'SUCCESS' && $res['return_code'] != 'SUCCESS') {
|
||
return;
|
||
}
|
||
|
||
$plugin = new PluginService();
|
||
$wechat = $plugin->getWxmpService(0);
|
||
$sign = $wechat->pay->makeSign($res);
|
||
if ($sign != $res['sign']) {
|
||
echo "Sign 错误";
|
||
$this->handleError($res['out_trade_no'], 'Sign错误');
|
||
return;
|
||
}
|
||
|
||
//SUCCESS:退款成功,CLOSED:退款关闭,ABNORMAL:退款异常
|
||
if($res['refund_status'] == 'SUCCESS'){
|
||
$status = 0; //已完成状态
|
||
}elseif ($res['refund_status'] == 'CLOSED'){
|
||
$status = 2; //退款关闭状态
|
||
}elseif ($res['refund_status'] == 'ABNORMAL'){
|
||
$status = 3; //退款异常
|
||
}else{
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$paymentOrderUnion = PaymentOrderUnion::findOne(['order_no' => $res['out_trade_no']]);
|
||
if($paymentOrderUnion == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$paymentOrder = PaymentOrder::findOne(['payment_order_union_id' => $paymentOrderUnion->id]);
|
||
if($paymentOrder == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
$order = Order::findOne(['order_no' => $paymentOrder->order_no]);
|
||
if($order == null){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
$order->status = $status;
|
||
$order->updated_at = time();
|
||
if(!$order){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
|
||
return;
|
||
}catch (\Exception $e){
|
||
echo "退款失败";
|
||
return;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
} |