course/app/notify/controller/WechatPayNotifyController.php

345 lines
15 KiB
PHP
Raw Normal View History

<?php
namespace app\notify\controller;
use app\common\model\Requirement;
use app\common\model\RequirementOrder;
use app\common\service\Channel\wechat\WechatConstants;
use support\Request;
use think\Exception;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
class WechatPayNotifyController
{
/**
* @desc 需求订单支付回调
* @param Request $request
* @return void
*/
public function requirement_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
raw_log('wechat_pay/requirement_notify', ['post' => $post_data, 'header' => $header]);
$inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
$inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
$inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
$inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
$mch_id = getenv('MERCHANT_ID');
// 根据通知的平台证书序列号,查询本地平台证书文件,
$platformCertificateFilePath = 'file://' . base_path() . '/certificate/wechatpay_660FAD2D6E804E37BE9D77EF5882718CC1E3399F.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, json_encode($post_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
$inWechatpaySignature,
$platformPublicKeyInstance
);
// 验签
if ($timeOffsetStatus && $verifiedStatus) {
// 使用PHP7的数据解构语法从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $post_data;
// 加密文本消息解密
$inBodyResource = AesGcm::decrypt($ciphertext, getenv('API_V3'), $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
$pay_result = json_decode($inBodyResource, true);
if ($pay_result['trade_state'] == 'SUCCESS') {
$order = RequirementOrder::where(['out_trade_no' => $pay_result['out_trade_no']])->findOrEmpty();
if ($order->isEmpty()) {
throw new Exception('未找到订单' . $pay_result['out_trade_no']);
}
if ($order->amount * 100 != $pay_result['amount']['total']) {
throw new Exception('订单金额不一致-' . $pay_result['out_trade_no']);
}
if ($order->pay_status == 0) {
$res = $order->save([
'pay_status' => 1,
'transaction_id' => $pay_result['transaction_id'],
'pay_time' => date('Y-m-d H:i:s', strtotime($pay_result['success_time'])),
]);
$requirement = Requirement::where(['id' => $order->requirement_id])->findOrEmpty();
$requirement->save([
'requirement_pay_order_status' => 1
]);
if ($requirement->deposit_pay_status == 1) {
//保证金已支付,进入服务中状态
$requirement->save([
'status' => 3
]);
}
if ($res) {
return json('success');
}
}
return json('success');
}
} else {
throw new Exception('验签失败');
}
} catch (Exception $e) {
var_dump($e->getMessage());
raw_log('wechat_pay/requirement_notify_error', ['exception' => $e->getMessage()]);
}
}
/**
* @desc 需求退款
* @param Request $request
* @return \support\Response|void
*/
public function requirement_refund_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
$post_data = '{"id":"ce358553-a4ae-5ecd-bab0-c4a31292989d","create_time":"2024-07-04T17:40:35+08:00","resource_type":"encrypt-resource","event_type":"REFUND.SUCCESS","summary":"退款成功","resource":{"original_type":"refund","algorithm":"AEAD_AES_256_GCM","ciphertext":"uc/STAVhRAgsEn+Wcl7ZDq4JiXh5KxLyX3c6WKtnZPLKq/ch1JGFKMR2Fbdvk5W5p5qcd2NJLwaUEmPjopV3n5aAD/r7DGsn+wUhiUwk71YIRhSZyrIrOTNXFLZ/yIu5cr7qkBnEP1YCD/oeSmNy6cz2uq8kag90M6RtOgJO4KFsJ0tOqW/OWs3h4eBoWxyRzKVZHY/FyNSeOgKN8ZodkRlP0Tjm2oPqtaxJcvE3O8TG5jkKlCopk/q8pd/lYUP8k0W1R+LYc2njh6NMc+plmH/6qrI7Ep5AzuU89PhDoQY8WemqogyABqtnXQ+8yMIWkmQSHHB3I1WKegqGFNSXHoUyViONoy7FKdWmstpUfAtjPjXJl23g3WYkjeaKO4bPKZakKj2KUscPQUs8dOa0eggA0mxqLMHgZl9+UKqoC4e/7a+CdR3DMKlJjYFC/Zisfjxy++1gPC4Oh5BIP7QVT3atsgNkZynXAY+3qmF9/lyeWONzrPXdukanEZMwLi2UXIELHEQvPUv7aKgI","associated_data":"refund","nonce":"xaAOLXTSOskU"}}';
$header = '{"x-real-ip":"175.24.211.24","host":"sypt.lingruikj.com","x-forwarded-proto":"https","content-length":"840","user-agent":"Mozilla/4.0","content-type":"application/json","wechatpay-nonce":"gSSvoVuO1PPtuPtdFvvugy99YI1leUMF","wechatpay-timestamp":"1720086041","wechatpay-serial":"660FAD2D6E804E37BE9D77EF5882718CC1E3399F","wechatpay-signature":"Vatqwnzb0cYGMT1nOnpp086CUV8URBgWVeqPJW1tw/tt/w1htnnTs1lk0v+Z/i3cqpnkfr1XErzMQZ1yZXA7qH7nloRdjBYWLwJiwTrnrLDMLU//Oz1sUve4Mt910zIPGkMTbg2Zr+b6YXqPNVBYvFtjjRnBlqRpyVz07lsVDKA4Ygfslw+sZur4qC/yZy6d3fKwxIRy6S/GHBd+/kRnuagyjheuU+JZ32ScozXdt6AQF05S3VGzohiNvrIu48v9imlf3K6NdzGnSJPeiKQ9BSoOw0CkSl9idEYIIFfdbhbu9kc5l4V8bNQc45W8EUylXLT7cFa6B63+TZts5KOosw==","wechatpay-signature-type":"WECHATPAY2-SHA256-RSA2048","pragma":"no-cache","accept":"*/*"}';
$post_data = json_decode($post_data, true);
$header = json_decode($header, true);
raw_log('wechat_pay/requirement_refund_notify', ['post' => $post_data, 'header' => $header]);
$inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
$inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
$inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
$inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
$mch_id = getenv('MERCHANT_ID');
// 根据通知的平台证书序列号,查询本地平台证书文件,
$platformCertificateFilePath = 'file://' . base_path() . '/certificate/wechatpay_660FAD2D6E804E37BE9D77EF5882718CC1E3399F.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, json_encode($post_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
$inWechatpaySignature,
$platformPublicKeyInstance
);
// 验签
if ($timeOffsetStatus && $verifiedStatus) {
// 使用PHP7的数据解构语法从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $post_data;
// 加密文本消息解密
$inBodyResource = AesGcm::decrypt($ciphertext, getenv('API_V3'), $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
$pay_result = json_decode($inBodyResource, true);
if ($pay_result['refund_status'] == 'SUCCESS') {
$order = RequirementOrder::where(['out_trade_no' => $pay_result['out_trade_no']])->findOrEmpty();
if ($order->isEmpty()) {
throw new Exception('未找到订单' . $pay_result['out_trade_no']);
}
if ($order->pay_status != 1) {
throw new Exception('订单状态错误-' . $order->pay_status . $pay_result['out_trade_no']);
}
if ($order->is_refund != 0) {
throw new Exception('订单退款状态错误-' . $order->is_refund . $pay_result['out_trade_no']);
}
if ($order->refund_amount * 100 != $pay_result['amount']['total']) {
throw new Exception('退款金额不一致-' . $pay_result['out_trade_no']);
}
$order->save([
'refund_transaction_id' => $pay_result['refund_id'],
'is_refund' => 1,
'refund_time' => date('Y-m-d H:i:s', strtotime($pay_result['success_time'])),
]);
$requirement = Requirement::where(['id' => $order->requirement_id])->findOrEmpty();
if (!$requirement->isEmpty()) {
$requirement->save([
'requirement_pay_order_status' => 3
]);
if ($order->deposit_pay_status == 3) {
//保证金已退款,更新需求状态为已退款
$requirement->save([
'status' => 5
]);
}
}
return json('success');
}
} else {
throw new Exception('验签失败');
}
} catch (Exception $e) {
var_dump($e->getMessage());
raw_log('wechat_pay/requirement_refund_notify_error', ['exception' => $e->getMessage()]);
}
}
/**
* @desc 保证金订单回调
* @param Request $request
* @return void
*/
public function requirement_deposit_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
raw_log('wechat_pay/requirement_notify', ['post' => $post_data, 'header' => $header]);
$inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
$inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
$inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
$inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
$mch_id = getenv('MERCHANT_ID');
// 根据通知的平台证书序列号,查询本地平台证书文件,
$platformCertificateFilePath = 'file://' . base_path() . '/certificate/wechatpay_660FAD2D6E804E37BE9D77EF5882718CC1E3399F.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, json_encode($post_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
$inWechatpaySignature,
$platformPublicKeyInstance
);
// 验签
if ($timeOffsetStatus && $verifiedStatus) {
}
} catch (Exception $e) {
}
}
/**
* @desc 拍照服务支付回调
* @param Request $request
* @return void
*/
public function photo_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
raw_log('wechat_pay/photo_notify', ['post' => $post_data, 'header' => $header]);
} catch (Exception $e) {
}
}
/**
* @desc 支付保证金回调
* @param Request $request
* @return void
*/
public function photo_deposit_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
raw_log('wechat_pay/photo_deposit_notify', ['post' => $post_data, 'header' => $header]);
//@todo:支付成功更新拍照服务中保证金状态
} catch (Exception $e) {
}
}
/**
* @desc 拍照退款
* @param Request $request
* @return void
*/
public function photo_refund_notify(Request $request)
{
try {
$post_data = $request->post();
$header = $request->header();
raw_log('wechat_pay/refund_notify', ['post' => $post_data, 'header' => $header]);
$inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
$inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
$inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
$inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
$mch_id = getenv('MERCHANT_ID');
// 根据通知的平台证书序列号,查询本地平台证书文件,
$platformCertificateFilePath = 'file://' . base_path() . '/certificate/wechatpay_660FAD2D6E804E37BE9D77EF5882718CC1E3399F.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, json_encode($post_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
$inWechatpaySignature,
$platformPublicKeyInstance
);
// 验签
if ($timeOffsetStatus && $verifiedStatus) {
}
} catch (Exception $e) {
}
}
/**
* @desc 拍照订单保证金退款回调
* @param Request $request
* @return void
*/
public function photo_deposit_refund_notify(Request $request)
{
try {
}catch (Exception $e){
}
}
}