这次是第二次对接微信公众号的支付了,第一次代码写的很乱,没有找现成的SDK,感觉里面乱七八糟的东西太多不够清爽,而我仅仅是做一个小功能,对接又不复杂干脆自己做。

不想重复做轮子的朋友可以参考一下:Senparc C# SDK  

这里我只说一下公众号内支付,APP以及其他的支付,等我以后用得到的时候再总结。

简单的说对接过程分为4步

1、拿到用户的openid
2、使用微信接口下单获取preorder_id
3、前端H5调用微信支付对话框
4、接收微信支付结果的通知

好了,现在开始具体过程介绍

0.公众号信息准备

1、公众号的appid,appsecret
登录微信公众平台,在开发一栏里找到基本配置

2、微信支付平台的商户id(mch_id), 支付key(这个是自己设置的)

1.获取用户openid

每个用户在公众号里都有一个唯一的openid,公众号可以通过openid获取用户的信息,当然获取用户信息是需要用户同意的。但是只获取openid不需要用户同意。

这里没提到的内容可以参考官方文档,:微信网页授权

要获取openid,首先要获取code,然后根据code获取openid。这个过程是为了要用户授权,也就是下面的绿色页面。

获取code跳转到这个链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

参数
appid:是公众号的唯一标识
redirect_uri:是授权后重定向的回调链接地址,请使用urlEncode对链接进行处理
response_type:返回类型,请填写code
scope:是应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
state:否 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 是 无论直接打开还是做页面302重定向时候,必须带此参数

在这里我们scope参数使用snsapi_base,使用snsapi_userinfo 会弹出绿色页面,但是结果是一样的。

如果没出错的话,页面会跳转到指定的redirect_uri页面,并附带上code和state参数。

获取code后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数
appid:公众号的唯一标识
secret:公众号的appsecret
code:填写第一步获取的code参数
grant_type:填写authorization_code

正确时返回的JSON数据包如下

{ "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" } 

看到这里面的openid这个参数没?这时就可以取用了,获取到的refresh_token可以保存起来,以后直接用refresh_token获取openid。

2.获取prepay_id

使用微信公众号支付必须在微信留个案底,需要把订单信息提交给微信,这时候就需要使用统一下单接口,官方文档

处于安全角度,使用这个接口需要对传输的信息加密,为了避免篡改,需要用到支付key,过程是这样的:
1、生成一个随机数:32位,可以创建一个Guid。
2、生成安全签名:把提交到微信的参数按照首字母字典排序(a-z),编辑成key=value&key=value…的形式,然后末尾加上key,用md5加个密。
3、创建提交的xml
4、使用post提交到微信接口

· 把要传的参数使用字典排序(除了sign):

SortedDictionary<String, String> param = new SortedDictionary<string, string>();
param.Add("appid", appid);
param.Add("attach", attach);
param.Add("body", body);
param.Add("mch_id", config.mchid);
param.Add("nonce_str", Guid.NewGuid().ToString().Replace("-", "").ToUpper());
param.Add("notify_url", notifyurl);
param.Add("openid", openid);
param.Add("out_trade_no", orderno);
param.Add("spbill_create_ip", System.Web.HttpContext.Current.Request.UserHostAddress);
param.Add("total_fee", ((Int32)(price * 100)).ToString());
param.Add("trade_type", "JSAPI");

· 参数生成字符串

private String GetUnEncyptKey(SortedDictionary<String, String> sort){List<String> lstParam = new List<String>();foreach (var item in sort){lstParam.Add(String.Format("{0}={1}", item.Key, item.Value));}return String.Join("&", lstParam);
}

· MD5加密

/// <summary>
/// 签名字符串
/// </summary>
/// <param name="prestr">需要签名的字符串</param>
/// <param name="key">密钥</param>
/// <param name="_input_charset">编码格式</param>
/// <returns>签名结果</returns>
public static string Sign(string prestr, string key, string _input_charset)
{StringBuilder sb = new StringBuilder(32);prestr = prestr +"&key="+ key;MD5 md5 = new MD5CryptoServiceProvider();byte[] t = md5.ComputeHash(Encoding.GetEncoding(_input_charset).GetBytes(prestr));for (int i = 0; i < t.Length; i++){sb.Append(t[i].ToString("x").PadLeft(2, '0'));}return sb.ToString();
}

