- Present enums as string. Modify your
StartUp.cs
, add the highlight part below:
services.AddMemoryCache().AddMvcCore().AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
})
.AddDataAnnotationsLocalization();
-
Enable XML Comments
- Manually add the two lines in PropertyGroup below to the .csproj file:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
2. Add the options in the code below
services.AddSwaggerGen(options =>
{
options.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{AppDomain.CurrentDomain.FriendlyName}.xml"), true);
});
await Db.Queryable<Entity>().Where(_ => _.SampleFieldName== sampleFieldValue)
.GroupBy("AnothterFieldNameInStringFormat")
.Select<ResultModel>("AnotherFieldNameInStringFormat, Count(AnotherFieldNameInStringFormat) Total")
.ToListAsync();
这与 Nest 默认的字段名映射规则有关。C# 项目字段名往往是 CamelCase,然而 Nest API在创建索引时,默认会将 CamelCase 的字段名,转换为 camelCase 的字段名。当然,查询的时候,它也会精确的按照 camelCase 字段名映射数据。如果你只用 Nest,其实是不会有任何问题的。毕竟 AutoMapper 对字段名大小写是很宽容的。
当我们引入 Logstash 动态更新索引之后,不和谐的一幕出现了。凡是 Logstash 更新的过数据,查询的时候会返回搜索结果,但所有字段的值都是null。这是因为Logstash在更新索引的时候,没有做 CamelCase => camelCase 的字段名转换。
了解了问题产生的原因,解决起来也就容易了。幸运的是,Nest有一个配置参数,可以设置为索引时不做字段名转换。直接上代码
public static void AddElasticsearch(
this IServiceCollection services, string connectionUrl, string connectionIndex)
{
var defaultIndex = connectionIndex;
var settings = new ConnectionSettings(new Uri(connectionUrl))
.DefaultIndex(defaultIndex);
settings.DefaultFieldNameInferrer(p => p);
var client = new ElasticClient(settings);
services.AddSingleton(client);
}
需要注意的是,代码修改后,别忘记重建索引。否则你会发现原来不正常的( Logstash更新过的数据)都正常了,原来搜索正常的,现在却所有字段名都变成了null。
- Buefy is a lightweight UI components library for Vue.js based on Bulma
@keyup.enter="eventHandler"
doesn't work in el-input
, but @keyup.enter.native="eventHandler"
does. #element-ui
git rm -rf . && git clean -fxd
is the best way to delete all files except .git directory. #git
- To make your dynamic LINQ query safe, you must use placeholders for all user input. Never concatenate your string! #dotnetcore
try_files $uri $uir/ =404;
is better than try_files $uri $uri/ /index.html;
, because it can avoid endless loop when /index.html doesn't exist. #nginx
git tag -n99
show tags along with annotations Reference
- new crontab task added
0 6 * * * /bin/docker container prune -f
10 6 * * * /bin/docker rmi $(/bin/docker images -f "dangling=true" -q)
这两天在和开发小程序的同事对接supay支付,今天总算基本搞完了。他们的文档过于糟糕,太多槽要吐,记录一下也许会帮到其他也需要对接superpay的人。先说说我们的业务流程
- 小程序 wx.login 拿到 code
- 小程序 wx.getUserInfo 拿到加密的 userData和iv
- 小程序登录请求公司后端服务器 /wechatMiniProgram/login 接口三方登录,登录成功拿到可访问公司其他接口的 accessToken
- 小程序拿着accessToken下订单
- 小程序拿着订单id请求公司后端服务器 /supay/wechatMiniProgramPay/{orderId}
- 公司服务器请求 supay 小程序下单接口,获取pay_info 给小程序。故事主要发生在这里。
他们的文档里是有一个流程图的,写成文本大体是下面这样。
- 小程序向公司后台服务器发起下单支付请求
- 公司后台服务器请求 superpay 服务器获取 openid
- superpay 服务器返回 openid 给公司后台服务器
- 公司后台服务器拿着openid 请求superpay服务器(小程序下单接口)拿 pay_info
- 公司服务器把 pay_info 返回给小程序
- 小程序拿 pay_info 发起支付
这个流程图事后看其实也不算错,只是其中第2步和第3步是不必要的。因为小程序在三方登录的时候,我们已经可以拿到openid和unionid。补充一句,小程序支付只需要openid,并不需要unionid。
在和superpay的技术同事沟通过程中,我发现最有价值的聊天记录包括
不要管其他的接口了,就用小程序下单
交易状态 TRADE_FINISHED 不需要处理
小程序下单返回的接口数据中,所有时间均是北京时间
inner_trade_no是 supay 的单号,mch_order_no和outer_trade_no 是你们的单号
trade_amount是人民币金额,虽然例子里写的是纽币
签名的时候字典序是重要的,文档里虽然没有提到,但在签名串字典序末尾追加一个 &key=商户appsecret 再md5是至关重要的。
因为签名需要拼一个query string格式的串,我就想当然的认为是post这个串到supay服务器。这是我的错,这里要以例子为准。例子里写的就是post一个json格式的数据过去。
10.07.2020 补充一个吐槽,小程序返回的 trade_amount 单位并不是人民币,是纽币。而且小程序各接口没有一个能返回人民币实际支付额。我的解决办法是拿自己的订单号调用 superpay 给非小程序支付的查询交易详情接口,这样就能拿到人民币交易金额数据。