2016-12-23 16:53:57 u013248535 阅读数 29153
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27832 人正在学习 去看看 秦子恒

发送消息,是指用户公众号向用户发送相应形式的消息。根据微信开发文档,由以下四种形式:被动回复,群发接口,客服消息接口以及模板消息接口。本文将基于Java语言以及个人微信测试号,说明被动回复、客服消息接口以及模板消息接口的使用实现,群发接口并未涉及。
1. 被动回复
被动回复只能应用于在接收到用户的互动数据之后,才能向用户发送消息。这一部分较为简单,正式进行微信开发的第一步就是,在公众号中基本配置->服务器配置中设置URL(服务器地址)时,这时该URL链接指定的地址就是对应着Java Web下的一个Servlet,配置好对应的Token及相关参数之后,则微信服务器将会将所有的用户与公众号的互动信息都转发到该Servlet,然后开发者根据接收到的用户互动数据,再进行处理。所谓的被动回复,就是在该Servlet中判断接收到你指定的消息时(例如某个字眼),则直接将想要回复的消息打包成官方指定的XML数据格式,写回到输出流中即可。在这里不过过多解释,如下示例代码:

response.getWriter().write( MessageUtil.MessageToXML(new TextMessage.Builder(fromUserName,toUserName,new Date().getTime(),"最新资讯请查看下方微信菜单栏,谢谢您的关注").build()));

2.客服消息接口
客服消息接口,应用于公众号主动向特定用户(必须满足该用户在48小时内与公众号有交互)发送特定格式的消息,应用场景例如:用户在微页面上完成了抽奖,而这时候公众号主动向用户推送中奖信息。所回复的不同消息的格式,参见开发者文档,下面以回复文本消息作为示例,需要注意的是推送的消息data必须满足json格式,请求类型为post。返回的json数据中,若errorcode为0,则代表推送成功。

 //推送中奖消息
        String data = "{"+
                "\"touser\":\""+openid+"\","+
                "\"msgtype\":\"text\","+
                "\"text\":"+
                "{"+
                "\"content\":\""+content+"\""+
                "}"+
                "}";
        System.out.println(data);
        String reMsg0 = UrlReqUtil.post("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+access_token,data);
        JSONObject jsonObject = JSONObject.fromObject(reMsg0);
        if(0 != (Integer) jsonObject.get("errcode")) throw new RuntimeException("通知用户失败");

3.模板消息接口
模板消息接口的使用场景大体与客服消息接口一致,只是不需要证明对象用户“在线”,即48小时内与当前公众号有交互记录,因而应用范围更为广泛。在具有权限的服务号中使用该接口时,需要向系统申请对应模板,并得到模板号,作为调用凭据。在测试号环境下,则需要自定义模板。例如:
这里写图片描述
其中模板内容需要严格遵循指定的格式,即在需要调用才填入的变量值的定义方式为:{{xxxx.DATA}},其中“xxxx”为调用时对应的字段名。
以下是调用代码:jsonData数据部分遵循json数据格式。
其中touser:为用户在该公众号下的openid
template_id:为模板id
对于每个字段,包含两个值,一是value,即填入模板的具体值;二是color,即对应的字体颜色。
请求方式为post,判断是否成功同样是依据errcode字段,为0则成功。

        //推送模板消息
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String jsonData = "{" +
                "\"touser\":\""+openid+"\"," +
                "\"template_id\":\"maD2W1yaTvkXmh1dRjXEsMHUc9dDP8Xh1eANP***ig\"," +
                "\"topcolor\":\"#FF0000\"," +
                "\"data\":{" +
                "\"title\":{\"value\":\"恭喜您中奖啦\",\"color\":\"#173177\"}," +
                "\"nickname\":{\"value\":\""+nickname+"\",\"color\":\"#173177\"}," +
                "\"prizeLevel\":{\"value\":\""+rewardLevel+"\",\"color\":\"#173177\"}," +
                "\"prizeContent\":{\"value\":\""+ ConfigParamUtil.PRIZE_CONTENT.split(",")[rewardLevel]+"\",\"color\":\"#173177\"}," +
                "\"time\":{\"value\":\""+dateFormat.format(new Date())+"\",\"color\":\"#173177\"}," +
                "\"bonus\":{\"value\":\"10积分\",\"color\":\"#173177\"}}}";
        String reMsg1 = UrlReqUtil.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+access_token,jsonData);
        JSONObject jsonObject = JSONObject.fromObject(reMsg1);
        if(0 != (Integer) jsonObject.get("errcode")) throw new RuntimeException("通知用户失败");
2015-12-10 20:24:26 qq_16558621 阅读数 1131
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27832 人正在学习 去看看 秦子恒

这几天做微信开发,深一脚浅一脚,总算摸出来一些门道和一些小小的感悟。

今天给大家分享一个在微信平台php发送HTTP GET请求的方法:

public function get_request($url)
		{
		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $url);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		$data = curl_exec($curl);
		if (curl_errno($curl)) {return 'ERROR '.curl_error($curl);}
		curl_close($curl);
		return $data;
	   }

2016-07-15 10:34:41 u013292160 阅读数 6381
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27832 人正在学习 去看看 秦子恒

微信分享功能开发

用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。

一.服务器端程序

package com.wiimedia.controller;


import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.google.gson.Gson;
import com.wiimedia.model.Ticket;
import com.wiimedia.service.ArticleSolrService;
import com.wiimedia.service.TicketRepository;
import com.wiimedia.service.TicketRepositorySolr;
import com.wiimedia.utils.GetRandomStr;
import com.wiimedia.utils.SignatureBean;
import com.wiimedia.utils.weixin.WeixinUtil;
/**
 * 
 * 
 *<p>Project:mryl_phone_v2</p> 
 * 
 *<p>Package:com.wiimedia.controller</p> 
 * 
 *<p>Description:微信分享Controller</p>
 *
 *<p>Company:Wiimedia</p>
 *
 *@Athor:SongJia
 *
 *@Date:2016-7-15 上午09:34:10
 *
 */

@Controller
@RequestMapping("/WeixinshareController/Api/Inteface")
public class WeixinshareController {
    @Autowired
    private TicketRepositorySolr ticketRepositorySolr;

