笔者在上个月接到一个需求,大概是需要计算一条数据的最大办理时间从而发送任务超期的微信小程序服务通知,俺也是第一次接触到需要调用微信的API去进行发送消息,该博客权当记录此次功能开发的过程了~
本身微信的官方文档是提供了采用http调用的方式去进行调用微信的API微信小程序官方文档
但是俺想着都已经是什么年代了,于是找到了GitHub上的一个资料GitHub地址
我们可以看到几乎涵盖了所有微信相关的API,在这里不得不感慨一下binarywang,王哥他们真的太厉害了~

可以理解为不同的jar包对应引入了不从的SDK库,使调用的更方便,更简洁,下面就来依次讲解吧:
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.0.0</version>
</dependency>
准备工作当然不止后端的JAR包引入,我们还需要选择一个将要发送消息通知的模板,此步如果是全栈大怨种就看该官方文档,很详细选择服务通知模板,如果是后端好哥们,就让前端自己研究,宗旨是需要拿到模板ID很重要!!见下图,为我圈中的那个ID,需要被后端拿到。

我们先看我们所需要的所有配置,笔者均写到了yml中,可能不是太好看,见谅~
wx:
miniapp:
#上面拿到的很重要的那个模板ID
template-id: g19lTFku79jXC58CDzTnoIeazJC8HHvbW82apat_vgs
configs:
#微信小程序的appid 开发者工具拿到
appid: wx05e2612sfav212bddev12
#开发者工具拿到Secret
secret: 91b5a9e5645e8cf2123213safasfgwgf
#微信小程序消息服务器配置的token
token: 123
#微信小程序消息服务器配置的EncodingAESKey
aesKey:
msgDataFormat: JSON
该配置文件笔者这里为两个,大家也可以只写一个,主要目的是为了注入引入的JAR包中的WxMaService,只有用这个,我们才能进行调用API
这里需要注意的是笔者的WxProperties是写的另一个配置文件,如果大家觉得写配置文件很麻烦,也可以写一个,采用手动注入值的放肆,这个WxProperties见下一个配置文件:
/**
* @describe:
* @author: jiazl /
* @version: v1.0
*/
@Slf4j
@Configuration
@EnableConfigurationProperties(WxProperties.class)
public class WxConfig {
private final WxProperties properties;
@Autowired
public WxConfig(WxProperties properties) {
this.properties = properties;
}
@Bean
public WxMaService getService() {
if (properties == null || properties.getAppid() == null || properties.getSecret() == null) {
throw new WxRuntimeException("required wechat param not found");
}
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(properties.getAppid());
config.setSecret(properties.getSecret());
config.setToken(properties.getToken());
config.setAesKey(properties.getAesKey());
config.setMsgDataFormat(properties.getMsgDataFormat());
WxMaService service = new WxMaServiceImpl();
service.setWxMaConfig(config);
return service;
}
采用配置类注入的方式,如果大家不想写配置,可以采用手动设置值,目的是为了让上面的配置中的service注入到容器里面。
@Data
@ConfigurationProperties(prefix = "wx.miniapp.configs")
public class WxProperties {
/**
* 设置微信小程序的appid
*/
private String appid;
/**
* 设置微信小程序的Secret
*/
private String secret;
/**
* 设置微信小程序消息服务器配置的token
*/
private String token;
/**
* 设置微信小程序消息服务器配置的EncodingAESKey
*/
private String aesKey;
/**
* 消息格式,XML或者JSON
*/
private String msgDataFormat;
}
@RestController
@Slf4j
@Api(tags = "征兵测试接口")
public class ZbSendDemoController {
@Autowired
private WxMaService wxService;
@Value("${wx.miniapp.template-id}")
private String templteId;
@Resource
public RabbitTemplate rabbitTemplate;
/**
* 跳转的小程序页面
*/
private static final String PAGES_ZP = "pages/draft-review/list/list";
@GetMapping("/api/zphs/sendZbhsMsg")
@ApiOperation("传openId发送微信服务通知")
public ApiResult<Boolean> sendMsg(String openID) {
sendSmallMsg(openID);
return ApiResult.success(true);
}
private void sendSmallMsg(String openId) {
Map<String, String> map = new HashMap<>();
map.put("phrase1","测试");
map.put("thing3", "您收到了应征公民测试测试的任务提醒消息");
map.put("time12", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
WxMaSubscribeMessage wxMaSubscribeMessage = WxMaSubscribeMessage.builder()
.toUser(openId)
.templateId(templteId)
.page(PAGES_ZP)
.build();
// 设置将推送的消息
map.forEach((k, v) -> {
wxMaSubscribeMessage.addData(new WxMaSubscribeMessage.Data(k, v));
});
try {
log.info("开始发送消息!!!!");
wxService.getMsgService().sendSubscribeMsg(wxMaSubscribeMessage);
log.info("消息发送成功!!!!");
} catch (WxErrorException e) {
e.printStackTrace();
}
}
@GetMapping("/api/zphs/sendMqDemo")
@ApiOperation("消息队列发送微信服务通知测试")
public ApiResult<Boolean> sendMqDemo(String taskId,String time,String state,String id ) {
sendMessage( taskId, time, state,id);
return ApiResult.success(true);
}
public void sendMessage(String taskId,String time,String state,String id) {
//发送延时队列消息
Map<String, Object> map = new HashMap<>(10);
map.put("taskId", taskId);
map.put("state", state);
map.put("bzpId",id);
String message = JSON.toJSONString(map);
log.info("开始发送!!!");
rabbitTemplate.convertAndSend(RabbitMqSendMsgConfig.DELAYED_EXCHANGE_NAME, RabbitMqSendMsgConfig.DELAYED_ROUTING_KEY,
message, msg -> {
msg.getMessageProperties().setDelay(Integer.parseInt(time));
return msg;
});
log.info("发送消息成功!!!");
}
笔者这里的Controller很乱,因为里面不仅有发送消息的代码,也有RabbitMq的代码,当然这都是和具体业务相关,我们的重点是sendSubscribeMsg
到这一步,消息就发送成功了,我们可以看到实例:

到这里,我们需要有几个地方注意:
1 模板中当前状态,温馨提示,工单创建时间均为参数对应值,代码是为发送前的Map里面
2 Controller最上面有一行:
private static final String PAGES_ZP = "pages/draft-review/list/list";
对应为点击进入小城许跳转的页面,为具体业务所定
3OpenId是个很重要的东西,是登录微信小程序都会获取到的,唯一性的,微信的API就是通过OpenId给具体的用户发送消息,所以第一个方法内我的参数就为OpenId,这个OpenId是前端传输到后端的,我在这里仅仅是一个Demo接口,切记
4如果有时间,我会写一篇RabbitMq的文章,讲解一下用法及踩过的坑,然后将整个业务需求进行描述讲解
5注意图片中的参数的个数及名称

一定要和微信小程序模板上的保持一致,个数及参数名(模板的参数可以在微信开发者工具上看),注意部分参数有字数限制,具体限制要求可以查看微信开发者工具上的具体描述。
6祝大家天天开心~~~~
好了,俺这次的文章就到这里结束了,祝大家都找到新的工作,天天开心,万事如意~~
敬礼!
salute!!
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送