欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#公众号开发之给用户发红包

程序员文章站 2023-12-13 11:23:10
红包功能简单介绍: 1、商户调用接口时,通过指定发送对象以及发送金额的方式发放红包,这样的方式,允许商户灵活的应用于各种各样丰富的活动场景 2、领取到红包后,用户的资金...

红包功能简单介绍:

1、商户调用接口时,通过指定发送对象以及发送金额的方式发放红包,这样的方式,允许商户灵活的应用于各种各样丰富的活动场景

2、领取到红包后,用户的资金直接进入微信零钱,避免繁复的领奖流程,带给用户微信支付原生的流畅体验

现金红包官网

调用现金红包接口需要使用到证书,请前往商户平台下载证书

官网有关详细证书的介绍,

因为发送现金红包是从商户平台余额扣款,所以商户平台的账户余额必须有充足的余额

下面是调用红包接口详细代码:

1、签名的md5加密类:

/// <summary>
/// md5utilhelper 的摘要说明。
/// </summary>
public class md5utilhelper
{
  public md5utilhelper()
  {
    //
    // todo: 在此处添加构造函数逻辑
    //
  }

  /// <summary>
      /// 获取大写的md5签名结果
  /// </summary>
  /// <param name="encypstr"></param>
  /// <param name="charset"></param>
  /// <returns></returns>
  public static string getmd5(string encypstr, string charset)
  {
    string retstr;
    md5cryptoserviceprovider m5 = new md5cryptoserviceprovider();

    //创建md5对象
    byte[] inputbye;
    byte[] outputbye;

    //使用gb2312编码方式把字符串转化为字节数组.
    try
    {
      inputbye = encoding.getencoding(charset).getbytes(encypstr);
    }
    catch (exception ex)
    {
      inputbye = encoding.getencoding("gb2312").getbytes(encypstr);
    }
    outputbye = m5.computehash(inputbye);

    retstr = system.bitconverter.tostring(outputbye);
    retstr = retstr.replace("-", "").toupper();
    return retstr;
  }
}

2、处理参数的类:

public class requesthandler
  {

    public requesthandler(httpcontext httpcontext)
    {
      parameters = new hashtable();

      this.httpcontext = httpcontext ?? httpcontext.current;

    }
    /// <summary>
    /// 密钥
    /// </summary>
    private string key;

    protected httpcontext httpcontext;

    /// <summary>
    /// 请求的参数
    /// </summary>
    protected hashtable parameters;

    /// <summary>
    /// debug信息
    /// </summary>
    private string debuginfo;

    /// <summary>
    /// 初始化函数
    /// </summary>
    public virtual void init()
    {
    }
    /// <summary>
    /// 获取debug信息
    /// </summary>
    /// <returns></returns>
    public string getdebuginfo()
    {
      return debuginfo;
    }
    /// <summary>
    /// 获取密钥
    /// </summary>
    /// <returns></returns>
    public string getkey()
    {
      return key;
    }
    /// <summary>
    /// 设置密钥
    /// </summary>
    /// <param name="key"></param>
    public void setkey(string key)
    {
      this.key = key;
    }

    /// <summary>
    /// 设置参数值
    /// </summary>
    /// <param name="parameter"></param>
    /// <param name="parametervalue"></param>
    public void setparameter(string parameter, string parametervalue)
    {
      if (parameter != null && parameter != "")
      {
        if (parameters.contains(parameter))
        {
          parameters.remove(parameter);
        }

        parameters.add(parameter, parametervalue);
      }
    }


    /// <summary>
    /// 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名
    /// </summary>
    /// <param name="key">参数名</param>
    /// <param name="value">参数值</param>
    /// key和value通常用于填充最后一组参数
    /// <returns></returns>
    public virtual string createmd5sign(string key, string value)
    {
      stringbuilder sb = new stringbuilder();

      arraylist akeys = new arraylist(parameters.keys);
      akeys.sort();

      foreach (string k in akeys)
      {
        string v = (string)parameters[k];
        if (null != v && "".compareto(v) != 0
          && "sign".compareto(k) != 0 && "key".compareto(k) != 0)
        {
          sb.append(k + "=" + v + "&");
        }
      }

      sb.append(key + "=" + value);
      string sign = md5utilhelper.getmd5(sb.tostring(), getcharset()).toupper();

      return sign;
    }

    /// <summary>
    /// 输出xml
    /// </summary>
    /// <returns></returns>
    public string parsexml()
    {
      stringbuilder sb = new stringbuilder();
      sb.append("<xml>");
      foreach (string k in parameters.keys)
      {
        string v = (string)parameters[k];
        if (regex.ismatch(v, @"^[0-9.]$"))
        {

          sb.append("<" + k + ">" + v + "</" + k + ">");
        }
        else
        {
          sb.append("<" + k + "><![cdata[" + v + "]]></" + k + ">");
        }

      }
      sb.append("</xml>");
      return sb.tostring();
    }


    /// <summary>
    /// 设置debug信息
    /// </summary>
    /// <param name="debuginfo"></param>
    public void setdebuginfo(string debuginfo)
    {
      this.debuginfo = debuginfo;
    }

    public hashtable getallparameters()
    {
      return this.parameters;
    }

    protected virtual string getcharset()
    {
      return this.httpcontext.request.contentencoding.bodyname;
    }
  }

