一文搞懂微信公众号中的网页授权支付

花了一些时间读完了微信公众号号支付流程,并实现了微信支付,在开发中遇见了不少坑,现在一一给大家讲解并说明解决方法。

准备步骤:

1、准备申请好的公众号,公众号中设置与开发-----基本配置中能够获取到公众号的id和secret:

        APPID:123456789123456

        AppSecret:123456789qwerty

2、 IP白名单设置:通过开发者ID及密码调用获取access_token接口时,需要设置访问来源IP为白名单。而access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。

3、服务器配置:

        1.URL:具体的一个服务器上请求路径,这里主要是用于验证消息的确来自微信服务器

        2.token需要自己配置,微信上的token需要和服务端的token一致,主要用于验证。

        这个地方配置了以后主要是用来做接收微信公众号中触发的各种事件:同名的该url需要get和post两种方式去实现,get请求用于做验证,post请求用于做微信回调事件触发。

举例:

@router.get("/checkOpenToken")
async def checkOpenToken(signature, timestamp, nonce, echostr):
    try:
        if sign_sha1(signature, timestamp, nonce):
            return int(echostr)
        else:
            logger.error("加密字符串 不等于 微信返回字符串,验证失败!!!")
            return "验证失败!"
    except Exception as error:
        return f"微信服务器配置验证出现异常:{error}"


@router.post("/checkOpenToken", summary="回复微信消息")
async def subscribed(request: Request, signature, timestamp, nonce, openid):
    if sign_sha1(signature, timestamp, nonce):
        try:
            rec_msg = await request.body()
            root = ET.fromstring(rec_msg)
            msg_type = root.find("MsgType").text
            adminid = root.find("ToUserName").text
            openid = root.find("FromUserName").text
            create_time = root.find("CreateTime").text
            event = root.find("Event").text
            eventKey = root.find("EventKey").text
            ####TODO   业务代码
            return JSONResponse(status_code=status.HTTP_200_OK, content="success"
                                )
        except Exception as error:
            logger.error(f"微信回复信息报错:{error}")
            return JSONResponse(status_code=status.HTTP_200_OK, content=error
                                )

def sign_sha1(signature, timestamp, nonce):
    temp = [settings.token, timestamp, nonce]
    temp.sort()
    hashcode = hashlib.sha1("".join(temp).encode('utf-8')).hexdigest()
    logger.info(f"加密:{hashcode},微信返回:{signature}")
    if hashcode == signature:
        return True

这里是公众号消息接收功能完成了。

接下来就是微信网页授权开发了:

       想要在公众号中嵌入自己的web页面需要在设置与开发----功能设置----网页授权域名中添加你的域名,你需要下载一个txt文件并放在根目录下,微信在你设置域名时去判断该文件是否存在,并且文件中内容是否一致。如此来确保页面正确。

之后你就可以访问该域名下的所有静态文件了。并在这些页面中你能够通过页面获取到网页授权access_token,这个网页授权access_token和普通的access_token是没有任何关联的。

网页授权token获取

最后一步我们该如何唤起微信支付呢?

首先登录【微信支付商户平台 (opens new window)—>产品中心—>开发配置】,设置后一般5分钟内生效。

这里需要选择JSAPI支付:按照规则填写,这里的域名必须是备案的。

这里我们可以在商户平台拿到我们需要的一些配置:

        1.商户id:123456789qwert

        2.商户证书序列号:由微信商户平台支持

        3.APIv3秘钥:需要申请商户API证书(只有超级管理员才能操作),API证书是有CA颁发,在APIv3中,调用微信支付所有接口需要

        4.私钥证书:将生成的证书放在项目中

开发步骤:

        1.将前端收到的回调:code携带,调用

        "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + settings.appid + "&secret=" + settings.appsecret + "&code=" + code + "&grant_type=authorization_code"

这个接口将会返回网页授权token,获取到网页授权token后,

        2.前端调用下订单接口:会返回给前端需要的prepay_id,paySign,noncestr,timestamp

这里为什么要将noncestr,timestamp一起返回呢,因为是要保持前端真正唤起微信支付的校验一致。支付完成后,就等着支付回调了。

        3.支付回调接口就是在前端发起真正支付请求时配置的,拿到支付回调我们需要解密回调接口收到的信息,返回所有传入的参数,进行我们入库的操作。

预支付:

