好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C# MVC 微信支付教程系列之扫码支付代码实例

今天,我们来一起探讨一下这个微信扫码支付。何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微信号,也可以扫一扫对方的二维码。扫码支付,作为,微信支付里面,不可或缺的一个功能,对商品的支付提供了极为方便的体验,用途也非常的多。

例如我们在地铁、公交站常见的那些自动售货机(不错,就是那种投硬币,就可以自动出货的那种机器)中都用到。微信(支付宝)的扫码支付的出现,大大的减少了这方面的风险,近些年来,二维码的应用越来越广,甚至有些地方,直接用来自动售票(就是把起始点设定好,票价设定好,直接把二维码贴出来,让乘客自动扫相关的二维码,完成购票,上车的时候,只需要提供自己的支付凭证给乘车员验证即可),这样,不仅绿色环保了,还大大的提高了售票的速度(去过大车站购票的人应该深有体验,排队买个票,好歹半个小时以上,心里也是万头草泥马在奔腾的)。

咱就不扯远了,说回咱么今天要做的微信支付之扫码支付。微信官方的文档,这个扫码支付(nativepay)分为两种,一种是[生成扫描支付模式],另外一种是[生成直接支付url,支付url有效期为2小时],至于这里面,两种扫码模式,怎么灵活利用呢,官方也没有一个明确的说明。个人理解为,第一种(生成扫描支付模式),适用于固定二维码的,就是永久使用的那种。

例如一些商家的公众号的二维码,是永久的,什么时候扫,都是关注这个公众号的,但是,这种的话,我记得微信是有限量的,貌似是一个公众号,限量10w,个人观点,觉得这个限量,是足够我们使用的。第二种(生成直接支付url,支付url有效期为2小时),这种的话,因为有有效期这种时间限制,超过了2个小时,该二维码就失效,但是对生成的二维码数量没有限制,所以,这种个人观点觉得适用于那种临时根据实际情况生成的二维码,例如:公众平台登陆的时候二次验证的二维码,自定义生成,仅为一次性缴费使用的二维码,等等)。接下来,我们就开始讲讲实际例子,首先将的就是第一种模式。

扫码支付之模式一(生成扫描支付模式):

首先,我们新建一个[mvc]的项目(asp.net的官方的demo就是了,要asp.net的自己看demo吧,demo地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1),然后把系统自动生成的homecontroler和view中的home都删了。

然后自己新建一个homecontroler,代码如下:

?

// get: home

public actionresult index()

{

  return view();

}

再添加一个view,代码如下:

?

@{

  layout = null;

}

<!doctype html>

< html >

< head >

  < meta name = "viewport" content = "width=device-width" />

  < title >首页</ title >

</ head >

< body >

  < div >

  </ div >

</ body >

</ html >

接下来,我们先把官方的demo的一些我们会用到的东西拷贝过来,其中包括以下几个文件夹,如下图:

就这个lib和business两个,把这两个文件夹,支付复制到咱们的新项目中,并且包含在项目中,如下:

然后我们再[重新生成]以下项目,或者快捷键:ctrl+shift+b,这时候,会提下如下错误:

这时候,我们去添加引用,把lib文件夹中的litjson.dll 添加上即可,如下图:

到这里,我们就基本把官方的demo的环境给搭建好了,接下来,我们就要开始编写代码了。

首先,我的逻辑是,从前到后,就是从前端到后端。前端是显示二维码的地方,那么我们就先给他一个div(本文使用到的是jquery的二维码生成插件,全名叫:jquery.qrcode.min.js,我会传到附件上),然后在页面加载完毕的时候,会请求后台,让他返回二维码字符串,然后再通过jquery的二维码生成插件,让他生成二维码并显示在前台,代码如下:

前端:

?

@{

  layout = null ;

}

<!doctype html>

<html>

<head>

  <meta name= "viewport" content= "width=device-width" />

  <title>首页</title>

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel= "stylesheet" />

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/mobile.css" rel= "stylesheet" />

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/icon.css" rel= "stylesheet" />

</head>

<body>

  <p>

   模式一:生成扫描支付模式

   <br />

   <div id= "qrcode1" >

   </div>

  </p>

  <p>

   模式二:生成直接支付url,支付url有效期为2小时

   <br />

   <div id= "qrcode2" >

   </div>

  </p>

  <script src= "~/scripts/jquery-1.10.2.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/jquery.easyui.min.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/easyloader.js" ></script>

  <script src= "~/scripts/jquery.qrcode.min.js" ></script>

  <script type= "text/javascript" >

   $( function () {

    fgetqrcode1();

   })

   function fgetqrcode1() {

    $.messager.progress({

     title: "" ,

     msg: "正在生成二维码:模式一,请稍后..."

    });

    $.ajax({

     type: "post" ,

     url: "/home/getqrcode1" ,

     data: {

      time: new date(),

      productid:7788

     },

     success: function (json) {

      $.messager.progress( 'close' ); //记得关闭

      if (json.result) {

       $( '#qrcode1' ).qrcode(json.str); //生成二维码

      }

      else {

       $( '#qrcode1' ).html( "二维码生成失败" );

      }

     }

    })

   }

  </script>

</body>

</html>

后端:

?

using system;

using system.collections.generic;

using system.linq;

using system.web;

using system.web.mvc;

using wxpayapi;

namespace wxpay.controllers

{

  public class homecontroller : controller

  {

   // get: home

   public actionresult index()

   {

    return view();

   }

   /// <summary>

   /// 模式一

   /// </summary>

   /// <returns></returns>

   [httppost]

   public actionresult getqrcode1()

   {

    object objresult = "" ;

    string strproductid = request.form[ "productid" ];

    string strqrcodestr = getprepayurl(strproductid);

    if (! string .isnullorwhitespace(strproductid))

    {

     objresult = new { result = true , str = strqrcodestr };

    }

    else

    {

     objresult = new { result = false };

    }

    return json(objresult);

   }

   /**

   * 生成扫描支付模式一url

   * @param productid 商品id

   * @return 模式一url

   */

   public string getprepayurl( string productid)

   {

    wxpaydata data = new wxpaydata();

    data.setvalue( "appid" , wxpayconfig.appid); //公众帐号id

    data.setvalue( "mch_id" , wxpayconfig.mchid); //商户号

    data.setvalue( "time_stamp" , wxpayapi.generatetimestamp()); //时间戳

    data.setvalue( "nonce_str" , wxpayapi.generatenoncestr()); //随机字符串

    data.setvalue( "product_id" , productid); //商品id

    data.setvalue( "sign" , data.makesign()); //签名

    string str = tourlparams(data.getvalues()); //转换为url串

    string url = "weixin://wxpay/bizpayurl?" + str;

    return url;

   }

   /**

   * 参数数组转换为url格式

   * @param map 参数名与参数值的映射表

   * @return url字符串

   */

   private string tourlparams(sorteddictionary< string , object > map)

   {

    string buff = "" ;

    foreach (keyvaluepair< string , object > pair in map)

    {

     buff += pair.key + "=" + pair.value + "&" ;

    }

    buff = buff.trim( '&' );

    return buff;

   }

  }

}

这时候,模式一是不是感觉就完成了?那么我们现在试试,我们浏览该页面,如下:

然后用微信扫一扫功能扫一下,发现提示如下:

这是什么鬼,是不是,你心里面是不是想知道为啥,那我来告诉你,这是为啥,这是因为,你还没有设置回调页面或者回调页面有问题,这个时候,我们再新建一个control,命名为:nativenotifycontroller.cs,代码如下:

?

using system;

using system.collections.generic;

using system.linq;

using system.text;

using system.web;

using system.web.mvc;

using wxpayapi;

namespace wxpay.controllers

{

  public class nativenotifycontroller : controller

  {

   // get: nativenotify

   public actionresult index()

   {

    string strdata = processnotify();

    response.write(strdata);

    return view();

   }

   public string processnotify()

   {

    wxpaydata notifydata = getnotifydata();

    //检查openid和product_id是否返回

    if (!notifydata.isset( "openid" ) || !notifydata.isset( "product_id" ))

    {

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , "回调数据异常" );

     return res.toxml();

    }

    //调统一下单接口,获得下单结果

    string openid = notifydata.getvalue( "openid" ).tostring();

    string product_id = notifydata.getvalue( "product_id" ).tostring();

    wxpaydata unifiedorderresult = new wxpaydata();

    try

    {

     unifiedorderresult = unifiedorder(openid, product_id);

    }

    catch (exception ex) //若在调统一下单接口时抛异常,立即返回结果给微信支付后台

    {

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , "统一下单失败" );

     return res.toxml();

    }

    //若下单失败,则立即返回结果给微信支付后台

    if (!unifiedorderresult.isset( "appid" ) || !unifiedorderresult.isset( "mch_id" ) || !unifiedorderresult.isset( "prepay_id" ))

    {

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , "统一下单失败" );

     return res.toxml();

    }

    //统一下单成功,则返回成功结果给微信支付后台

    wxpaydata data = new wxpaydata();

    data.setvalue( "return_code" , "success" );

    data.setvalue( "return_msg" , "ok" );

    data.setvalue( "appid" , wxpayconfig.appid);

    data.setvalue( "mch_id" , wxpayconfig.mchid);

    data.setvalue( "nonce_str" , wxpayapi.generatenoncestr());

    data.setvalue( "prepay_id" , unifiedorderresult.getvalue( "prepay_id" ));

    data.setvalue( "result_code" , "success" );

    data.setvalue( "err_code_des" , "ok" );

    data.setvalue( "sign" , data.makesign());

    return data.toxml();

   }

   /// <summary>

   /// 接收从微信支付后台发送过来的数据并验证签名

   /// </summary>

   /// <returns>微信支付后台返回的数据</returns>

   public wxpaydata getnotifydata()

   {

    //接收从微信后台post过来的数据

    system.io.stream s = request.inputstream;

    int count = 0;

    byte [] buffer = new byte [1024];

    stringbuilder builder = new stringbuilder();

    while ((count = s.read(buffer, 0, 1024)) > 0)

    {

     builder.append(encoding.utf8.getstring(buffer, 0, count));

    }

    s.flush();

    s.close();

    s.dispose();

    //转换数据格式并验证签名

    wxpaydata data = new wxpaydata();

    try

    {

     data.fromxml(builder.tostring());

    }

    catch (wxpayexception ex)

    {

     //若签名错误,则立即返回结果给微信支付后台

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , ex.message);

    }

    return data;

   }

   private wxpaydata unifiedorder( string openid, string productid)

   {

    //统一下单

    wxpaydata req = new wxpaydata();

    req.setvalue( "body" , "广东xxxx股份有限公司" );

    req.setvalue( "attach" , "附加信息,用于后台或者存入数据库,做自己的判断" );

    req.setvalue( "out_trade_no" , wxpayapi.generateouttradeno());

    req.setvalue( "total_fee" , 1);

    req.setvalue( "time_start" , datetime.now.tostring( "yyyymmddhhmmss" ));

    req.setvalue( "time_expire" , datetime.now.addminutes(10).tostring( "yyyymmddhhmmss" ));

    req.setvalue( "goods_tag" , "商品的备忘,可以自定义" );

    req.setvalue( "trade_type" , "native" );

    req.setvalue( "openid" , openid);

    req.setvalue( "product_id" , productid);

    wxpaydata result = wxpayapi.unifiedorder(req);

    return result;

   }

  }

}

记得,也要新建一个view,就是在index那里,右键添加一个view,view的代码如下(你没眼花,就是空的,不管他):

?

@{

  layout = null;

}

<!doctype html>

< html >

< head >

  < meta name = "viewport" content = "width=device-width" />

  < title >index</ title >

</ head >

< body >

  < div >

  </ div >

</ body >

</ html >

接着,把这个项目,发布出来,放到服务器的iis上,这里面,我把他发布在http://sm.lmx.ren/上面(必须要发布到网上哈,如果不懂发布的,你可以自己去学习基础知识先了),这还没完,还需要把到公众平台上,设置回调页面,操作如下:

这样,就大功告成了。这时候,我们再试试扫码,发现已经得到以下提示了,这样子,就代表,我们的模式一,已经成功完成了。如下图:

 

这时候,细心的朋友就会提问了,我这都支付成功了,怎么页面没啥提示呀,这页面不交互很不友好啊。嗯,没错,童鞋,你有前途,现在我就告诉你,怎么做交互,但是,为了你日后更加有前途,我只告诉你逻辑,具体怎么实现,自己来想,多动脑。

那么逻辑是怎么的呢?常规逻辑下,我们微信扫页面上的这个二维码的时候,这个时候,他已经把我们二维码里面的参数,传到微信服务器,然后有他们开始统一下单(如果对逻辑不清晰,可以看看官方的文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3):他们在统一下单的时候,就会生成一个product_id,这个家伙的作用呢 ,就是告诉你现在微信服务器,已经生成了一个单号,劳资已经收到你的支付请求了,赶紧给老子付款,o(∩_∩)o哈哈~。。。停,停,停。这时候,思路不能继续往下走了。