· 把刚才生成的sign加入到SortedDictionary中然后生成xml:

param.Add("sign", "签名值");
/// <summary>
/// 把提交的参数参数转换为xml
/// </summary>
/// <param name="requestInfo"></param>
/// <returns></returns>
public static String GetPostXML(SortedDictionary<String, String> requestInfo)
{List<String> xml = new List<String>();xml.Add("<xml>");SortedDictionary<String, String> post_param = ExcludeEmpty(requestInfo);foreach (var item in post_param){if (item.Key == "detail"){xml.Add(String.Format("<{0}><![CDATA[{1}]]</{0}>", item.Key, item.Value));}else {xml.Add(String.Format("<{0}>{1}</{0}>", item.Key, item.Value));}}xml.Add("</xml>");return String.Join("", xml);}

(微信的detail 是使用CDATA防止xml转义的,其他参数不能采用)

好了,把XML使用POST提交到接口吧,地址是:https://api.mch.weixin.qq.com/pay/unifiedorder

返回结果也是xml的,可以返序列化。使用这段代码可以直接反序列化成实体类:

/// <summary>
/// 反序列化xml
/// </summary>
/// <param name="xml">XML字符串</param>
/// <returns></returns>
public static T Deserialize<T>(string xml)
{try{String typename=typeof(T).Name;xml = xml.Replace("<xml>", "<" + typename + ">").Replace("</xml>", "</" + typename + ">");using (StringReader sr = new StringReader(xml)){XmlSerializer xmldes = new XmlSerializer(typeof(T));return (T)xmldes.Deserialize(sr);}}catch (Exception e){return default(T);}
}

好了,正常情况下就可以获取到prepay_id了。

3.前端H5调用微信支付对话框

请参考官方文档

对接过统一下单接口,这个过程就很简单了。按照这个文档做就好了。这里的随机字符串和签名都是重新生成的,生成方式和前面说的一样。

前端页面JS:

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

好了,到现在支付就完成了,下面还需要获取一下支付通知,最终确认一下支付状态。

4.接收支付通知

请自行阅读一下,官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7

简单说明一下文档中return_code 和result_code 分别表示通信结果和业务(支付)执行结果。收到参数后自己记录一下信息,尤其是支付单号transaction_id,然后再按照约定格式返回一个xml表示成功就可以了。

必须要注意的是,一定要对收到的参数进行签名,验证收到的消息来源是否来自微信,千万不可懒。因为加密所需的key只有你和微信知道,所以加密结果可能能对起来。如果key泄漏了会很危险,因为其他人可能会伪造一个结果,告诉你支付成功了。key可以在微信支付平台中修改。

最后

这次对接过程还比较顺利,没有遇到什么坑,记得第一次做微信接口的时候,不知道是文档我没理解,还是其他什么原因,用了很长事件。当然只按照上面说的是不行的,这里只是提供一个思路和几个辅助的代码段,还需要按照你自己的业务逻辑进行改造,至于其他接口大同小异,不在叙述了。