@router.post("/order")
async def createOrder(wxpayRequest: WxpayRequest):
    # 调用接口创建订单
    try:
        out_trade_no = worker.get_id()
        description = goods_exist.goods_name
        print("description:" + str(description))
        amount = wxpayRequest.payer_total
        print("amount:" + str(amount))
        payer = {'openid': wxpayRequest.openid}
        print("payer:" + str(payer))
        code, message = wxpay.pay(
            description=description,
            out_trade_no=str(out_trade_no),
            amount={'total': amount},
            pay_type=WeChatPayType.JSAPI,
            payer=payer
        )
        print("code:" + str(code))
        result = json.loads(message)
        print("message:" + str(result))
        if code in range(200, 300):
            prepay_id = result.get('prepay_id')
            logger.info("获取预支付id" + str(prepay_id))
            timestamp = str(int(time.time()))
            noncestr = str(uuid.uuid4()).replace('-', '')
            package = 'prepay_id=' + prepay_id
            paySign = wxpay.sign([settings.appid, timestamp, noncestr, package])
            print("打印预支付签名:" + str(paySign))
            logger.info(f"创建一条order记录成功")
            return JSONResponse(status_code=status.HTTP_200_OK, content={
                "prepay_id": prepay_id,
                "paySign": paySign,
                "noncestr": noncestr,
                "timestamp": timestamp
            }
                                )
    except Exception:
        raise HTTPException(status_code=400, detail="下单失败,请稍后重试")

支付回调:

@router.post("/notify")
async def notify(request: Request):
    headers = {
        'Wechatpay-Signature': request.headers.get('wechatpay-signature'),
        'Wechatpay-Timestamp': request.headers.get('wechatpay-timestamp'),
        'Wechatpay-Nonce': request.headers.get('wechatpay-nonce'),
        'Wechatpay-Serial': request.headers.get('wechatpay-serial')
    }
    result = wxpay.callback(headers=headers, body=await request.body())
    print("打印回调结果:" + str(result))
    if result and result.get('event_type') == 'TRANSACTION.SUCCESS':
        resp = result.get('resource')
        out_trade_no = resp.get('out_trade_no')
        transaction_id = resp.get('transaction_id')
        success_time = resp.get('success_time')
        payer = resp.get('payer')
        print("打印用户:" + str(payer))
        openid = payer.get("openid")
        print("打印openid:" + openid)
        amount = resp.get('amount').get('total')
        # TODO: 根据返回参数进行必要的业务处理,处理完后返回200或204
        successTime = datetime.now()
        return {'code': 'SUCCESS', 'message': '成功'}
    else:
        return {'code': 'FAILED', 'message': '失败'}

至此整个业务流程完毕,并且能够实现微信支付。如果想要完整的工具和代码流程方法,请加入我们的公众号,我们的公众号是可以实现PDF总结,图片总结,网页总结等功能的哦,是一款十分好用的公众号,并且会定期推送对于开发有帮助的文章,我们一直关注于最新的AI前沿技术。

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CAN(Controller Area Network,控制器局域网)总线协议是一种广泛应用于工业自动化、汽车电子等领域的串行通讯协议。其帧格式如下: <img src="https://img-blog.csdnimg.cn/20200925125252655.png" width="400"> CAN总线协议的帧分为标准帧和扩展帧两种,其标准帧包含11位标识符,扩展帧包含29位标识符。在CAN总线上,所有节点都可以同时发送和接收数据,因此需要在帧包含发送方和接收方的信息。 帧格式的具体解释如下: 1. 帧起始符(SOF):一个固定的位模式,表示帧的起始。 2. 报控制(CTRL):包含几个控制位,如IDE、RTR等。其IDE表示标识符的类型,0表示标准帧,1表示扩展帧;RTR表示远程请求帧,0表示数据帧,1表示远程请求帧。 3. 标识符(ID):11位或29位的标识符,用于区分不同的CAN消息。 4. 控制域(CTL):包含几个控制位,如DLC、EDL等。其DLC表示数据长度,即数据域的字节数;EDL表示数据长度是否扩展,0表示标准数据帧,1表示扩展数据帧。 5. 数据域(DATA):0~8字节的数据。 6. CRC:用于校验数据是否正确。 7. 确认位(ACK):由接收方发送的确认信息,表示数据是否正确接收。 8. 结束符(EOF):一个固定的位模式,表示帧的结束。 以上就是CAN总线协议的帧格式。在实际应用,节点之间通过CAN总线进行数据交换,通过解析帧的各个字段,可以判断消息的发送方、接收方、数据内容等信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毛毛的毛毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值