记得,前面有个叫做[统一下单[,那既然有这个步骤,那我们可以利用一下,就是当他统一下单成功的时候,我们可以在页面更新一下状态,告诉客户:您已成功扫描,并下单成功,请支付。是不是,我们可以提示他们这个。然后等用户在手机上,支付成功的时候,这个时候,页面是不是也要反馈给用户,告诉他,小子,你的钱已经到我的口袋了,你可以走了(你走,我没有你这样的宝宝)。o(∩_∩)o哈哈~,但是,你还要停,停住,停下来。我们服务公司怎么知道这个微信用户已经付款成功了呢?来,我们把视线回到代码上,找到lib/config.cs,如下图:

然后打开config.cs,找到以下代码:

对了,你很聪明。微信的处理逻辑就是,等用户支付成功之后,他会给这个链接发送支付结果,默认是以前那个aspx的页面,现在我换成mvc,所以,我们得手动新建一个control了,命名为:resultnotifycontroller,然后代码如下:

?

using lmxpublic.log;

using system;

using system.collections.generic;

using system.linq;

using system.text;

using system.web;

using system.web.mvc;

using wxpayapi;

namespace wxpay.controllers

{

  public class resultnotifycontroller : controller

  {

   // get: resultnotify

   public actionresult index()

   {

    string strdata = processnotify();

    response.write(strdata);

    return view();

   }

   public string processnotify()

   {

    wxpaydata notifydata = getnotifydata();

    //检查支付结果中transaction_id是否存在

    if (!notifydata.isset( "transaction_id" ))

    {

     //若transaction_id不存在,则立即返回结果给微信支付后台

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , "支付结果中微信订单号不存在" );

     return res.toxml();

    }

    string transaction_id = notifydata.getvalue( "transaction_id" ).tostring();

    //查询订单,判断订单真实性

    if (!queryorder(transaction_id))

    {

     //若订单查询失败,则立即返回结果给微信支付后台

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , "订单查询失败" );

     return res.toxml();

    }

    //查询订单成功

    else

    {

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "success" );

     res.setvalue( "return_msg" , "ok" );

     log.info( this .gettype().tostring(), "order query success : " + res.toxml());

     string strxml = res.toxml();

     filelog.writelog(strxml);

     return res.toxml(); //如果我们走到这一步了,那就代表,用户已经支付成功了,所以,该干嘛干嘛了。

    }

   }

   /// <summary>

   /// 接收从微信支付后台发送过来的数据并验证签名

   /// </summary>

   /// <returns>微信支付后台返回的数据</returns>

   public wxpaydata getnotifydata()

   {

    //接收从微信后台post过来的数据

    system.io.stream s = request.inputstream;

    int count = 0;

    byte [] buffer = new byte [1024];

    stringbuilder builder = new stringbuilder();

    while ((count = s.read(buffer, 0, 1024)) > 0)

    {

     builder.append(encoding.utf8.getstring(buffer, 0, count));

    }

    s.flush();

    s.close();

    s.dispose();

    log.info( this .gettype().tostring(), "receive data from wechat : " + builder.tostring());

    //转换数据格式并验证签名

    wxpaydata data = new wxpaydata();

    try

    {

     data.fromxml(builder.tostring());

    }

    catch (wxpayexception ex)

    {

     //若签名错误,则立即返回结果给微信支付后台

     wxpaydata res = new wxpaydata();

     res.setvalue( "return_code" , "fail" );

     res.setvalue( "return_msg" , ex.message);

     log.error( this .gettype().tostring(), "sign check error : " + res.toxml());

     return res;

    }

   

    return data;

   }

   //查询订单

   private bool queryorder( string transaction_id)

   {

    wxpaydata req = new wxpaydata();

    req.setvalue( "transaction_id" , transaction_id);

    wxpaydata res = wxpayapi.orderquery(req);

    if (res.getvalue( "return_code" ).tostring() == "success" &&

     res.getvalue( "result_code" ).tostring() == "success" )

    {

     return true ;

    }

    else

    {

     return false ;

    }

   }

  }

}

前台,对,也是要新建一个view,代码如下(没错,也是空的)

?

@{

  layout = null;

}

<!doctype html>

< html >

< head >

  < meta name = "viewport" content = "width=device-width" />

  < title >index</ title >

</ head >

< body >

  < div >

  </ div >

</ body >

</ html >

好,模式一就到这里了,呼呼。。。没想到啊,一个模式一,让我从上午写到下午,真心累。。。还有一个模式二呢。。。喝口水先,咱,接着来。

好,喝完水,接着干,下面是模式二:

模式二(生成直接支付url,支付url有效期为2小时)

由于有了上面模式一的详细说明,模式二,我就简单一点的来说了,如果又不懂的,到群里来问我吧。

模式二,前端,增加一些代码,如下(完整的,包括模式一的代码了):

?

@{

  layout = null ;

}

<!doctype html>

<html>

<head>

  <meta name= "viewport" content= "width=device-width" />

  <title>首页</title>

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel= "stylesheet" />

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/mobile.css" rel= "stylesheet" />

  <link href= "~/scripts/jquery-easyui-1.4.5/themes/icon.css" rel= "stylesheet" />

</head>

<body>

  <p>

   模式一:生成扫描支付模式

   <br />

   <div id= "qrcode1" >

   </div>

  </p>

  <p>

   模式二:生成直接支付url,支付url有效期为2小时

   <br />

   <div id= "qrcode2" >

   </div>

  </p>

  <script src= "~/scripts/jquery-1.10.2.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/jquery.easyui.min.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js" ></script>

  <script src= "~/scripts/jquery-easyui-1.4.5/easyloader.js" ></script>

  <script src= "~/scripts/jquery.qrcode.min.js" ></script>

  <script type= "text/javascript" >

   $( function () {

    fgetqrcode1();

   })

   function fgetqrcode1() {

    $.messager.progress({

     title: "" ,

     msg: "正在生成二维码:模式一,请稍后..."

    });

    $.ajax({

     type: "post" ,

     url: "/home/getqrcode1" ,

     data: {

      time: new date(),

      productid:7788

     },

     success: function (json) {

      $.messager.progress( 'close' ); //记得关闭

      if (json.result) {

       $( '#qrcode1' ).qrcode(json.str); //生成二维码

      }

      else {

       $( '#qrcode1' ).html( "二维码生成失败" );

      }

      fgetqrcode2();

     },

     error: function (json) {

      $( '#qrcode1' ).html( "二维码生成失败" );

      fgetqrcode2();

     }

    })

   }

   function fgetqrcode2() {

    $.messager.progress({

     title: "" ,

     msg: "正在生成二维码:模式二,请稍后..."

    });

    $.ajax({

     type: "post" ,

     url: "/home/getqrcode2" ,

     data: {

      time: new date(),

      productid: 7788

     },

     success: function (json) {

      $.messager.progress( 'close' ); //记得关闭

      if (json.result) {

       $( '#qrcode2' ).qrcode(json.str); //生成二维码

      }

      else {

       $( '#qrcode2' ).html( "二维码生成失败" );

      }

     },

     error: function (json) {

      $( '#qrcode2' ).html( "二维码生成失败" );

     }

    })

   }

  </script>

</body>

</html>

后端:

?

using system;

using system.collections.generic;

using system.linq;

using system.web;

using system.web.mvc;

using wxpayapi;

namespace wxpay.controllers

{

  public class homecontroller : controller

  {

   // get: home

   public actionresult index()

   {

    return view();

   }

   /// <summary>

   /// 模式一

   /// </summary>

   /// <returns></returns>

   [httppost]

   public actionresult getqrcode1()

   {

    object objresult = "" ;

    string strproductid = request.form[ "productid" ];

    string strqrcodestr = getprepayurl(strproductid);

    if (! string .isnullorwhitespace(strproductid))

    {

     objresult = new { result = true , str = strqrcodestr };

    }

    else

    {

     objresult = new { result = false };

    }

    return json(objresult);

   }

   /// <summary>

   /// 模式二

   /// </summary>

   /// <returns></returns>

   [httppost]

   public actionresult getqrcode2()

   {

    object objresult = "" ;

    string strproductid = request.form[ "productid" ];

    string strqrcodestr = getpayurl(strproductid);

    if (! string .isnullorwhitespace(strproductid))

    {

     objresult = new { result = true , str = strqrcodestr };

    }

    else

    {

     objresult = new { result = false };

    }

    return json(objresult);

   }

   /**

   * 生成扫描支付模式一url

   * @param productid 商品id

   * @return 模式一url

   */

