Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信分享 #120

Open
mingyun opened this issue Mar 28, 2018 · 1 comment
Open

微信分享 #120

mingyun opened this issue Mar 28, 2018 · 1 comment

Comments

@mingyun
Copy link
Owner

mingyun commented Mar 28, 2018

文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
微信 JS 接口签名校验工具 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

<?php
namespace app\Services;
use RedisFacade;
class WxShare {
  private $appId;
  private $appSecret;

  public function __construct($appId, $appSecret) {
    $this->appId = $appId;
    $this->appSecret = $appSecret;
  }

  public function getSignPackage($url) {
    $jsapiTicket = $this->getJsApiTicket();

    // 注意 URL 一定要动态获取,不能 hardcode.Ajax获取的时候前端传递 location.href.split('#')[0]
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    // $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

    $timestamp = time();
    $nonceStr = $this->createNonceStr();

    // 这里参数的顺序要按照 key 值 ASCII 码升序排序
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

    $signature = sha1($string);

    $signPackage = array(
      "appId"     => $this->appId,
      "nonceStr"  => $nonceStr,
      "timestamp" => $timestamp,
      "url"       => $url,
      "signature" => $signature,
      "rawString" => $string
    );
    return $signPackage; 
  }

  private function createNonceStr($length = 16) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
      $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
  }

  private function getJsApiTicket() {
    // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
    $key_ticket = 'wechatshare_ticket';
    $jsondata = RedisFacade::get($key_ticket);
    if (empty($jsondata)) {
      $accessToken = $this->getAccessToken();
      // 如果是企业号用以下 URL 获取 ticket
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
      $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
      $res = json_decode($this->httpGet($url));
      $ticket = $res->ticket;
      if ($ticket) {
        $jsondata = serialize($ticket);
        RedisFacade::set($key_ticket,$jsondata);
        RedisFacade::expire($key_ticket, 1800);
      }
    } else {
      //$ticket = $data->jsapi_ticket;
      $ticket = unserialize($jsondata);
    }

    return $ticket;
  }

  private function getAccessToken() {
    // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
    $key_token = 'wechatshare_token';
    $jsondata = RedisFacade::get($key_token);
    if (empty($jsondata)) {
      // 如果是企业号用以下URL获取access_token
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
      $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
      $ret = $this->httpGet($url);
      $res = json_decode($ret);
      $access_token = $res->access_token;
      if ($access_token) {
        $jsondata = serialize($access_token);
        RedisFacade::set($key_token,$jsondata);
        RedisFacade::expire($key_token, 1800);
      }
    } else {
      $access_token = unserialize($jsondata);
    }
    return $access_token;
  }

  private function httpGet($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    $res = curl_exec($curl);
    $errors = curl_error($curl);
    \Log::info("Share",['ret'=>json_encode($res),'error'=>$errors]);
    curl_close($curl);
    return $res;
  }
}

先登录公众号 功能设置”里填写“JS接口安全域名” 不加 http 一个月只能改3次,还要在根目录上传一个TXT问题
invalid signature 签名错误 可能是 Ajax来获取签名的时候 url 和访问页面的url不同

获取access_token时却报出下列错误信息:
{"errcode":40164,"errmsg":"invalid ip 61.172.68.219, not in whitelist hint: [KJZfAa0644e575]"}
{"ret":""{"errcode":41001,"errmsg":"access_token missing hint:[FOOOrA0226vr29!]"}"","error":""}
解读:错误代码:40164,
错误信息:无效ip,不在白名单中
于是开始往IP白名单这个方向思考,因为换了个地方,网络不同,电脑的ip地址变了。所以要再设置一下白名单

二、解决方法

登录公众平台,开发->基本配置->IP白名单->查看->修改->将ip地址添加进去即可

@mingyun
Copy link
Owner Author

mingyun commented Mar 29, 2018

设置JS接口安全域名后,公众号开发者可在该域名下调用微信开放的JS接口。
注意事项:
1、可填写三个域名或路径(例:wx.qq.com或wx.qq.com/mp),需使用字母、数字及“-”的组合,不支持IP地址、端口号及短链域名。
2、填写的域名须通过ICP备案的验证。
3、 将文件MP_verify_0JUHzKF4q95bDNcv.txt(点击下载)上传至填写域名或路径指向的web服务器(或虚拟主机)的目录(若填写域名,将文件放置在域名根目录下,例如wx.qq.com/MP_verify_0JUHzKF4q95bDNcv.txt;若填写路径,将文件放置在路径目录下,例如wx.qq.com/mp/MP_verify_0JUHzKF4q95bDNcv.txt),并确保可以访问。
4、 一个自然月内最多可修改并保存三次,本月剩余保存次数:2

在IP白名单内的IP来源,获取access_token接口才可调用成功。

$app_like_webinar_wait_key = 'saas:app:like:webinar:wait:'.$data['webinar_id'];
$app_like_webinar_wait_count = RedisFacade::incr($app_like_webinar_wait_key);
if( $app_like_webinar_wait_count <= 1 || RedisFacade::ttl($app_like_webinar_wait_key) == -1 ){
RedisFacade::expire($app_like_webinar_wait_key, 1);
}
if($app_like_webinar_wait_count > 1){
sleep(1);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant