164 lines
8.0 KiB
PHP
Raw Normal View History

2023-01-18 17:10:33 +08:00
<?php
namespace app\api\controller;
2023-03-22 16:51:51 +08:00
use app\api\BaseController;
use EasyWeChat\Factory;
2023-01-18 17:10:33 +08:00
use EasyWeChat\Pay\Application;
use EasyWeChat\Pay\Message;
2023-03-22 16:51:51 +08:00
use think\facade\Db;
2023-01-18 17:10:33 +08:00
use think\facade\Log;
2023-03-22 16:51:51 +08:00
use think\facade\Request;
2023-01-18 17:10:33 +08:00
2023-03-22 16:51:51 +08:00
class PayNotify extends BaseController
{
2023-01-18 17:10:33 +08:00
public function index(){
$config = [
'mch_id' => 1635725673,
'app_id' => 'wx6e14cb98394e36bc',
// 商户证书
'private_key' => config_path() .'certs/apiclient_key.pem',
'certificate' => config_path() .'certs/apiclient_cert.pem',
// v3 API 秘钥
// 'secret_key' => '43A03299A3C3FED3D8CE7B820Fxxxxx',
// v2 API 秘钥
'v2_secret_key' => '95d195Dcf6ec66156dfeeb4E7435faef',
// 平台证书:微信支付 APIv3 平台证书,需要使用工具下载
// 下载工具https://github.com/wechatpay-apiv3/CertificateDownloader
// 'platform_certs' => [
// // '/path/to/wechatpay/cert.pem',
// ],
/**
* 接口请求相关配置,超时时间等,具体可用参数请参考:
* https://github.com/symfony/symfony/blob/5.3/src/Symfony/Contracts/HttpClient/HttpClientInterface.php
*/
'http' => [
'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启
'timeout' => 5.0,
// 'base_uri' => 'https://api.mch.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri
],
];
$app= new Application($config);
$server = $app->getServer();
$server->handlePaid(function (Message $message, \Closure $next) {
Log::error($message);
// $message->out_trade_no 获取商户订单号
// $message->payer['openid'] 获取支付者 openid
// 🚨🚨🚨 注意:推送信息不一定靠谱哈,请务必验证
// 建议是拿订单号调用微信支付查询接口,以查询到的订单状态为准
return $next($message);
});
// 默认返回 ['code' => 'SUCCESS', 'message' => '成功']
return $server->serve();
}
2023-03-22 16:51:51 +08:00
// 接收微信支付状态的通知 商城后台采购商品回调
public function notify()
{
// 配置信息
$config = [
'app_id' => 'wx0b3defb62f0f910b',//注意这个APPID只能是公众号的id没有的话要去申请并且在微信支付平台里绑定
'mch_id' => '1635725673',//商户号
'key' => '95d195Dcf6ec66156dfeeb4E7435faef',//支付秘钥
'secret' => 'c02aa7ad9e4a5c423862e068b6cb4ad4',
'notify_url' => Request::instance()->domain().'/api/PayNotify/notify',//异步回调通知地址
];
// 这个就是 easywechat 封装的了, 一行代码搞定, 照着写就行了
$app = Factory::payment($config);
// 用 easywechat 封装的方法接收微信的信息, 根据 $message 的内容进行处理, 之后要告知微信服务器处理好了, 否则微信会一直请求这个 url, 发送信息
$response = $app->handlePaidNotify(function($message, $fail){
// 首先查看 order 表, 如果 order 表有记录, 表示已经支付过了
$order = Db::table('cms_store_product_order')->where('order_sn', $message['out_trade_no'])->find();
if ($order) {
return true; // 如果已经生成订单, 表示已经处理完了, 告诉微信不用再通知了
}
// 查看支付日志
$payLog = Db::table('cms_store_product_paylog')->where('out_trade_no', $message['out_trade_no'])->find();
if (!$payLog || $payLog['time_end']) { // 如果订单不存在 或者 订单已经支付过了
return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
}
// 更新支付时间为当前时间
$paid_at = time();
// return_code 表示通信状态,不代表支付状态
if ($message['return_code'] === 'SUCCESS') {
// 用户是否支付成功
if ($message['result_code'] === 'SUCCESS') {
$post_id = $payLog['product_id'];
// 创建订单记录
$order_arr = [
'order_sn' => $message['out_trade_no'],
'total_fee' => bcdiv($message['total_fee'],'100',2),
'pay_log_id' => $payLog['id'],
'status' => 1,
'admin_id' => $payLog['admin_id'],
'paid_at' => $paid_at,
'product_id' => $post_id,
'number' => $payLog['number'],
];
Db::table('cms_store_product_order')->strict(false)->field(true)->insert($order_arr);
// 减库存
Db::table('cms_store_product')->where('product_id', $post_id)->dec('stock',$payLog['number'])->update();
// 更新 PayLog, 这里的字段都是根据微信支付结果通知的字段设置的(https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8)
$pay_log = [
'appid' => $message['appid'],
'bank_type' => $message['bank_type'],
'total_fee' => $message['total_fee'],
'trade_type' => $message['trade_type'],
'is_subscribe' => $message['is_subscribe'],
'mch_id' => $message['mch_id'],
'nonce_str' => $message['nonce_str'],
'openid' => $message['openid'],
'sign' => $message['sign'],
'cash_fee' => $message['cash_fee'],
'fee_type' => $message['fee_type'],
'transaction_id' => $message['transaction_id'],
'time_end' => $paid_at,
'result_code' => $message['result_code'],
'return_code' => $message['return_code'],
];
Db::table('cms_store_product_paylog')->where('out_trade_no', $message['out_trade_no'])->update($pay_log);
}
} else {
// 如果支付失败, 也更新 PayLog, 跟上面一样, 就是多了 error 信息
$pay_log = [
'appid' => $message['appid'],
'bank_type' => $message['bank_type'],
'total_fee' => $message['total_fee'],
'trade_type' => $message['trade_type'],
'is_subscribe' => $message['is_subscribe'],
'mch_id' => $message['mch_id'],
'nonce_str' => $message['nonce_str'],
'openid' => $message['openid'],
'sign' => $message['sign'],
'cash_fee' => $message['cash_fee'],
'fee_type' => $message['fee_type'],
'transaction_id' => $message['transaction_id'],
'time_end' => $paid_at,
'result_code' => $message['result_code'],
'return_code' => $message['return_code'],
'err_code' => $message['err_code'],
'err_code_des' => $message['err_code_des'],
];
Db::table('cms_store_product_paylog')->where('out_trade_no', $message['out_trade_no'])->update($pay_log);
return $fail('通信失败,请稍后再通知我');
}
return true; // 返回处理完成
});
// 这里是必须这样返回的, 会发送给微信服务器处理结果
return $response;
}
2023-01-18 17:10:33 +08:00
}