yuupuu 发表于 2020-9-18 15:19

微信公众号实现长链接转短链接!w.url.cn短网址生成

本帖最后由 yuupuu 于 2020-9-18 15:23 编辑

微信公众号开发者平台提供短网址生成的API,最终生成的短网址是w.url.cn的,下面是详细的代码。

官方文档
https://developers.weixin.qq.com/doc/offiaccount/Account_Management/URL_Shortener.html


请求参数
access_token
action 此处填long2short,代表长链接转短链接
long_url 需要转换的原链接


HTTP POST请求网址
https://api.weixin.qq.com/cgi-bin/shorturl?access_token=ACCESS_TOKEN


请求流程
1、获取本地缓存的access_token,如果超过有效期,则重新获取,如果还没过期,直接使用缓存的access_token
2、构建请求参数,发起POST请求
3、获得短网址


代码
appid和appsecret可以申请一个微信公众号测试账号进行开发
申请地址:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login


<?php
header("Content-type:application/json");

// 声明APPID、APPSECRET
$appid = "xxx";
$appsecret = "xxx";

// 获取access_token和jsapi_ticket
function getToken(){
    $file = file_get_contents("access_token.json",true);//读取access_token.json里面的数据
    $result = json_decode($file,true);

//判断access_token是否在有效期内,如果在有效期则获取缓存的access_token
//如果过期了则请求接口生成新的access_token并且缓存access_token.json
if (time() > $result['expires']){
      $data = array();
      $data['access_token'] = getNewToken();
      $data['expires'] = time()+7000;
      $jsonStr =json_encode($data);
      $fp = fopen("access_token.json", "w");
      fwrite($fp, $jsonStr);
      fclose($fp);
      return $data['access_token'];
    }else{
      return $result['access_token'];
    }
}

//获取新的access_token
function getNewToken($appid,$appsecret){
    global $appid;
    global $appsecret;
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret."";
    $access_token_Arr =file_get_contents($url);
    $token_jsonarr = json_decode($access_token_Arr, true);
    return $token_jsonarr["access_token"];
}

// 获得长链接
$long_url = trim($_GET["long_url"]);

// 过滤
if (empty($long_url)) {
    $result = array(
      "result" => "101",
      "msg" => "请传入长链接"
    );
} else if (strpos($long_url,'http') !== false){
    //初始化 CURL
    $ch = curl_init();
    //请求地址
    curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/cgi-bin/shorturl?access_token='.getToken());
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    $postdata ='{"action":"long2short","long_url":"'.$long_url.'"}';
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    // 对认证证书来源的检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    // 从证书中检查SSL加密算法是否存在
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    //获取的信息以文件流的形式返回,而不是直接输出
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    //发起请求
    $dwzStr = curl_exec($ch);
    //解析数据
    $arr_dwzStr = json_decode($dwzStr, true);
    $dwz = $arr_dwzStr["short_url"];
    //关闭请求
    curl_close($ch);

    // 返回结果
    $result = array(
      "result" => "100",
      "msg" => "解析成功",
      "dwz" => $dwz
    );
}else{
    $result = array(
      "result" => "102",
      "msg" => "长链接不合法"
    );
}

// 返回JSON
echo json_encode($result,JSON_UNESCAPED_UNICODE);
?>


生成示例
{"result":"100","msg":"生成成功","dwz":"https:\/\/w.url.cn\/s\/AVuvUup"}

cnhong 发表于 2020-9-18 16:04

唉,已经自己搭建自用的短网址了,仅仅自己用

cnhong 发表于 2020-9-18 18:24

本帖最后由 cnhong 于 2020-9-18 18:42 编辑

稍微加了点东西{:1_886:}
支持验证TOKEN<?php
header("Content-type:application/json");

// 声明APPID、APPSECRET
define("APPID", "wxxxxxb4a7e599xxxx");
define("SECRET", "9a01e1xxxx1377c13acxxxxc87c167de");
//校验用的TOKEN
define("TOKEN", "cnhong2020");

//校验
if (isset($_GET['echostr']))
{
    Valid::exec();
}

// 获取access_token和jsapi_ticket
function getToken(){
    $file = @file_get_contents("access_token.json",true);//读取access_token.json里面的数据
    $result = json_decode($file,true);

//判断access_token是否在有效期内,如果在有效期则获取缓存的access_token
//如果过期了则请求接口生成新的access_token并且缓存access_token.json
if (!isset($result['expires']) || time() > $result['expires']){
      $data = array();
      $data['access_token'] = getNewToken();
      $data['expires'] = time()+7000;
      $jsonStr =json_encode($data);
      file_put_contents("access_token.json",$jsonStr);      return $data['access_token'];
    }else{
      return $result['access_token'];
    }
}

