微信二次分享解决图标文案失效方案

转自:https://www.cnblogs.com/backtozero/p/7064247.html

前言

刚进入一家新公司,接到的第一个任务就是需要需要自定义微信分享的效果(自定义缩略图,标题,摘要),一开始真是一脸懵逼,在网上搜索了半天之后大概有了方案。值得注意的是一开始搜索到的解决方案全是调用微信的自带的JS-SDK,然而腾讯是不会让广大吃瓜群众这么轻而易举的调用他们的东西的。微信开发团队已经把调用的权限收回,现在无法直接在页面直接调用JS-SDK了。话不多说,直接上干货。

预期效果

原始的分享效果:

 

使用微信JS-SDK的分享效果:

可以看出缩略图,标题,摘要样式良好,给用户的体验很好。

准备工作

微信官方开发者文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

现在的思路已经很明确了,就是通过调用微信的JS-SDK实现自定义分享效果。但是这个调用过程比较繁琐,需要提前准备如下东西:

(1)微信服务号一个,并且已经通过了实名认证;

   没有实名认证的话,一些接口没有调用权限。

(2)一个ICP备案的域名;

这个域名需要设置为微信公众号后台的JS接口安全域名,否则微信仍然不允许调用它的接口。

这时大家应该就犯难了,这样的话岂不是不能在本地测试,只能部署到生产环境才能测试?不用着急,解决方案告诉大家:花生壳的内网穿透服务(收费,20元以内)

花生壳官网:http://hsk.oray.com/price/#personal

选择个人免费版就可以了,虽然说是免费版,但是其实注册过程中还是要收几块钱的,因为我自己买了域名和流量所以花的钱更多一些,但也在20元以内。不建议大家购买流量,送的流量可以用很久了。

当准备好上面提到的就可以开始敲代码了。

(3)安装微信开发者工具,用于本地调试。

下载地址:https://mp.weixin.qq.com/debug/cgi-bin/webdebugger/download?from=mpwiki&os=x64

官方使用教程:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140

具体步骤

(1)查看AppId,AppSecret以及绑定域名

进入微信后台,找到下面的菜单

获取AppID和AppSecret

设置JS接口安全域名

 

 

注意第三步,如果微信服务器不能在我们的服务器上访问到这个txt文件,域名是无法设置成功的,这里先告诉大家在哪里设置,想要成功设置域名还需要使用花生壳的服务,让微信服务器访问我们本地工程中的的txt文件才行。

hkh3321313.vicp.io是在花生壳上购买的域名,免费送的域名是在太难记了,完全不能忍。

 

(2)引入JS文件

这里需要注意是http还是https,如果生产环境是https,务必前缀是https,都则会出现mix content这样的错误,导致引入失败。

<script typet="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

 

(3)通过AppId和AppSecret请求accessToken,然后通过accessToken获取jsapi_ticket,生成config接口所需参数

因为获取这两个参数的次数是有限制的(accessToke 每日2000次,jsapi_ticket 每日100000次),有效期是7200秒,每两小时请求一次就行啦,把获取的accessToke和jsapi_ticket保存在后台,所以accessToken和jsapi_ticket这两个参数的获取是通过ajax方式请求后台,而不是实时去获取的。

config几个参数需要详细说明一下:

  1. timestamp  生成签名的时间戳  create_nonce_str()
  2. nonceStr  随机生成的字符串 create_timestamp()
  3. signature  按照微信文档签名算法生成的签名 makeWXTicket()

附上signature算法的官方说明:

https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.15697429783636763#buzhou3

在附录1中可以找到详细说明。

此外,官方提供了一个签名算法的校验工具:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

下面只附上了主要的方法:

复制代码
//获取accessToken
private JSONObject getAccessToken(){
    //String accessTokenUrl= https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    String requestUrl = accessTokenUrl.replace("APPID",appId).replace("APPSECRET",appSecret);
    log.info("getAccessToken.requestUrl====>"+requestUrl);
    JSONObject result = HttpUtil.doGet(requestUrl);
    return result ;
}

//获取ticket
private JSONObject getJsApiTicket(){
//String apiTicketUrl= https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
String requestUrl = apiTicketUrl.replace(“ACCESS_TOKEN”, accessToken);
log.info(“getJsApiTicket.requestUrl====>”+requestUrl);
JSONObject result = HttpUtil.doGet(requestUrl);
return result;
}

