千家信息网

微信公众平台之支付开发的示例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章给大家分享的是有关微信公众平台之支付开发的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。公众号支付就是在微信里面的H5页面唤起微信支付,不用扫码即可付款的功
千家信息网最后更新 2026年11月01日微信公众平台之支付开发的示例分析

这篇文章给大家分享的是有关微信公众平台之支付开发的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

公众号支付就是在微信里面的H5页面唤起微信支付,不用扫码即可付款的功能。做这个功能首先要明确的就是,只有和商户号mch_id匹配的appid才能成功支付。商户号在注册成功的时候就会将相关信息发送到邮箱里面。而唤起支付的一个关键是靠openid拿到统一下单。而openid是和appid一一对应的。也就是说如果你登录使用的appid不是公众号的appid,得到的openid就无法唤起公众号内的支付(会出现appid和商户号不匹配的错误)。曾经就在这个地方绕了个弯,因为微信的开放平台可以创建网站应用,也有一个appid和appsecreat,也可以在微信里面一键登录。

业务流程

下面是微信的官方流程,看似有点复杂,重点就是要拿到统一下单接口返回的json串,其他按照官方demo基本就能正确,下面说一下几个细节。

创建订单

在调用微信公众号支付之前,首先我们自己要把订单创建好。比如一个充值的订单。主要是先确定下金额再进行下一步。

public JsonResult CreateRecharegOrder(decimal money) { if (money < (decimal)0.01) return Json(new PaymentResult("充值金额非法!")); var user = _workContext.CurrentUser; var order = _paymentService.CreateRechargeOrder(user.Id, money); return Json(new PaymentResult(true) {OrderId = order.OrderNumber}); }

调用统一下单

订单创建成功之后,页面跳转到支付页面,这个时候就是按照官方的流程去拿prepay_id和paySign,微信的demo中提供了一个jsApiPay的对象。但这个对象需要一个page对象初始化。