    @RequestMapping("/getSignature")
    public String getSignature( HttpServletRequest request,
            HttpServletResponse response) throws IOException, ParseException{
        //获取签名页面链接
        String url = request.getParameter("url");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //从数据库中获取标签,并检查标签是否过期
        Ticket oldticket = ticketRepositorySolr.getTicketById("20160114wiimediamrylsong1152");
        if(oldticket==null){//第一次访问,标签不存在。
            executeTicket(response,"1",url,format);
            return null;
        }else{//标签存在,判断标签是否超时
            String oldAcquiretime = oldticket.getAcquiretime();
            long difference=format.parse(format.format(new Date())).getTime()-format.parse(oldAcquiretime).getTime();
            if(difference>7100000){//标签超时,重新到微信服务器请求标签超时时间为7200秒(7200000毫秒)
                executeTicket(response,"2",url,format);
                return null;    
            }else{//标签未超时
                /** 
                 * 注意事项                                           
                 * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
                 * 2.签名用的url必须是调用JS接口页面的完整URL。                      
                 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。    
                 * 
                 ****根据第1点要求          signature  配置的时候很容易出错,需要把生成  Ticket的  noncestr和 timestamp传给客户端***
                 */
                String signature = signature(oldticket.getTicket(),oldticket.getTimestamp(),oldticket.getNoncestr(),url);
                SignatureBean signatureBean = new SignatureBean();
                signatureBean.setNoncestr(oldticket.getNoncestr());
                signatureBean.setSignature(signature);
                signatureBean.setTimestamp(oldticket.getTimestamp());
                signatureBean.setUrl(url);
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().print(new Gson().toJson(signatureBean));
                return null;    
            } 
        }


    }
    /**
     * 
     *<p>Project:mryl_phone_v2</p> 
     * 
     *<p>:mryl_phone_v2</p> 
     * 
     *<p>Description:更新和获取ticket的方法,因为用的solr所以更新和新增是一样的ID无则添加,有责更新</p>
     *
     *<p>Company:Wiimedia</p>
     *
     *@Athor:SongJia
     *
     *@Date:2016-7-15 上午09:45:00 
     *
     */
    public void executeTicket(HttpServletResponse response,String flag,String url,SimpleDateFormat format) throws IOException{

        //获取签名随即字符串
        GetRandomStr randomStr = new GetRandomStr();
        String noncestr = randomStr.getRandomString(15);
        //获取签名时间戳
        String timestamp = Long.toString(System.currentTimeMillis());
        //请求accessToken
        String accessTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=您的APPID&secret=您的密匙";
        String tokenJson = WeixinUtil.httpRequest(accessTokenUrl, "GET", null);
        Gson gson = new Gson();
        ShareAccess_Token token = gson.fromJson(tokenJson, ShareAccess_Token.class);
        String to= token.getAccess_token();
        //获取标签
        String urlTicket ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+to+"&type=jsapi";
        String ticketJson = WeixinUtil.httpRequest(urlTicket, "GET", null);
        Ticket ticket = gson.fromJson(ticketJson, Ticket.class);
        String t = ticket.getTicket();
        //String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        //我的Ticket ID是写死的
        String acquiretime = format.format(new Date());
        ticket.setTid("20160114wiimediamrylsong1152");
        ticket.setAcquiretime(acquiretime);
        ticket.setTimestamp(timestamp);
        ticket.setNoncestr(noncestr);
        //因为用的SOLR所以更新和添加的方法是一样的,可以根据自己具体需求进行修改,本文不再贴出代码.
        if(flag.equals("2")){
            ticketRepositorySolr.addTicketToSolr(ticket);   
        }else{
            ticketRepositorySolr.addTicketToSolr(ticket);
        }
        /** 
         * 注意事项                                           
         * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
         * 2.签名用的url必须是调用JS接口页面的完整URL。                      
         * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。    
         * 
         *根据第1点要求          signature  配置的时候很容易出错,需要把生成  Ticket的  noncestr和 timestamp传给客户端*
         */
        String signature = signature(t,timestamp,noncestr,url);
        SignatureBean signatureBean = new SignatureBean();
        signatureBean.setNoncestr(noncestr);
        signatureBean.setSignature(signature);
        signatureBean.setTimestamp(timestamp);
        signatureBean.setUrl(url);
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print(new Gson().toJson(signatureBean));
    }