//生成json
function msg($result, $msg, $dwz=""){
    $array = array(
      "result" => $result,
      "msg" => $msg,
      "dwz" => $dwz
    );
    return json_encode($array,JSON_UNESCAPED_UNICODE);
}

//获取新的access_token
function getNewToken(){
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . APPID . "&secret=" . SECRET;
    $access_token_json = (new Curl($url))->exec();
    $token_arr = json_decode($access_token_json, true);
    //获取access_token失败
    if(!isset($token_arr["access_token"])){
      echo msg(302, "获取access_token失败!");
      exit;
    }
    return $token_arr["access_token"];
}

// 获得长链接
$long_url = trim($_GET["long_url"]);

// 过滤
if (empty($long_url)) {
    echo msg(101, "请传入长链接");
} else if (strpos($long_url,'http') !== false){
    $url = 'https://api.weixin.qq.com/cgi-bin/shorturl?access_token='.getToken();
    $postData = array(
      'action'=>'long2short',
      'long_url'=>$long_url
    );
    //获取数据
    $curl = new Curl($url, $postData);
    $dwzStr = $curl->exec();
    //解析数据
    $arr_dwzStr = json_decode($dwzStr, true);
    //print_r($arr_dwzStr);
    //判断是否出错
    if($arr_dwzStr["errcode"]==0){
      $dwz = $arr_dwzStr["short_url"];
      // 返回结果
      echo msg(200, "生成成功", $dwz);
    }else{
      echo msg(301, "生成失败");
    }
}else{
    echo msg(103, "长链接不合法");
}
//curl类
class Curl{
    private $ch;
    function __construct($url, $postdata=''){
      $this->ch = curl_init();
      //请求地址
      curl_setopt($this->ch, CURLOPT_URL, $url);
      //post数据
      if(is_array($postdata)){
            curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'POST');
            curl_setopt($this->ch, CURLOPT_POSTFIELDS, json_encode($postdata));
      }
      
      // 验证HTTPS证书
                if(strlen($url) > 5 && strtolower(substr($url,0,5)) == 'https' ) {
                        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false);
                        curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, false);
                }
      //获取的信息以文件流的形式返回,而不是直接输出
      curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
    }
   
    public function exec(){
                $reponse = curl_exec($this->ch);
                curl_close($this->ch);
                return $reponse;
      }
}
//校验类
class Valid{
      public static function exec()//校验-外部调用
    {
      $echoStr = $_GET["echostr"];
      if(self::checkSignature()){
            echo $echoStr;
      }
      exit;
    }
    private static function checkSignature()
      {
                $signature = $_GET["signature"];
                $timestamp = $_GET["timestamp"];
                $nonce = $_GET["nonce"];
               
                $token = TOKEN;
                $tmpArr = array($token, $timestamp, $nonce);
                sort($tmpArr, SORT_STRING);
                $tmpStr = implode( $tmpArr );
                $tmpStr = sha1( $tmpStr );
               
                if( $tmpStr == $signature ){
                        return true;
                }else{
                        return false;
                }
      }
}
?>

慵懒丶L先森 发表于 2020-9-18 15:22

你这排版看起来有点难受。。。。

yuupuu 发表于 2020-9-18 15:23

慵懒丶L先森 发表于 2020-9-18 15:22
你这排版看起来有点难受。。。。

刷新...已经修改

iflower 发表于 2020-9-18 15:47

路过看不懂,但还是得支持下

eshao2010 发表于 2020-9-18 17:01

个人未认证订阅号可以吗?

starblacker 发表于 2020-9-18 17:36

生成地址可以去掉反斜杠\吗?直接https://w.url.cn/s/AVuvUup

huomavip 发表于 2020-9-18 18:07

谢谢,虽然用不到,url.cn今日也加入跳转白名单了,稳定可靠的也就剩w.url.cn了

huomavip 发表于 2020-9-18 19:08

cnhong 发表于 2020-9-18 18:24
稍微加了点东西
支持验证TOKEN

建议使用 redis 保存更新access_token
页: [1] 2
查看完整版本: 微信公众号实现长链接转短链接!w.url.cn短网址生成