[LoginValid] public ActionResult H5Pay(string orderNumber) { var user = _workContext.CurrentUser; var order = _paymentService.GetOrderByOrderNumber(orderNumber); //判断订单是否存在 //订单是否已经支付了 var openid = user.OpenId; var jsApipay = new JsApiPayMvc(this.ControllerContext.HttpContext); jsApipay.openid = openid; jsApipay.total_fee = (int)order.Amount * 100; WxPayData unifiedOrderResult = jsApipay.GetUnifiedOrderResult(); ViewBag.wxJsApiParam = jsApipay.GetJsApiParameters();//获取H5调起JS API参数  ViewBag.unifiedOrder = unifiedOrderResult.ToPrintStr(); ViewBag.OrderNumber = order.OrderNumber; return View(); }

在MVC中我们简单改一下就可以了。也就是把page对象换成httpContext即可。然后里面的方法就可以直接用了。

JsApiPayMvc:

using System;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Runtime.Serialization;using System.IO;using System.Text;using System.Net;using System.Web.Security;using LitJson;namespace WxPayAPI{ public class JsApiPayMvc { ///  /// 保存页面对象,因为要在类的方法中使用Page的Request对象 ///  public HttpContextBase context { get; set; } ///  /// openid用于调用统一下单接口 ///  public string openid { get; set; } ///  /// access_token用于获取收货地址js函数入口参数 ///  public string access_token { get; set; } ///  /// 商品金额,用于统一下单 ///  public int total_fee { get; set; } ///  /// 统一下单接口返回结果 ///  public WxPayData unifiedOrderResult { get; set; } public JsApiPayMvc(HttpContextBase _context) { context = _context; } /** *  * 网页授权获取用户基本信息的全部过程 * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html * 第一步:利用url跳转获取code * 第二步:利用code去获取openid和access_token *  */ public void GetOpenidAndAccessToken(string code) { if (!string.IsNullOrEmpty(code)) { //获取code码,以获取openid和access_token Log.Debug(this.GetType().ToString(), "Get code : " + code); GetOpenidAndAccessTokenFromCode(code); } else { //构造网页授权获取code的URL string host = context.Request.Url.Host; string path = context.Request.Path; string redirect_uri = HttpUtility.UrlEncode("http://" + host + path); WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID); data.SetValue("redirect_uri", redirect_uri); data.SetValue("response_type", "code"); data.SetValue("scope", "snsapi_base"); data.SetValue("state", "STATE" + "#wechat_redirect"); string url = "https://open.weixin.qq.com/connect/oauth3/authorize?" + data.ToUrl(); Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url); try { //触发微信返回code码  context.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常 } catch(System.Threading.ThreadAbortException ex) { } } } /** *  * 通过code换取网页授权access_token和openid的返回数据,正确时返回的JSON数据包如下: * { * "access_token":"ACCESS_TOKEN", * "expires_in":7200, * "refresh_token":"REFRESH_TOKEN", * "openid":"OPENID", * "scope":"SCOPE", * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" * } * 其中access_token可用于获取共享收货地址 * openid是微信支付jsapi支付接口统一下单时必须的参数 * 更详细的说明请参考网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html * @失败时抛异常WxPayException */ public void GetOpenidAndAccessTokenFromCode(string code) { try { //构造获取openid及access_token的url WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID); data.SetValue("secret", WxPayConfig.APPSECRET); data.SetValue("code", code); data.SetValue("grant_type", "authorization_code"); string url = "https://api.weixin.qq.com/sns/oauth3/access_token?" + data.ToUrl(); //请求url以获取数据 string result = HttpService.Get(url); Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result); //保存access_token,用于收货地址获取 JsonData jd = JsonMapper.ToObject(result); access_token = (string)jd["access_token"]; //获取用户openid openid = (string)jd["openid"]; Log.Debug(this.GetType().ToString(), "Get openid : " + openid); Log.Debug(this.GetType().ToString(), "Get access_token : " + access_token); } catch (Exception ex) { Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString()); } } /** * 调用统一下单,获得下单结果 * @return 统一下单结果 * @失败时抛异常WxPayException */ public WxPayData GetUnifiedOrderResult() { //统一下单  WxPayData data = new WxPayData(); data.SetValue("body", "test"); data.SetValue("attach", "test"); data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo()); data.SetValue("total_fee", total_fee); data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); data.SetValue("goods_tag", "test"); data.SetValue("trade_type", "JSAPI"); data.SetValue("openid", openid); WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "") { Log.Error(this.GetType().ToString(), "UnifiedOrder response error!"); throw new WxPayException("UnifiedOrder response error!"); } unifiedOrderResult = result; return result; } /** *  * 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数, * 微信浏览器调起JSAPI时的输入参数格式如下: * { * "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入  * "timeStamp":" 1395712654", //时间戳,自1970年以来的秒数 * "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串 * "package" : "prepay_id=u802345jgfjsdfgsdg888",  * "signType" : "MD5", //微信签名方式: * "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名  * } * @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用 * 更详细的说明请参考网页端调起支付API:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7 *  */ public string GetJsApiParameters() { Log.Debug(this.GetType().ToString(), "JsApiPay::GetJsApiParam is processing...");  WxPayData jsApiParam = new WxPayData(); jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid")); jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp()); jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr()); jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id")); jsApiParam.SetValue("signType", "MD5"); jsApiParam.SetValue("paySign", jsApiParam.MakeSign()); string parameters = jsApiParam.ToJson(); Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters); return parameters; } /** *  * 获取收货地址js函数入口参数,详情请参考收货地址共享接口:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_9 * @return string 共享收货地址js函数需要的参数,json格式可以直接做参数使用 */ public string GetEditAddressParameters() { string parameter = ""; try { string host = context.Request.Url.Host; string path = context.Request.Path; string queryString = context.Request.Url.Query; //这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整url string url = "http://" + host + path + queryString; //构造需要用SHA1算法加密的数据 WxPayData signData = new WxPayData(); signData.SetValue("appid",WxPayConfig.APPID); signData.SetValue("url", url); signData.SetValue("timestamp",WxPayApi.GenerateTimeStamp()); signData.SetValue("noncestr",WxPayApi.GenerateNonceStr()); signData.SetValue("accesstoken",access_token); string param = signData.ToUrl(); Log.Debug(this.GetType().ToString(), "SHA1 encrypt param : " + param); //SHA1加密 string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1"); Log.Debug(this.GetType().ToString(), "SHA1 encrypt result : " + addrSign); //获取收货地址js函数入口参数 WxPayData afterData = new WxPayData(); afterData.SetValue("appId",WxPayConfig.APPID); afterData.SetValue("scope","jsapi_address"); afterData.SetValue("signType","sha1"); afterData.SetValue("addrSign",addrSign); afterData.SetValue("timeStamp",signData.GetValue("timestamp")); afterData.SetValue("nonceStr",signData.GetValue("noncestr")); //转为json格式 parameter = afterData.ToJson(); Log.Debug(this.GetType().ToString(), "Get EditAddressParam : " + parameter); } catch (Exception ex) { Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString()); } return parameter; } }}

这个页面可以在本地调试,可以比较方便的确认参数是否ok。

唤起支付

官方页面的示例如下:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 但主要的参数(mark部分)是由后台生成的,也就是上一个步骤的ViewBag.wxJsApiParam

function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入  "timeStamp":" 1395712654", //时间戳,自1970年以来的秒数  "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串  "package" : "prepay_id=u802345jgfjsdfgsdg888",  "signType" : "MD5", //微信签名方式:  "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名  }, function(res){  if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。  } ); }

所以在MVC中要这样写:

@{ ViewBag.Title = "微信支付"; Layout = "~/Views/Shared/_Layout.cshtml";}
订单详情:@Html.Raw(ViewBag.unifiedOrder)

必须要用Html.Raw,不然json解析不对,无法支付。这个时候点击页面,会出现微信的加载效果,但别高兴的太早,还是会出错,出现一个"3当前的URL未注册"

原因就在于,需要在公众号中设置支付目录。而这个支付目录是大小写敏感的,所以你得多试几次。直到弹出输入密码的窗口才是真的流程正确了。然后支付成功之后马上就可以收到js中的回调,这个时候你可以去处理你的订单和业务逻辑。

感谢各位的阅读!关于"微信公众平台之支付开发的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

支付 参数 统一 公众 订单 成功 地址 网页 页面 对象 用户 信息 函数 商户 接口 数据 官方 就是 时候 格式 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 喔噻互联网科技有限公司 北京路客互联网科技有限公司 上海挚品互联网科技 极限挑战互联网科技 互联网科技网站 大白互联网科技 互联网 科技服务平台 济南和联互联网科技有限公司 新华互联网科技2019 科技互联网的估值 互联网保险科技创业 想开互联网科技公司怎么样 企晟互联网信息科技有限公司 滨湖区互联网智能科技产品有哪些 科技互联网的核心竞争力 中国互联网有什么科技 济南小医互联网科技有限公司招聘 兰石爱特工业互联网科技分公司 北京品多多互联网科技有限公司 承德科技产业互联网平台 云之行互联网科技 苏州找大状互联网科技有限公司 互联网科技活动banner 工业互联网科技新基建 海南科技产业互联网平台 卫星互联网科技股票 互联网和黑科技的看法 互联网科技的全部知识 锡山区互联网智能科技产品供应 小米互联网科技园入驻
0