    /**
     * 
     *<p>Project:mryl_phone_v2</p> 
     * 
     *<p>:mryl_phone_v2</p> 
     * 
     *<p>Description:根据标签,时间戳,密匙,URL进行签名</p>
     *
     *<p>Company:Wiimedia</p>
     *
     *@Athor:SongJia
     *
     *@Date:2016-7-15 上午09:37:13 
     *
     */
    private String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {
        jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;
        timestamp = "timestamp=" + timestamp;
        noncestr = "noncestr=" + noncestr;
        url = "url=" + url;
        String[] arr = new String[] { jsapi_ticket, timestamp, noncestr, url };
        // 将token、timestamp、nonce,url参数进行字典序排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
            if (i != arr.length - 1) {
                content.append("&");
            }
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        return tmpStr;
    }
    /**
     * 将字节转换为十六进制字符串
     * 
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {

        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }
    /**
     * 将字节数组转换为十六进制字符串
     * 
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }



    class ShareAccess_Token{
        private  String access_token;
        private  String expires_in;
        public String getAccess_token() {
            return access_token;
        }
        public void setAccess_token(String accessToken) {
            access_token = accessToken;
        }
        public String getExpires_in() {
            return expires_in;
        }
        public void setExpires_in(String expiresIn) {
            expires_in = expiresIn;
        }

    }
}


二.客户端代码.

<script type="text/javascript">
            var url = window.location.href;
            var articleId = "";
            var shareTitle="明日医疗资讯";
            var shareImgUrl="";
            var userinfo = localStorage.getItem("_userinfo");
            var timestamp;
            var noncestr;
            var signature;
            //获取签名
             $.ajax({
                     type: "GET",
                     url: "WeixinshareController/Api/Inteface/getSignature",
                     //data:{timestamp:timestamp,noncestr:noncestr,url:url},
                     data:{url:url},
                     success: function(data){
                                var objData=JSON.parse(data); 
                                timestamp=objData.timestamp;    
                                noncestr=objData.noncestr;  
                                signature=objData.signature;
                                 console.log(objData);
                                 wxShare();
                     }
                 });
            function wxShare(){
            wx.config({
                debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: '您的appid', // 和获取Ticke的必须一样------必填,公众号的唯一标识
                timestamp:timestamp, // 必填,生成签名的时间戳
                nonceStr: noncestr, // 必填,生成签名的随机串
                signature: signature,// 必填,签名,见附录1
                jsApiList: [
                'onMenuShareAppMessage'
                ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
            });
            }
            wx.ready(function(){
                 //config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,
                 //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关
                 //接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

                //----------“分享给朋友”
                wx.onMenuShareAppMessage({
                    title: "明日医疗资讯", // 分享标题
                    desc: shareTitle, // 分享描述
                    link: url, // 分享链接
                    imgUrl: shareImgUrl, // 分享图标
                    type: '', // 分享类型,music、video或link,不填默认为link
                    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                    success: function () { 
                        // 用户确认分享后执行的回调函数、
                    },
                    cancel: function () { 
                        // 用户取消分享后执行的回调函数
                    }
                });
                //------------"分享到朋友圈"
                wx.onMenuShareTimeline({
                    title: '明日医疗资讯', // 分享标题
                    link: '', // 分享链接
                    imgUrl: shareImgUrl, // 分享图标
                    success: function () { 
                        // 用户确认分享后执行的回调函数
                    },
                    cancel: function () { 
                        // 用户取消分享后执行的回调函数
                    }
                });
                //-------------分享到QQ
                wx.onMenuShareQQ({
                    title: '明日医疗资讯', // 分享标题
                    desc: shareTitle, // 分享描述
                    link: '', // 分享链接
                    imgUrl: shareImgUrl, // 分享图标
                    success: function () { 
                       // 用户确认分享后执行的回调函数
                    },
                    cancel: function () { 
                       // 用户取消分享后执行的回调函数
                    }
                });
                //-------------分享到QQ空间
                wx.onMenuShareQZone({
                    title: '明日医疗资讯', // 分享标题
                    desc: shareTitle, // 分享描述
                    link: '', // 分享链接
                    imgUrl: shareImgUrl, // 分享图标
                    success: function () { 
                       // 用户确认分享后执行的回调函数
                    },
                    cancel: function () { 
                        // 用户取消分享后执行的回调函数
                    }
                });

            });

三.服务器需要的工具类和Model

① Ticket

package com.wiimedia.model;


public class Ticket{
    private String tid;
    private String ticket;   
    private String errcode;
    private String errmsg; 
    private String expires_in;
    private String acquiretime;
    private String noncestr;
    private String timestamp;

    public Ticket(String tid, String ticket, String errcode, String errmsg,
            String expiresIn, String acquiretime, String noncestr,
            String timestamp) {
        super();
        this.tid = tid;
        this.ticket = ticket;
        this.errcode = errcode;
        this.errmsg = errmsg;
        expires_in = expiresIn;
        this.acquiretime = acquiretime;
        this.noncestr = noncestr;
        this.timestamp = timestamp;
    }
    public String getTid() {
        return tid;
    }
    public void setTid(String tid) {
        this.tid = tid;
    }
    public String getTicket() {
        return ticket;
    }
    public void setTicket(String ticket) {
        this.ticket = ticket;
    }
    public String getErrcode() {
        return errcode;
    }
    public void setErrcode(String errcode) {
        this.errcode = errcode;
    }
    public String getErrmsg() {
        return errmsg;
    }
    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }
    public String getExpires_in() {
        return expires_in;
    }
    public void setExpires_in(String expiresIn) {
        expires_in = expiresIn;
    }
    public String getAcquiretime() {
        return acquiretime;
    }
    public void setAcquiretime(String acquiretime) {
        this.acquiretime = acquiretime;
    }
    public String getNoncestr() {
        return noncestr;
    }
    public void setNoncestr(String noncestr) {
        this.noncestr = noncestr;
    }
    public String getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }



}

② 添加到数据库的业务根据自己需要进行实现.
③ GetRandomStr

package com.wiimedia.utils;

import java.util.Random;

public class GetRandomStr {
    /**
     * 
     *<p>Project:mryl_phone_v2</p> 
     * 
     *<p>:mryl_phone_v2</p> 
     * 
     *<p>Description:生成随即字符串 </p>
     *
     *<p>Company:Wiimedia</p>
     *
     *@Athor:SongJia
     *
     *@Date:2016-7-14 上午11:14:46 
     *
     */
    public  String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
        Random random = new Random();   
        StringBuffer sb = new StringBuffer();   
        for (int i = 0; i < length; i++) {   
            int number = random.nextInt(base.length());   
            sb.append(base.charAt(number));   
        }   
        return sb.toString();   
     }
}

