Files
pay/includes/vendor/cccyun/wechatpay-sdk/src/JsApiTool.php
T
2025-11-28 10:08:12 +08:00

156 lines
4.9 KiB
PHP

<?php
namespace WeChatPay;
use Exception;
/**
* JSAPI支付工具类
* 实现了从微信公众平台获取code、通过code获取openid和access_token
*/
class JsApiTool
{
const GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
const GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
const GET_MINIAPP_TOKEN_URL = "https://api.weixin.qq.com/sns/jscode2session";
private $appid;
private $appsecret;
/**
* 网页授权接口微信服务器返回的数据,返回样例如下
* {
* "access_token":"ACCESS_TOKEN",
* "expires_in":7200,
* "refresh_token":"REFRESH_TOKEN",
* "openid":"OPENID",
* "scope":"SCOPE",
* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
* }
* openid是微信支付jsapi支付接口必须的参数
* @var array
*/
public $data = null;
public function __construct($appid, $appsecret)
{
$this->appid = $appid;
$this->appsecret = $appsecret;
}
/**
* 通过跳转获取用户的openid,跳转流程如下:
* 1、设置自己需要调回的url及其其他参数,跳转到微信服务器
* 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
*
* @return string 用户的openid
* @throws Exception
*/
public function GetOpenid(): string
{
if (!isset($_GET['code'])) {
$this->login();
}
$code = $_GET['code'];
return $this->GetOpenidFromMp($code);
}
/**
* 跳转到微信公众平台登录
*/
public function login()
{
if (function_exists('is_https')) {
$redirect_uri = (is_https() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
} else {
$redirect_uri = ($_SERVER['SERVER_PORT'] == 443 ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
$param = [
"appid" => $this->appid,
"redirect_uri" => $redirect_uri,
"response_type" => "code",
"scope" => "snsapi_base",
"state" => "STATE"
];
$url = self::GET_AUTH_CODE_URL . '?' . http_build_query($param) . "#wechat_redirect";
Header("Location: $url");
exit;
}
/**
* 从公众平台获取openid
* @param string $code 微信跳转回来带上的code
*
* @return string openid
* @throws Exception
*/
public function GetOpenidFromMp(string $code): string
{
$param = [
"appid" => $this->appid,
"secret" => $this->appsecret,
"code" => $code,
"grant_type" => "authorization_code"
];
$url = self::GET_ACCESS_TOKEN_URL . '?' . http_build_query($param);
$res = $this->curl($url);
$data = json_decode($res, true);
if (isset($data['access_token']) && isset($data['openid'])) {
$this->data = $data;
return $data['openid'];
} elseif (isset($data['errcode'])) {
throw new Exception('Openid获取失败 [' . $data['errcode'] . ']' . $data['errmsg']);
} else {
throw new Exception('Openid获取失败,原因未知');
}
}
/**
* 微信小程序获取Openid
* @param string $code 登录时获取的code
*
* @return string openid
* @throws Exception
*/
public function AppGetOpenid(string $code): string
{
$param = [
"appid" => $this->appid,
"secret" => $this->appsecret,
"js_code" => $code,
"grant_type" => "authorization_code"
];
$url = self::GET_MINIAPP_TOKEN_URL . '?' . http_build_query($param);
$res = $this->curl($url);
$data = json_decode($res, true);
if (isset($data['session_key']) && isset($data['openid'])) {
$this->data = $data;
return $data['openid'];
} elseif (isset($data['errcode'])) {
throw new Exception('获取openid失败 [' . $data['errcode'] . ']' . $data['errmsg']);
} else {
throw new Exception('获取openid失败,原因未知');
}
}
/**
* 发起GET请求
* @param string $url 请求url
* @return string
*/
private function curl(string $url): string
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_TIMEOUT, 6);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
}