3、调用现金红包处理类:

 /// <summary>
 /// 企业号微信支付接口
 /// </summary>
 public static class tenpay
 {

   #region 企业向用户发红包
   /// <summary>
   /// 用于企业向微信用户个人发红包
   /// 目前支持向指定微信用户的openid个人发红包
   /// </summary>
   /// <param name="certpassword">apiclient_cert.p12证书密码即商户号</param>
   /// <param name="data">微信支付需要post的xml数据</param>
   /// <param name="certpath">apiclient_cert.p12的证书物理位置(例如:e:\projects\文档\微信商户平台证书\商户平台api证书</param>
   /// <param name="timeout"></param>
   /// <returns></returns>
   public static string sendredpack(string data, string certpassword,string certpath, int timeout = config.time_out)
   {
     var urlformat = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
     string cert = certpath;

     servicepointmanager.servercertificatevalidationcallback = new remotecertificatevalidationcallback(checkvalidationresult);
     x509certificate2 cer = new x509certificate2(cert, certpassword, x509keystorageflags.persistkeyset | x509keystorageflags.machinekeyset);

     var formdatabytes = data == null ? new byte[0] : encoding.utf8.getbytes(data);
     memorystream ms = new memorystream();
     ms.write(formdatabytes, 0, formdatabytes.length);
     ms.seek(0, seekorigin.begin);//设置指针读取位置

     httpwebrequest request = (httpwebrequest)webrequest.create(urlformat);
     request.clientcertificates.add(cer);
     request.method = "post";
     request.timeout = timeout;

     request.useragent = "mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/31.0.1650.57 safari/537.36";

     #region 输入二进制流
     if (ms != null)
     {
       ms.position = 0;
       //直接写入流
       stream requeststream = request.getrequeststream();
       byte[] buffer = new byte[1024];
       int bytesread = 0;
       while ((bytesread = ms.read(buffer, 0, buffer.length)) != 0)
       {
         requeststream.write(buffer, 0, bytesread);
       }
       ms.close();//关闭文件访问
     }
     #endregion

     httpwebresponse response = (httpwebresponse)request.getresponse();

     using (stream responsestream = response.getresponsestream())
     {
       using (streamreader mystreamreader = new streamreader(responsestream, encoding.getencoding("utf-8")))
       {
         string retstring = mystreamreader.readtoend();
         return retstring;
       }
     }
   }
   private static bool checkvalidationresult(object sender, x509certificate certificate, x509chain chain, sslpolicyerrors errors)
   {
     if (errors == sslpolicyerrors.none)
       return true;
     return false;
   }
   #endregion

 }

4、调用现金红包接口

#region 发送红包
bool fals = false;  //记录发送红包是否成功
string xmlresult = null; //现金红包接口返回的xml
string certpath = null; //证书在服务器的物理位置
string data = null; //调用现金红包接口需要的数据
try
{
  //创建支付应答对象
  requesthandler packagereqhandler = new requesthandler(null);
  //初始化
  packagereqhandler.init();
  string noncestr = tenpayv3util.getnoncestr(); //时间戳
  //设置package订单参数
  packagereqhandler.setparameter("nonce_str", noncestr);  //随机字符串,不长于32位
  packagereqhandler.setparameter("mch_billno", system.configuration.configurationmanager.appsettings["tenpayv3_mchid"] + model.journalnumber);//商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字。接口根据商户订单号支持重入,如出现超时可再调用。
  packagereqhandler.setparameter("mch_id", system.configuration.configurationmanager.appsettings["tenpayv3_mchid"]); //微信支付分配的商户号
  packagereqhandler.setparameter("wxappid", system.configuration.configurationmanager.appsettings["tenpayv3_appid"]);//微信分配的公众账号id(企业号corpid即为此appid)。接口传入的所有appid应该为公众号的appid(在mp.weixin.qq.com申请的),不能为app的appid(在open.weixin.qq.com申请的)。 
  packagereqhandler.setparameter("send_name", "测试");//商户名称
  packagereqhandler.setparameter("re_openid", model.bankcard); //用户openid 接受红包的用户用户在wxappid下的openid
  packagereqhandler.setparameter("total_amount", convert.toint32((decimal)(model.amount * 100m)).tostring(cultureinfo.invariantculture)); //付款金额 单位分
  packagereqhandler.setparameter("total_num", "1"); //红包发放总人数
  packagereqhandler.setparameter("wishing", "测试红包"); //红包祝福语
  packagereqhandler.setparameter("client_ip", httpcontext.current.request.userhostaddress);//ip地址
  packagereqhandler.setparameter("act_name", "测试红包");//活动名称
  packagereqhandler.setparameter("remark", "测试红包");   //备注
  string sign = packagereqhandler.createmd5sign("key", system.configuration.configurationmanager.appsettings["tenpayv3_key"]);
  packagereqhandler.setparameter("sign", sign);            //签名
  data = packagereqhandler.parsexml();
  certpath = server.mappath("~/") + system.configuration.configurationmanager.appsettings["certpath"];
  xmlresult = sendredpack(data, system.configuration.configurationmanager.appsettings["tenpayv3_mchid"],certpath);
  var res = xdocument.parse(xmlresult);
  string return_code = res.element("xml").element("return_code").value;
  if ("success".equals(return_code))
  {
    string result_code = res.element("xml").element("result_code").value;
    if ("success".equals(result_code))
    {
      fals = true;
    }
  }
}
catch (exception exception)
{
}
#endregion

注意:证书所在文件夹权限,iis必须有权限对该文件夹操作的权限。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: