您的位置:首页 > 移动开发 > 微信开发

Grails框架实现微信自定义分享页

2016-09-27 14:06 381 查看
微信分享说明文档

官方实例

微信web开发者工具可以在pc端进行测试开发

下面我来说说具体来实现这个自定义分享

需要在官方申请一个公众号

在Grails 2.4.4中需要安装rest-client-builder 2.1.1 插件

下面由代码来讲解这个分享过程

WeixinpayConfig.groovy 配置微信相关参数信息

package com.weixin.config;

/**
 * 
 * @author lvbaolin
 * @date 2016年5月27日上午11:10:50
 * @company 北京远中和科技
 *
 *          配置微信参数
 */

public class WeixinpayConfig {

// 配置基本信息

//微信分享使用
//公众号appId
public static String SHAREDAPPID = "*****";

//微信分享使用
//公众号secret
public static String SHAREDSECRET = "****";

//获取access_token 路径
public static String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token";

//获得jsapi_ticket 路径
public static String TICKENT = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

// 基本信息结束
}


WinxinUtils.groovy 请求微信工具类

package com.weixinpay.util

import grails.plugins.rest.client.RestBuilder
import org.springframework.http.HttpStatus
import business.BusinessException
import com.weixin.config.WeixinpayConfig

class WinxinUtils {

/**
* 对微信发起get请求获取相关数据
* @param 
* @return
*/
private static getWeixinRequest(def path){
RestBuilder rest = new RestBuilder()
def resp = rest.get(path)
if(resp.statusCode == HttpStatus.OK) {
//println resp.body
return resp.json
} else
throw new Exception(resp.text)
return null

}

}


WeixinsignUtils.groovy 生成随机字符串和SHA1加密

package com.weixin.sign;

import java.util.Map;
import com.weixin.config.WeixinpayConfig;
import com.weixin.util.MapUtil;

/**
 * 
 * @author lvbaolin
 * @date 2016年5月27日上午11:45:29
 * @company 北京远中和科技
 *
 *          
 */
public class WeixinsignUtils {

/**
* 随机字符串,不长于32位。推荐随机数生成算法
* 
* @return
*/
public static String createStr() {
// TODO Auto-generated method stub
String str = "";
char[] ch = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p','q','r','s','t','u','v','w','x','y','z'};
// int n = 1 + (int) (Math.random() * 25) ;
int n = 20;
for (int i = 0; i < n; i++) {
int x = 1 + (int) (Math.random() * 33);
str += ch[x];
}
return str;
}

/**
* create sign
* 
* @param map
* @return
*/
public static String createSHA1_Sign(Map<String, String> map) {

String result = MapUtil.mapJoin(map, true, false);
//System.out.println(result);
try {
result = SHA1.getSHA1HexString(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("sign create error");
}
return result;
}

}


MapUtil.groovy Map工具类

package com.weixin.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author lvbaolin
 * @date 2016年5月30日下午2:55:35
 * @company 北京远中和科技
 *
 */
public class MapUtil {

public static Map<String,Object> toMap(Object object){
        Map<String,Object> map = new HashMap<String, Object>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            Object obj;
            try {
                obj = field.get(object);
                if(obj!=null){
                    map.put(field.getName(), obj);
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
/**
* Map key 排序(ASCII字典序排序)
* @param map
* @return
*/
public static Map<String,String> order(Map<String, String> map){
HashMap<String, String> tempMap = new LinkedHashMap<String, String>();
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(	map.entrySet());

Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1,Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});

for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
tempMap.put(item.getKey(), item.getValue());
}

return tempMap;
}

/**
* 转换对象为map
* @param object
* @param ignore
* @return
*/
public static Map<String,String> objectToMap(Object object,String... ignore){
Map<String,String> tempMap = new LinkedHashMap<String, String>();
for(Field f : object.getClass().getDeclaredFields()){
if(!f.isAccessible()){
f.setAccessible(true);
}
boolean ig = false;
if(ignore!=null&&ignore.length>0){
for(String i : ignore){
if(i.equals(f.getName())){
ig = true;
break;
}
}
}
if(ig){
continue;
}else{
Object o = null;
try {
o = f.get(object);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
tempMap.put(f.getName(), o==null?"":o.toString());
}
}
return tempMap;
}

/**
* url 参数串连
* @param map
* @param keyLower
* @param valueUrlencode
* @return
*/
public static String mapJoin(Map<String, String> map,boolean keyLower,boolean valueUrlencode){
StringBuilder stringBuilder = new StringBuilder();
for(String key :map.keySet()){
if(map.get(key)!=null&&!"".equals(map.get(key))){
try {
String temp = (key.endsWith("_")&&key.length()>1)?key.substring(0,key.length()-1):key;
stringBuilder.append(keyLower?temp.toLowerCase():temp)
.append("=")
.append(valueUrlencode?URLEncoder.encode(map.get(key),"utf-8").replace("+", "%20"):map.get(key))
.append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
if(stringBuilder.length()>0){
stringBuilder.deleteCharAt(stringBuilder.length()-1);
}
return stringBuilder.toString();
}

/**
* 简单 xml 转换为 Map
* @param reader
* @return
*/
public static Map<String,String> xmlToMap(String xml){
try {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
Element element = document.getDocumentElement();
NodeList nodeList = element.getChildNodes();
Map<String, String> map = new LinkedHashMap<String, String>();
for(int i=0;i<nodeList.getLength();i++){
Element e = (Element) nodeList.item(i);
map.put(e.getNodeName(),e.getTextContent());
}
return map;
} catch (DOMException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}


SHA1.groovy 把字符串进行SHA1加密

package com.weixin.sign;

import java.security.MessageDigest;

public class SHA1 {

public static String getSHA1HexString(String str) throws Exception {
        // SHA1签名生成
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(str.getBytes());
        byte[] digest = md.digest();

        StringBuffer hexstr = new StringBuffer();
        String shaHex = "";
        for (int i = 0; i < digest.length; i++) {
            shaHex = Integer.toHexString(digest[i] & 0xFF);
            if (shaHex.length() < 2) {
                hexstr.append(0);
            }
            hexstr.append(shaHex);
        }
        return hexstr.toString();
    }

private final int[] abcde = {   
            0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0   
        };   
    // 摘要数据存储数组   
    private int[] digestInt = new int[5];   
    // 计算过程中的临时数据存储数组   
    private int[] tmpData = new int[80];   
    // 计算sha-1摘要   
    private int process_input_bytes(byte[] bytedata) {   
        // 初试化常量   
        System.arraycopy(abcde, 0, digestInt, 0, abcde.length);   
        // 格式化输入字节数组,补10及长度数据   
        byte[] newbyte = byteArrayFormatData(bytedata);   
        // 获取数据摘要计算的数据单元个数   
        int MCount = newbyte.length / 64;   
        // 循环对每个数据单元进行摘要计算   
        for (int pos = 0; pos < MCount; pos++) {   
            // 将每个单元的数据转换成16个整型数据,并保存到tmpData的前16个数组元素中   
            for (int j = 0; j < 16; j++) {   
                tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4));   
            }   
            // 摘要计算函数   
            encrypt();   
        }   
        return 20;   
    }   
    // 格式化输入字节数组格式   
    private byte[] byteArrayFormatData(byte[] bytedata) {   
        // 补0数量   
        int zeros = 0;   
        // 补位后总位数   
        int size = 0;   
        // 原始数据长度   
        int n = bytedata.length;   
        // 模64后的剩余位数   
        int m = n % 64;   
        // 计算添加0的个数以及添加10后的总长度   
        if (m < 56) {   
            zeros = 55 - m;   
            size = n - m + 64;   
        } else if (m == 56) {   
            zeros = 63;   
            size = n + 8 + 64;   
        } else {   
            zeros = 63 - m + 56;   
            size = (n + 64) - m + 64;   
        }   
        // 补位后生成的新数组内容   
        byte[] newbyte = new byte[size];   
        // 复制数组的前面部分   
        System.arraycopy(bytedata, 0, newbyte, 0, n);   
        // 获得数组Append数据元素的位置   
        int l = n;   
        // 补1操作   
        newbyte[l++] = (byte) 0x80;   
        // 补0操作   
        for (int i = 0; i < zeros; i++) {   
            newbyte[l++] = (byte) 0x00;   
        }   
        // 计算数据长度,补数据长度位共8字节,长整型   
        long N = (long) n * 8;   
        byte h8 = (byte) (N & 0xFF);   
        byte h7 = (byte) ((N >> 8) & 0xFF);   
        byte h6 = (byte) ((N >> 16) & 0xFF);   
        byte h5 = (byte) ((N >> 24) & 0xFF);   
        byte h4 = (byte) ((N >> 32) & 0xFF);   
        byte h3 = (byte) ((N >> 40) & 0xFF);   
        byte h2 = (byte) ((N >> 48) & 0xFF);   
        byte h1 = (byte) (N >> 56);   
        newbyte[l++] = h1;   
        newbyte[l++] = h2;   
        newbyte[l++] = h3;   
        newbyte[l++] = h4;   
        newbyte[l++] = h5;   
        newbyte[l++] = h6;   
        newbyte[l++] = h7;   
        newbyte[l++] = h8;   
        return newbyte;   
    }   
    private int f1(int x, int y, int z) {   
        return (x & y) | (~x & z);   
    }   
    private int f2(int x, int y, int z) {   
        return x ^ y ^ z;   
    }   
    private int f3(int x, int y, int z) {   
        return (x & y) | (x & z) | (y & z);   
    }   
    private int f4(int x, int y) {   
        return (x << y) | x >>> (32 - y);   
    }   
    // 单元摘要计算函数   
    private void encrypt() {   
        for (int i = 16; i <= 79; i++) {   
            tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^   
                    tmpData[i - 16], 1);   
        }   
        int[] tmpabcde = new int[5];   
        for (int i1 = 0; i1 < tmpabcde.length; i1++) {   
            tmpabcde[i1] = digestInt[i1];   
        }   
        for (int j = 0; j <= 19; j++) {   
            int tmp = f4(tmpabcde[0], 5) +   
                f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +   
                tmpData[j] + 0x5a827999;   
            tmpabcde[4] = tmpabcde[3];   
            tmpabcde[3] = tmpabcde[2];   
            tmpabcde[2] = f4(tmpabcde[1], 30);   
            tmpabcde[1] = tmpabcde[0];   
            tmpabcde[0] = tmp;   
        }   
        for (int k = 20; k <= 39; k++) {   
            int tmp = f4(tmpabcde[0], 5) +   
                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +   
                tmpData[k] + 0x6ed9eba1;   
            tmpabcde[4] = tmpabcde[3];   
            tmpabcde[3] = tmpabcde[2];   
            tmpabcde[2] = f4(tmpabcde[1], 30);   
            tmpabcde[1] = tmpabcde[0];   
            tmpabcde[0] = tmp;   
        }   
        for (int l = 40; l <= 59; l++) {   
            int tmp = f4(tmpabcde[0], 5) +   
                f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +   
                tmpData[l] + 0x8f1bbcdc;   
            tmpabcde[4] = tmpabcde[3];   
            tmpabcde[3] = tmpabcde[2];   
            tmpabcde[2] = f4(tmpabcde[1], 30);   
            tmpabcde[1] = tmpabcde[0];   
            tmpabcde[0] = tmp;   
        }   
        for (int m = 60; m <= 79; m++) {   
            int tmp = f4(tmpabcde[0], 5) +   
                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +   
                tmpData[m] + 0xca62c1d6;   
            tmpabcde[4] = tmpabcde[3];   
            tmpabcde[3] = tmpabcde[2];   
            tmpabcde[2] = f4(tmpabcde[1], 30);   
            tmpabcde[1] = tmpabcde[0];   
            tmpabcde[0] = tmp;   
        }   
        for (int i2 = 0; i2 < tmpabcde.length; i2++) {   
            digestInt[i2] = digestInt[i2] + tmpabcde[i2];   
        }   
        for (int n = 0; n < tmpData.length; n++) {   
            tmpData
= 0;   
        }   
    }   
    // 4字节数组转换为整数   
    private int byteArrayToInt(byte[] bytedata, int i) {   
        return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) |   
        ((bytedata[i + 2] & 0xff) << 8) | (bytedata[i + 3] & 0xff);   
    }   
    // 整数转换为4字节数组   
    private void intToByteArray(int intValue, byte[] byteData, int i) {   
        byteData[i] = (byte) (intValue >>> 24);   
        byteData[i + 1] = (byte) (intValue >>> 16);   
        byteData[i + 2] = (byte) (intValue >>> 8);   
        byteData[i + 3] = (byte) intValue;   
    }   
    // 将字节转换为十六进制字符串   
    private static String byteToHexString(byte ib) {   
        char[] Digit = {   
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',   
                'D', 'E', 'F'   
            };   
        char[] ob = new char[2];   
        ob[0] = Digit[(ib >>> 4) & 0X0F];   
        ob[1] = Digit[ib & 0X0F];   
        String s = new String(ob);   
        return s;   
    }   
    // 将字节数组转换为十六进制字符串   
    private static String byteArrayToHexString(byte[] bytearray) {   
        String strDigest = "";   
        for (int i = 0; i < bytearray.length; i++) {   
            strDigest += byteToHexString(bytearray[i]);   
        }   
        return strDigest;   
    }   
    // 计算sha-1摘要,返回相应的字节数组   
    public byte[] getDigestOfBytes(byte[] byteData) {   
        process_input_bytes(byteData);   
        byte[] digest = new byte[20];   
        for (int i = 0; i < digestInt.length; i++) {   
            intToByteArray(digestInt[i], digest, i * 4);   
        }   
        return digest;   
    }   
    // 计算sha-1摘要,返回相应的十六进制字符串   
    public String getDigestOfString(byte[] byteData) {   
        return byteArrayToHexString(getDigestOfBytes(byteData));   
    }   
    
    /**/
    public static void main(String[] args) {   
        String data = "123456";   
        System.out.println(data);   
        String digest = new SHA1().getDigestOfString(data.getBytes());   
        System.out.println(digest);  
         
       // System.out.println( ToMD5.convertSHA1(data).toUpperCase());  
    }   
}


SharedController.groovy 这个就是请求分享的入口controller

package business

import grails.converters.JSON

import com.weixin.config.WeixinpayConfig
import com.weixin.sign.WeixinsignUtils
import com.weixin.util.MapUtil
import com.weixinpay.util.WinxinUtils

class TopicController {

def grailsApplication
def show(){
def result = [:]
//分享出去的数据
result.data = [data:data]

//获取access_token 路径
def access_token_path = "${WeixinpayConfig.ACCESS_TOKEN }?appid=${WeixinpayConfig.SHAREDAPPID}&grant_type=client_credential&secret=${WeixinpayConfig.SHAREDSECRET }"
def token_data = WinxinUtils.getWeixinRequest(access_token_path)

//print "token_data=$token_data"

//获取jsapi_ticket 路径
def ticket_path = "${WeixinpayConfig.TICKENT }?access_token=${token_data.access_token }&type=jsapi"
def ticket_data = WinxinUtils.getWeixinRequest(ticket_path)
//print "ticket_data=$ticket_data"
//
def requestMap = [:]

//有效的jsapi_ticket
requestMap.jsapi_ticket = ticket_data.ticket

//随机字符串
requestMap.nonceStr = WeixinsignUtils.createStr()

//timestamp生成签名的时间戳
requestMap.timestamp = new Date().time + ""

//当前网页的url
requestMap.url = grailsApplication.config.topic.shareUrl+"/topic/show?tid="+params.tid

//请求map进行排序
Map<String, String> map = MapUtil.order(requestMap)

//生成签名
requestMap.signature = WeixinsignUtils.createSHA1_Sign(map).toLowerCase()

//必填,公众号的唯一标识
requestMap.appId=WeixinpayConfig.SHAREDAPPID

//print requestMap

result.weixin = requestMap
//render result as JSON
[result: result]
}


下面的js代码是在分享页面增加的微信

<script>
  /*
   * 注意:
   * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
   * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
   * 3. 常见问题及完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
   * * 开发中遇到问题详见文档“附录5-常见错误及解决办法”解决,如仍未能解决可通过以下渠道反馈:
   * 邮箱地址:weixin-open@qq.com
   * 邮件主题:【微信JS-SDK反馈】具体问题
   * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
   */
  wx.config({
      debug: false,
      appId: '${result?.weixin?.appId}',
      timestamp: ${result?.weixin?.timestamp},
      nonceStr: '${result?.weixin?.nonceStr}',
      signature: '${result?.weixin?.signature}',
      jsApiList: [
        'checkJsApi',
        'onMenuShareTimeline',
        'onMenuShareAppMessage',
        'onMenuShareQQ',
        'onMenuShareWeibo',
        'onMenuShareQZone'
      ]
  });
</script>


shared.js 分享出去时配置相关自定义信息

/*
 * 注意:
 * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
 * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
 * 3. 完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
 *
 * 如有问题请通过以下渠道反馈:
 * 邮箱地址:weixin-open@qq.com
 * 邮件主题:【微信JS-SDK反馈】具体问题
 * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
 */

function divHide(){
$(".yes_box").hide();
}

function sharedSuccess(){
$(".yes_box").show();
window.setTimeout("divHide()",1000);//使用字符串执行方法 
}

//sharedSuccess();

wx.ready(function() {

// 2. 分享接口
// 2.1 自定义分享内容及分享结果接口
wx.onMenuShareAppMessage({
title : $("#title").val(), // 分享标题
desc : $("#desc").val(), // 分享描述
link : $("#link").val(), // 分享链接
imgUrl : $("#imgUrl").val(), // 分享图标
// type: '', // 分享类型,music、video或link,不填默认为link
// dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
trigger : function(res) {
//alert('用户点击分享给朋友');
},
complete : function(res) {
//alert(JSON.stringify(res));
},
success : function(res) {
sharedSuccess();
//alert('已分享');
},
cancel : function(res) {
//alert('已取消');
},
fail : function(res) {
alert(JSON.stringify(res));
}
});

// 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
   wx.onMenuShareTimeline({
     title: $("#title").val(),
       link: $("#link").val(),
       imgUrl: $("#imgUrl").val(),
     trigger: function (res) {
       // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
       //alert('用户点击分享到朋友圈');
     },
     success: function (res) {
   	  sharedSuccess();
       //alert('已分享');
     },
     cancel: function (res) {
       //alert('已取消');
     },
     fail: function (res) {
       alert(JSON.stringify(res));
     }
   });

 // 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口
   wx.onMenuShareQQ({
     title: $("#title").val(),
       desc: $("#desc").val(),
       link: $("#link").val(),
       imgUrl: $("#imgUrl").val(),
     trigger: function (res) {
       //alert('用户点击分享到QQ');
     },
     complete: function (res) {
       //alert(JSON.stringify(res));
     },
     success: function (res) {
   	  sharedSuccess();
       //alert('已分享');
     },
     cancel: function (res) {
       //alert('已取消');
     },
     fail: function (res) {
       alert(JSON.stringify(res));
     }
   });
 
 // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口
   wx.onMenuShareWeibo({
     title: $("#title").val(),
       desc: $("#desc").val(),
       link: $("#link").val(),
       imgUrl: $("#imgUrl").val(),
     trigger: function (res) {
       //alert('用户点击分享到微博');
     },
     complete: function (res) {
       //alert(JSON.stringify(res));
     },
     success: function (res) {
   	  sharedSuccess();
       //alert('已分享');
     },
     cancel: function (res) {
       //alert('已取消');
     },
     fail: function (res) {
       alert(JSON.stringify(res));
     }
   });

 // 2.5 监听“分享到QZone”按钮点击、自定义分享内容及分享接口
   wx.onMenuShareQZone({
     title: $("#title").val(),
       desc: $("#desc").val(),
       link: $("#link").val(),
       imgUrl: $("#imgUrl").val(),
     trigger: function (res) {
       //alert('用户点击分享到QZone');
     },
     complete: function (res) {
       //alert(JSON.stringify(res));
     },
     success: function (res) {
   	  sharedSuccess();
       //alert('已分享');
     },
     cancel: function (res) {
       //alert('已取消');
     },
     fail: function (res) {
       alert(JSON.stringify(res));
     }
   });

});

wx.error(function(res) {
// alert("验证失败。");
alert(res.errMsg);
});


这样就完成了,微信页面的分享了,其中包含了后台生成的分享配置信息,和页面的自定义的信息。

分享成功的效果图:



希望这个能够帮助到你。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