折腾了一天,终于把这个图片接口(https://api.mch.weixin.qq.com/v3/merchant/media/upload)调通了。看到社区里面有不少小伙伴遇到了一样的问题,这里简单分享一下我的测试代码。因为我是用java开发的,所以下面内容的代码示例都是java的。
水平有限,如有错漏之处,请多多指教。
public class uploadFileTest { public static void main(String[] args) { // TODO Auto-generated method stub try { // 换行符 String LINE_END = "\r\n" ; String PREFIX = "--" ; // 定义数据分隔线 String BOUNDARY = "" ; //商户号 String mchid = "" ; //证书序列号 String serial_no = "" ; //商户私钥( 拷贝apiclient_key.pem文件里-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----之间的内容) String rsaPrivateKeyFile = "" ; //微信支付平台公钥文件 String rsaPublicKey = "" ; //时间戳 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( //文件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 URL url = new URL( "https://api.mch.weixin.qq.com/v3/merchant/media/upload" ); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置为POST conn.setRequestMethod( "POST" ); // 发送POST请求必须设置如下两行 conn.setDoOutput( true ); conn.setDoInput( true ); conn.setUseCaches( false ); // 设置请求头参数 conn.setRequestProperty( "Charsert" , "UTF-8" ); conn.setRequestProperty( "Accept" , "application/json" ); conn.setRequestProperty( "Content-Type" , "multipart/form-data; boundary=" + BOUNDARY); conn.setRequestProperty( "Authorization" , authorization); DataOutputStream dos = new DataOutputStream(conn.getOutputStream()); //拼装请求内容第一部分 StringBuilder strSb = new StringBuilder(); strSb.append(PREFIX).append(BOUNDARY).append(LINE_END) .append( "Content-Disposition: form-data; name=\"meta\";" + LINE_END) .append( "Content-Type: application/json; " + LINE_END) .append(LINE_END) // 空行 .append( "{\"filename\":\"" +filename+ "\",\"sha256\":\"" +fileSha256+ "\"}" ) .append(LINE_END); dos.write(strSb.toString().getBytes());
dos.flush(); //拼装请求内容第二部分 StringBuilder fileSbStart = new StringBuilder(); fileSbStart.append(PREFIX).append(BOUNDARY).append(LINE_END) .append( "Content-Disposition: form-data; name=\"file\"; filename=\"" + filename+ "\";" + LINE_END) .append( "Content-Type: image/jpeg" + LINE_END) .append(LINE_END); // 空行 dos.write(fileSbStart.toString().getBytes());
dos.flush(); //文件二进制内容 InputStream is = new FileInputStream(file); byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len = is.read(buffer)) != - 1 ){ dos.write(buffer, 0 ,len); } is.close(); //拼装请求内容结尾 StringBuilder fileSbEnd = new StringBuilder(); fileSbEnd.append(LINE_END) .append(PREFIX).append(BOUNDARY).append(PREFIX) .append(LINE_END); dos.write(fileSbEnd.toString().getBytes());
dos.flush(); dos.close(); //接收返回 //打印返回头信息 System.out.println( "接口返回头信息:" ); Map<String, List<String>> responseHeader = conn.getHeaderFields(); for (Map.Entry<String, List<String>> entry : responseHeader.entrySet()) { System.out.println(entry.getKey()+ ":" + entry.getValue()); } //打印返回内容 int responseCode = conn.getResponseCode(); String rescontent = "" ; if ((responseCode+ "" ).startsWith( "2" )){ //成功 rescontent = new String(InputStreamTOByte(conn.getInputStream())); System.out.println( "图片上传成功:" +rescontent); } else { //失败 rescontent = new String(InputStreamTOByte(conn.getErrorStream())); System.out.println( "图片上传失败:" +rescontent); } //验证微信支付返回签名 String Wtimestamp = responseHeader.get( "Wechatpay-Timestamp" ).get( 0 ); String Wnonce = responseHeader.get( "Wechatpay-Nonce" ).get( 0 ); String Wsign = responseHeader.get( "Wechatpay-Signature" ).get( 0 ); //拼装待签名串 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( "签名验证失败" ); } } catch (Exception e) { System.out.println( "发送POST请求异常!" + e); e.printStackTrace(); } } } |
这里是不是还有拼接一个append(PREFIX)
公钥跟私钥 都是要用pem密钥文件吗
String fileSha256 = DigestUtils.sha256Hex(
new
FileInputStream(file)
);//文件sha256值
签名是16进制串吗?不是Base64吗?