| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <?php
- namespace app\api\controller;
- use app\admin\command\Api;
- use app\api\service\CallbackService;
- use app\api\service\WxService;
- use think\Response;
- use WeChatPay\Crypto\AesGcm;
- use WeChatPay\Crypto\Rsa;
- use WeChatPay\Formatter;
- /**
- * 支付回调
- */
- class Callback extends Api
- {
- protected $noNeedLogin = ["*"];
- private $service;
- public function __construct($name = null)
- {
- $this->service = new CallbackService();
- parent::__construct($name);
- }
- public function index()
- {
- return 1;
- }
- //获取微信回调http头信息
- private function getHeaders()
- {
- $headers = [];
- foreach ($_SERVER as $key => $value) {
- if ('HTTP_' == substr($key, 0, 5)) {
- $headers[str_replace('_', '-', substr($key, 5))] = $value;
- }
- if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
- $header['AUTHORIZATION'] = $_SERVER['PHP_AUTH_DIGEST'];
- } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
- $header['AUTHORIZATION'] = base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW']);
- }
- if (isset($_SERVER['CONTENT_LENGTH'])) {
- $header['CONTENT-LENGTH'] = $_SERVER['CONTENT_LENGTH'];
- }
- if (isset($_SERVER['CONTENT_TYPE'])) {
- $header['CONTENT-TYPE'] = $_SERVER['CONTENT_TYPE'];
- }
- }
- return $headers;
- }
- private function verify()
- {
- $header = $this->getHeaders();
- // 请根据实际情况获取
- $inWechatpaySignature = isset($header['WECHATPAY-SIGNATURE']) ? $header['WECHATPAY-SIGNATURE'] : "";
- // 请根据实际情况获取
- $inWechatpayTimestamp = isset($header['WECHATPAY-TIMESTAMP']) ? $header['WECHATPAY-TIMESTAMP'] : "";
- // 请根据实际情况获取
- // $inWechatpaySerial = $header['WECHATPAY-SERIAL'];
- // 请根据实际情况获取
- $inWechatpayNonce = isset($header['WECHATPAY-NONCE']) ? $header['WECHATPAY-NONCE'] : "";
- //读取微信传过来的信息,是一个json字符串
- $inBody = file_get_contents('php://input');
- $config = WxService::wxPayConfigByType("app");
- // 在商户平台上设置的APIv3密钥
- $apiv3Key = $config["mch_v3_api"];
- // 根据通知的平台证书序列号,查询本地平台证书文件
- $platformPublicKeyInstance = Rsa::from("file://" . $config["platform_certificate_file_path"], Rsa::KEY_TYPE_PUBLIC);
- // 检查通知时间偏移量,允许5分钟之内的偏移
- $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
- // 构造验签名串
- $verifiedStatus = Rsa::verify(
- Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
- $inWechatpaySignature,
- $platformPublicKeyInstance
- );
- return [
- $timeOffsetStatus,
- $verifiedStatus,
- $inBody,
- $apiv3Key
- ];
- }
- /**
- * @throws \Exception
- */
- public function wxpay()
- {
- list($timeOffsetStatus, $verifiedStatus, $inBody, $apiv3Key) = $this->verify();
- if ($timeOffsetStatus && $verifiedStatus) {
- // 转换通知的JSON文本消息为PHP Array数组
- $inBodyArray = (array)json_decode($inBody, true);
- // 使用PHP7的数据解构语法,从Array中解构并赋值变量
- ['resource' => [
- 'ciphertext' => $ciphertext,
- 'nonce' => $nonce,
- 'associated_data' => $aad
- ]] = $inBodyArray;
- // 加密文本消息解密
- $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
- // 把解密后的文本转换为PHP Array数组
- $inBodyResourceArray = (array)json_decode($inBodyResource, true);
- if (isset($inBodyResourceArray["out_trade_no"]) && isset($inBodyResourceArray["trade_state"])) {
- if ($inBodyResourceArray["trade_state"] == "SUCCESS") {
- if (false !== stristr($inBodyResourceArray["out_trade_no"], "RBU")) {
- $res = $this->service->rechargeBalanceSuccess($inBodyResourceArray["out_trade_no"]);
- } else if (false !== stristr($inBodyResourceArray["out_trade_no"], "RBM")) {
- $res = $this->service->rechargeMembershipSuccess($inBodyResourceArray["out_trade_no"]);
- } else {
- $res = $this->service->payOrderSuccess($inBodyResourceArray["out_trade_no"]);
- }
- $response_code = 200;
- $response_body = ["code" => "SUCCESS", "message" => "成功"];
- if (0 == $res->code()) {
- $response_code = 500;
- $response_body = ["code" => "FAIL", "message" => "失败"];
- }
- \think\Log::custom_log("微信支付回调 no:{$inBodyResourceArray["out_trade_no"]}!",
- [
- "inBodyResourceArray" => $inBodyResourceArray,
- "res" => [$res->code(), $res->msg(), $res->data()],
- "response_code" => $response_code,
- "response_body" => $response_body
- ]);
- return new Response(json_encode($response_body), $response_code);
- }
- }
- }
- \think\Log::custom_log("微信支付回调, 支付失败! inBody", $inBody);
- return new Response(json_encode(["code" => "FAIL", "message" => "失败"]), 500);
- }
- public function wxrefund()
- {
- list($timeOffsetStatus, $verifiedStatus, $inBody, $apiv3Key) = $this->verify();
- if ($timeOffsetStatus && $verifiedStatus) {
- // 转换通知的JSON文本消息为PHP Array数组
- $inBodyArray = (array)json_decode($inBody, true);
- // 使用PHP7的数据解构语法,从Array中解构并赋值变量
- ['resource' => [
- 'ciphertext' => $ciphertext,
- 'nonce' => $nonce,
- 'associated_data' => $aad
- ]] = $inBodyArray;
- // 加密文本消息解密
- $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
- // 把解密后的文本转换为PHP Array数组
- $inBodyResourceArray = (array)json_decode($inBodyResource, true);
- if (isset($inBodyResourceArray["out_trade_no"]) && isset($inBodyResourceArray["refund_status"])) {
- if ($inBodyResourceArray["refund_status"] == "SUCCESS") {
- $res = $this->service->refundSuccess($inBodyResourceArray["out_trade_no"]);
- $response_code = 200;
- $response_body = ["code" => "SUCCESS", "message" => "成功"];
- if (0 == $res->code()) {
- $response_code = 500;
- $response_body = ["code" => "FAIL", "message" => "失败"];
- }
- \think\Log::custom_log("微信退款回调 no:{$inBodyResourceArray["out_trade_no"]}!",
- [
- "inBodyResourceArray" => $inBodyResourceArray,
- "res" => [$res->code(), $res->msg(), $res->data()],
- "response_code" => $response_code,
- "response_body" => $response_body
- ]);
- return new Response(json_encode($response_body), $response_code);
- }
- }
- }
- \think\Log::custom_log("微信支付退款回调, 支付失败! inBody", $inBody);
- return new Response(json_encode(["code" => "FAIL", "message" => "失败"]), 500);
- }
- public function alipay()
- {
- echo "SUCCESS";
- }
- }
|