//生成微信权限验证的参数
public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
Map<String, String> ret = new HashMap<String, String>();
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String string1;
String signature = “”;

</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">注意这里参数名必须全部小写,且必须有序</span>
string1 = "jsapi_ticket=" + jsApiTicket +
        "&amp;noncestr=" + <span style="line-height:1.5;">nonceStr </span>+
        "&amp;timestamp=" + timestamp +
        "&amp;url=" +<span style="line-height:1.5;"> url;
log.info(</span>"String1=====&gt;"+<span style="line-height:1.5;">string1);
</span><span style="color:rgb(0,0,255);line-height:1.5;">try</span><span style="line-height:1.5;">
{
    MessageDigest crypt </span>= MessageDigest.getInstance("SHA-1"<span style="line-height:1.5;">);
    crypt.reset();
    crypt.update(string1.getBytes(</span>"UTF-8"<span style="line-height:1.5;">));
    signature </span>=<span style="line-height:1.5;"> byteToHex(crypt.digest());
    log.info(</span>"signature=====&gt;"+<span style="line-height:1.5;">signature);
}
</span><span style="color:rgb(0,0,255);line-height:1.5;">catch</span><span style="line-height:1.5;"> (NoSuchAlgorithmException e)
{
    log.error(</span>"WeChatController.makeWXTicket=====Start"<span style="line-height:1.5;">);
    log.error(e.getMessage(),e);
    log.error(</span>"WeChatController.makeWXTicket=====End"<span style="line-height:1.5;">);
}
</span><span style="color:rgb(0,0,255);line-height:1.5;">catch</span><span style="line-height:1.5;"> (UnsupportedEncodingException e)
{
    log.error(</span>"WeChatController.makeWXTicket=====Start"<span style="line-height:1.5;">);
    log.error(e.getMessage(),e);
    log.error(</span>"WeChatController.makeWXTicket=====End"<span style="line-height:1.5;">);
}

ret.put(</span>"url"<span style="line-height:1.5;">, url);
ret.put(</span>"jsapi_ticket"<span style="line-height:1.5;">, jsApiTicket);
ret.put(</span>"nonceStr"<span style="line-height:1.5;">, <span style="line-height:1.5;">nonceStr</span>);
ret.put(</span>"timestamp"<span style="line-height:1.5;">, timestamp);
ret.put(</span>"signature"<span style="line-height:1.5;">, signature);
ret.put(</span>"appid"<span style="line-height:1.5;">, appId);

</span><span style="color:rgb(0,0,255);line-height:1.5;">return</span><span style="line-height:1.5;"> ret;

}
//字节数组转换为十六进制字符串
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
//生成随机字符串
private static String createNonceStr() {
return UUID.randomUUID().toString();
}
//生成时间戳
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}

复制代码

HttpUtil代码

复制代码
public class HttpUtil {
public static Log logger = LogFactory.getLog(HttpUtil.class);
//get请求
public static com.alibaba.fastjson.JSONObject doGet(String requestUrl) {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String responseContent = null;
com.alibaba.fastjson.JSONObject result = null;
try {
//创建Get请求,
HttpGet httpGet = new HttpGet(requestUrl);
//执行Get请求,
response = httpClient.execute(httpGet);
//得到响应体
HttpEntity entity = response.getEntity();
//获取响应内容
responseContent = EntityUtils.toString(entity,“UTF-8”);
//转换为map
result = JSON.parseObject(responseContent);
} catch (IOException e) {
logger.error(“HttpUtil=Start");
logger.error(e.getMessage(),e);
logger.error("HttpUtil
=End”);
}
return result;
}
}
复制代码

 

(4)通过config接口注入权限验证配置

官方示例:

复制代码
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ‘’, // 必填,公众号的唯一标识
   timestamp: , // 必填,生成签名的时间戳
nonceStr: ‘’, // 必填,生成签名的随机串
signature: ‘’,// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
复制代码

自己的代码:

其中的url不能硬编码写在后台,必须通过动态传递。

复制代码
$(function(){
var url = location.href.split(’#’).toString();//url不能写死
KaTeX parse error: Expected 'EOF', got '}' at position 2610: … } }) }̲);</span></pre>…{wechat.appId}")
private String appId;
@Value(" w e c h a t . a p p S e c r e t &quot; &lt; s p a n s t y l e = &quot; l i n e − h e i g h t : 1.5 ; &quot; &gt; ) p r i v a t e S t r i n g a p p S e c r e t ; @ V a l u e ( &lt; / s p a n &gt; &quot; {wechat.appSecret}&quot;&lt;span style=&quot;line-height:1.5;&quot;&gt;) private String appSecret; @Value(&lt;/span&gt;&quot; wechat.appSecret"<spanstyle="lineheight:1.5;">)privateStringappSecret;@Value(</span>"{wechat.url.accessToken}")
private String accessTokenUrl;
@Value("${wechat.url.apiTicket}")
private String apiTicketUrl;
</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">微信参数</span>