④ SignatureBean

package com.wiimedia.utils;

public class SignatureBean {
    private String noncestr;
    private String url;
    private String timestamp;
    private String signature;
    public String getNoncestr() {
        return noncestr;
    }
    public void setNoncestr(String noncestr) {
        this.noncestr = noncestr;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }
    public String getSignature() {
        return signature;
    }
    public void setSignature(String signature) {
        this.signature = signature;
    }

}

⑤ WeixinUtil

package com.wiimedia.utils.weixin;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

/**
     * 
     *<p>Project:mryl_phone_v2</p> 
     * 
     *<p>:mryl_phone_v2</p> 
     * 
     *<p>Description:公众平台接口工具类</p>
     *
     *<p>Company:Wiimedia</p>
     *
     *@Athor:SongJia
     *
     *@Date:2016-7-15 上午09:37:13 
     *
     */
public class WeixinUtil {

    /** 
     * 发起https请求并获取结果 
     *  
     * @param requestUrl 请求地址 
     * @param requestMethod 请求方式(GET、POST) 
     * @param outputStr 提交的数据 
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
     */  
    public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {  

        StringBuffer buffer = new StringBuffer();  
        try {  
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 从上述SSLContext对象中得到SSLSocketFactory对象  
            SSLSocketFactory ssf = sslContext.getSocketFactory();  

            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  

            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 设置请求方式(GET/POST)  
            httpUrlConn.setRequestMethod(requestMethod);  

            if ("GET".equalsIgnoreCase(requestMethod))  
                httpUrlConn.connect();  

            // 当有数据需要提交时  
            if (null != outputStr) {  
                OutputStream outputStream = httpUrlConn.getOutputStream();  
                // 注意编码格式,防止中文乱码  
                outputStream.write(outputStr.getBytes("UTF-8"));  
                outputStream.close();  
            }  

            // 将返回的输入流转换成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 释放资源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  
            return buffer.toString();  
        } catch (ConnectException ce) {  
            ce.printStackTrace(); 
        } catch (Exception e) {  
            e.printStackTrace();
        }  
        return "";  
    }
}

四 至此,分享功能已经开发完成,但是,在生成signature的时候会遇到很多问题,这里提供一些wx.config失败的排错方法.

① 确认自己的生成的signature是否正确
在微信提供的http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign进行校验

② wx.config中使用的noncestr, timestamp与用以签名中的对应noncestr, timestamp是否一致一致…如上面(一.服务器代码)
(有可能因为JS页面加载顺序问题,服务器生成的signature,noncestr,timestamp在wx.config中没有获取到)。

③ 确认url是页面完整的url,包括GET参数部分
需要去掉#后面的部分

④ config 中的 appid 与用来获取 jsapi_ticket 的 appid 是否一致

⑤ 报错{errmsg:config:ok}是debug的正常返回把调试模式关掉就OK
wx.config debug: false,



