signaturer.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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 = PUB_APPID;
  15. const appsecret = PUB_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 send_submsg_url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";
  21. const prefix = 'signaturer';
  22. const try_sleep = 5;
  23. private $mData;
  24. private static $stInstance = null;
  25. public static function instance()
  26. {
  27. if(self::$stInstance == null) {
  28. self::$stInstance = new signaturer();
  29. }
  30. return self::$stInstance;
  31. }
  32. private function __construct()
  33. {
  34. $this->mData = [];
  35. }
  36. public function signurl($sign_url)
  37. {
  38. $ticket = $this->rjsapi_ticket();
  39. if($ticket == false) {
  40. Log::record(__METHOD__ . " sign error",Log::ERR);
  41. return false;
  42. }
  43. $timestamp = time();
  44. $nonceStr = $this->noncestr();
  45. $string = "jsapi_ticket={$ticket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$sign_url}";
  46. $signature = sha1($string);
  47. Log::record(__METHOD__ . " signurl={$sign_url} noncestr={$nonceStr} timestamp={$timestamp} ticket={$ticket} signature={$signature}",Log::DEBUG);
  48. return ["appid" => signaturer::appid,"noncestr" => $nonceStr,"timestamp" => $timestamp,"signature" => $signature];
  49. }
  50. public function minicode($path,$width)
  51. {
  52. $token = $this->access_token();
  53. if($token == false) return false;
  54. $access_token = $token['token'];
  55. $param = ['path' => $path,'width' => $width];
  56. $url = self::getwxacode_url . "?access_token={$access_token}";
  57. $resp = http_post_data($url,json_encode($param));
  58. return $resp;
  59. }
  60. public function send_submsg($openid,$tmpid,$page,$data)
  61. {
  62. $token = $this->access_token();
  63. if($token == false) return false;
  64. $access_token = $token['token'];
  65. $url = self::send_submsg_url . "?access_token={$access_token}";
  66. $param = ['touser' => $openid,'template_id' => $tmpid,'page' => $page,'data' => $data];
  67. $resp = http_post_data($url,json_encode($param));
  68. $resp = json_decode($resp,true);
  69. if($resp['errcode'] == 0 || $resp['errmsg'] == 'ok') {
  70. return true;
  71. }
  72. else {
  73. Log::record("send_submsg errmsg:{$resp['errmsg']}",Log::ERR);
  74. return false;
  75. }
  76. }
  77. private function noncestr($length = 16)
  78. {
  79. $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  80. $str = "";
  81. for ($i = 0; $i < $length; $i++) {
  82. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  83. }
  84. return $str;
  85. }
  86. private function rjsapi_ticket()
  87. {
  88. if(empty($this->mData) || empty($this->mData['jsapi_ticket'])) {
  89. $fReadCache = true;
  90. }
  91. else
  92. {
  93. $expires = $this->mData['jsapi_ticket']['expires'];
  94. if(time() >= $expires) {
  95. $fReadCache = true;
  96. } else {
  97. $fReadCache = false;
  98. }
  99. }
  100. if($fReadCache)
  101. {
  102. $items = rcache('jsapi_ticket',self::prefix);
  103. if(empty($items)) {
  104. $this->mData['jsapi_ticket'] = $this->request();
  105. }
  106. else
  107. {
  108. $expires = intval($items['expires']);
  109. if($expires <= time()) {
  110. $this->mData['jsapi_ticket'] = $this->request();
  111. } else {
  112. $this->mData['jsapi_ticket'] = $items;
  113. }
  114. }
  115. }
  116. return $this->mData['jsapi_ticket']['ticket'];
  117. }
  118. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  119. public function request()
  120. {
  121. while (true)
  122. {
  123. $token = $this->access_token();
  124. if($token != false) {
  125. break;
  126. } else {
  127. sleep(signaturer::try_sleep);
  128. }
  129. }
  130. $accessToken = $token['token'];
  131. while (true)
  132. {
  133. $ticket = $this->jsapi_ticket($accessToken);
  134. if($ticket != false) {
  135. break;
  136. }
  137. else {
  138. sleep(signaturer::try_sleep);
  139. }
  140. }
  141. $ticket['expires'] = intval($ticket['expires'] / 2 + time());
  142. wcache('jsapi_ticket',$ticket,self::prefix);
  143. Log::record(__METHOD__ . " ticket={$ticket['ticket']}",Log::DEBUG);
  144. return $ticket;
  145. }
  146. private function jsapi_ticket($accessToken)
  147. {
  148. $params = ['type' => 'jsapi','access_token' => $accessToken];
  149. $res = http_request(self::ticket_url,$params);
  150. if($res == false) return false;
  151. $res = json_decode($res,true);
  152. if($res['errcode'] != 0) {
  153. Log::record("jsapi_ticket error : code={$res['errcode']} msg={$res['errmsg']}",Log::ERR);
  154. return false;
  155. }
  156. $ticket['expires'] = intval($res['expires_in']);
  157. $ticket['ticket'] = $res['ticket'];
  158. return $ticket;
  159. }
  160. private function access_token()
  161. {
  162. $params = ['grant_type' => 'client_credential','appid' => signaturer::appid,'secret' => signaturer::appsecret];
  163. $res = http_request(self::access_token_url,$params);
  164. if($res == false) return false;
  165. $res = json_decode($res,true);
  166. if(array_key_exists('errcode',$res)) {
  167. $code = $res['errcode'];
  168. $msg = $res['errmsg'];
  169. Log::record("signurl access_token error code={$code} msg={$msg}",Log::DEBUG);
  170. return false;
  171. }
  172. else {
  173. $token['expires'] = intval($res['expires_in']);
  174. $token['token'] = $res['access_token'];
  175. return $token;
  176. }
  177. }
  178. }