收藏
回答

使用wechatpay-apiv3创建client调用上传电子发票文件接口,一直验签失败

1.创建client,在wechatpay-go官方库说,使用option.WithWechayPayAutoAuthCipher会自动帮忙验签2.在使用post,调用/v3/new-tax-control-fapiao/fapiao-applications/upload-fapiao-file这个接口,一直验签失败。在truncated_sign_message中没有看到有请求体。请问应该如何使用POST调用上传电子发票文件接口

回答关注问题邀请回答
收藏

2 个回答

  • 北望沣渭
    北望沣渭
    04-29

    抄这个 https://github.com/wechatpay-apiv3/wechatpay-go/blob/main/services/fileuploader/marketing_image_uploader.go

    // Copyright 2021 Tencent Inc. All rights reserved.
    
    package fileuploader
    
    
    import (
    	"context"
    	"io"
    
    
    	"github.com/wechatpay-apiv3/wechatpay-go/core"
    	"github.com/wechatpay-apiv3/wechatpay-go/services"
    )
    
    
    // MarketingImageUploadResponse 图片上传API(营销专用)返回结果
    type MarketingImageUploadResponse struct {
    	MediaUrl *string `json:"media_url"` // revive:disable-line:var-naming
    }
    
    
    // MarketingImageUploader 图片上传API(营销专用)
    //
    // 通过本接口上传图片后可获得图片url地址。图片url可在微信支付营销相关的API使用,
    // 包括商家券、代金券、支付有礼等。
    // 接口文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_0_1.shtml
    type MarketingImageUploader services.Service
    
    
    // Upload 上传图片至微信支付营销系统
    func (u *MarketingImageUploader) Upload(
    	ctx context.Context, fileReader io.Reader, filename string, contentType string,
    ) (*MarketingImageUploadResponse, *core.APIResult, error) {
    	result, err := (*baseFileUploader)(u).upload(
    		ctx, "/v3/marketing/favor/media/image-upload", fileReader, filename, contentType, map[string]interface{}{},
    	)
    	if err != nil {
    		return nil, result, err
    	}
    
    
    	var resp = new(MarketingImageUploadResponse)
    	if err = core.UnMarshalResponse(result.Response, resp); err != nil {
    		return nil, result, err
    	}
    	return resp, result, nil
    }
    
    04-29
    有用 1
    回复 2
    • 三十七
      三十七
      05-06
      请问是用这个接口上传电子发票文件,还是抄这个实现方式来调用上传电子发票文件接口。
      05-06
      回复
    • 三十七
      三十七
      05-06
      感谢,有用
      05-06
      回复
  • Mica
    Mica
    07-30
    @ApiOperation("上传电子发票文件")
    @PostMapping("uploadFapiaoFile")
    public Result uploadFapiaoFile() throws IOException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, InvalidKeyException {
        String url = wxPay.getDomain() + "/v3/new-tax-control-fapiao/fapiao-applications/upload-fapiao-file";
        HttpUrl parse = HttpUrl.parse(url);
        String path = "E:\\online-consultation\\处方.pdf";
        String sm3 = FileUtils.sm3(path);
        // String sm3 = FileUtils.sm3(path);
        log.info("SM3[{}]", sm3);
    
        JSONObject meta = new JSONObject();
        meta.put("file_type", "PDF");
        meta.put("digest", sm3);
        meta.put("digest_algorithm", "SM3");
    
    
        String signatureString = WxSignatureUtil.getSignatureString("POST", parse, meta.toString());
        log.info("signature[{}]", signatureString);
        MultipartBody multipartBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("meta", "meta", RequestBody.create(MediaType.parse("application/json"), meta.toString()))
                .addFormDataPart("file", "file", RequestBody.create(new File(path), MediaType.parse("pdf/plain")))
    
                .build();
        OkHttpClient client = new OkHttpClient();
        Request build = new Request.Builder()
                .addHeader("Content-Type", "multipart/form-data")
                .addHeader("Authorization", signatureString)
                .addHeader("Accept", "application/json")
                .url(url)
                .post(multipartBody)
                .build();
        Response response = client.newCall(build).execute();
        ResponseBody responseBody = response.body();
        String string = responseBody.string();
        return Result.ok(string);
    }
    public static String sm3(String path) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        try (FileInputStream fis = new FileInputStream(path);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            SM3.Digest sm3 = new SM3.Digest();
            sm3.update(baos.toByteArray());
            byte[] digest = sm3.digest();
            return Hex.toHexString(digest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Slf4j
    public class WxSignatureUtil {
        private static String serial = "";
        private static String mchid = "";
    
        public static String getSignatureString(String method, HttpUrl url, String body) throws UnsupportedEncodingException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
            String nonceStr = RandomStrUtils.getRandomString(32);
            long timestamp = System.currentTimeMillis() / 1000;
            String message = buildMessage(method, url, timestamp, nonceStr, body);
            String signature = sign(message.getBytes("utf-8"));
            log.info("签名值:[{}]", signature);
            return "WECHATPAY2-SHA256-RSA2048 mchid=\"" + mchid + "\","
                    + "nonce_str=\"" + nonceStr + "\","
                    + "timestamp=\"" + timestamp + "\","
                    + "serial_no=\"" + serial + "\","
                    + "signature=\"" + signature + "\"";
        }
    
        public static String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {
            Signature sign = Signature.getInstance("SHA256withRSA");
            InputStream resourceAsStream = WxSignatureUtil.class.getClassLoader().getResourceAsStream("apiclient_key.pem");
            sign.initSign(PemUtil.loadPrivateKey(resourceAsStream));
            sign.update(message);
            return Base64.getEncoder().encodeToString(sign.sign());
        }
    
        public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
            String canonicalUrl = url.encodedPath();
            if (url.encodedQuery() != null) {
                canonicalUrl += "?" + url.encodedQuery();
            }
            StringBuilder sb = new StringBuilder(method + "\n"
                    + canonicalUrl + "\n"
                    + timestamp + "\n"
                    + nonceStr + "\n");
            if (!StringUtils.isEmpty(body)) {
                sb.append(body + "\n");
            } else {
                sb.append(""+"\n");
            }
            String str = sb.toString();
            log.info("构造签名体:[{}]", str);
            return str;
        }
    
    }
    
    


    {

    "code": "SIGN_ERROR",

    "detail": {

    "detail": {

    "issue": "sign not match"

    },

    "field": "signature",

    "location": "authorization",

    "sign_information": {

    "method": "POST",

    "sign_message_length": 116,

    "truncated_sign_message": "POST\n/v3/new-tax-control-fapiao/fapiao-applications/upload-fapiao-file\n1722331061\nHp19Fkd3BaYXp3rMXSjzA88wJCT5GE32\n\n",

    "url": "/v3/new-tax-control-fapiao/fapiao-applications/upload-fapiao-file"

    }

    },

    "message": "错误的签名,验签失败"

    }我也遇到这种情况,兄弟你解决了吗

    07-30
    有用
    回复
登录 后发表内容