微信小程序---订阅消息

在做退款的时候需要给用户发一条消息,告诉他已经在退款了,一开始是想用模板消息来做的,但是看微信开发文档说模板消息要下线,推荐用订阅信息。这边记录一些步骤。

1,登录微信公众平台获取订阅信息的模板id

登录微信公众平台,点击订阅信息,我的模板,添加我的模板,微信会提供一些常用的模板,可以选择,也可以自己申请,通过就可以使用了,把模板id复制下来保存一下。代码里面需要用到。微信小程序---订阅消息_第1张图片

          

2,获取下发权限

看微信开发文档用的是这个接口: wx.requestSubscribeMessage ,详细信息可以自己查看微信开发文档

https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html

下面简单的看一下代码的实现:

index.wxml 代码

  
  

index.js 代码 ,简单介绍一下,tmplIds 参数是在微信公众平台申请的订阅信息模板id,wx.requestSubscribeMessage 方法是判断用户是否授权发订阅模板的信息,同意了就发http请求,请求后台的接口,然后可能是为了安全考虑这个请求的地址必须是https 请求,这个问题可以在微信开发工具里面设置一下,设置他不要验证域名;

步骤是,打开微信开发工具--设置--项目设置 ,这个就可以不要验证域名,真实环境肯定是不推荐这么做的,但是这样调试方便。

微信小程序---订阅消息_第2张图片

 

  sendMsg: function (e) {
    wx.requestSubscribeMessage({
      tmplIds: ["0a-wSlLk6TGc9f8qsar9XtF65qtDh5XiSIhmSGSDrn0"],
      success: function (res) {
        //成功
        console.log(res)
        if (res['0a-wSlLk6TGc9f8qsar9XtF65qtDh5XiSIhmSGSDrn0'] === 'accept'){
          console.log("用户同意授权了")
          wx.login({
            success(res) {
              console.log(res.code)
             
              wx.request({
                url: 'http://3s.dkys.org:25451/farina-api/subscription/subscription',
                method: 'POST',
                data: { 
                  code : res.code,
                  price : 1001,
                  url : "index.html",
                
                },
                header: {
                  'content-type': 'application/x-www-form-urlencoded', // POST请求
                  'token': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE1NzU2MDM5NTY5MjcsInVpZCI6IjE4MTI3MDg0ODIiLCJzcmMiOiJBUFAiLCJpYXQiOjE1NzU1OTYxODA5Mjd9.fW_U_MQtovt7d5Nzl7HR1i9pe_y62oTO7gmVU4FrgO4",
                },
                success(res) {
                  console.log(res)
                }
              })
              
            }
          })


        
        }else{
          console.log("用户拒绝了======================")
        }

     
      },
      fail(err) {
        //失败
        console.log("这个是失败的哦=========");
        console.error(err);
      }
    })
  }

price,是退款金额,URL,是订阅信息返回用户点击的回跳页面,code,就不要介绍了吧,请求头,content-type ,常规请求头,token,我们项目的key,

3.调用接口下发订阅消息

拉下发订阅信息接口的代码我是写在了后端,

工具包类

package io.farina.MessageSubscription;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