   public string getprepayurl( string productid)

   {

    wxpaydata data = new wxpaydata();

    data.setvalue( "appid" , wxpayconfig.appid); //公众帐号id

    data.setvalue( "mch_id" , wxpayconfig.mchid); //商户号

    data.setvalue( "time_stamp" , wxpayapi.generatetimestamp()); //时间戳

    data.setvalue( "nonce_str" , wxpayapi.generatenoncestr()); //随机字符串

    data.setvalue( "product_id" , productid); //商品id

    data.setvalue( "sign" , data.makesign()); //签名

    string str = tourlparams(data.getvalues()); //转换为url串

    string url = "weixin://wxpay/bizpayurl?" + str;

    return url;

   }

   /**

   * 参数数组转换为url格式

   * @param map 参数名与参数值的映射表

   * @return url字符串

   */

   private string tourlparams(sorteddictionary< string , object > map)

   {

    string buff = "" ;

    foreach (keyvaluepair< string , object > pair in map)

    {

     buff += pair.key + "=" + pair.value + "&" ;

    }

    buff = buff.trim( '&' );

    return buff;

   }

   /**

   * 生成直接支付url,支付url有效期为2小时,模式二

   * @param productid 商品id

   * @return 模式二url

   */

   public string getpayurl( string productid)

   {

    wxpaydata data = new wxpaydata();

    data.setvalue( "body" , "广东xxxx股份有限公司" ); //商品描述

    data.setvalue( "attach" , "附加信息,用于后台或者存入数据库,做自己的判断" ); //附加数据

    data.setvalue( "out_trade_no" , wxpayapi.generateouttradeno()); //随机字符串

    data.setvalue( "total_fee" , 1); //总金额

    data.setvalue( "time_start" , datetime.now.tostring( "yyyymmddhhmmss" )); //交易起始时间

    data.setvalue( "time_expire" , datetime.now.addminutes(10).tostring( "yyyymmddhhmmss" )); //交易结束时间

    data.setvalue( "goods_tag" , "商品的备忘,可以自定义" ); //商品标记

    data.setvalue( "trade_type" , "native" ); //交易类型

    data.setvalue( "product_id" , productid); //商品id

    wxpaydata result = wxpayapi.unifiedorder(data); //调用统一下单接口

    string url = result.getvalue( "code_url" ).tostring(); //获得统一下单接口返回的二维码链接

   

    return url;

   }

  }

}

特此更正,感谢[ abc54288]的指出,模式二也是有回调的,回调的接口设置在config.cs,中,如下图:

所以下面的作废,但是如果需要手动查询订单情况的,还可以用下列的方法查询。再次感谢园友:[ abc54288]。

由于模式二是没有支付结果回调的,所以,我们要查询支付成功与否,需要自己写方法来查询,官方提供的查询支付成功与否的方法有以下,

?

/***

   * 订单查询完整业务流程逻辑

   * @param transaction_id 微信订单号(优先使用)

   * @param out_trade_no 商户订单号

   * @return 订单查询结果(xml格式)

   */

   public static string run( string transaction_id, string out_trade_no)

   {

    log.info( "orderquery" , "orderquery is processing..." );

    wxpaydata data = new wxpaydata();

    if (! string .isnullorempty(transaction_id)) //如果微信订单号存在,则以微信订单号为准

    {

     data.setvalue( "transaction_id" , transaction_id);

    }

    else //微信订单号不存在,才根据商户订单号去查单

    {

     data.setvalue( "out_trade_no" , out_trade_no);

    }

    wxpaydata result = wxpayapi.orderquery(data); //提交订单查询请求给api,接收返回数据

    log.info( "orderquery" , "orderquery process complete, result : " + result.toxml());

    return result.toprintstr();

   }

可以通过这个微信订单号(transaction_id)来查询,也可以通过商户订单号(out_trade_no),所以,我们要合理利用这里面的技巧,上述模式二,我用的out_trade_no 是一个随机字符串,我们可以把这个字符串记录好,放数据库还是放哪里,你自己喜欢,然后写一个ajsx长轮询来,定时查询这个商户订单号,看看有没有支付成功,来做支付确认。

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

原文链接:http://www.cnblogs.com/nangong/p/9fa625bfb92a986125f0ba72704c46ec.html

dy("nrwz");

查看更多关于C# MVC 微信支付教程系列之扫码支付代码实例的详细内容...

  阅读:46次