- v3图片上传接口java代码(httpclient和httpmime实现)
之前用HttpURLConnection实现的,现在改成用httpclient和httpmime实现(我用的是4.5.9版本),感觉会简单一点。水平有限,如有错误请指正。 [代码]public[代码] [代码]class[代码] [代码]uploadFileTest2 {[代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]void[代码] [代码]main(String[] args) {[代码][代码] [代码] [代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码] [代码] [代码][代码]//商户号[代码][代码] [代码][代码]String mchid = [代码][代码]""[代码][代码];[代码][代码] [代码][代码]//证书序列号[代码][代码] [代码][代码]String serial_no = [代码][代码]""[代码][代码];[代码][代码] [代码][代码]//商户私钥(拷贝apiclient_key.pem文件里-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----之间的内容[代码][代码])[代码][代码] [代码][代码]String rsaPrivateKey = [代码][代码]""[代码][代码];[代码][代码] [代码][代码]//微信支付平台公钥[代码][代码] [代码][代码]String rsaPublicKeyFile = [代码][代码]""[代码][代码]; [代码][代码] [代码][代码]//时间戳[代码][代码] [代码][代码]String timestamp = Long.toString(System.currentTimeMillis()/[代码][代码]1000[代码][代码]);[代码][代码] [代码][代码]//随机数[代码][代码] [代码][代码]String nonce_str = [代码][代码]""[代码][代码];[代码][代码] [代码] [代码] [代码][代码]//图片文件[代码][代码] [代码][代码]String filePath = [代码][代码]""[代码][代码];[代码][代码]//文件路径[代码][代码] [代码][代码]File file = [代码][代码]new[代码] [代码]File(filePath);[代码][代码] [代码][代码]String filename = file.getName();[代码][代码]//文件名[代码][代码] [代码][代码]String fileSha256 = DigestUtils.sha256Hex([代码][代码]new[代码] [代码]FileInputStream(file));[代码][代码]//文件sha256[代码][代码] [代码] [代码] [代码][代码]//拼签名串[代码][代码] [代码][代码]StringBuffer sb = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]sb.append([代码][代码]"POST"[代码][代码]).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]sb.append([代码][代码]"/v3/merchant/media/upload"[代码][代码]).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]sb.append(timestamp).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]sb.append(nonce_str).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]sb.append([代码][代码]"{\"filename\":\""[代码][代码]+filename+[代码][代码]"\",\"sha256\":\""[代码][代码]+fileSha256+[代码][代码]"\"}"[代码][代码]).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]System.out.println([代码][代码]"签名原串:"[代码][代码]+sb.toString());[代码][代码] [代码] [代码] [代码][代码]//计算签名[代码][代码] [代码][代码]String sign = [代码][代码]new[代码] [代码]String(Base64.encodeBase64(signRSA(sb.toString(),rsaPrivateKey)));[代码][代码] [代码][代码]System.out.println([代码][代码]"签名sign值:"[代码][代码]+sign);[代码][代码] [代码] [代码] [代码][代码]//拼装http头的Authorization内容[代码][代码] [代码][代码]String authorization =[代码][代码]"WECHATPAY2-SHA256-RSA2048 mchid=\""[代码][代码]+mchid+[代码][代码]"\",nonce_str=\""[代码][代码]+nonce_str+[代码][代码]"\",signature=\""[代码][代码]+sign+[代码][代码]"\",timestamp=\""[代码][代码]+timestamp+[代码][代码]"\",serial_no=\""[代码][代码]+serial_no+[代码][代码]"\""[代码][代码];[代码][代码] [代码][代码]System.out.println([代码][代码]"authorization值:"[代码][代码]+authorization);[代码][代码] [代码] [代码] [代码][代码]//接口URL[代码][代码] [代码][代码]String url = [代码][代码]"https://api.mch.weixin.qq.com/v3/merchant/media/upload"[代码][代码]; [代码][代码] [代码][代码]CloseableHttpClient httpclient = HttpClients.createDefault(); [代码][代码] [代码][代码]HttpPost httpPost = [代码][代码]new[代码] [代码]HttpPost(url);[代码][代码] [代码] [代码] [代码][代码]//设置头部[代码][代码] [代码][代码]httpPost.addHeader([代码][代码]"Accept"[代码][代码], [代码][代码]"application/json"[代码][代码]);[代码][代码] [代码][代码]httpPost.addHeader([代码][代码]"Content-Type"[代码][代码], [代码][代码]"multipart/form-data"[代码][代码]);[代码][代码] [代码][代码]httpPost.addHeader([代码][代码]"Authorization"[代码][代码], authorization);[代码][代码] [代码] [代码] [代码][代码]//创建MultipartEntityBuilder [代码][代码] [代码][代码]MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()[代码].setMode(HttpMultipartMode.RFC6532);[代码] [代码][代码]//设置boundary[代码][代码] [代码][代码]multipartEntityBuilder.setBoundary([代码][代码]""[代码][代码]);[代码][代码] [代码][代码]multipartEntityBuilder.setCharset(Charset.forName([代码][代码]"UTF-8"[代码][代码]));[代码][代码] [代码][代码]//设置meta内容[代码][代码] [代码][代码]multipartEntityBuilder.addTextBody([代码][代码]"meta"[代码][代码], [代码][代码]"{\"filename\":\""[代码][代码]+filename+[代码][代码]"\",\"sha256\":\""[代码][代码]+fileSha256+[代码][代码]"\"}"[代码][代码], ContentType.APPLICATION_JSON);[代码][代码] [代码][代码]//设置图片内容[代码][代码] [代码][代码]multipartEntityBuilder.addBinaryBody([代码][代码]"file"[代码][代码], file, ContentType.create([代码][代码]"image/jpg"[代码][代码]), filename);[代码][代码] [代码][代码]//放入内容[代码][代码] [代码][代码]httpPost.setEntity(multipartEntityBuilder.build()); [代码][代码] [代码] [代码] [代码][代码]//获取返回内容[代码][代码] [代码][代码]CloseableHttpResponse response = httpclient.execute(httpPost);[代码][代码] [代码][代码]HttpEntity httpEntity = response.getEntity(); [代码][代码] [代码][代码]String rescontent = [代码][代码]new[代码] [代码]String(InputStreamTOByte(httpEntity.getContent()));[代码][代码] [代码][代码]System.out.println([代码][代码]"返回内容:"[代码] [代码]+ rescontent);[代码][代码] [代码][代码]//获取返回的http header[代码][代码] [代码][代码]Header headers[] = response.getAllHeaders(); [代码][代码] [代码][代码]int[代码] [代码]i = [代码][代码]0[代码][代码]; [代码][代码] [代码][代码]while[代码] [代码](i < headers.length) { [代码][代码] [代码][代码]System.out.println(headers[i].getName() + [代码][代码]": "[代码] [代码]+ headers[i].getValue()); [代码][代码] [代码][代码]i++; [代码][代码] [代码][代码]} [代码][代码] [代码] [代码] [代码][代码]//验证微信支付返回签名[代码][代码] [代码][代码]String Wtimestamp = response.getHeaders([代码][代码]"Wechatpay-Timestamp"[代码][代码])[[代码][代码]0[代码][代码]].getValue();[代码][代码] [代码][代码]String Wnonce = response.getHeaders([代码][代码]"Wechatpay-Nonce"[代码][代码])[[代码][代码]0[代码][代码]].getValue();[代码][代码] [代码][代码]String Wsign = response.getHeaders([代码][代码]"Wechatpay-Signature"[代码][代码])[[代码][代码]0[代码][代码]].getValue();[代码][代码] [代码][代码]//拼装待签名串[代码][代码] [代码][代码]StringBuffer ss = [代码][代码]new[代码] [代码]StringBuffer();[代码][代码] [代码][代码]ss.append(Wtimestamp).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]ss.append(Wnonce).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]ss.append(rescontent).append([代码][代码]"\n"[代码][代码]);[代码][代码] [代码][代码]//验证签名[代码][代码] [代码][代码]if[代码][代码](verifyRSA(ss.toString(), Base64.decodeBase64(Wsign.getBytes()), rsaPublicKeyFile)) {[代码][代码] [代码][代码]System.out.println([代码][代码]"签名验证成功"[代码][代码]);[代码][代码] [代码][代码]} [代码][代码]else[代码] [代码]{[代码][代码] [代码][代码]System.out.println([代码][代码]"签名验证失败"[代码][代码]);[代码][代码] [代码][代码]}[代码][代码] [代码] [代码] [代码][代码]EntityUtils.consume(httpEntity);[代码][代码] [代码][代码]response.close();[代码][代码] [代码] [代码] [代码][代码]} [代码][代码]catch[代码] [代码](Exception e) {[代码][代码] [代码][代码]System.out.println([代码][代码]"发送POST请求异常!"[代码] [代码]+ e);[代码][代码] [代码][代码]e.printStackTrace();[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]}[代码][代码] [代码] [代码] [代码][代码]public[代码] [代码]static[代码] [代码]byte[代码][代码][] InputStreamTOByte(InputStream in) [代码][代码]throws[代码] [代码]IOException{ [代码][代码] [代码] [代码] [代码][代码]int[代码] [代码]BUFFER_SIZE = [代码][代码]4096[代码][代码]; [代码][代码] [代码][代码]ByteArrayOutputStream outStream = [代码][代码]new[代码] [代码]ByteArrayOutputStream(); [代码][代码] [代码][代码]byte[代码][代码][] data = [代码][代码]new[代码] [代码]byte[代码][代码][BUFFER_SIZE]; [代码][代码] [代码][代码]int[代码] [代码]count = -[代码][代码]1[代码][代码]; [代码][代码] [代码] [代码] [代码][代码]while[代码][代码]((count = in.read(data,[代码][代码]0[代码][代码],BUFFER_SIZE)) != -[代码][代码]1[代码][代码]) [代码][代码] [代码][代码]outStream.write(data, [代码][代码]0[代码][代码], count); [代码][代码] [代码] [代码] [代码][代码]data = [代码][代码]null[代码][代码]; [代码][代码] [代码][代码]byte[代码][代码][] outByte = outStream.toByteArray();[代码][代码] [代码][代码]outStream.close();[代码][代码] [代码] [代码] [代码][代码]return[代码] [代码]outByte; [代码][代码] [代码][代码]} [代码][代码] [代码] [代码] [代码] public static byte[] signRSA(String data, String priKey) throws Exception { //签名的类型 Signature sign = Signature.getInstance("SHA256withRSA"); //读取商户私钥,该方法传入商户私钥证书的内容即可 byte[] keyBytes = Base64.decodeBase64(priKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); sign.initSign(privateKey); sign.update(data.getBytes("UTF-8")); return sign.sign(); } public static boolean verifyRSA(String data, byte[] sign, String pubKey) throws Exception{ if(data == null || sign == null || pubKey == null){ return false; } CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(pubKey); Certificate c = cf.generateCertificate(in); in.close(); PublicKey publicKey = c.getPublicKey(); Signature signature = Signature.getInstance("SHA256WithRSA"); signature.initVerify(publicKey); signature.update(data.getBytes("UTF-8")); return signature.verify(sign); } [代码][代码] [代码] [代码] [代码]}[代码]
2019-09-17 - 微信开发者工具 1.02.1909051 RC 更新说明
下载地址 Windows 64 、 Windows 32 、 macOS已知问题 本地预览正常,真机预览空白;尝试关闭 项目详情 - 本地设置 - 代码保护;将在最近的 nightly 和 RC 版本修复 1. 本地编译时进行合并编译本地编译时使用合并编译可以加快小程序加载的速度, 通过 [代码]项目详情 - 本地设置 - 本地编译时进行合并编译[代码] 可以打开此功能 [图片] 使用合并编译后,主包的 js 文件会被打包成一个 [代码]__APP__/appservice.js[代码] 文件 [图片] 合并编译对于错误调试暂时还是不友好的,异步报错从控制台中点击会先跳转到合并后的文件,而如果合并后的文件过大会导致调试器卡顿 2. PC 微信开发版小程序自动预览PC 微信内测版 支持小程序 开发者工具 [代码]设置 - 通用设置 - 启用 PC 端自动预览[代码],可以将开发版小程序通过自动预览推送到同登录态的 PC 微信上 [图片] 3. 自动真机调试增加自动真机调试功能,减少真机调试扫码的交互 [图片] 4. 使用测试号进行多帐号调试在 [代码]菜单 - 工具 - 多帐号调试[代码],可以打开多帐号调试帐号管理面板 本次为所有 appid 添加了 4 个测试帐号,可以使用测试号进行多帐号调试 [图片] 5. 支持多线程 [代码]worker[代码] 的单步调试本次更新优化了多线程 [代码]worker[代码] 的编译和代码加载的方式,从而支持了单步调试 [图片] 6. 公众号网页调试增加 url 收藏功能之前只有通过地址栏历史记录的匹配交互来快速调试常用页面,本次新增了收藏功能,更加便利 [图片] 7. 云开发套餐支持代金券支付在云开发控制台支付套餐时,可以选择使用代金券进行支付 [图片] 8. 新增周期性更新调试拉取周期性数据由于微信客户端每隔 12 个小时才会发起一次请求,调试周期性更新功能会显得不太方便。 目前新增能够在开发者工具上调试整个流程,操作路径为点击菜单 [代码]工具 -> 拉取周期性缓存数据[代码], 点击后开发者工具会立即向配置的数据下载地址请求数据,如下图所示: [图片] 清除周期性数据如果需要清除工具缓存的周期性数据,可以通过点击工具栏的 [代码]清除数据缓存[代码] 或者 [代码]全部清除[代码] 来进行清除。 9. 支持小游戏关系链互动数据开发在小游戏项目 [代码]project.config.json[代码] 中指定 [代码]jsserverRoot[代码] 为项目内目录,可以在该目录下进行小游戏关系链互动数据开发,右键支持直接上传到开发环境或正式环境,或者对比文件 [图片] 10. 小游戏节点审查插件通过 [代码]菜单 - 工具 - 插件[代码] 打开插件面板,可以添加小游戏节点审查调试器插件 [图片] 添加插件后重启工具,选择 [代码]Game Inspector[代码] 调试器面板,支持使用主流游戏引擎的小游戏获取当前游戏场景下的节点树信息 [图片]
2019-09-09