回归主题,16年1月初我对微信开发比较好奇,由于自己是一个比较喜欢钱的人,所以对支付功能颇为冲动,就用公司信息在微信平台申请了一个服务号,还给腾讯打赏了300大洋做了下认证,抽空看了下微信支付官方的文档,大概了解了一下微信支付的流程以及开发过程,说实话,虽然看完了,但是对微信官方提供的文档有些不满,感觉不清不楚的,但是大概的支付方式已经了解,这时候,我的懒劲又来了,在网上找到了做微信对接的C#SDK:Senparc.Weixin.MP。这个类库的封装,在我看来,还是不错的,基本囊货了微信的功能,并且在不断的完善。类库是开源的,每个功能都有写简单的单元测试,看起来一目了然。主要对接DLL对应的功能如下:

  公众号+微信支付 SDK:Senparc.Weixin.MP.dll

  企业号 SDK:Senparc.Weixin.QY.dll

  开放平台 SDK:Senparc.Weixin.Open.dll

  官方地址:http://weixin.senparc.com/ 

  当然,我们要完成公众号微信支付功能的开发,需要使用Senparc.Weixin.MP.dll这个DLL,查阅了一下官方提供的DEMO以及教程,并没有载入微信支付相关的说明,没办法,既然拿到源码了,自己找吧。

  打开Senparc.Weixin.MP.sln,根据英文文件夹名称的分类,可以初步判断,关于微信支付,被封装在TenPayLib文件夹中,但是我还发现,里面存在名称叫“TenPayLibV3”的文件夹,那如何选择呢?网上搜索了一下,得出这个结论:2014年9月10号之前申请的为v2版,之后申请的为v3版。我用来测试微信支付的服务号是在16年刚申请,并且通过验证的,那么果断使用V3吧。

  打开TenPayLibV3文件夹:

  

  这里发现多个类库,每一个都是做什么的呢?我们这里不一一叙述,感兴趣的朋友可以下载来看,每一个类的文件头都有功能说明与描述,对照微信官方支付说明,我们直接开始做支付。

  进入微信公众号,点击功能菜单中的微信支付:并相应点击 使用教程-公众号支付

  

  迅速对文档内容重温、浏览,以方便在Senparc.Weixin.MP.dll中查找相应的功能。

  

  先配置支付授权目录,添加支付测试白名单,支付目录只支持三个,并且域名必须经过ICP备案。授权目录的作用是,如果要发起微信支付请求,请求的链接地址必须在授权目录下,否则身份无效,支付不能成功。测试白名单中添加的个人微信号,才能完成微信支付测试目录支付的测试,不在白名单中人员发起支付申请,支付不能成功。

  配置完成后,如何调用呢?我们继续看官方说明:H5调起支付API  

  “在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。

  注意:WeixinJSBridge内置对象在其他浏览器中无效。

  列表中参数名区分大小,大小写错误签名验证会失败。”

  OK,这里说明了几个事情,第一必须在微信浏览器进行;第二,参数区分大小写;第三,数据格式为JSON。

  官方说明,只要在页面中调用如下脚本,即可开启微信支付功能:

 

  我的调用代码:因为我要在点击按钮确认支付之后,在调用微信支付进行后续操作,把官方代码提出到方法中

 function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": $('#APPID').val(), //公众号名称,由商户传入
"timeStamp": $('#Timestamp').val(), //时间戳,自1970年以来的秒数
"nonceStr": $('#Noncestr').val(), //随机串
"package": $('#package').val(),
"signType": "MD5", //微信签名方式:
"paySign": $('#paySign').val() //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
//支付成功,后续自行处理 }
else
{
//支付取消,或者其他错误,自行处理
}
}
);
}  

  好吧,那这堆参数是从哪来的,都是啥玩意儿?我们逐个分析一下:

  appId:这个做微信开发都应该知道,公众号在开发者菜单就能找到

  timeStamp:时间戳,官方描述为“自1970年以来的秒数”,不用担心,肯定能从支付类库里找到

  nonceStr:官方解释是随机串“e61463f8efa94090b1f366cccfbbb444”,靠啥玩意儿?详见随机数生成算法,原来就是一套加密规则和算法,做过URL请求接口的朋友应该知道,有些公司JSON串的签名方式和这比较类似。

  package:预支付ID,调用官方API统一下单接口可以获得

  signType:字符串"MD5"

  paySign:官方解释是微信签名“70EA570631E4BB79628FBCA90534C63FF7FADD89”,好吧,我忍了,在看下签名生成算法,看来和随机串一个鸟样

  到这里,官方的接口说明已经了解的很清楚了,那么下面就要解决调用微信支付的这几个参数了,通过Senparc.Weixin.MP.dll应该如何使用呢?既然需要先调用统一下单接口获取预支付订单ID,好吧,我们先来研究一下,如何获得这个ID吧。

  官方给出了详细说明,我们不在赘述,各参数研究按照上述接口的方式自行研究解决,唯一区别在于,调用官方接口需要传入一个XML,那很好办,拼接一下就可以了,预支付调用方法如下:

//这里通过官方的一个实体,用户自行使用,我这里是直接读取的CONFIG文件
private static Senparc.Weixin.MP.TenPayLibV3.TenPayV3Info tenPayV3Info = new Senparc.Weixin.MP.TenPayLibV3.TenPayV3Info(ConfigurationManager.AppSettings["corpId"], ConfigurationManager.AppSettings["corpSecret"], ConfigurationManager.AppSettings["mch_id"]
, ConfigurationManager.AppSettings["key"], ConfigurationManager.AppSettings["v3url"]); /// <summary>
/// 微信预支付
/// </summary>
/// <param name="attach"></param>
/// <param name="body"></param>
/// <param name="openid"></param>
/// <param name="price"></param>
/// <param name="orderNum"></param>
/// <returns></returns>
public static string PayInfo(string attach, string body, string openid, string price, string orderNum = "1833431773763549")
{
RequestHandler requestHandler = new RequestHandler(HttpContext.Current);
//微信分配的公众账号ID(企业号corpid即为此appId)
requestHandler.SetParameter("appid", tenPayV3Info.AppId);
//附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
requestHandler.SetParameter("attach", attach);
//商品或支付单简要描述
requestHandler.SetParameter("body", body);
//微信支付分配的商户号
requestHandler.SetParameter("mch_id", tenPayV3Info.MchId);
//随机字符串,不长于32位。
requestHandler.SetParameter("nonce_str", TenPayUtil.GetNoncestr());
//接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
requestHandler.SetParameter("notify_url", tenPayV3Info.TenPayV3Notify);
//trade_type=JSAPI,此参数必传,用户在商户公众号appid下的唯一标识。
requestHandler.SetParameter("openid", openid);
//商户系统内部的订单号,32个字符内、可包含字母,自己生成
requestHandler.SetParameter("out_trade_no", orderNum);
//APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
requestHandler.SetParameter("spbill_create_ip", "127.0.0.1");
//订单总金额,单位为分,做过银联支付的朋友应该知道,代表金额为12位,末位分分
requestHandler.SetParameter("total_fee", price);
//取值如下:JSAPI,NATIVE,APP,我们这里使用JSAPI
requestHandler.SetParameter("trade_type", "JSAPI");
//设置KEY
requestHandler.SetKey(tenPayV3Info.Key); requestHandler.CreateMd5Sign();
requestHandler.GetRequestURL();
requestHandler.CreateSHA1Sign();
string data = requestHandler.ParseXML();
requestHandler.GetDebugInfo(); //获取并返回预支付XML信息
return TenPayV3.Unifiedorder(data);
}
}

好的,拿到预支付订单的返回数据,一切又都好办了,根据返回参数的不同,自行解决,我们只关心调用正确的过程,操作继续,在返回的正确XML数据中,我们获取到了 <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>(官方示例),好的,开始在页面做支付吧!

这里,我封装了一个实体,用来传输常用的数据,当然,各位也可以参考Senparc.Weixin.MP.dll提供的实体类。

public class ShareInfo
{
string corpId = string.Empty;
public string CorpId
{
get { return corpId; }
set { corpId = value; }
}
string ticket = string.Empty; public string Ticket
{
get { return ticket; }
set { ticket = value; }
}
string noncestr = string.Empty; public string Noncestr
{
get { return noncestr; }
set { noncestr = value; }
}
string timestamp = string.Empty; public string Timestamp
{
get { return timestamp; }
set { timestamp = value; }
} private string paySign = string.Empty;
public string PaySign
{
get { return paySign; }
set { paySign = value; }
} private string package = string.Empty; public string Package
{
get { return package; }
set { package = value; }
}
}

我们继续,来看一下支付接口需要用到的参数如何获取:

public static ShareInfo GetPayInfo(string prepayid)
{
shareInfo = new ShareInfo();
//检查是否已经注册jssdk
if (!JsApiTicketContainer.CheckRegistered(corpId))
{
JsApiTicketContainer.Register(corpId, corpSecret);
}
JsApiTicketResult jsApiTicket = JsApiTicketContainer.GetTicketResult(corpId);
JSSDKHelper jssdkHelper = new JSSDKHelper();
shareInfo.Ticket = jsApiTicket.ticket;
shareInfo.CorpId = corpId.ToLower();
shareInfo.Noncestr = JSSDKHelper.GetNoncestr().ToLower();
shareInfo.Timestamp = JSSDKHelper.GetTimestamp().ToLower();
shareInfo.Package="prepay_id=" + prepayid.ToLower(); RequestHandler requestHandler = new RequestHandler(HttpContext.Current); requestHandler.SetParameter("appId", shareInfo.CorpId);
requestHandler.SetParameter("timeStamp", shareInfo.Timestamp);
requestHandler.SetParameter("nonceStr", shareInfo.Noncestr);
requestHandler.SetParameter("package", shareInfo.Package);
requestHandler.SetParameter("signType", "MD5"); requestHandler.SetKey(tenPayV3Info.Key);
requestHandler.CreateMd5Sign();
requestHandler.GetRequestURL();
requestHandler.CreateSHA1Sign();
shareInfo.PaySign = (requestHandler.GetAllParameters()["sign"]).ToString();
return shareInfo;
}

这样,支付接口需要用到的参数,就都封装在ShareInfo里了,好吧,调用之后,我们回到页面的后置代码中,或者你采用的ORM对应代码中去,将参数输出到页面

好的,写到这里,大家参照上面的JS代码,就可以完成整个的支付功能了。最后,再附送一个生成商家订单号的方法,代码如下:

好了,一切都是这样的简单,一两个小时,微信支付轻松搞定!

  

C#微信支付的更多相关文章

  1. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  2. 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付                  今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...

  3. 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付         今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...

  4. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

  5. Android—基于微信开放平台v3SDK,开发微信支付填坑。

    接触微信支付之前听说过这是一个坑,,,心里已经有了准备...我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束 ...

  6. 解决新版Android studio导入微信支付和支付宝官方Demo的问题

    最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...

  7. C#开发微信门户及应用(35)--微信支付之企业付款封装操作

    在前面几篇随笔,都是介绍微信支付及红包相关的内容,其实支付部分的内容还有很多,例如企业付款.公众号支付或刷卡支付.摇一摇红包.代金券等方面的内容,这些都是微信接口支持的内容,本篇继续微信支付这一主题, ...

  8. C#开发微信门户及应用(32)--微信支付接入和API封装使用

    在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...

  9. C#开发微信门户及应用(40)--使用微信JSAPI实现微信支付功能

    在我前面的几篇博客,有介绍了微信支付.微信红包.企业付款等各种和支付相关的操作,不过上面都是基于微信普通API的封装,本篇随笔继续微信支付这一主题,继续介绍基于微信网页JSAPI的方式发起的微信支付功 ...

  10. app使用微信支付成功后,点击返回到该app却跳到另外一个app去了

    刚接手了公司iOS的两个APP, 现在碰到了这样一个问题: 有一台iPhone在一个APP中使用了微信支付,支付成功后,点击返回到该APP,结果却跳到了另外一个APP去了. 这两个APP都是公司开发的 ...

随机推荐

  1. logistic function 和 sigmoid function

     简单说, 只要曲线是 “S”形的函数都是sigmoid function: 满足公式<1>的形式的函数都是logistic function. 两者的相同点是: 函数曲线都是“S”形. ...

  2. 时尚与深度学习系列:Fashion forward: Forecasting visual style in fashion

           https://arxiv.org/pdf/1705.06394.pdf         将深度学习与时尚预测联系在一起,是一个很有趣但是估计结果会没什么成效的话题.因为,时尚预测这一领 ...

  3. STM32中IO口的8中工作模式

    该文摘自:http://blog.csdn.net/kevinhg/article/details/17490273 一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两 ...

  4. ACM学习历程—HDU 1272 小希的迷宫(并查集)

    Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就 ...

  5. MongoDB中的一些坑(最好不要用)

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷 ...

  6. 洛谷 1979 华容道——最短路+dp

    题目:https://www.luogu.org/problemnew/show/P1979 感到无从下手.但不妨用dp的角度来看.因为空格只有在指定棋子的旁边才有用,所以状态记成制定棋子的位置与空格 ...

  7. Poj_1011_Sticks(剪枝)

    一.Description 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位.然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度. ...

  8. Linux 切换字符界面和图形界面

    1. 切换方式 # root 权限 systemctl get-default # 获取当前模式 systemctl set-default graphical.target # 设置开机为图形界面 ...

  9. [bzoj2440]完全平方数(二分+mobius反演)

    解题关键:由容斥原理得,num=1的倍数的数量−一个质数平方数(9,25,49...)的倍数的数量+两个质数的积平方数(36,100,225...)的数量−三个质数...... 这道题用莫比乌斯的正向 ...

  10. CentOS6下安装Java jdk1.7.0_10和 maven

    安装步骤如下: 1. 下载JDK7.0_10 (jdk-7u10-linux-i586.tar.gz) 地址: 2. 卸载系统自带的开源JDK 查看是否安装JDK rpm -qa | grep jav ...