public class HttpUtil {

private static final CloseableHttpClient httpclient = HttpClients.createDefault();

/**
 * 发送HttpGet请求
 * @param url
 * @return
 */
public static String sendGet(String url) {

    HttpGet httpget = new HttpGet(url);
    CloseableHttpResponse response = null;
    try {
        response = httpclient.execute(httpget);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    String result = null;
    try {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            result = EntityUtils.toString(entity);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return result;
}

/**
 * 发送HttpPost请求,参数为map
 * @param url
 * @param map
 * @return
 */
public static String sendPost(String url, Map map) {
    List formparams = new ArrayList();
    for (Map.Entry entry : map.entrySet()) {
        formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
    }
    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
    HttpPost httppost = new HttpPost(url);
    httppost.setEntity(entity);
    CloseableHttpResponse response = null;
    try {
        response = httpclient.execute(httppost);
    } catch (IOException e) {
        e.printStackTrace();
    }
    HttpEntity entity1 = response.getEntity();
    String result = null;
    try {
        result = EntityUtils.toString(entity1);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

/**
 * 发送不带参数的HttpPost请求
 * @param url
 * @return
 */
public static String sendPost(String url) {
    HttpPost httppost = new HttpPost(url);
    CloseableHttpResponse response = null;
    try {
        response = httpclient.execute(httppost);
    } catch (IOException e) {
        e.printStackTrace();
    }
    HttpEntity entity = response.getEntity();
    String result = null;
    try {
        result = EntityUtils.toString(entity);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}
/**
 * 向指定 URL 发送POST方法的请求
 * 
 * @param url
 *            发送请求的 URL
 * @param string
 *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
 * @return 所代表远程资源的响应结果
 */
public static String sendPost(String url, String string) {
    PrintWriter out = null;
    BufferedReader in = null;
    String result = "";
    try {
        URL realUrl = new URL(url);
        // 打开和URL之间的连接
        URLConnection conn = realUrl.openConnection();
        // 设置通用的请求属性
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        // 发送POST请求必须设置如下两行
        conn.setDoOutput(true);
        conn.setDoInput(true);
        // 获取URLConnection对象对应的输出流
        out = new PrintWriter(conn.getOutputStream());
        // 发送请求参数
        out.print(string);
        // flush输出流的缓冲
        out.flush();
        // 定义BufferedReader输入流来读取URL的响应
        in = new BufferedReader(
                new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
            result += line;
        }
    } catch (Exception e) {
        System.out.println("发送 POST 请求出现异常!"+e);
        e.printStackTrace();
    }
    //使用finally块来关闭输出流、输入流
    finally{
        try{
            if(out!=null){
                out.close();
            }
            if(in!=null){
                in.close();
            }
        }
        catch(IOException ex){
            ex.printStackTrace();
        }
    }
    return result;
}  



}
package io.farina.MessageSubscription;

public class TemplateParam {
	

		private String key;  
		private String value;  

		public TemplateParam(String key,String value){  
		    this.key=key;  
		    this.value=value;  
		}  
		public String getValue() {  
		    return value;  
		}  
		public void setValue(String value) {  
		    this.value = value;  
		}
		public String getKey() {
			return key;
		}
		public void setKey(String key) {
			this.key = key;
		}  


}
package io.farina.MessageSubscription;

import java.util.List;

public class Template {
	
	private String touser;  
	private String template_id;  
	private String page;
	private List templateParamList;
	public String getTouser() {
		return touser;
	}
	public void setTouser(String touser) {
		this.touser = touser;
	}
	public String getTemplate_id() {
		return template_id;
	}
	public void setTemplate_id(String template_id) {
		this.template_id = template_id;
	}
	public String getPage() {
		return page;
	}
	public void setPage(String page) {
		this.page = page;
	}
	public List getTemplateParamList() {
		return templateParamList;
	}
	public void setTemplateParamList(List templateParamList) {
		this.templateParamList = templateParamList;
	}    
	public String toJSON() {  
	    StringBuffer buffer = new StringBuffer();  
	    buffer.append("{");  
	    buffer.append(String.format("\"touser\":\"%s\"", this.touser)).append(",");  
	    buffer.append(String.format("\"template_id\":\"%s\"", this.template_id)).append(",");  
	    buffer.append(String.format("\"page\":\"%s\"", this.page)).append(","); 
	    buffer.append("\"data\":{");  
	    TemplateParam param = null;  
	    for (int i = 0; i < this.templateParamList.size(); i++) {  
	         param = templateParamList.get(i);  
	        // 判断是否追加逗号  
	        if (i < this.templateParamList.size() - 1){  
	            buffer.append(String.format("\"%s\": {\"value\":\"%s\"},", param.getKey(), param.getValue()));  
	        }else{  
	            buffer.append(String.format("\"%s\": {\"value\":\"%s\"}", param.getKey(), param.getValue()));  
	        }  
	    }  
	    buffer.append("}");  
	    buffer.append("}");  
	    return buffer.toString();  
	    } 

	
	
	

}
package io.farina.MessageSubscription;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;
/**
 * 实现了 MyX509TrustManager 接口
 * @author admin
 *
 */
public class MyX509TrustManager implements X509TrustManager  {
	

	 
	// 检查客户端证书
	public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
	}
 
	// 检查服务器端证书
	public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
	}
 
	// 返回受信任的X509证书数组
	public X509Certificate[] getAcceptedIssuers() {
		return null;
	}



}

下发订阅信息接口

package io.farina.MessageSubscription;

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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;


/****
 * 退款提示
 * @author admin
 *
 */
@RestController
@RequestMapping("subscription")
public class MessageSubscriptionController2 {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	

	
	/***
	 * 获取ACCESS_TOKEN
	 * @return
	 */
	public String  subscroption() {
		String appid="微信小程序appid";
		String secret="微信小程序secret";
		String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
				+ appid+ "&secret="+ secret;
		String results = HttpUtil.sendGet(url);
		JSONObject jsonObject =JSONObject.parseObject(results);
		String Access_Token=jsonObject.get("access_token").toString();
		return Access_Token;
	
	}
	
	/****
	 * 获取opneid和sessionKey
	 * 
	 * @param code
	 * @return
	 * @throws Exception 
	 */
	public JSONObject getSessionKeyOrOpenId(String code) throws Exception {

			// 微信端登录code
			String wxCode = code;
			// 请求路径
			String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
			String appid="小程序appid";
			String secret="小程序secret";

			//b2d42c4f39cf71f60416546cdb2855e1
			String requestUrlParam = "appid="+appid+"&secret="+secret+"&js_code=" + wxCode
					+ "&grant_type=authorization_code";
			// Java发post请求
			//HttpUtil.sendPost(url, map);
			
			JSONObject jsonObject = JSON.parseObject(HttpUtil.sendPost(requestUrl, requestUrlParam));
			if (jsonObject.get("errcode")!=null) {
				 //logger.error("code获取oppid和sessionkey 异常,检查小程序配置是否正确");
				 throw new Exception("异常信息:"+jsonObject.get("errmsg").toString());
			}
			return jsonObject;
	}
	

	/****
	 * 退款信息订阅
	 * @param price 提款金额
	 * @param url 小程序仓库的地址
	 * @param code  code
	 */
	@RequestMapping(value = "/subscription", method = RequestMethod.POST)
	public void sund(
			@RequestParam(value = "price", required = false) String price,
			@RequestParam(value = "url", required = true) String url,
			@RequestParam(value = "code", required = true) String code) {
		log.info("请求提款接口参数,提款金额:[{}],返回地址:[{}],code:[{}]",price,url,code);
		//获取openid
		Map map = new HashMap();
		com.alibaba.fastjson.JSONObject SessionKeyOpenId;
		String openid="";
		try {
			SessionKeyOpenId =getSessionKeyOrOpenId(code);
			openid = SessionKeyOpenId.getString("openid");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String access_Token=subscroption();
		Template template=new Template();  
		//订阅消息 模块id,
		template.setTemplate_id("订阅信息模板id"); 
		//openId
		template.setTouser(openid);
		//这个是订阅信息点进去的时候进去的界面,
		template.setPage(url);
		List paras=new ArrayList();  
		//这些参数在/订阅信息/详情/详细信息里面找 ,把后面的  {
    {thing5.DATA}} 取 thing5
		paras.add(new TemplateParam("thing5","预计1~5工作日到微信钱包,请注意查收"));  
		paras.add(new TemplateParam("amount1",price));  
		paras.add(new TemplateParam("thing4","提款到微信钱包"));  
		template.setTemplateParamList(paras); 
		//给订阅的用户发信息的地址
	    String requestUrl="https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";  
	    //替换 ACCESS_TOKEN
	    requestUrl=requestUrl.replace("ACCESS_TOKEN", access_Token); 
		//用户授权后给用户发订阅的信息,用户授权在前端处理
	    JSONObject jsonResult=httpsRequest(requestUrl, "POST", template.toJSON());  
	    int newcode=Integer.parseInt(jsonResult.get("errcode").toString());
	    if (jsonResult.get("errmsg").equals("ok")&&newcode==0) {
	    	log.info("订阅信息发送成功====");
	    	
		}	
	    log.info("订阅信息发送失败====");
	   
	}
	

	public  JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {   
	    JSONObject jsonObject = null;  
	    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(); 
	        jsonObject= JSONObject.parseObject(buffer.toString());
	    } catch (ConnectException ce) {    
	        ce.printStackTrace();  
	    } catch (Exception e) {    
	        e.printStackTrace();  
	    }    
	    return jsonObject;    
	}

}

ok,代码大概就是这个样子

 

你可能感兴趣的:(java,小程序)