C#微信公众号支付接口对接相关推荐

  1. php调用微信公众号支付接口,Thinkphp微信公众号支付接口

    本文实例为大家分享了Thinkphp微信公众号支付接口,供大家参考,具体内容如下 第一步 先把文件夹的那两个图片 配置成一样的路径 除了域名要改 其他保持一致. 第二步  把 Weixinpay 这个 ...

  2. php微信公众号支付接口案例,Thinkphp微信公众号支付接口

    本文实例为大家分享了Thinkphp微信公众号支付接口,供大家参考,具体内容如下 第一步 先把文件夹的那两个图片 配置成一样的路径 除了域名要改 其他保持一致. 第二步 把 Weixinpay 这个文 ...

  3. vue 微信公众号支付接口_基于vue的h5项目之支付宝支付与微信支付

    本文仅记录基于vue开发h5项目过程中使用支付宝和微信支付过程中的重点与槽点,仅为前端部分,如有疏漏不正之处,请于文末评论探讨.注意:标红部分灰常重要,仔细阅读官方文档非常重要,耐心非常重要,细心非常 ...

  4. php h5微信公众号支付接口,微信公众号H5支付接口调用方法

    本文实例为大家分享了 微信内h5调用支付接口的具体代码,供大家参考,具体内容如下 官方文档 微信公众号h5接口调用 // 判断微信版本是否在5.0以上 // window.navigator.user ...

  5. 关于微信公众号支付接口开发遇到的奇葩问题,始终返回get_brand_wcpay_request:fail。

    最近公司开发网站针对微信公众号的支付功能. 由于公司目前的这个项目网站是使用asp代码开发的,但是微信官方给出的demo中是没有asp版本的,所以楼主只有下载demo的php版本作为参考写了一个asp ...

  6. vue 微信公众号支付接口_总结vue项目中使用微信公众号支付的方法

    本篇文章给大家带来的内容是总结vue项目中使用微信公众号支付的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助. 微信公众号支付 1. 使用jssdk调用微信支付,具体查看开发文档 ...

  7. vue 微信公众号支付接口_vue做微信公众号分享,支付

    在前段时间做了一个微信公众号,因为我又是新手,没什么经验,拿起vue就开始,导致一坑再坑,简直阔怕!!! 对于此次项目,我主要用到的是vue的整框架和必要的插件,但是我没用vuex,用vuex的话会方 ...

  8. vue 微信公众号支付接口_vue页面在微信公众号调用支付接口

    // 点击了点击购买按钮 async handlePurchase() { const vm = this // 获取选中的套餐信息,用的是axios的post方法,因此要包装一下params con ...

  9. 微信公众号支付(JSAPI)对接备忘

    0 说明 本文里说的微信公众号支付对接指的是对接第三方支付平台的微信公众号支付接口. 非微信支付官方文档里的公众号支付开发者文档那样的对接.不过,毕竟腾讯会把一部分渠道放给银行或有支付牌照的支付机构, ...

最新文章

  1. 2021年春季学期-信号与系统-第十四次作业参考答案-第七小题参考答案
  2. ES transport client使用
  3. python好用-Python里三个好用的调试神器
  4. 深度对比Python的3种“字符串格式化”方法,看看你喜欢哪一种?
  5. package.json和package-lock.json
  6. java 常用类库_JAVA(三)JAVA常用类库/JAVA IO
  7. 多重 for 循环,如何提高效率?
  8. mysql 命令 select_Mysql基础命令(二)select查询操作
  9. Leetcode每日一题:面试题02.02.kth-node-from-end-of-list-lcci(返回倒数第k个节点)
  10. 概率中的独立和不相关
  11. windows系统bat批处理 windows 关机,重启,锁定,休眠,注销
  12. treebagger matlab,MATLAB – TreeBagger example
  13. 分组取出值最大的数据
  14. 通过python读取ini配置文件
  15. JavaWeb图书管理系统+论文+答辩ppt
  16. 软件工程导论复习之总体设计
  17. win10家庭中文版安装win7虚拟机
  18. winpe查看不到linux硬盘,winpe不显示硬盘?教你轻松搞定pe下不显示硬盘问题
  19. 接收蓝牙信号并发送到云端服务器,蓝牙如何可以与云服务器连接
  20. 将知网caj格式转换成pdf格式

热门文章

  1. java怎样实现换肤功能_umi项目换肤功能的实现
  2. MFC输出普朗克常数
  3. sd卡数据恢复软件免费版从哪里可以获得
  4. k8s滚动升级_kubernetes滚动更新
  5. redmine 表格_Redmine Custom tables 自定义表格插件 - Redmine插件中文站
  6. 中央民族大学计算机优势专业排名,中央民族大学优势专业排名,2021年中央民族大学最好的专业排名...
  7. c#开发地磅称重软件
  8. 新建一个docker镜像
  9. java redis session共享_Springboot+redis实现session共享
  10. gesture-recycler