GO语言 GOLANG 上传微信电子小票图片
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 上传微信电子小票图片的更多相关文章
- C语言 HTTP上传文件-利用libcurl库上传文件
原文 http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们 ...
- Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)
ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...
- 从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.(抄的...) UEditor是非常好用的富文 ...
- hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images
hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images, 本例子主要是使用HTML5 的File API,建立一個可存取到该file的url, 一个空的img标签,ID为img0,把 ...
- 【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端
原文地址:http://docode.top/Article/Detail/10002 目录: 1.Http协议上传文件(以图片为例)请求报文体内容格式 2.完整版HttpWebRequest模拟上传 ...
- php用jquery-ajax上传多张图片限制图片大小
php用jquery-ajax上传多张图片限制图片大小 /** * 上传图片,默认大小限制为3M * @param String $fileInputName * @param number $siz ...
- MVC下form表单一次上传多种类型的图片(每种类型的图片可以上传多张)
form表单一次上传多种类型的图片(每种类型的图片可以上传多张) controller中的action方法 public ActionResult UploadImage( ) { in ...
- springboot上传文件并检查图片大小与格式
@PostMapping(value = "/uploadDriverImage") public JsonResVo uploadDriverImage(@RequestPara ...
- vue代码上传服务器后背景图片404解决方法
问题:代码上传服务器后,图片404,使用的font-awesome图标也是404 解决办法: 如果你用了vue-cil,那么在build目录下找到utils.js中的ExtractTextPlugin ...
- iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片
图片上传时必要将图片进行压缩,不然会上传失败 首先是同系统相册选择图片和视频.iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项 ...
随机推荐
- 【阿里云采购季】3月采购完,IT运维躺赢一年2
阿里云2020上云采购季正式上线啦!今年的采购季可以逛些啥? 采购季正式期时间: 3月2日-3月31日 在这段时间里,想买啥就买吧,别忘了把想买的产品加入购物车噢,特惠产品叠加购物车满减,更划算 ...
- 在游戏运营行业,Serverless 如何解决数据采集分析痛点?
简介: 众所周知,游戏行业在当今的互联网行业中算是一棵常青树.在疫情之前的 2019 年,中国游戏市场营收规模约 2884.8 亿元,同比增长 17.1%.2020 年因为疫情,游戏行业更是突飞猛进. ...
- 【ESSD技术解读-01】 云原生时代,阿里云 ESSD 快照服务 助力企业级数据保护
简介:本文以云原生为时代背景,介绍了阿里云块存储快照服务如何基于高性能 ESSD 云盘提升快照服务性能,提供轻量.实时的用户体验及揭秘背后的技术原理.依据行业发展及云上数据保护场景,为企业用户及备份 ...
- 谁来拯救存量SGX1平台?又一个内核特性合并的血泪史
简介: 今天的故事主角,是一个被称为Flexible Launch Control的SGX平台特性. 前言 自从Intel内核开发人员Jarkko Sakkinen于2017年9月2日在inte ...
- 从技术到科学,中国AI向何处去?
简介: 如果从达特茅斯会议起算,AI已经走过65年历程,尤其是近些年深度学习兴起后,AI迎来了空前未有的繁荣.不过,最近两年中国AI热潮似乎有所回落,在理论突破和落地应用上都遇到了挑战,外界不乏批评 ...
- [FAQ] 英文字母输入时变成了胖体
如下,在输入法上右键,切换为 "半角" 即可. Link:https://www.cnblogs.com/farwish/p/17513598.html
- IIncrementalGenerator 获取引用程序集的所有类型
本文告诉大家如何在使用 IIncrementalGenerator 进行增量的 Source Generator 生成代码时,如何获取到当前正在分析的程序集所引用的所有的程序集,以及引用的程序集里面的 ...
- C# 获取指定文件夹中所有的文件(包括子文件夹的文件)
有个需求中需要播放指定路径的声音,但你必须要有该路径的声音才可以播放,如果没有该文件则播放默认的声音,该方法用于初始化应用的时候获取指定目录的所有文件,便于后来播放声音的时判断路径是否存在. usin ...
- CF1800F Dasha and Nightmares
F.Dasha and Nightmares 题意:\(n\) 个字符串 \(s_i\),问有多少对不同的 \((i, j) \ (1 \le i \le j \le n)\),使得 \(s_i\) ...
- SpringBoot3.1.5对应新版本SpringCloud开发(1)-Eureka注册中心
服务的提供者和消费者 服务之间可以通过Spring提供的RestTemplate来进行http请求去请求另一个Springboot的项目,这就叫做服务间的远程调用. 当一个服务通过远程调用去调用另一个 ...