course/app/notify/controller/WechatPayNotifyController.php

345 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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){
}
}
}