signaturer.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: stanley-king
  5. * Date: 2017/6/20
  6. * Time: 上午10:25
  7. */
  8. namespace thrid_author;
  9. require_once(BASE_CORE_PATH . "/framework/function/http.php");
  10. use bonus\parameters;
  11. use Log;
  12. class signaturer
  13. {
  14. const appid = SIGN_APPID;
  15. const appsecret = SIGN_APPSECRET;
  16. const access_token_url = "https://api.weixin.qq.com/cgi-bin/token";
  17. const ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
  18. const createwxaqrcode_url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode";
  19. const getwxacode_url = "https://api.weixin.qq.com/wxa/getwxacode";
  20. const prefix = 'signaturer';
  21. const try_sleep = 5;
  22. private $mData;
  23. private static $stInstance = null;
  24. public static function instance()
  25. {
  26. if(self::$stInstance == null) {
  27. self::$stInstance = new signaturer();
  28. }
  29. return self::$stInstance;
  30. }
  31. private function __construct()
  32. {
  33. $this->mData = [];
  34. }
  35. public function signurl($sign_url)
  36. {
  37. $ticket = $this->rjsapi_ticket();
  38. if($ticket == false) {
  39. Log::record(__METHOD__ . " sign error",Log::ERR);
  40. return false;
  41. }
  42. $timestamp = time();
  43. $nonceStr = $this->noncestr();
  44. $string = "jsapi_ticket={$ticket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$sign_url}";
  45. $signature = sha1($string);
  46. Log::record(__METHOD__ . " signurl={$sign_url} noncestr={$nonceStr} timestamp={$timestamp} ticket={$ticket} signature={$signature}",Log::DEBUG);
  47. return ["appid" => signaturer::appid,"noncestr" => $nonceStr,"timestamp" => $timestamp,"signature" => $signature];
  48. }
  49. public function minicode($path,$width)
  50. {
  51. $token = $this->access_token();
  52. if($token == false) return false;
  53. $access_token = $token['token'];
  54. $param = ['path' => $path,'width' => $width];
  55. $url = self::getwxacode_url . "?access_token={$access_token}";
  56. $resp = http_post_data($url,json_encode($param));
  57. return $resp;
  58. }
  59. private function noncestr($length = 16)
  60. {
  61. $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  62. $str = "";
  63. for ($i = 0; $i < $length; $i++) {
  64. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  65. }
  66. return $str;
  67. }
  68. private function rjsapi_ticket()
  69. {
  70. if(empty($this->mData) || empty($this->mData['jsapi_ticket'])) {
  71. $fReadCache = true;
  72. }
  73. else
  74. {
  75. $expires = $this->mData['jsapi_ticket']['expires'];
  76. if(time() >= $expires) {
  77. $fReadCache = true;
  78. } else {
  79. $fReadCache = false;
  80. }
  81. }
  82. if($fReadCache)
  83. {
  84. $items = rcache('jsapi_ticket',self::prefix);
  85. if(empty($items)) {
  86. $this->mData['jsapi_ticket'] = $this->request();
  87. }
  88. else
  89. {
  90. $expires = intval($items['expires']);
  91. if($expires <= time()) {
  92. $this->mData['jsapi_ticket'] = $this->request();
  93. } else {
  94. $this->mData['jsapi_ticket'] = $items;
  95. }
  96. }
  97. }
  98. return $this->mData['jsapi_ticket']['ticket'];
  99. }
  100. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  101. public function request()
  102. {
  103. while (true)
  104. {
  105. $token = $this->access_token();
  106. if($token != false) {
  107. break;
  108. } else {
  109. sleep(signaturer::try_sleep);
  110. }
  111. }
  112. $accessToken = $token['token'];
  113. while (true)
  114. {
  115. $ticket = $this->jsapi_ticket($accessToken);
  116. if($ticket != false) {
  117. break;
  118. }
  119. else {
  120. sleep(signaturer::try_sleep);
  121. }
  122. }
  123. $ticket['expires'] = intval($ticket['expires'] / 2 + time());
  124. wcache('jsapi_ticket',$ticket,self::prefix);
  125. Log::record(__METHOD__ . " ticket={$ticket['ticket']}",Log::DEBUG);
  126. return $ticket;
  127. }
  128. private function jsapi_ticket($accessToken)
  129. {
  130. $params = ['type' => 'jsapi','access_token' => $accessToken];
  131. $res = http_request(self::ticket_url,$params);
  132. if($res == false) return false;
  133. $res = json_decode($res,true);
  134. if($res['errcode'] != 0) {
  135. Log::record("jsapi_ticket error : code={$res['errcode']} msg={$res['errmsg']}",Log::ERR);
  136. return false;
  137. }
  138. $ticket['expires'] = intval($res['expires_in']);
  139. $ticket['ticket'] = $res['ticket'];
  140. return $ticket;
  141. }
  142. private function access_token()
  143. {
  144. $params = ['grant_type' => 'client_credential','appid' => signaturer::appid,'secret' => signaturer::appsecret];
  145. $res = http_request(self::access_token_url,$params);
  146. if($res == false) return false;
  147. $res = json_decode($res,true);
  148. if(array_key_exists('errcode',$res)) {
  149. $code = $res['errcode'];
  150. $msg = $res['errmsg'];
  151. Log::record("signurl access_token error code={$code} msg={$msg}",Log::DEBUG);
  152. return false;
  153. }
  154. else {
  155. $token['expires'] = intval($res['expires_in']);
  156. $token['token'] = $res['access_token'];
  157. return $token;
  158. }
  159. }
  160. }