企业号微信支付 公众号支付 H5调起支付API示例代码 JSSDK C# .NET
Posted 汪杰的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了企业号微信支付 公众号支付 H5调起支付API示例代码 JSSDK C# .NET相关的知识,希望对你有一定的参考价值。
先看效果
1.本文演示的是微信【企业号】的H5页面微信支付
2.本项目基于开源微信框架WeiXinMPSDK开发:https://github.com/JeffreySu/WeiXinMPSDK 感谢作者苏志巍的开源精神
一、准备部分
相关参数:
AppId:公众号的唯一标识(登陆微信企业号后台 - 设置 - 账号信息 - CorpID)
AppSecret:(微信企业号后台 - 设置 - 权限管理 - 新建一个拥有所有应用权限的普通管理组 - Secret)
Key:商户API密钥(登陆微信商户后台 - 账户中心 - API安全 - API密钥)
MchId:商户ID(微信企业号后台 - 服务中心 - 微信支付 - 微信支付 -商户信息 - 商户号)
后台设置:
微信企业号后台 - 服务中心 - 微信支付 - 微信支付 - 开发配置 :
1.测试授权目录,改成线上支付页面的目录(例:http://www.abc.com/wxpay/)
2.测试白名单,加上测试用户的白名单,只有白名单用户可以付款
二、代码
前端:
使用微信支付先引入JSSDK:http://res.wx.qq.com/open/js/jweixin-1.0.0.js
页面打开即初始化:
$.ajax({
type: "GET",
url: "/WxPay/GetPayConfig",
beforeSend: function () {
$("#btnPay").attr({ "disabled": "disabled" });//获取到配置之前,禁止点击付款按钮
},
success: function (data) {
$("#btnPay").removeAttr("disabled");//获取到配置,打开付款按钮
wx.config({
debug: true, // 开启调试模式,成功失败都会有alert框
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timeStamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: [\'chooseWXPay\'] // 必填,需要使用的JS接口列表
});
wx.ready(function () {
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
wx.error(function (res) {
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
}
});
对应的后端代码:
/// <summary> /// 获取微信支付配置 /// </summary> /// <returns></returns> [HttpGet] public JsonResult GetPayConfig() { string timeStamp = Senparc.Weixin.MP.TenPayLib.TenPayUtil.GetTimestamp(); string nonceStr = Senparc.Weixin.MP.TenPayLib.TenPayUtil.GetNoncestr(); string signature = new Senparc.Weixin.MP.TenPayLib.RequestHandler(null).CreateMd5Sign(); return Json(new { appId = AppId, timeStamp = timeStamp, nonceStr = nonceStr, signature = signature }, JsonRequestBehavior.AllowGet); }
用户点击支付触发的函数(微信JSSDK的chooseWXPay函数):
function startWxPay() {
$.ajax({
type: "POST",
url: "/WxPay/GetPaySign",
data: { code: code, openid: openid },
beforeSend: function () {
$("#btnPay").attr({ "disabled": "disabled" });
},
success: function (res) {
$("#btnPay").removeAttr("disabled");
if (res.openid != null && res.openid != undefined && res.openid != "") {
window.localStorage.setItem("openid", res.openid);
}
wx.chooseWXPay({
timestamp: res.data.timeStamp, // 支付签名时间戳
nonceStr: res.data.nonceStr, // 支付签名随机串,不长于32 位
package: res.data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: "MD5", // 签名方式,默认为\'SHA1\',使用新版支付需传入\'MD5\'
paySign: res.data.paysign, // 支付签名
success: function (res) {
//支付成功
},
cancel: function (res) {
//支付取消
}
});
}
});
}
对应的服务端代码:
/// <summary> /// 支付接口 /// </summary> /// <param name="code"></param> /// <param name="openid"></param> /// <returns></returns> [HttpPost] public JsonResult GetPaySign(string code, string openid) { string body = "支付测试";//支付描述 string nonce_str = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr(); string notify_url = "http://" + HttpContext.Request.Url.Host + "/WxPay/PayNotifyUrl";//支付结果回调地址,不能带参数(PayNotifyUrl回调里能接到订单号out_trade_no参数) string out_trade_no = "WxPay_" + DateTime.Now.ToString("yyyyMMddHHmmssfff");//订单号:32个字符内、不得重复 string spbill_create_ip = Request.UserHostAddress;//用户端IP int total_fee = 1;//订单金额(单位:分),整数 string trade_type = "JSAPI";//JSAPI,NATIVE,APP,WAP #region 获取用户微信OpenId string openidExt = string.Empty; if (string.IsNullOrEmpty(openid)) { if (!Senparc.Weixin.QY.Containers.AccessTokenContainer.CheckRegistered(AppId)) { Senparc.Weixin.QY.Containers.AccessTokenContainer.Register(AppId, AppSecret); } var accountToken = Senparc.Weixin.QY.Containers.AccessTokenContainer.GetToken(AppId, AppSecret); var user = Senparc.Weixin.QY.AdvancedAPIs.OAuth2Api.GetUserId(accountToken, code); var model = Senparc.Weixin.QY.CommonAPIs.CommonApi.ConvertToOpenId(accountToken, user.UserId); openidExt = model.openid; } else { openidExt = openid; } #endregion #region 调用统一支付接口获得prepay_id(预支付交易会话标识) Senparc.Weixin.MP.TenPayLibV3.RequestHandler packageReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler(null); packageReqHandler.SetParameter("appid", AppId); packageReqHandler.SetParameter("body", body); packageReqHandler.SetParameter("mch_id", MchId); packageReqHandler.SetParameter("nonce_str", nonce_str); packageReqHandler.SetParameter("notify_url", notify_url); packageReqHandler.SetParameter("openid", openidExt); packageReqHandler.SetParameter("out_trade_no", out_trade_no); packageReqHandler.SetParameter("spbill_create_ip", spbill_create_ip); packageReqHandler.SetParameter("total_fee", total_fee.ToString()); packageReqHandler.SetParameter("trade_type", trade_type); packageReqHandler.SetParameter("sign", packageReqHandler.CreateMd5Sign("key", Key)); string data = packageReqHandler.ParseXML(); var result = Senparc.Weixin.MP.AdvancedAPIs.TenPayV3.Unifiedorder(data); var res = System.Xml.Linq.XDocument.Parse(result); string prepay_id = res.Element("xml").Element("prepay_id").Value; #endregion #region 支付参数 string timeStamp = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetTimestamp(); nonce_str = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr(); Senparc.Weixin.MP.TenPayLibV3.RequestHandler paysignReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler(null); paysignReqHandler.SetParameter("appId", AppId); paysignReqHandler.SetParameter("timeStamp", timeStamp); paysignReqHandler.SetParameter("nonceStr", nonce_str); paysignReqHandler.SetParameter("package", string.Format("prepay_id={0}", prepay_id)); paysignReqHandler.SetParameter("signType", "MD5"); string paysign = paysignReqHandler.CreateMd5Sign("key", Key); paysignReqHandler.SetParameter("paysign", paysign); #endregion return Json(new { data = paysignReqHandler.GetAllParameters(), openid = openidExt }, JsonRequestBehavior.AllowGet); }
前端页面全部代码:
<!DOCTYPE html> <html> <head> <title>企业号微信支付测试</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script> </head> <body> <input type="button" onclick="startWxPay()" class="btn btn-primary btn-lg btn-block" value="点击付费(¥:0.01元)" id="btnPay" style="margin-top:80px;" /> <script type="text/javascript"> var code = GetQueryString("code"); var openid = window.localStorage.getItem("openid"); $.ajax({ type: "GET", url: "/WxPay/GetPayConfig", beforeSend: function () { $("#btnPay").attr({ "disabled": "disabled" });//获取到配置之前,禁止点击付款按钮 }, success: function (data) { $("#btnPay").removeAttr("disabled");//获取到配置,打开付款按钮 wx.config({ debug: true, // 开启调试模式,成功失败都会有alert框 appId: data.appId, // 必填,公众号的唯一标识 timestamp: data.timeStamp, // 必填,生成签名的时间戳 nonceStr: data.nonceStr, // 必填,生成签名的随机串 signature: data.signature,// 必填,签名 jsApiList: [\'chooseWXPay\'] // 必填,需要使用的JS接口列表 }); wx.ready(function () { // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 }); wx.error(function (res) { // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); } }); function startWxPay() { $.ajax({ type: "POST", url: "/WxPay/GetPaySign", data: { code: code, openid: openid }, beforeSend: function () { $("#btnPay").attr({ "disabled": "disabled" }); }, success: function (res) { $("#btnPay").removeAttr("disabled"); if (res.openid != null && res.openid != undefined && res.openid != "") { window.localStorage.setItem("openid", res.openid); } wx.chooseWXPay({ timestamp: res.data.timeStamp, // 支付签名时间戳 nonceStr: res.data.nonceStr, // 支付签名随机串,不长于32 位 package: res.data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***) signType: "MD5", // 签名方式,默认为\'SHA1\',使用新版支付需传入\'MD5\' paySign: res.data.paysign, // 支付签名 success: function (res) { //支付成功 }, cancel: function (res) { //支付取消 } }); } }); } function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } </script> </body> </html>
后端控制器全部代码:
using Senparc.Weixin.HttpUtility; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; namespace CNPCCMS.Controllers { public class WxPayController : Controller { private static string AppId = "改成你的AppId"; private static string AppSecret = "改成你的AppSecret"; private static string Key = "改成你的Key"; private static string MchId = "改成你的MchId"; /// <summary> /// 获取微信支付配置 /// </summary> /// <returns></returns> [HttpGet] public JsonResult GetPayConfig() { string timeStamp = Senparc.Weixin.MP.TenPayLib.TenPayUtil.GetTimestamp(); string nonceStr = Senparc.Weixin.MP.TenPayLib.TenPayUtil.GetNoncestr(); string signature = new Senparc.Weixin.MP.TenPayLib.RequestHandler(null).CreateMd5Sign(); return Json(new { appId = AppId, timeStamp = timeStamp, nonceStr = nonceStr, signature = signature }, JsonRequestBehavior.AllowGet); } /// <summary> /// 支付接口 /// </summary> /// <param name="code"></param> /// <param name="openid"></param> /// <returns></returns> [HttpPost] public JsonResult GetPaySign(string code, string openid) { string body = "支付测试";//支付描述 string nonce_str = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr(); string notify_url = "http://" + HttpContext.Request.Url.Host + "/WxPay/PayNotifyUrl";//支付结果回调地址,不能带参数(PayNotifyUrl回调里能接到订单号out_trade_no参数) string out_trade_no = "WxPay_" + DateTime.Now.ToString("yyyyMMddHHmmssfff");//订单号:32个字符内、不得重复 string spbill_create_ip = Request.UserHostAddress;//用户端IP int total_fee = 1;//订单金额(单位:分),整数 string trade_type = "JSAPI";//JSAPI,NATIVE,APP,WAP #region 获取用户微信OpenId string openidExt = string.Empty; if (string.IsNullOrEmpty(openid)) { if (!Senparc.Weixin.QY.Containers.AccessTokenContainer.CheckRegistered(AppId)) { Senparc.Weixin.QY.Containers.AccessTokenContainer.Register(AppId, AppSecret); } var accountToken = Senparc.Weixin.QY.Containers.AccessTokenContainer.GetToken(AppId, AppSecret); var user = Senparc.Weixin.QY.AdvancedAPIs.OAuth2Api.GetUserId(accountToken, code); var model = Senparc.Weixin.QY.CommonAPIs.CommonApi.ConvertToOpenId(accountToken, user.UserId); openidExt = model.openid; } else { openidExt = openid; } #endregion #region 调用统一支付接口获得prepay_id(预支付交易会话标识) Senparc.Weixin.MP.TenPayLibV3.RequestHandler packageReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler(null); packageReqHandler.SetParameter("appid", AppId); packageReqHandler.SetParameter("body", body); packageReqHandler.SetParameter("mch_id", MchId); packageReqHandler.SetParameter("nonce_str", nonce_str); packageReqHandler.SetParameter("notify_url", notify_url); packageReqHandler.SetParameter("openid", openidExt); packageReqHandler.SetParameter("out_trade_no", out_trade_no); packageReqHandler.SetParameter("spbill_create_ip", spbill_create_ip); packageReqHandler.SetParameter("total_fee", total_fee.ToString()); packageReqHandler.SetParameter("trade_type", trade_type); packageReqHandler.SetParameter("sign", packageReqHandler.CreateMd5Sign("key", Key)); string data = packageReqHandler.ParseXML(); var result = Senparc.Weixin.MP.AdvancedAPIs.TenPayV3.Unifiedorder(data); var res = System.Xml.Linq.XDocument.Parse(result); string prepay_id = res.Element("xml").Element("prepay_id").Value; #endregion #region 支付参数 string timeStamp = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetTimestamp(); nonce_str = Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr(); Senparc.Weixin.MP.TenPayLibV3.RequestHandler paysignReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler(null); paysignReqHandler.SetParameter("appId", AppId); paysignReqHandler.SetParameter("timeStamp", timeStamp); paysignReqHandler.SetParameter("nonceStr", nonce_str); paysignReqHandler.SetParameter("package", string.Format("prepay_id={0}", prepay_id)); paysignReqHandler.SetParameter("signType", "MD5"); string paysign = paysignReqHandler.CreateMd5Sign("key", Key); paysignReqHandler.SetParameter("paysign", paysign); #endregion return Json(new { data = paysignReqHandler.GetAllParameters(), openid = openidExt }, JsonRequestBehavior.AllowGet); } /// <summary> /// 支付结果回调地址 /// </summary> /// <returns><以上是关于企业号微信支付 公众号支付 H5调起支付API示例代码 JSSDK C# .NET的主要内容,如果未能解决你的问题,请参考以下文章