private String accessToken;
private String jsApiTicket;
//获取参数的时刻
private Long getTiketTime = 0L;
private Long getTokenTime = 0L;
//参数的有效时间,单位是秒(s)
private Long tokenExpireTime = 0L;
private Long ticketExpireTime = 0L;

</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">获取微信参数</span>
@RequestMapping("/wechatParam"<span style="line-height:1.5;">)
@ResponseBody
public Map</span>&lt;String, String&gt;<span style="line-height:1.5;"> getWechatParam(String url){
    </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">当前时间</span>
    <span style="color:rgb(0,0,255);line-height:1.5;">long</span> now =<span style="line-height:1.5;"> System.currentTimeMillis();
    log.info(</span>"currentTime====&gt;"+now+"ms"<span style="line-height:1.5;">);

    </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">判断accessToken是否已经存在或者token是否过期</span>
    <span style="color:rgb(0,0,255);line-height:1.5;">if</span>(StringUtils.isBlank(accessToken)||(now - getTokenTime &gt; tokenExpireTime*1000<span style="line-height:1.5;">)){
        JSONObject tokenInfo </span>=<span style="line-height:1.5;"> getAccessToken();
        </span><span style="color:rgb(0,0,255);line-height:1.5;">if</span>(tokenInfo != <span style="color:rgb(0,0,255);line-height:1.5;">null</span><span style="line-height:1.5;">){
            log.info(</span>"tokenInfo====&gt;"+<span style="line-height:1.5;">tokenInfo.toJSONString());
            accessToken </span>= tokenInfo.getString("access_token"<span style="line-height:1.5;">);
            tokenExpireTime </span>= tokenInfo.getLongValue("expires_in"<span style="line-height:1.5;">);
            </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">获取token的时间</span>
            getTokenTime =<span style="line-height:1.5;"> System.currentTimeMillis();
            log.info(</span>"accessToken====&gt;"+<span style="line-height:1.5;">accessToken);
            log.info(</span>"tokenExpireTime====&gt;"+tokenExpireTime+"s"<span style="line-height:1.5;">);
            log.info(</span>"getTokenTime====&gt;"+getTokenTime+"ms"<span style="line-height:1.5;">);
        }</span><span style="color:rgb(0,0,255);line-height:1.5;">else</span><span style="line-height:1.5;">{
            log.info(</span>"====&gt;tokenInfo is null~"<span style="line-height:1.5;">);
            log.info(</span>"====&gt;failure of getting tokenInfo,please do some check~"<span style="line-height:1.5;">);
        }

    }

    </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">判断jsApiTicket是否已经存在或者是否过期</span>
    <span style="color:rgb(0,0,255);line-height:1.5;">if</span>(StringUtils.isBlank(jsApiTicket)||(now - getTiketTime &gt; ticketExpireTime*1000<span style="line-height:1.5;">)){
        JSONObject ticketInfo </span>=<span style="line-height:1.5;"> getJsApiTicket();
        </span><span style="color:rgb(0,0,255);line-height:1.5;">if</span>(ticketInfo!=<span style="color:rgb(0,0,255);line-height:1.5;">null</span><span style="line-height:1.5;">){
            log.info(</span>"ticketInfo====&gt;"+<span style="line-height:1.5;">ticketInfo.toJSONString());
            jsApiTicket </span>= ticketInfo.getString("ticket"<span style="line-height:1.5;">);
            ticketExpireTime </span>= ticketInfo.getLongValue("expires_in"<span style="line-height:1.5;">);
            getTiketTime </span>=<span style="line-height:1.5;"> System.currentTimeMillis();
            log.info(</span>"jsApiTicket====&gt;"+<span style="line-height:1.5;">jsApiTicket);
            log.info(</span>"ticketExpireTime====&gt;"+ticketExpireTime+"s"<span style="line-height:1.5;">);
            log.info(</span>"getTiketTime====&gt;"+getTiketTime+"ms"<span style="line-height:1.5;">);
        }</span><span style="color:rgb(0,0,255);line-height:1.5;">else</span><span style="line-height:1.5;">{
            log.info(</span>"====&gt;ticketInfo is null~"<span style="line-height:1.5;">);
            log.info(</span>"====&gt;failure of getting tokenInfo,please do some check~"<span style="line-height:1.5;">);
        }
    }

    </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">生成微信权限验证的参数</span>
    Map&lt;String, String&gt; wechatParam=<span style="line-height:1.5;"> makeWXTicket(jsApiTicket,url);
    </span><span style="color:rgb(0,0,255);line-height:1.5;">return</span><span style="line-height:1.5;"> wechatParam;
}

