Miniprogram.Class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <?php
  2. /**
  3. * 微信小程序相关接口类
  4. * Created by PhpStorm.
  5. * User: phperstar
  6. * Date: 2019/10/26
  7. * Time: 11:44 AM
  8. */
  9. namespace Util\WeiXin;
  10. use Mall\Framework\Core\ResultWrapper;
  11. use Mall\Framework\Core\ErrorCode;
  12. use Mall\Framework\Factory;
  13. class Miniprogram
  14. {
  15. /**
  16. * 小程序 appId
  17. * @var string $appid
  18. */
  19. private $appid;
  20. /**
  21. * 小程序 appSecret
  22. * @var string $appSecret
  23. */
  24. private $appSecret;
  25. /**
  26. * 促销卡
  27. * @var string $cardid
  28. */
  29. private $cardid;
  30. /**
  31. * openId 和 session_key关联关系缓存key
  32. */
  33. private $openidAndSessionKey = 'openidAndSessionKey';
  34. /**
  35. * path和打开小程序二维码地址关联关系缓存key
  36. */
  37. private $pathAndWxaqrcodeKey = 'pathAndWxaqrcodeKey';
  38. /**
  39. * path和小程序码地址关联关系缓存key
  40. */
  41. private $pathAndWxacodeunlimitKey = 'pathAndWxacodeunlimitKey';
  42. /**
  43. * 微信小程序接口主域名
  44. * @var string $apiUrl
  45. */
  46. private $apiUrl = 'https://api.weixin.qq.com/sns/';
  47. /**
  48. * 微信公众号接口主域名
  49. * @var string $apiUrl
  50. */
  51. private $baseUrl = 'https://api.weixin.qq.com/cgi-bin/';
  52. public function __construct($appid='', $appsecret='', $cardid='')
  53. {
  54. $this->appid = $appid;
  55. $this->appSecret = $appsecret;
  56. $this->cardid = $cardid;
  57. }
  58. /**
  59. * 获取小程序二维码
  60. * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
  61. */
  62. public function getwxacodeunlimit($access_token, $parms)
  63. {
  64. $key = md5($this->appid.$parms['path'].$parms['params']);
  65. $imgsrc = Factory::cache('default')->hget($this->pathAndWxacodeunlimitKey, $key);
  66. if(!empty($imgsrc)){
  67. return ResultWrapper::success($imgsrc);
  68. }
  69. $apiUrl = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$access_token;
  70. $postData = [
  71. 'scene' => $parms['params'],
  72. 'page' => $parms['path'],
  73. 'width' => 430,
  74. 'auto_color' => true,
  75. ];
  76. $reponse = request($apiUrl, json_encode($postData));
  77. if($reponse['httpcode'] != 200){
  78. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  79. }else{
  80. if(!is_object($reponse['content'])){
  81. $base64 = 'data:'.$reponse['content_type'].';base64,'.base64_encode($reponse['content']);
  82. $upload = Factory::baseImg();
  83. $upload->move($base64);
  84. $imgsrc = $upload->getSaveName();
  85. Factory::cache('default')->hset($this->pathAndWxacodeunlimitKey, $key, $imgsrc);
  86. return ResultWrapper::success($imgsrc);
  87. }
  88. $reponseData = json_decode($reponse['content'], true);
  89. if( isset($reponseData['errcode']) ){
  90. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  91. }
  92. }
  93. }
  94. /**
  95. * 获取小程序码
  96. * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
  97. */
  98. public function createwxaqrcode($access_token, $path)
  99. {
  100. $key = md5($this->appid.$path);
  101. $imgsrc = Factory::cache('default')->hget($this->pathAndWxaqrcodeKey, $key);
  102. if(!empty($imgsrc)){
  103. return ResultWrapper::success($imgsrc);
  104. }
  105. $apiUrl = $this->baseUrl.'wxaapp/createwxaqrcode?access_token='.$access_token;
  106. $postData = [
  107. 'access_token' => $access_token,
  108. 'path' => $path,
  109. 'width' => 430,
  110. ];
  111. $reponse = request($apiUrl, json_encode($postData));
  112. if($reponse['httpcode'] != 200){
  113. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  114. }else{
  115. if(!is_object($reponse['content'])){
  116. $base64 = 'data:image/jpeg;base64,'.base64_encode($reponse['content']);
  117. $upload = Factory::baseImg();
  118. $upload->move($base64);
  119. $imgsrc = $upload->getSaveName();
  120. Factory::cache('default')->hset($this->pathAndWxaqrcodeKey, $key, $imgsrc);
  121. return ResultWrapper::success(URL_UPLOAD.$imgsrc);
  122. }
  123. $reponseData = json_decode($reponse['content'], true);
  124. if( isset($reponseData['errcode']) ){
  125. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  126. }
  127. }
  128. }
  129. /**
  130. * 发送客服消息给用户
  131. * 官网地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html
  132. */
  133. public function messageCustomSend($access_token, $content, $openid)
  134. {
  135. $apiUrl = $this->baseUrl.'message/custom/send?access_token='.$access_token;
  136. $postData = [
  137. 'access_token' => $access_token,
  138. 'touser' => $openid,
  139. 'msgtype' => 'text',
  140. 'text' => ['content'=>$content],
  141. ];
  142. $reponse = request($apiUrl, json_encode($postData));
  143. if($reponse['httpcode'] != 200){
  144. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  145. }else{
  146. $reponseData = json_decode($reponse['content'], true);
  147. if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
  148. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  149. }
  150. return ResultWrapper::success($reponseData['errmsg']);
  151. }
  152. }
  153. /**
  154. * 发送订阅消息
  155. * 官网地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
  156. */
  157. public function subscribeMessageSend($access_token, $templateId, $openid, $page, $data)
  158. {
  159. $apiUrl = $this->baseUrl.'message/subscribe/send?access_token='.$access_token;
  160. $postData = [
  161. 'access_token' => $access_token,
  162. 'touser' => $openid,
  163. 'template_id' => $templateId,
  164. 'data' => $data
  165. ];
  166. if($page){
  167. $postData['page'] = $page;
  168. }
  169. $reponse = request($apiUrl, json_encode($postData));
  170. if($reponse['httpcode'] != 200){
  171. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  172. }else{
  173. $reponseData = json_decode($reponse['content'], true);
  174. if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
  175. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  176. }
  177. return ResultWrapper::success($reponseData['errmsg']);
  178. }
  179. }
  180. /**
  181. * 组合模板并添加至帐号下的个人模板库
  182. * 官网地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html
  183. */
  184. public function addtemplate($access_token, $tid, $kidList, $sceneDesc)
  185. {
  186. $apiUrl = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token='.$access_token;
  187. $postData = [
  188. 'tid' => $tid,
  189. 'kidList' => $kidList,
  190. 'sceneDesc' => $sceneDesc,
  191. ];
  192. $curl_option = [
  193. CURLOPT_HTTPHEADER => [
  194. 'content-type: application/json'
  195. ],
  196. ];
  197. $reponse = request($apiUrl, json_encode($postData), 10, false, $curl_option);
  198. if($reponse['httpcode'] != 200){
  199. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  200. }else{
  201. $reponseData = json_decode($reponse['content'], true);
  202. if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
  203. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  204. }
  205. return ResultWrapper::success($reponseData['priTmplId']);
  206. }
  207. }
  208. /**
  209. * 登录凭证校验
  210. * 官方文档对应地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
  211. * @param string $jsCode 通过 wx.login 接口获得临时登录凭证 code
  212. * @return ResultWrapper
  213. */
  214. public function jscode2session($jsCode)
  215. {
  216. $apiUrl = $this->apiUrl.'jscode2session?appid='.$this->appid.'&secret='.$this->appSecret.'&js_code='.$jsCode.'&grant_type=authorization_code';
  217. $reponse = request($apiUrl);
  218. if($reponse['httpcode'] != 200){
  219. return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
  220. }else{
  221. $reponseData = json_decode($reponse['content'], true);
  222. if( isset($reponseData['errcode']) ){
  223. return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
  224. }
  225. Factory::cache('default')->hset($this->openidAndSessionKey, $reponseData['openid'], $reponseData['session_key']);
  226. return ResultWrapper::success(['openid'=>$reponseData['openid'],'unionid'=> isset($reponseData['unionid']) ? $reponseData['unionid'] : '']);
  227. }
  228. }
  229. /**
  230. * 数据解密算法
  231. * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
  232. * @param string $iv 加密算法的初始向量
  233. * @param string $encryptedData 包括敏感数据在内的完整用户信息的加密数据
  234. * @param string $openid 用户标识
  235. * @return ResultWrapper
  236. */
  237. public function decryptData($iv, $encryptedData, $openid)
  238. {
  239. $session_key = Factory::cache('default')->hget($this->openidAndSessionKey, $openid);
  240. if(empty($session_key)){
  241. return ResultWrapper::fail('登陆会话session_key过期', ErrorCode::$notAllowAccess);
  242. }
  243. if (strlen($session_key) != 24) {
  244. return ResultWrapper::fail('无效的session_key', ErrorCode::$paramError);
  245. }
  246. $aesKey=base64_decode($session_key);
  247. if (strlen($iv) != 24) {
  248. return ResultWrapper::fail('无效的iv', ErrorCode::$paramError);
  249. }
  250. $aesIV=base64_decode($iv);
  251. $aesCipher=base64_decode($encryptedData);
  252. $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
  253. $dataObj=json_decode( $result, true);
  254. if( $dataObj == NULL )
  255. {
  256. return ResultWrapper::fail('解密后得到的buffer非法', ErrorCode::$paramError);
  257. }
  258. if( $dataObj['watermark']['appid'] != $this->appid )
  259. {
  260. return ResultWrapper::fail('解密后得到的buffer非法', ErrorCode::$paramError);
  261. }
  262. return ResultWrapper::success($dataObj);
  263. }
  264. }