能力有限,希望有问题及时邮箱或留言,谢谢.

Email:358106209@qq.com

2016-01-06 13:16:53 frozleaf 阅读数 1963
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27832 人正在学习 去看看 秦子恒

方式一:

通过手机QQ的发送图片功能,选择微信小视频并发送



方式二 :

通过在手机QQ上转发


2015-08-28 15:42:14 u010773333 阅读数 5612
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27832 人正在学习 去看看 秦子恒

      上几篇文章基本是介绍有手机客户端触发的事件在先,这种有手机微信客户端触发的请求,咱们的服务器被动响应,这种模式我个人理解为被动发送信息。

但是除此之外我们有时间要让用户推送消息,比如向家长每天发送孩子的作业信息。这就要用到模板消息了

对于模板消息首先要添加

进入模板选择行业之后就要等两天才能用模板消息

能用模板消息之后 根据自己的情况,查看模板选择适用于自己的模板 如果没有可以自己定义 只要微信官方审核通过就可以用(我申请的好像说是7-15天,完成审计,但是好像30分钟就给我发通知说申请成功)

后两个都是我自己申请的模板。

给一个我调用模板的方法

 [WebMethod(Description = "测试优学酷能力报告")]
        public string TestEveryOneWeek(string featherOpenid)
        {
            string url = "http://......";
            string first = "亲爱的家长,您孩子能力报告出炉通知\n";
            var keyword1 = string.Format("英语");
            var keyword2 = "单词、语法很棒哦!听力、口语还不错!差一点就当学霸了,继续加油!\n";
            var remark = "点击“详情”查看";
            //得到所需要的模板数据
            var data = MessageTemplate.NoticeYouxuekuEvery(first, keyword1, keyword2, remark);
            //模板标号
            string templateid = "XakPchhUx1InpJX0pxDqmDKKQz6-ocrPTn682sV5VSw";
            featherOpenid = "............";  //我个人微信的openid
            bool sendsucess = SendTemplateMessageService.SendTemplateMessage(templateid, featherOpenid, url, data);
            if (sendsucess)
            {
                return "成功";
            }
            else
            {
                return "失败";
            }
        }

要给所谓的消息,制成固定格式如下 格式并添加颜色

      public static object NoticeYouxuekuEvery(string first, string keyword1, string keyword2,string remark)
        {
            var data = new
            {
                first = new TemplateDataItem(first, "#000000"),
                keyword1 = new TemplateDataItem(keyword1, "#000000"),
                keyword2 = new TemplateDataItem(keyword2, "#000000"),
                remark = new TemplateDataItem(remark, "#000000")
            };
            return data;
        }

里面的first,keyword1,keyword2,remark都是模板里面的参数。

调用发送消息方法如下

public static bool SendTemplateMessage(string templateId, string openId, string url, object data)
        {
            WeiXinService weixin = new WeiXinService();
            var accessToken = weixin.GetAccessToken();
            var getInfoUrl = string.Format(GetBaseUserInfoApi, accessToken, openId);
            WeiXinUserInfo userInfo = HttpClientHelper.GetResponse<WeiXinUserInfo>(getInfoUrl);
            string resultes=null;
            //判断用户是否关注公众号
            switch (userInfo.Subscribe)
            {
                case 0:
                    break;
                default:
                    var sendUrl = string.Format(SendMessageApi, accessToken);
                    var msg = new TemplateMessage
                    {
                        template_id = templateId,
                        touser = openId,
                        url = url,
                        data = data
                    };
                   //序列化实体为json
                   string json = JsonConvert.SerializeObject(msg, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
                   //调用消息发送接口
                   var result = HttpClientHelper.PostResponse<TemplateMessageResult>(string.Format(sendUrl, accessToken), json);
                   resultes = result.errmsg;
                    break;
            }
            if (resultes=="ok")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

如果知道了用户的openid,这样就可以使用模板消息,主动向手机客户端发送消息了。



微信开发

阅读数 913

微信开发之JSSDK调用

阅读数 20068

没有更多推荐了,返回首页