微信小程序开发实战10_2 小程序支付请求签名

这篇具有很好参考价值的文章主要介绍了微信小程序开发实战10_2 小程序支付请求签名。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

为了保证支付接口使用的安全,微信支付平台在支付API中使用了一些用于接口安全调用的技术。在调用时接口需要使用商户私钥进行接口调用的签名,获取到微信支付平台的应答之后也需要对应答进行签名验证。微信的应答签名使用平台证书来进行签名验证,因此在调用支付接口前还需要实现平台证书的下载以及管理。另外微信支付在回调通知和平台证书下载接口中,对关键信息进行了AES-256-GCM加密,因此开发者还需要了解如何使用APIv3密钥进行数据解密。在调用具体接口之前需要了解这是逻辑,并实现接口调用的一些基础代码。

11.1基本规则

商户接入微信支付,调用API必须遵循以下规则:
1)微信支付API v3使用 JSON 作为消息体的数据交换格式。请求须设置HTTP头部:

  • Content-Type: application/json
  • Accept: application/json
    2)请求的唯一标识
    微信支付给每个接收到的请求分配了一个唯一标识。请求的唯一标识包含在应答的HTTP头Request-ID中。
    3)错误信息
    微信支付API v3使用HTTP状态码来表示请求处理的结果。
  • 处理成功的请求,如果有应答的消息体将返回200,若没有应答的消息体将返回204。
  • 已经被成功接受待处理的请求,将返回202。
  • 请求处理失败时,如缺少必要的入参、支付时余额不足,将会返回4xx范围内的错误码。
  • 请求处理时发生了微信支付侧的服务系统错误,将返回500/501/503的状态码。这种情况比较少见。
    4)User Agent
    HTTP协议要求发起请求的客户端在每一次请求中都使用HTTP头 User-Agent来标识自己。微信支付API v3很可能会拒绝处理无User-Agent 的请求。

11.2请求签名

微信支付使用APIv3密钥对请求进行签名。微信支付会在收到请求后进行签名的验证。如果签名验证不通过,微信支付将会拒绝处理请求,并返回401 Unauthorized。
开发人员调用支付接口时需要按照以下的规则构造签名串。签名串一共有五行,每一行为一个参数,行尾以 \n结束,包括最后一行。
HTTP请求方法\n
URL\n
请求时间戳\n
请求随机串\n
请求报文主体\n

然后使用商户私钥对待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。
微信支付要求请求使用HTTP Authorization头来传递签名。Authorization由认证类型和签名信息两个部分组成。具体内容为:

  • 认证类型,目前为WECHATPAY2-SHA256-RSA2048
  • 签名信息:包括发起请求的商户的商户号mchid,商户API证书的serial_no,请求随机串nonce_str,时间戳timestamp,签名值signature。
    Authorization 头的示例如下:
    Authorization:WECHATPAY2-SHA256-RSA2048 mchid=“1900009191”,nonce_str=“593BEC0C930BF1AFEB40B4A08C8FB242”,signature=“uOVRnA4qG…”,timestamp=“1554208460”,serial_no=“1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C”’
    下面我们一步步来实现向微信支付服务器发送一个POST请求,首先来看看如何生成向请求头中的Authorization信息。
    接下来首先给出商户数据结构的定义,定义商户对象是需要指定商户的类型(直连商户、服务商商户),以及商户的参数(商户号、商户关联的APPID), 以及为商户对象加载商户密钥以及商户证书。以下是商户结构的定义代码:
type MchWxapp struct {
   //商户类型 0直连商户 1服务商商户
   MchType       int
   //商户对应的appid
   Appid     string
   //商户号
   Mchid     string
   //商户的API v3密钥
   MchAPIKey  string
   //商户API私钥
   MchPrivateKey *rsa.PrivateKey
   //商户 API 证书
   MchCertificate *x509.Certificate
}

商户的API私钥用于生成调用签名,接下来给出商户密钥的加载代码:

func LoadPrivateKeyWithPath(path string) (privateKey *rsa.PrivateKey, err error) {
   privateKeyBytes, err := ioutil.ReadFile(path)
   if err != nil {
      return nil, err 
   }
   block, _ := pem.Decode([]byte(privateKeyStr))
   if block == nil {
      return nil, fmt.Errorf("decode private key err")
   }
   key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
   if err != nil {
      return nil, err 
   }
   privateKey, ok := key.(*rsa.PrivateKey)
   if !ok {
      return nil, fmt.Errorf("%s is not rsa private key", privateKeyStr)
   }
   return privateKey, nil
}

生成请求头Authorization信息时需要用到商户证书的SerialNumber,以下是商户证书的加载代码:

func LoadCertificateWithPath(path string) (certificate *x509.Certificate, err error) {
   certificateBytes, err := ioutil.ReadFile(path)
   if err != nil {
      return nil, err 
   }
   block, _ := pem.Decode([]byte(certificateStr))
   if block == nil {
      return nil, fmt.Errorf("decode certificate err")
   }
   certificate, err = x509.ParseCertificate(block.Bytes)
   if err != nil {
      return nil, err 
   }
}

接下来要进行签名串的构造以及对签名串进行签名,具体代码如下:

func GenerateWxPayReqHeader(ctx *MchParam, method string, rawUrl string, signBody string) (authorization string, err error){
   timestamp := time.Now().Unix()
   url, err := url.Parse(rawUrl)
   if err != nil {
      return "", err
   }
   nonce, err := GenerateNonce()
   if err != nil {
      return "", err
   }

   SignatureMessageFormat := "%s\n%s\n%d\n%s\n%s\n"
   message := fmt.Sprintf(SignatureMessageFormat, method, url.RequestURI(), timestamp, nonce, signBody)
   signatureResult, err := SignSHA256WithRSA(ctx.MchPrivateKey, message)
   if err != nil {
      return "", err
   }

   certSerialNo := fmt.Sprintf("%X", ctx.MchCertificate.SerialNumber)
   HeaderAuthorizationFormat := "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\""
   authorization = fmt.Sprintf(HeaderAuthorizationFormat, ctx.Mchid, nonce, timestamp, certSerialNo, signatureResult)
   return authorization, nil
}

代码中使用GenerateNonce()生成一个32个字节的请求随机串,并调用SignSHA256WithRSA对待签名串进行SHA256 with RSA签名。下面是函数SignSHA256WithRSA的实现:

func SignSHA256WithRSA(privateKey *rsa.PrivateKey, source string) 
	(signature string, err error) {
   h := crypto.Hash.New(crypto.SHA256)
   _, err = h.Write([]byte(source))
   if err != nil {
      return "", nil
   }
   hashed := h.Sum(nil)
   signatureByte, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
   if err != nil {
      return "", err
   }
   return base64.StdEncoding.EncodeToString(signatureByte), nil
}

最后来我们通过代码来看看如何通过HTTP的POST方法来调用支付接口。以下代码中去掉了响应数据签名验证的逻辑,响应数据签名验证稍后再来分析:文章来源地址https://www.toymoban.com/news/detail-500159.html

func WxPayPostV3(ctx *MchParam, url string, data []byte) (string, error) {
   token, err := GenerateWxPayReqHeader(ctx, http.MethodPost, url, string(data))
   if err != nil {
      log.Println(err)
      return "", err
   }

   request, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
   if err != nil {
      return "", err
   }
   request.Header.Add("Authorization", token)
   request.Header.Add("User-Agent", "go pay sdk")
   request.Header.Add("Content-type", "application/json;charset='utf-8'")
   request.Header.Add("Accept", "application/json")

   client := &http.Client{Timeout: 5 * time.Second}
   resp, err := client.Do(request)
   if err != nil {
      log.Println(err)
      return "", err
   }
   defer resp.Body.Close()

   result, _ := ioutil.ReadAll(resp.Body)
   if resp.StatusCode != 200 && resp.StatusCode != 204 {
      err := fmt.Errorf("status:%d;msg=%s", resp.StatusCode, string(result))
      log.Println(err)
      return string(result), err
   }

   return string(result), nil
}

