写这篇文章记录最近一次接入微信公众号支付的一些思路。
首先无论是支付宝还是微信用h5编写的代码想获取微信的授权都必须发一个get请求给https://open.weixin.qq.com/connect/oauth2/authorize,后面的参数省略,其中有一个参数redirect_uri很重要这个是授权返回的你本地程序的url你可以在这个返回的过程中带几个自己的参数。
[HttpGet]
public ActionResult McrMsgOAuth(string OrganizationId,string WId)
{
string RootUrl = GlobalContext.WeChatPay.WebSevRootUrl;
WxModel model = new WxModel();
model.WxOAuthUrl = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}##wechat_redirect", GlobalContext.WeChatPay.AppId, WebHelper.HtmlEncode(string.Format("{0}/ParkingLotManage/KadPay/McrMsgOAuthReCall?WId="+WId, RootUrl)), "snsapi_userinfo", OrganizationId);
return View(model);
}
授权的过程需要取一次token,顺便把openid取到,当然你可以利用现有的信息取到一些个人资料。下面的代码就是取token的方法。
public static PayAccess GetPayAccessToken(string code) {
string ApiUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
string RequestParameter = string.Format("appid={0}&secret={1}&code={2}&grant_type={3}", GlobalContext.WeChatPay.AppId, GlobalContext.WeChatPay.AppSecret, code, "authorization_code");
string WxData = WebHelper.UseGetPushApi(ApiUrl, RequestParameter, Encoding.UTF8);
//log.AppendAndSave("WeiXinAccount_GetPayAccessToken", string.Format("WxData:{0}", WxData));
PayAccess access = null;
if (!string.IsNullOrWhiteSpace(WxData) && WxData.IndexOf("errcode") < 0)
{//请求成功
try
{
access = JsonConvert.DeserializeObject<PayAccess>(WxData);
}
catch (Exception ex)
{
}
}
return access;
}
取到的信息可以缓存起来或者组织存成数据库信息。很多过程视业务而定,在整个支付过程中需要用cookie缓存一个个人用户信息来避免反复授权。其次要缓存整个交易过程中的一些信息,并不是所有信息都要通过url传递的这点大家都应该了解。
[HttpGet]
public async Task<ActionResult> McrMsgOAuthReCall(string code, string state,string WId)
{
LogHelper.Write("McrMsgOAuthReCall!! code:" + code + ",state:" + state + ",WId:" + WId);
//state是组织机构id
PayAccess access = WebHelper.GetPayAccessToken(code);
//WebHelper.GetWxUserInfo(access.access_token, access.openid);
var UserId = IdGeneratorHelper.Instance.GetId();
MembersEntity entity = new MembersEntity();
entity.OpenId = access.openid;
entity.Id = UserId;
entity.OrganizationId = long.Parse(state);
entity.RegisterTime = DateTime.Now;
CarModel model = new CarModel();
model.OrganizationId = long.Parse(state);
model.UserId = UserId + "";
model.PayMethod = 1;
model.OpenId = access.openid;
model.WId = WId;
CacheFactory.Cache.SetCache<CarModel>(UserId+"", model);
LogHelper.Write("openid:" + access.openid + ",userId:" + UserId + ",OrganizationId:" + state);
TData<string> obj = await membersBLL.AddForm(entity);
if (obj.Tag == 1) {
_httpContextAccessor.HttpContext.Response.Cookies.Append(GlobalContext.WeChatPay.McrMsgUserCookieKey + state, UserId+"");
}
//授权完userid openid 组织机构id存到数据库
//存cookie
return this.RedirectToRoute(new { controller = "KadPay", action = "McrMsgConfirmOrder", Dsn="", WId=WId, UserId = UserId });
}
最近是为了测试支付,通过授权之后直接到订单页面支付了。订单的一些信息是通过service取到的,现在是测试机器不可能一直联通所以为了方便就直接new一个对象把值都构建出来。
[HttpGet]
public ActionResult McrMsgConfirmOrder(string WId, string Dsn, string UserId,string CarNumber) {
ViewBag.flag = false;
LogHelper.Write("McrMsgConfirmOrder:WId:" + WId + ",Dsn:" + Dsn + ",UserId:" +UserId);
//Payment payment = ParkingTcpService.Instance().GetUnpaidParkingFee(int.Parse(WId), "", Dsn);
Payment payment = new Payment();
payment.PlateNO = "闽DXC921";
payment.ParkingName = "科安达停车场";
payment.EntTime = DateTime.Now;
payment.ParkingTime = 40;
payment.TotalAmount = 0.01;
OrdersEntity entity = new OrdersEntity();
entity.OrderNo = IdGeneratorHelper.Instance.GetId() + "";
entity.PayUserId = long.Parse(UserId);
LogHelper.Write("McrMsgConfirmOrder:UserId" + UserId + "");
LogHelper.Write((payment!=null) +"");
if (payment != null)
{
entity.LicencePlateNo = payment.PlateNO;
entity.ParkingLotName = payment.ParkingName;
entity.TimeIn = payment.EntTime;
entity.TimeOut = ((DateTime)payment.EntTime).AddSeconds(payment.ParkingTime * 60);
entity.ParkingTime = payment.ParkingTime + "";
entity.TotalFee = payment.TotalAmount*100;
}
LogHelper.Write("WeChatPay:TotalFee" + entity.TotalFee + "");
LogHelper.Write("WeChatPay:UserId" + entity.PayUserId);
ActionResult result = new ViewResult();
CarModel cache = CacheFactory.Cache.GetCache<CarModel>(entity.PayUserId + "");
WxPayData data = new WxPayData();
data.SetValue("body", string.Format("{0}停车缴费", entity.LicencePlateNo));
data.SetValue("attach", string.Format(""));
data.SetValue("out_trade_no", entity.OrderNo);
//data.SetValue("total_fee", re.Price.ToString());//支付金额 /分
data.SetValue("total_fee", entity.TotalFee + "");
var timeStamp = DateTime.Now.ToString("yyyyMMddHHmmss");
data.SetValue("time_start", timeStamp);
data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
//data.SetValue("goods_tag", "test");//订单优惠标记
data.SetValue("trade_type", "JSAPI");//交易类型
data.SetValue("openid", cache.OpenId);
LogHelper.Write("WeChatPay:OpenId" + cache.OpenId + "");
data.SetValue("notify_url", GlobalContext.WeChatPay.NOTIFY_URL);
string IPAddress = _httpContextAccessor.HttpContext.Connection.LocalIpAddress.ToString();
WxPayData wxdata = WxUtil.UnifiedOrder(data, IPAddress);
if (!wxdata.IsSet("appid") || !wxdata.IsSet("prepay_id") || wxdata.GetValue("prepay_id").ToString() == "")
{
return result;
}
string ViewStr = WxUtil.GetJsApiParameters(wxdata, timeStamp);
LogHelper.Write(ViewStr);
//ViewBag.wxJsApiParam = ViewStr;
ViewData["wxJsApiParam"] = ViewStr;
return View(entity);
}
返回来的值可以构成一串json字符串,传递到前端配合一些js就可以唤起支付了。其他有些部分的代码就在微信提供的demo里面。我不知道是不是大家都这样,代码中用到linq,但是打开编译环境确实.net framework 2.0,需要手工把编译环境改成.net framework 4.0。
最后附上前端调用的js
<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall() {
//alert("jsApiCall");
WeixinJSBridge.invoke(
'getBrandWCPayRequest', @Html.Raw(ViewData["wxJsApiParam"]),//josn串/**/
function (res) {
WeixinJSBridge.log(res.err_msg);
//alert(res.err_code + res.err_desc + res.err_msg);
if (res.err_msg == "get_brand_wcpay_request:ok") {
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
location.href = "McrMsgPayOK";
}
}
);
}
function callpay() {
//alert(typeof WeixinJSBridge);
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}
else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}
else {
jsApiCall();
}
}
</script>
文章就写到这里了希望对大家有所帮助