• 支付回调内容


    描述

      作为新手开发,哈哈,请大佬多加指点。

      nodejs开发微信公众号真的让我特别的烦,微信的沙箱功能一点都不好使。完成了支付功能后还要处理支付回调的业务逻辑,这次我要做的就是支付后完成推送模板消息的内容。

    过程

      填写完成支付的回调地址notify_url后,进入到了公网能够直接访问的回调地址。(这里需要注意的是回调和支付都要加入到支付的安全目录,比如支付或者回调的路由为http://www.aaa.ccc/pay/notify,则支付目录直接填写http://www.aaa.ccc/pay)

      当支付功能实现后,微信服务器会以post的方式访问这个地址,并提供一串xml格式的数据(解析xml的方式我觉得用raw-body或者koa-xml-body都是蛮不错的)。

      支付回调微信服务器会多次post请求,我试过用xml包装

      <xml>
        <return_code><![CDATA[<%=return_code%>]]></return_code>
        <return_msg><![CDATA[<%=return_msg%>]]></return_msg>
      </xml>

    但还是失败的,依然会多次请求。所以我就定义了一个变量,用作标量。但是这样会遇到的问题就是,一个人购买成功,推送了一条模板消息。接下来另外一个人购买,就会遇到推送不出去的模板消息。所以我做了一些调整,就是查询订单,然后再到数据库里面去查询订单,通过比较后再进行相应的逻辑处理。

    代码

       Demo1 

    const xmlParse = require('koa-xml-body');
    const getRawBody = require('raw-body');
    const heredoc = require('heredoc');
    const ejs = require('ejs');

    const util = require('../../utils/util');

    let flag = 1;
    /**
    微信回调通知
    */
    exports.notify = async(ctx,next)=>{
    console.log('<===============================支付回调开始==================================>');
    console.log('<===============================支付成功==================================>');
    let backXml = {};
    //console.log('支付回调后的数据:',ctx);
    let data = await getRawBody(ctx.req,{
      length:ctx.length,
      limit:'1mb',
      encoding:ctx.charset
    });
    data = await util.parseXMLAsync(data);
    data = util.formatMessage(data.xml);
    console.log('data:',data);
    ctx.data = data;
    if(data.result_code === 'SUCCESS' && (flag++) === 1){
      await putMsg.payOk(ctx,next);
      backXml.code = 'SUCCESS';
      backXml.msg = 'OK'
    }else{
      backXml.code = 'FAIL';
      backXml.msg = '报文为空';
    }
    console.log('<===============================支付回调结束==================================>');
      return backTemp(backXml);
    }

    /**
    用于返回给微信服务器的数据
    告诉微信服务器,我收到信息了,不要在调用回调action了
    */
    let backTemp = (data)=>{
      let xmlDataTmpl = heredoc(function(body){/*
         <xml>
          <return_code><![CDATA[<%=return_code%>]]></return_code>
          <return_msg><![CDATA[<%=return_msg%>]]></return_msg>
         </xml>
      */});
      data = ejs.compile(xmlDataTmpl)({return_code:data.code,return_msg:data.msg});
      console.log(data);
      return data;
    }

    Demo2

      查询订单orderquery

      exports.orderquery = async(ctx)=>{

    //请求路径

    let url = 'https://api.mch.weixin.qq.com/pay/orderquery';
    //请求参数
    let data = {

    appid : ctx.orderqueryData.appid,
    mch_id : ctx.orderqueryData.mch_id,
    out_trade_no : ctx.orderqueryData.out_trade_no,
    nonce_str : ctx.orderqueryData.nonce_str,
    transaction_id : ctx.orderqueryData.transaction_id,
    sign_type : ctx.orderqueryData.sign_type||'MD5',
    key : ctx.orderqueryData.key

    }
    let stringA = 'appid='+ data.appid
          +'&mch_id='+ data.mch_id
          +'&nonce_str='+ data.nonce_str
          +'&out_trade_no='+ data.out_trade_no
          +'&sign_type=' + data.sign_type
          +'&transaction_id='+ data.transaction_id;
    let stringSignTemp = stringA + '&key=' + config.config.wechat.key;
    console.log('加密的sign:',stringSignTemp);
    data.sign = MD5(stringSignTemp).toUpperCase();
    //封装成xml
    let xmlDataTmpl = heredoc(function(body){/*
        <xml>
        <appid><%=appid%></appid>
        <mch_id><%=mch_id%></mch_id>
        <nonce_str><%=nonce_str%></nonce_str>
        <out_trade_no><%=out_trade_no%></out_trade_no>
        <sign_type><%=sign_type%></sign_type>
        <transaction_id><%=transaction_id%></transaction_id>
        <sign><%=sign%></sign>
      </xml>
    */});
    data = ejs.compile(xmlDataTmpl)(data);
    console.log('orderquery的ejs解析支付的xml数据为:',data);
    data = await request({url:url,method:'post',body:data,xml:true});
    console.log('orderquery通过接口请求后得到的数据:',data.body);
    data = await util.parseXMLAsync(data.body);
    data = util.formatMessage(data.xml);
    console.log('经过处理后的data:',data);
    return data;

    }

      回调通知

    exports.notify = async(ctx,next)=>{
    console.log('<===============================支付回调开始==================================>');
    //用于返回给微信服务的状态通知
    let backXml = {};
    //解析微信服务器发过来的xml数据
    let data = await getRawBody(ctx.req,{
      length:ctx.length,
      limit:'1mb',
      encoding:ctx.charset
    });
    data = await util.parseXMLAsync(data);
    data = util.formatMessage(data.xml);
    //查询订单
    ctx.orderqueryData = data;
    data = await pay.orderquery(ctx);
    console.log('查询订单返回的数据:',data);
    //查询数据库里面的订单
    dbData = await Order.findOne({transaction_id:data.transaction_id}).exec();
    console.log('从数据库里面查询到的数据:',dbData);
    console.log('dbData',dbData);
    if(data.trade_state === 'SUCCESS' && !dbData){
      //生成订单
      let order = new Order({
      transaction_id : data.transaction_id
    });
    let doc = await order.save();
    if(doc){
      ctx.data = data;
      putMsg.payOk(ctx);
      backXml.code = "SUCCESS";
      backXml.msg = '添加订单成功!';
    }else{
      backXml.code = "FAIL";
      backXml.msg = '添加订单失败!';
    }
      return backTemp(backXml);
    }
    }

     

  • 相关阅读:
    mac下mysql忘记了密码怎么办
    图片标签的四种路径
    三栏布局
    MongoDB学习笔记
    mysql B+ 树
    移动终端设备ID
    前端基础HTML以及常用的标签
    python--os模块
    python--基本数据 类型
    python基础3、4---流程控制、运算符
  • 原文地址:https://www.cnblogs.com/TomAndJerry/p/9252199.html
Copyright © 2020-2023  润新知