GO语言 GOLANG 上传微信电子小票图片、GO HTTP POST 图片文件、GO 上传图片文件、multipart/form-data、image/jpeg、image/png。

GO 环境:

go version go1.21.4 windows/amd64

为了方便调试,我把http header Authorization、报文 meta json、都放在了TXT里。

package test

import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
person "main/models"
"net/http"
"os"
"path/filepath"
"strings"
) func TestWxXpUp() { fmt.Println(" 微信电子小票上传接口 ") // 设置代理
// os.Setenv("HTTP_PROXY", "http://127.0.0.1:8899")
// os.Setenv("HTTPS_PROXY", "https://127.0.0.1:9743") // 获取当前工作目录
dir, err := os.Getwd()
if err != nil {
fmt.Println("无法获取当前工作目录:", err)
return
} boundary := "ASSDFWDFBFWEFWWDF" //可以自己设定,需要比较复杂的字符串作
// 图片文件 START
picFilePath := "D:\\GO语言源码\\L1\\微信截图_20231124093553.jpg" var picBytes []byte
if _, err := os.Lstat(picFilePath); err == nil {
file, _ := os.Open(picFilePath)
defer file.Close() picBytes, _ = io.ReadAll(file)
} else {
log.Fatal("文件不存在:" + picFilePath)
} // 图片文件 END bodyFilePath := filepath.Join(dir, "xp_body.txt")
headerAuthPath := filepath.Join(dir, "xp_header.txt") // 报文 meta json
bodyBytes, err := os.ReadFile(bodyFilePath)
if err != nil {
fmt.Println("无法读取文件:", err)
return
} strBodyMeta := string(bodyBytes)
fmt.Println("文件内容:" + strBodyMeta) // http header Authorization
headerBytes, err := os.ReadFile(headerAuthPath)
if err != nil {
fmt.Println("无法读取文件:", err)
return
} strHeader := string(headerBytes)
fmt.Println("文件内容:" + strHeader) fileContentType := "image/jpeg"
pngsuffix := ".png"
//用文件后缀判定图片类型,不一定准确
picFilePathLowered := strings.ToLower(picFilePath)
if endsWith(picFilePathLowered, pngsuffix) {
fileContentType = "image/png"
} // HTTP 拼装开始
picData := "--" + boundary + "\r\n"
// HTTP 文本组装
picData = picData + "Content-Disposition:form-data;name=\"meta\"\r\nContent-Type:application/json\r\n\r\n"
picData = picData + string(bodyBytes) + "\r\n"
picData = picData + "--" + boundary + "\r\n"
// HTTP 文件组装
picData = picData + "Content-Disposition: form-data; name=\"file\"; filename=\"" + picFilePath + "\"\r\n" + "Content-Type: " + fileContentType + "\r\n\r\n"
picData = picData + string(picBytes) + "\r\n"
//最后的boundary 尾部会加2个-
picData = picData + "--" + boundary + "--" var myUrl = "https://api.mch.weixin.qq.com/v3/marketing/shopping-receipt/shoppingreceipts" // 创建一个HTTP请求,并设置请求方法和URL
req, err := http.NewRequest("POST", myUrl, strings.NewReader(picData))
if err != nil {
fmt.Println("创建请求时发生错误:", err)
return
} // 设置请求的Content-Type头部为
req.Header.Set("Content-Type", "multipart/form-data;boundary="+boundary)
req.Header.Set("Authorization", strHeader)
// 设置Accept 和 User-Agent 不然也会报错
req.Header.Set("User-Agent", "MyCustomUserAgent")
req.Header.Set("Accept", "application/json") // 创建一个HTTP客户端并发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("发送请求时发生错误:", err)
return
}
defer resp.Body.Close() // 读取响应的内容
body := &bytes.Buffer{}
_, err = body.ReadFrom(resp.Body)
if err != nil {
fmt.Println("读取响应时发生错误:", err)
return
} // 打印响应的状态码和内容
fmt.Println("响应状态码:", resp.StatusCode)
fmt.Println("响应内容:", body.String())
} func endsWith(str, suffix string) bool {
return len(str) >= len(suffix) && str[len(str)-len(suffix):] == suffix
}

控制台输出:

微信电子小票上传接口
文件body内容:{"transaction_id":"4200001992202311246726XXXX","openid":"ooIeqs39EYwsHoRh_q0GmQE_XXXX","sha256":"7a205561ba1995dac8f41851dd256731393a64db7435f75befa876c4dd3dc5c5","transaction_sub_mchid":"40082XXXX"}
文件header auth内容:WECHATPAY2-SHA256-RSA2048 mchid="21220XXXX",nonce_str="e804ba603e06410b9a04ffe5575fe385",signature="U+uBfn3xQIWmonvjvloWIupNPduKpfOut3y6YqETM7WjKxO6eCjn+pRPbT642XTiWeK7gEMsGF0V4n1ttgpd50870zUSepqbuU6jJ8TFwzE5cUQTvKs+7LJTy72XooS4wx8X+mAgwyR6nnhlRbdNAeQE+2TDVhs98juhvlGrxeuaNBavtHs/Hvp8kVcjsi/FXtNmU7ugMIS7EpSxgnF7qCf3x9MtTyzI1hvsq7oIjFcK3TY3+qDRQpcxYkiDXrB/eJmVipHbNAj+nfwMqlK3dUi0kftTIEnLkT36NKNuI+7B/Wy5hiv8dfrZZYkNVo9HYkvjO+rQRuj3QDgtlJROCQ==",timestamp="1700813854",serial_no="7B3505BC4F006C713E217C2E3FCE6ED5xxxxx"
响应状态码: 401
响应内容: {"code":"SIGN_ERROR","message":"Http头Authorization中的timestamp与发起请求的时间不得超过5分钟"}

