- 小程序基础库2.11.1更新
新增 框架 新增 matchMedia 接口新增 插件 支持 UDPSocket更新 框架 小游戏 wx.shareMessageToFriend 接口回调缺失问题更新 框架 开发者工具下自定义 tabBar 位置有误 详情更新 框架 插件支持 requireMiniProgram更新 框架 云开发增加 CDN 辅助方法帮助大数据云函数调用更新 框架 小程序强制更新更新 框架 使 promise 中的错误能反馈在错误处理函数中更新 框架 初始渲染缓存更新 组件 iOS 下自定义 tabBar 切换 tab 时错位 详情更新 组件 多个 scroll-view 同时下拉刷新动画冲突 详情更新 组件 video 锁屏按钮优化更新 组件 canvas 容器设置 css 动画报错更新 组件 优化 iOS 下 scroll-view scroll-anchoring 的性能更新 组件 插件支持 getPerformance 接口更新 组件 组件中使用云文件id时自动缓存更新 插件 支持 getVideoInfo 和 compressVideo更新 插件 插件内允许服务市场调用更新 API 小游戏支持videoDecoder更新 API media recorder / decoder 接口时序问题更新 API 服务市场协议更新增加 requestId修复 框架 链接中包含rpx被误转换修复 组件 video 在 iPad 下控件错位修复 组件 iOS video 全屏时控件显示不全修复 组件 iOS input type 无法动态修改修复 组件 自定义下拉刷新在原点无法横向滑动修复 组件 iOS 11 下 textarea 同层偶现错位修复 组件 【自定义组件】尝试对已经删除的自定义组件调用动画接口会产生报错修复 组件 同时使用超过50个云文件id放到img组件展示会失败 详情修复 组件 live-player封装为插件后,小程序调用requestFullScreen后,安卓无法进入全屏 详情修复 组件 live-player切换回来后不能继续播放 详情修复 API previewImage 接口传入 base64 在 iOS 13.4 会 crash 的问题微信团队 2020.05.21
2020-05-25 - 微信电子发票“自建平台”模式,开票后,发票插入卡包失败的问题?
我们自己已经具备电子发票开票能力,开票完成后,将电子发票插入微信卡包。 在插卡之前,已经上传成功PDF,用户也已经在页面授权。 但是插卡失败,插卡报文如下: { "appid":"我们的appid", "card_ext":{ "nonce_str":"UpNmSazc", "user_card":{ "billing_code":"12339993", "billing_no":"0500需要隐藏21107", "billing_time":1546159960, "check_code":"1218853需要隐藏882550067", "fee":10056, "fee_without_tax":8594, "info":[ { "name":"[0xe5][0x81][0x9c][0xe8][0xbd][0xa6][0xe5][0x9c][0xba][0xe5][0x81][0x9c][0xe8][0xbd][0xa6][0xe6][0x9c][0x8d][0xe5][0x8a][0xa1]", "num":1, "price":10056, "unit":"[0xe6][0xac][0xa1]" } ], "s_pdf_media_id":"7210101573048009265", "s_trip_pdf_media_id":"", "tax":1461, "title":"xxx[0xe7][0x89][0xa9][0xe4][0xb8][0x9a][0xe7][0xae][0xa1][0xe7][0x90][0x86][0xe6][0x9c][0x89][0xe9][0x99][0x90][0xe5][0x85][0xac][0xe5][0x8f][0xb8]" } }, "card_id":"pMlrp1TPFmjt4ZCglFIgnfAWNx_Q", "order_id":"k2chordaiyunnxxvtogu" } 返回报文: { "errcode":72031, "errmsg":"invalid params, fee is empty hint: [ZIejWA00154810]" } 发票金额是对的。。。。。。分为单位
2019-09-23 - .NET 对接V3 接口
不知道为什么网上资料好少,有也是java的。 也不知道是不是我太菜了搞了一天才搞定,最后发现是被自己坑了。。。。借助于fiddler才找的问题。 A. V3加密使用的是 SHA256-RSA 直接代码,我用的是p12直接解析。 [代码]// 1- 拼接待加密的字符串[代码] [代码] [代码][代码]string[代码] [代码]timestamp = GetTimeStamp();[代码][代码]//获取时间戳[代码] [代码] [代码][代码]string[代码] [代码]body = [代码][代码]"{\"stock_id\": \"\",\"out_request_no\": \"\",\"appid\": \"\",\"stock_creator_mchid\": \"\"\"coupon_value\": null,\"coupon_minimum\": null}"[代码][代码];[代码][代码]//这里只是一个例子[代码] [代码] [代码][代码]string[代码] [代码]method = [代码][代码]"POST"[代码][代码];[代码] [代码] [代码][代码]string[代码] [代码]apiurl = [代码][代码]"/v3/marketing/favor/users/1211111/coupons"[代码][代码];[代码][代码]//[代码] [代码] [代码][代码]string[代码] [代码]nonce_str = [代码][代码]"3fefdfc321ba5bfb60849d8d0f4ebf08"[代码][代码];[代码][代码]//32位的随机字符串[代码] [代码] [代码][代码]StringBuilder sbstrhead = [代码][代码]new[代码] [代码]StringBuilder();[代码] [代码] [代码][代码]sbstrhead.Append(method + [代码][代码]"\n"[代码][代码]);[代码] [代码] [代码][代码]sbstrhead.Append(apiurl + [代码][代码]"\n"[代码][代码]);[代码] [代码] [代码][代码]sbstrhead.Append(timestamp + [代码][代码]"\n"[代码][代码]);[代码] [代码] [代码][代码]sbstrhead.Append(nonce_str + [代码][代码]"\n"[代码][代码]);[代码] [代码] [代码][代码]sbstrhead.Append(body + [代码][代码]"\n"[代码][代码]); [代码] string pfxFilePath =@"F:\"; [代码] [代码][代码]// 2- 调用加密方法传入[代码] [代码] [代码][代码]string[代码] [代码]signstr =SHA256Encrypt(sbstrhead.ToString(), pfxFilePath, [代码][代码]"1234567"[代码][代码]);[代码] [代码] [代码][代码]/// <summary>[代码] [代码] [代码][代码]/// Allen -获取时间戳[代码] [代码] [代码][代码]/// </summary>[代码] [代码] [代码][代码]/// <returns></returns>[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]string[代码] [代码]GetTimeStamp()[代码] [代码] [代码][代码]{[代码] [代码] [代码][代码]//生成1970年到现在的秒数[代码] [代码] [代码][代码]TimeSpan timeSpan = (DateTime.UtcNow - [代码][代码]new[代码] [代码]DateTime(1970, 1, 1));[代码] [代码] [代码][代码]//TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);[代码] [代码] [代码][代码]return[代码] [代码]Convert.ToInt64(timeSpan.TotalSeconds).ToString();[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]/// <summary>[代码] [代码] [代码][代码]/// Allen - sha256签名带密钥[代码] [代码] [代码][代码]/// </summary>[代码] [代码] [代码][代码]/// <param name="data2">加密数据</param>[代码] [代码] [代码][代码]/// <param name="pfxFilePath">P12对应的物理地址 @"F:\key\xxxxxx_cert.p12";</param>[代码] [代码] [代码][代码]/// <param name="pwd">证书密码微信一般是商户号</param>[代码] [代码] [代码][代码]/// <returns></returns>[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]string[代码] [代码]SHA256Encrypt([代码][代码]string[代码] [代码]data2, [代码][代码]string[代码] [代码]pfxFilePath,[代码][代码]string[代码] [代码]pwd) [代码] [代码] [代码][代码]{[代码] [代码] [代码][代码]X509Certificate2 privateCert = [代码][代码]new[代码] [代码]X509Certificate2(pfxFilePath, pwd, X509KeyStorageFlags.Exportable);[代码] [代码] [代码][代码]RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)privateCert.PrivateKey;[代码] [代码] [代码][代码]// This one can:[代码] [代码] [代码][代码]RSACryptoServiceProvider privateKey1 = [代码][代码]new[代码] [代码]RSACryptoServiceProvider();[代码] [代码] [代码][代码]privateKey1.ImportParameters(privateKey.ExportParameters([代码][代码]true[代码][代码]));[代码] [代码] [代码][代码]byte[代码][代码][] data = Encoding.UTF8.GetBytes(data2);[代码] [代码] [代码][代码]byte[代码][代码][] signature = privateKey1.SignData(data, [代码][代码]"SHA256"[代码][代码]);[代码] [代码] [代码][代码]//密文[代码] [代码] [代码][代码]string[代码] [代码]sign = Convert.ToBase64String(signature);[代码] [代码] [代码][代码]return[代码] [代码]sign;[代码] [代码] [代码][代码]}[代码] B - 请求方法 [代码]//请求 Authorization 信息[代码][代码]var[代码] [代码]authormessage = [代码][代码]"WECHATPAY2-SHA256-RSA2048 mchid=\"\",serial_no=\"\",nonce_str=\""[代码] [代码]+ nonce_str + [代码][代码]"\",timestamp=\""[代码] [代码]+ timestamp + [代码][代码]"\",signature=\""[代码] [代码]+ signstr + [代码][代码]"\""[代码][代码]; [代码] [代码]/// <summary>[代码][代码] [代码][代码]/// Allen - POST V3 微信请求代码上叠加修正[代码][代码] [代码][代码]/// </summary>[代码][代码] [代码][代码]/// <param name="json"></param>[代码][代码] [代码][代码]/// <param name="url"></param>[代码][代码] [代码][代码]/// <param name="timeout"></param>[代码][代码] [代码][代码]/// <param name="encoding"></param>[代码][代码] [代码][代码]/// <param name="authormessage"></param>[代码][代码] [代码][代码]/// <param name="method"></param>[代码][代码] [代码][代码]/// <returns></returns>[代码][代码] [代码][代码]public[代码] [代码]static[代码] [代码]string[代码] [代码]PostV3([代码][代码]string[代码] [代码]json, [代码][代码]string[代码] [代码]url, [代码][代码]int[代码] [代码]timeout, Encoding encoding, [代码][代码]string[代码] [代码]authormessage, [代码][代码]string[代码] [代码]method)[代码][代码] [代码][代码]{[代码][代码] [代码][代码]System.GC.Collect();[代码][代码]//垃圾回收,回收没有正常关闭的http连接[代码] [代码] [代码][代码]string[代码] [代码]result = [代码][代码]""[代码][代码];[代码][代码]//返回结果[代码] [代码] [代码][代码]HttpWebRequest request = [代码][代码]null[代码][代码];[代码][代码] [代码][代码]HttpWebResponse response = [代码][代码]null[代码][代码];[代码][代码] [代码][代码]Stream reqStream = [代码][代码]null[代码][代码];[代码] [代码] [代码][代码]try[代码][代码] [代码][代码]{[代码][代码] [代码][代码]//设置最大连接数[代码][代码] [代码][代码]ServicePointManager.DefaultConnectionLimit = 200;[代码][代码] [代码][代码]//设置https验证方式[代码][代码] [代码][代码]if[代码] [代码](url.StartsWith([代码][代码]"https"[代码][代码], StringComparison.OrdinalIgnoreCase))[代码][代码] [代码][代码]{[代码][代码] [代码][代码]ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;[代码][代码] [代码][代码]ServicePointManager.ServerCertificateValidationCallback =[代码][代码] [代码][代码]new[代码] [代码]RemoteCertificateValidationCallback(CheckValidationResult);[代码][代码] [代码][代码]}[代码][代码] [代码][代码] [代码][代码]/***************************************************************[代码][代码] [代码][代码]* 下面设置HttpWebRequest的相关属性[代码][代码] [代码][代码]* ************************************************************/[代码][代码] [代码][代码]request = (HttpWebRequest)WebRequest.Create(url);[代码][代码] [代码][代码]request.Method = [代码][代码]"POST"[代码][代码];[代码] [代码] [代码][代码]request.Timeout = timeout * 1000;[代码] [代码] [代码][代码]//设置代理服务器[代码][代码] [代码][代码]//WebProxy proxy = new WebProxy(); //定义一个网关对象[代码][代码] [代码][代码]//proxy.Address = new Uri(WxPayConfig.PROXY_URL); //网关服务器端口:端口[代码][代码] [代码][代码]//request.Proxy = proxy;[代码] [代码] [代码][代码]//设置POST的数据类型和长度[代码][代码] [代码][代码]request.ContentType = [代码][代码]"application/json"[代码][代码];[代码][代码] [代码][代码]request.Accept = [代码][代码]"application/json"[代码][代码];[代码][代码] [代码][代码]request.UserAgent=[代码][代码]"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"[代码][代码];[代码][代码] [代码][代码]request.Headers.Add([代码][代码]"Authorization"[代码][代码], authormessage);[代码][代码] [代码][代码]//request.[代码] [代码] [代码][代码]byte[代码][代码][] data = System.Text.Encoding.UTF8.GetBytes(json);[代码][代码] [代码][代码]request.ContentLength = data.Length;[代码] [代码] [代码][代码]//往服务器写入数据[代码][代码] [代码][代码]reqStream = request.GetRequestStream();[代码][代码] [代码][代码]reqStream.Write(data, 0, data.Length);[代码][代码] [代码][代码]reqStream.Close();[代码] [代码] [代码][代码]//获取服务端返回[代码][代码] [代码][代码]response = (HttpWebResponse)request.GetResponse();[代码][代码] [代码][代码]// WebResponse response2 = request.GetResponseAsync();[代码][代码] [代码][代码]//获取服务端返回数据[代码][代码] [代码][代码]StreamReader sr = [代码][代码]new[代码] [代码]StreamReader(response.GetResponseStream(), encoding);[代码][代码] [代码][代码]result = sr.ReadToEnd().Trim();[代码][代码] [代码][代码]sr.Close();[代码][代码] [代码] [代码] [代码][代码]}[代码][代码] [代码][代码]catch[代码] [代码](System.Threading.ThreadAbortException e)[代码][代码] [代码][代码]{[代码][代码] [代码][代码]System.Threading.Thread.ResetAbort();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]catch[代码] [代码](WebException e)[代码][代码] [代码][代码]{[代码][代码] [代码][代码]//这里有异常的这里最重要因为非200返回的时候这里可以知道什么原因[代码][代码] [代码][代码]response = (HttpWebResponse)e.Response;[代码][代码] [代码][代码]//获取服务端返回数据[代码][代码] [代码][代码]StreamReader sr = [代码][代码]new[代码] [代码]StreamReader(response.GetResponseStream(), encoding);[代码][代码] [代码][代码]result = sr.ReadToEnd().Trim();[代码][代码] [代码][代码]sr.Close();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]catch[代码] [代码](Exception e)[代码][代码] [代码][代码]{[代码][代码] [代码][代码]throw[代码] [代码]new[代码] [代码]Exception(e.ToString());[代码][代码] [代码][代码]}[代码][代码] [代码][代码]finally[代码][代码] [代码][代码]{[代码][代码] [代码][代码]//关闭连接和流[代码][代码] [代码][代码]if[代码] [代码](response != [代码][代码]null[代码][代码])[代码][代码] [代码][代码]{[代码][代码] [代码][代码]response.Close();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码](request != [代码][代码]null[代码][代码])[代码][代码] [代码][代码]{[代码][代码] [代码][代码]request.Abort();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码] [代码] [代码] [代码] [代码][代码]return[代码] [代码]result;[代码][代码] [代码][代码]}[代码] 希望能帮到某些人。
2019-11-17