</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">获取accessToken</span>

private JSONObject getAccessToken(){
//String accessTokenUrl = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
String requestUrl = accessTokenUrl.replace(“APPID”,appId).replace(“APPSECRET”,appSecret);
log.info(“getAccessToken.requestUrl====>”+requestUrl);
JSONObject result = HttpUtil.doGet(requestUrl);
return result ;
}

</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">获取ticket</span>

private JSONObject getJsApiTicket(){
//String apiTicketUrl = https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
String requestUrl = apiTicketUrl.replace(“ACCESS_TOKEN”, accessToken);
log.info(“getJsApiTicket.requestUrl====>”+requestUrl);
JSONObject result = HttpUtil.doGet(requestUrl);
return result;
}

</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">生成微信权限验证的参数</span>
public Map&lt;String, String&gt;<span style="line-height:1.5;"> makeWXTicket(String jsApiTicket, String url) {
    Map</span>&lt;String, String&gt; ret = <span style="color:rgb(0,0,255);line-height:1.5;">new</span> HashMap&lt;String, String&gt;<span style="line-height:1.5;">();
    String nonceStr </span>=<span style="line-height:1.5;"> createNonceStr();
    String timestamp </span>=<span style="line-height:1.5;"> createTimestamp();
    String string1;
    String signature </span>= ""<span style="line-height:1.5;">;

    </span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">注意这里参数名必须全部小写,且必须有序</span>
    string1 = "jsapi_ticket=" + jsApiTicket +
            "&amp;noncestr=" + nonceStr +
            "&amp;timestamp=" + timestamp +
            "&amp;url=" +<span style="line-height:1.5;"> url;
    log.info(</span>"String1=====&gt;"+<span style="line-height:1.5;">string1);
    </span><span style="color:rgb(0,0,255);line-height:1.5;">try</span><span style="line-height:1.5;">
    {
        MessageDigest crypt </span>= MessageDigest.getInstance("SHA-1"<span style="line-height:1.5;">);
        crypt.reset();
        crypt.update(string1.getBytes(</span>"UTF-8"<span style="line-height:1.5;">));
        signature </span>=<span style="line-height:1.5;"> byteToHex(crypt.digest());
        log.info(</span>"signature=====&gt;"+<span style="line-height:1.5;">signature);
    }
    </span><span style="color:rgb(0,0,255);line-height:1.5;">catch</span><span style="line-height:1.5;"> (NoSuchAlgorithmException e)
    {
        log.error(</span>"WeChatController.makeWXTicket=====Start"<span style="line-height:1.5;">);
        log.error(e.getMessage(),e);
        log.error(</span>"WeChatController.makeWXTicket=====End"<span style="line-height:1.5;">);
    }
    </span><span style="color:rgb(0,0,255);line-height:1.5;">catch</span><span style="line-height:1.5;"> (UnsupportedEncodingException e)
    {
        log.error(</span>"WeChatController.makeWXTicket=====Start"<span style="line-height:1.5;">);
        log.error(e.getMessage(),e);
        log.error(</span>"WeChatController.makeWXTicket=====End"<span style="line-height:1.5;">);
    }

    ret.put(</span>"url"<span style="line-height:1.5;">, url);
    ret.put(</span>"jsapi_ticket"<span style="line-height:1.5;">, jsApiTicket);
    ret.put(</span>"nonceStr"<span style="line-height:1.5;">, nonceStr);
    ret.put(</span>"timestamp"<span style="line-height:1.5;">, timestamp);
    ret.put(</span>"signature"<span style="line-height:1.5;">, signature);
    ret.put(</span>"appid"<span style="line-height:1.5;">, appId);

    </span><span style="color:rgb(0,0,255);line-height:1.5;">return</span><span style="line-height:1.5;"> ret;
}
</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">字节数组转换为十六进制字符串</span>
private static String byteToHex(final <span style="color:rgb(0,0,255);line-height:1.5;">byte</span><span style="line-height:1.5;">[] hash) {
    Formatter formatter </span>= <span style="color:rgb(0,0,255);line-height:1.5;">new</span><span style="line-height:1.5;"> Formatter();
    </span><span style="color:rgb(0,0,255);line-height:1.5;">for</span> (<span style="color:rgb(0,0,255);line-height:1.5;">byte</span><span style="line-height:1.5;"> b : hash)
    {
        formatter.format(</span>"%02x"<span style="line-height:1.5;">, b);
    }
    String result </span>=<span style="line-height:1.5;"> formatter.toString();
    formatter.close();
    </span><span style="color:rgb(0,0,255);line-height:1.5;">return</span><span style="line-height:1.5;"> result;
}
</span><span style="color:rgb(0,128,0);line-height:1.5;">//</span><span style="color:rgb(0,128,0);line-height:1.5;">生成随机字符串</span>

