在做退款的时候需要给用户发一条消息,告诉他已经在退款了,一开始是想用模板消息来做的,但是看微信开发文档说模板消息要下线,推荐用订阅信息。这边记录一些步骤。
登录微信公众平台,点击订阅信息,我的模板,添加我的模板,微信会提供一些常用的模板,可以选择,也可以自己申请,通过就可以使用了,把模板id复制下来保存一下。代码里面需要用到。
看微信开发文档用的是这个接口: 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 请求,这个问题可以在微信开发工具里面设置一下,设置他不要验证域名;
步骤是,打开微信开发工具--设置--项目设置 ,这个就可以不要验证域名,真实环境肯定是不推荐这么做的,但是这样调试方便。
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);
}
})
}
拉下发订阅信息接口的代码我是写在了后端,
工具包类
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,代码大概就是这个样子