重点:

picData = picData + "Content-Disposition: form-data; name=\"file\"; filename=\"" + picFilePath + "\"\r\n" + "Content-Type: " + fileContentType + "\r\n\r\n"

这段原生报文里,一个空格都不能多,一个引号都不能少。否则微信会报错。

先前用C#调试,老报错,尝试POSTMAN,居然是通的,把“https://api.mch.weixin.qq.com”改成 HTTP的,然后用FIDDLER 抓包。和C#程序生成的报文做对比,才发现少了些空格,把它改成POSTMAN一样的格式后,成功。

--

GO语言 GOLANG 上传微信电子小票图片的更多相关文章

  1. C语言 HTTP上传文件-利用libcurl库上传文件

    原文  http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们 ...

  2. Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)

    ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...

  3. 从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能

    UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.(抄的...) UEditor是非常好用的富文 ...

  4. hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images

    hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images, 本例子主要是使用HTML5 的File API,建立一個可存取到该file的url, 一个空的img标签,ID为img0,把 ...

  5. 【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

    原文地址:http://docode.top/Article/Detail/10002 目录: 1.Http协议上传文件(以图片为例)请求报文体内容格式 2.完整版HttpWebRequest模拟上传 ...

  6. php用jquery-ajax上传多张图片限制图片大小

    php用jquery-ajax上传多张图片限制图片大小 /** * 上传图片,默认大小限制为3M * @param String $fileInputName * @param number $siz ...

  7. MVC下form表单一次上传多种类型的图片(每种类型的图片可以上传多张)

    form表单一次上传多种类型的图片(每种类型的图片可以上传多张) controller中的action方法 public ActionResult UploadImage( )        { in ...

  8. springboot上传文件并检查图片大小与格式

    @PostMapping(value = "/uploadDriverImage") public JsonResVo uploadDriverImage(@RequestPara ...

  9. vue代码上传服务器后背景图片404解决方法

    问题:代码上传服务器后,图片404,使用的font-awesome图标也是404 解决办法: 如果你用了vue-cil,那么在build目录下找到utils.js中的ExtractTextPlugin ...

  10. iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片

    图片上传时必要将图片进行压缩,不然会上传失败 首先是同系统相册选择图片和视频.iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项 ...

随机推荐

  1. 剑指offer39(Java)-数组中出现次数超过一半的数字(简单)

    题目: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, ...

  2. 牛客网-SQL专项训练7

    ①SQL语言可以分为多个类别,那么不属于数据操纵语言DML的是(B) 解析: SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL. 1. 数据查询语 ...

  3. 现代斗山X瓴羊:“一横四纵“解决方案聚焦中台场景级部署

    简介: 经过充分的调研后,现代斗山IT团队和业务团队,与瓴羊数据中台项目组一起完成了涵盖客户.商机.设备等多层面的问题梳理及痛点分析,并借助于瓴羊Dataphin+Quick BI+Quick Aud ...

  4. Dataphin产品核心功能大图(六)发布中心:生产和开发隔离模式下的保护伞

    ​简介:Dataphin,用中台方法论打造企业级好数据.Dataphin是阿里巴巴集团OneData数据治理方法论内部实践的云化输出,一站式提供数据采.建.管.用全生命周期的大数据能力,以助力企业显著 ...

  5. 饿了么EMonitor演进史

    简介: 可观测性作为技术体系的核心环节之一,跟随饿了么技术的飞速发展,不断自我革新. 序言 时间回到2008年,还在上海交通大学上学的张旭豪.康嘉等人在上海创办了饿了么,从校园外卖场景出发,饿了么一步 ...

  6. 【ClickHouse 技术系列】- 在 ClickHouse 中处理实时更新

    ​简介:本文翻译自 Altinity 针对 ClickHouse 的系列技术文章.面向联机分析处理(OLAP)的开源分析引擎 ClickHouse,因其优良的查询性能,PB级的数据规模,简单的架构,被 ...

  7. 干掉讨厌的 CPU 限流,让容器跑得更快

    ​简介: 让人讨厌的 CPU 限流影响容器运行,有时人们不得不牺牲容器部署密度来避免 CPU 限流出现.本文介绍的 CPU Burst 技术可以帮助您既能保证容器运行服务质量,又不降低容器部署密度.文 ...

  8. SpringBoot项目实现日志打印SQL明细(包括SQL语句和参数)几种方式

    前言 我们在开发项目的时候,都会连接数据库.有时候遇到问题需要根据我们编写的SQL进行分析,但如果不进行一些开发或者配置的话,这些SQL是不会打印到控制台的,它们默认是隐藏的.下面给大家介绍几种常用的 ...

  9. Fixing Missing Windows App Runtime Environment Prompt for Unpackaged WinUI 3 Applications

    This article will tell you how to fix the prompt for a missing Windows App Runtime environment when ...

  10. dockerfile构建镜像常用命令

    一.什么是dockerfile Dockerfile是一个包含用于组合映像的命令的文本文档.可以使用在命令行中调用任何命令. Docker通过读取Dockerfile中的指令自动生成映像. docke ...