到了这里,关于微信小程序开发实战10_2 小程序支付请求签名的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【小程序】零基础微信小程序开发+实战项目

    如何拥有一款属于你自己的小程序,惊喜就在下面! 目前,小程序行业已经成为互联网营销的热门黑马之一,依托于各大流量平台,小程序行业具有天然的用户基础和得天独厚的资源优势,凭借其方便快捷的操作以及简单通俗的模式,仅短短一年的时间,就迎来了爆发性的增

    2024年02月11日
    浏览(37)
  • 微信小程序开发入门与实战 ①(初始微信小程序)

    @作者 : SYFStrive   @博客首页 : HomePage 📜: 微信小程序 📌: 个人社区(欢迎大佬们加入) 👉: 社区链接🔗 📌: 觉得文章不错可以点点关注 👉: 微信小程序专栏🔗 💃: 感谢支持,学累了可以先看小段由小胖给大家带来的街舞😀 🔗: 阅读文章 👉 微信小程序 (🔥)

    2024年02月09日
    浏览(98)
  • 微信小程序开发实战9_2 小程序页面转发

    小程序页面转发是小程序分享的一个重要方式,在设计小程序应用时就需要考虑那些页面需要实现转发功能,以及页面的转发参数。本节介绍如何进行小程序页面的分享,并介绍如何获取小程序卡片的分享票据。 9.2.1小程序页面转发 微信小程序提供了页面的转发的功能,用户

    2024年02月16日
    浏览(33)
  • 微信小程序实战:智能水印相机小程序开发附源码

    一款智能水印相机,拍照自动添加时间、地点、经纬度等水印文字,可用于工作考勤、学习打卡、工作取证等,支持自定义内容以及给现有照片添加水印。无需安装,无需注册,即开即用。 主要是通过canvas给图片上添加上时间水印地点信息。首先通过官方API(chooseLocation)获取

    2024年02月09日
    浏览(42)
  • 微信小程序开发15 项目实战 基于云开发开发一个在线商城小程序

    在学完前 4 个模块之后,我相信你会对微信小程序的开发有一个全新的认识。在前面 3 个模块中,俊鹏分别从微信小程序内在的运行原理,小程序工程化开发以及具体实践层面,深度讲解了微信小程序开发所必要的知识和能力。而第 4 个模块里,我带你认识了微信小程序的云

    2024年02月11日
    浏览(35)
  • Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)

    欢迎继续阅读《Taro 小程序开发大型实战》系列,前情回顾: 熟悉的 React,熟悉的 Hooks:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型 多页面跳转和 Taro UI 组件库:我们用 Taro 自带的路由功能实现了多页面跳转,并用 Taro UI 组件库升级了应用界面 实现微信和支付

    2024年03月10日
    浏览(41)
  • 【微信小程序支付计算签名值-前端】

    1、后端通过JSAPI下单接口获取到发起支付的必要参数prepay_id,前端取到prepay_id就可以调用wx.requestPayment发起支付。调起支付的参数需要按照签名规则进行签名计算。微信支付文档 2、前端得到prepay_id后就可以按照规则计算签名了。 2.1 构造签名串,签名串一共有四行,每一行为

    2024年02月16日
    浏览(40)
  • (后续更新)【微信小程序】毕业设计 租房小程序开发实战,零基础开发房屋租赁系统小程序

    大家好,我是子木。 以前没接触过小程序,刚好毕业设计选题选到了小程序,有前端基础,于是在提交完开题后开始自学小程序(云开发),属于边学边开发的那种。缝缝补补,最终耗时1个多月写完了我的课题。 这段时间刚写完论文比较闲,所以来记录一下自己的开发过程

    2024年02月11日
    浏览(49)
  • uniapp微信小程序JSAPI支付前端生成签名,并调起微信支付

    签名方式使用的是SHA256withRSA 插件 npm install jsrsasign 使用

    2024年01月17日
    浏览(46)
  • 支付宝小程序开发踩坑笔记(支付宝、学习强国小程序)

    1、接口请求安卓端回调 success ,IOS 端回调 fail 原因: dataType 设置不对,默认是 json 格式,对返回数据会进行 json 解析,如果解析失败,就会回调 fail 。加密传输一般是 text 格式。 2、input 禁止输入空格 input 、 textarea 组件默认不会双向绑定,需要借助 setData 进行中转。 如果

    2024年01月25日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包