WxpubOAuth.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. namespace Pingpp;
  3. /**
  4. * 用于微信公众号OAuth2.0鉴权,用户授权后获取授权用户唯一标识openid
  5. * WxpubOAuth中的方法都是可选的,开发者也可根据实际情况自行开发相关功能,
  6. * 详细内容可参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
  7. */
  8. class WxpubOAuth
  9. {
  10. /**
  11. * 获取微信公众号授权用户唯一标识
  12. * @param $app_id 微信公众号应用唯一标识
  13. * @param $app_secret 微信公众号应用密钥(注意保密)
  14. * @param $code 授权code, 通过调用WxpubOAuth::createOauthUrlForCode来获取
  15. * @return openid 微信公众号授权用户唯一标识, 可用于微信网页内支付
  16. */
  17. public static function getOpenid($app_id, $app_secret, $code)
  18. {
  19. $url = WxpubOAuth::_createOauthUrlForOpenid($app_id, $app_secret, $code);
  20. $res = self::_getRequest($url);
  21. $data = json_decode($res, true);
  22. return $data['openid'];
  23. }
  24. /**
  25. * 用于获取授权code的URL地址,此地址用于用户身份鉴权,获取用户身份信息,同时重定向到$redirect_url
  26. * @param $app_id 微信公众号应用唯一标识
  27. * @param $redirect_url 授权后重定向的回调链接地址,重定向后此地址将带有授权code参数,
  28. * 该地址的域名需在微信公众号平台上进行设置,
  29. * 步骤为:登陆微信公众号平台 => 开发者中心 => 网页授权获取用户基本信息 => 修改
  30. * @param bool $more_info FALSE 不弹出授权页面,直接跳转,这个只能拿到用户openid
  31. * TRUE 弹出授权页面,这个可以通过 openid 拿到昵称、性别、所在地,
  32. * @return string 用于获取授权code的URL地址
  33. */
  34. public static function createOauthUrlForCode($app_id, $redirect_url, $more_info = false)
  35. {
  36. $urlObj = array();
  37. $urlObj['appid'] = $app_id;
  38. $urlObj['redirect_uri'] = $redirect_url;
  39. $urlObj['response_type'] = 'code';
  40. $urlObj['scope'] = $more_info ? 'snsapi_userinfo' : 'snsapi_base';
  41. $urlObj['state'] = 'STATE' . '#wechat_redirect';
  42. $queryStr = http_build_query($urlObj);
  43. return 'https://open.weixin.qq.com/connect/oauth2/authorize?' . $queryStr;
  44. }
  45. /**
  46. * 获取openid的URL地址
  47. * @param $app_id 微信公众号应用唯一标识
  48. * @param $app_secret 微信公众号应用密钥(注意保密)
  49. * @param $code 授权code, 通过调用WxpubOAuth::createOauthUrlForCode来获取
  50. * @return string 获取openid的URL地址
  51. */
  52. private static function _createOauthUrlForOpenid($app_id, $app_secret, $code)
  53. {
  54. $urlObj = array();
  55. $urlObj['appid'] = $app_id;
  56. $urlObj['secret'] = $app_secret;
  57. $urlObj['code'] = $code;
  58. $urlObj['grant_type'] = 'authorization_code';
  59. $queryStr = http_build_query($urlObj);
  60. return 'https://api.weixin.qq.com/sns/oauth2/access_token?' . $queryStr;
  61. }
  62. /**
  63. * GET 请求
  64. */
  65. private static function _getRequest($url) {
  66. $ch = curl_init();
  67. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  68. curl_setopt($ch, CURLOPT_URL, $url);
  69. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
  70. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
  71. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  72. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  73. $res = curl_exec($ch);
  74. curl_close($ch);
  75. return $res;
  76. }
  77. /**
  78. * 获取微信公众号 jsapi_ticket
  79. * @param $app_id 微信公众号应用唯一标识
  80. * @param $app_secret 微信公众号应用密钥(注意保密)
  81. * @return array 包含 jsapi_ticket 的数组或者错误信息
  82. */
  83. public static function getJsapiTicket($app_id, $app_secret) {
  84. $urlObj = array();
  85. $urlObj['appid'] = $app_id;
  86. $urlObj['secret'] = $app_secret;
  87. $urlObj['grant_type'] = 'client_credential';
  88. $queryStr = http_build_query($urlObj);
  89. $accessTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?' . $queryStr;
  90. $resp = self::_getRequest($accessTokenUrl);
  91. $resp = json_decode($resp, true);
  92. if (!is_array($resp) || isset($resp['errcode'])) {
  93. return $resp;
  94. }
  95. $urlObj = array();
  96. $urlObj['access_token'] = $resp['access_token'];
  97. $urlObj['type'] = 'jsapi';
  98. $queryStr = http_build_query($urlObj);
  99. $jsapiTicketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?' . $queryStr;
  100. $resp = self::_getRequest($jsapiTicketUrl);
  101. return json_decode($resp, true);
  102. }
  103. /**
  104. * 生成微信公众号 js sdk signature
  105. * @param $charge charge
  106. * @param $jsapi_ticket
  107. * @param $url 是当前网页的 URL,不包含 # 及其后面部分
  108. * @return string signature 字符串
  109. */
  110. public static function getSignature($charge, $jsapi_ticket, $url = NULL) {
  111. if (!isset($charge['credential']) || !isset($charge['credential']['wx_pub'])) {
  112. return null;
  113. }
  114. $credential = $charge['credential']['wx_pub'];
  115. $arrayToSign = array();
  116. $arrayToSign[] = 'jsapi_ticket=' . $jsapi_ticket;
  117. $arrayToSign[] = 'noncestr=' . $credential['nonceStr'];
  118. $arrayToSign[] = 'timestamp=' . $credential['timeStamp'];
  119. if (!$url) {
  120. $requestUri = explode('#', $_SERVER['REQUEST_URI']);
  121. $scheme = isset($_SERVER['REQUEST_SCHEME'])
  122. ? $_SERVER['REQUEST_SCHEME']
  123. : (isset($_SERVER['HTTPS'])
  124. && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http');
  125. $url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $requestUri[0];
  126. }
  127. $arrayToSign[] = 'url=' . $url;
  128. return sha1(implode('&', $arrayToSign));
  129. }
  130. }