private static String createNonceStr() {
return UUID.randomUUID().toString();
}
//生成时间戳
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}


页面js解决二次分享问题:

<script typet=“text/javascript” src=“https://res.wx.qq.com/open/js/jweixin-1.0.0.js”></script>
  <script type=“text/javascript”>
$(function(){
    refreshUrl();//刷新页面去除一次分享带的参数
    var url = location.href.split(’#’).toString();//url不能写死
    KaTeX parse error: Expected '}', got '&' at position 26: …><span> </span>&̲nbsp; &nbsp; &n…)");
var result = window.location.search.substr(1).match(reg);
return result ? decodeURIComponent(result[2]) : false;


};
function funcUrlDel(name) {//删除url指定参数名并返回新的url
var loca = window.location;
var baseUrl = loca.origin + loca.pathname + “?”;
var query = loca.search.substr(1);
if (query.indexOf(name) > -1) {
var obj = {};
var arr = query.split("&");
for (var i = 0; i < arr.length; i++) {
arr[i] = arr[i].split("=");
obj[arr[i][0]] = arr[i][1];
};
delete obj[name];
var url = baseUrl + JSON.stringify(obj).replace(/["{}]/g, “”).replace(/:/g, “=”).replace(/,/g, “&”);
return url
};
};

function getlinkSearch(key, reqStr) {

var reg = new RegExp("(^|&)" + key + “=([^&]*)(&|$)”);
var result = reqStr.substr(1).match(reg);
return result ? decodeURIComponent(result[2]) : false;
};


function refreshUrl() {//强制刷新到不带二次分享参数页面
var url = “”,
reqStr = “”;
if (fnGetQueryString(‘from’)) {//from为微信二次分享自带参数
url = funcUrlDel(‘from’);
var reqIndex = url.indexOf(’?’);
reqStr = url.substr(reqIndex);//截取去除from参数后的地址
if (getlinkSearch(‘isappinstalled’, reqStr)) {//isappinstalled为微信二次分享自带参数
url = url.substr(0, url.indexOf(’?’));//截取去除isappinstalled参数后的地址
window.location.href = url;
} else {
window.location.href = url;
}
}
};
  </script>

				<script>
					(function(){
						function setArticleH(btnReadmore,posi){
							var winH = $(window).height();
							var articleBox = $("div.article_content");
							var artH = articleBox.height();
							if(artH > winH*posi){
								articleBox.css({
									'height':winH*posi+'px',
									'overflow':'hidden'
								})
								btnReadmore.click(function(){
									articleBox.removeAttr("style");
									$(this).parent().remove();
								})
							}else{
								btnReadmore.parent().remove();
							}
						}
						var btnReadmore = $("#btn-readmore");
						if(btnReadmore.length>0){
							if(currentUserName){
								setArticleH(btnReadmore,3);
							}else{
								setArticleH(btnReadmore,1.2);
							}
						}
					})()
				</script>
				</article>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值