jsapi微信支付

1.商户号配置

 

 2.公众号配置

添加域名123

 

3.页面

 

@model HZSoft.Application.Entity.CustomerManage.OrdersEntity
@{
    ViewBag.Title = "微信支付";
    var wxModel = ViewBag.WxModel as HZSoft.Application.Entity.WeChatManage.WFTWxModel;
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="applicable-device" content="mobile">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <meta http-equiv="Cache-Control" content="no-transform" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="支付订单 - 号运来靓号网">
    <title>支付订单 - 号运来靓号网</title>
    <meta content="" name="keywords">
    <meta content="" name="description">
    <link rel="stylesheet" href="/themes/simplebootx_mobile/Public/css/weui.min.css">
    <link rel="stylesheet" href="/themes/simplebootx_mobile/Public/css/jquery-weui.min.css">
    <link rel="stylesheet" href="/themes/simplebootx_mobile/Public/css/css.css">
    <meta name="__hash__" content="137ccc9ca3ff27d6c709d815bd63ab8f_175ed9f66d3159947c7f7b2e755ad041" />
    <!-- Bytedance Tracking -->
    <script>
        (function (r, d, s, l) {
            var meteor = r.meteor = r.meteor || []; meteor.methods = ["track", "off", "on"]; meteor.factory = function (method) {
                return function () {
                    var args = Array.prototype.slice.call(arguments); args.unshift(method); meteor.push(args); return meteor
                }
            }; for (var i = 0; i < meteor.methods.length; i++) {
                var key = meteor.methods[i]; meteor[key] = meteor.factory(key)
            } meteor.load = function () {
                var js, fjs = d.getElementsByTagName(s)[0]; js = d.createElement(s);
                js.src = "https://analytics.snssdk.com/meteor.js/v1/" + l + "/sdk"; fjs.parentNode.insertBefore(js, fjs)
            }; meteor.load(); if (meteor.invoked) { return }
            meteor.invoked = true; meteor.track("pageview")
        })(window, document, "script", "1667359354378253");
    </script>
    <!-- End Bytedance Tracking -->
</head>
<body class="page">
    <div class="page-title">
        <a href="/webapp/xdd2/mobileinfo/@Model.TelphoneID"><i class="-back"></i></a>
        <h1>号码订购</h1>
    </div>
    <div class="weui-cells__title">
        配送信息
    </div>
    <div class="weui-cells weui-cells_form">
        <div class="weui-cell">
            <div class="weui-cell__hd">
                <label class="weui-label">联系人</label>
            </div>
            <div class="weui-cell__bd">
                <input class="weui-input" type="text" id="name" placeholder="请输入联系人姓名">
            </div>
        </div>
        <div class="weui-cell">
            <div class="weui-cell__hd">
                <label class="weui-label">联系电话</label>
            </div>
            <div class="weui-cell__bd">
                <input class="weui-input" type="number" id="mobile" pattern="[0-9]*" placeholder="请输入联系电话">
            </div>
        </div>
        <div class="weui-cell">
            <div class="weui-cell__hd">
                <label class="weui-label">配送城市</label>
            </div>
            <div class="weui-cell__bd">
                <input class="weui-input" type="text" id='city' placeholder="请选择城市" readonly>
            </div>
        </div>
        <div class="weui-cell">
            <div class="weui-cell__hd">
                <label class="weui-label">详细地址</label>
            </div>
            <div class="weui-cell__bd">
                <input class="weui-input" type="text" id="address" placeholder="请输入详细地址">
            </div>
        </div>
    </div>
    <div class="weui-cells__title">
        预订信息
    </div>
    <div class="weui-form-preview">
        <div class="weui-form-preview__bd">
            <div class="weui-form-preview__item">
                <label class="weui-form-preview__label">预定号码</label><span class="weui-form-preview__value color-yellow">
                    <h3>@Model.Tel</h3>
                </span>
            </div>
            <div class="weui-form-preview__item">
                <label class="weui-form-preview__label">订单总计</label><span class="weui-form-preview__value color-danger">
                    <h3>¥@Model.Price</h3>
                </span>
            </div>
        </div>
    </div>
    <div class="weui-cells__title">
        请选择支付方式
    </div>
    <div class="weui-cells weui-cells_radio">
        <label class="weui-cell weui-check__label" for="x11">
            <div class="weui-cell__hd">
                <img src="/themes/simplebootx_mobile/Public/images/weixin.png" width="20px">
            </div>
            <div class="weui-cell__bd">
                <p>
                    微信支付
                </p>
            </div>
            <div class="weui-cell__ft">
                <input type="radio" class="weui-check" value="wechat" name="paytype" id="x11" checked="checked"><span class="weui-icon-checked"></span>
            </div>
        </label>
    </div>
    <div class="page-btn">
        <a href="#" id="submit" data-id="@ViewBag.id" class="weui-btn" style="background: #ee5246;">立即支付</a>
    </div>
    <script src="/themes/simplebootx_mobile/Public/js/jquery.min.js"></script>
    <script src="/themes/simplebootx_mobile/Public/js/jquery-weui.min.js"></script>
    <script src="~/assets/wap/js/city-picker.min.js"></script>
    <script type="text/javascript">
        $(function () {
            var flag = IsPC(); //true为PC端,false为手机端

            $("#city").cityPicker({
                title: "请选择城市",
                showDistrict: false
            });
            var check = false
            $('#submit').bind('click', function () {
                var that = $(this);
                if (check) return;
                check = true;
                var id = that.data('id');
                var name = $('#name').val();
                var mobile = $('#mobile').val();
                var city = $('#city').val();
                var address = $('#address').val();
                var str = /^1[3|4|5|6|7|8|9][0-9]{9}$/;
                var paytype = $('input[name=paytype]:checked').val();
                if (name) {
                    if (str.exec(mobile)) {
                        if (city && city.indexOf("选择")<0) {
                            if (address) {
                                $.ajax({
                                    type: "post",
                                    url: "/webapp/xdd2/JsApi",
                                    data: {
                                        Id:@Model.Id,
                                        Receiver: name,
                                        ContactTel: mobile,
                                        City: city,
                                        Address: address,
                                        PayType: paytype
                                    },
                                    cache: false,
                                    async: false,
                                    dataType: "json",
                                    success: function (resObj) {
                                        if (resObj.status) {
                                            //头条推广转化(点击支付)
                                            meteor.track("form", { convert_id: "1667736631584772" })

                                                //JSApi支付
                                                WeixinJSBridge.invoke(
                                                'getBrandWCPayRequest', {
                                                    "appId":"@wxModel.appId",     //公众号名称,由商户传入
                                                    "timeStamp": "@wxModel.timeStamp",         //时间戳,自1970年以来的秒数
                                                    "nonceStr": "@wxModel.nonceStr", //随机串
                                                    "package": "@wxModel.package",
                                                    "signType": "MD5",         //微信签名方式:
                                                    "paySign": "@wxModel.paySign" //微信签名
                                                },
                                                function (res) {
                                                    if (res.err_msg == "get_brand_wcpay_request:ok") {
                                                        //支付成功,后续自行处理
                                                        $.toast("支付成功", function () {
                                                            document.location.href = '@wxModel.callback_url';
                                                        });
                                                    }
                                                    else if (res.err_msg == "get_brand_wcpay_request:cancel") {
                                                        //支付取消,或者其他错误,自行处理
                                                        $.toast("支付取消", "cancel");
                                                    }
                                                    else {
                                                        alert(res.err_msg);
                                                        $.toast("支付失败", "forbidden");
                                                    }
                                                });
                                        } else {
                                            $.hideLoading();
                                            //状态显示
                                            $.toptip(resObj.msg, resObj.status ? 'success' : 'error');
                                        }
                                    },
                                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                                        $.toast("提交失败,请重试", "forbidden");
                                    }
                                });

                            } else {
                                $.toast("请输入详细地址", "forbidden");
                            }
                        } else {
                            $.toast("请选择城市", "forbidden");
                        }
                    } else {
                        $.toast("请输入正确的手机号", "forbidden");
                    }
                } else {
                    $.toast("请输入姓名", "forbidden");
                }
                check = false;
                return false;
            });
        })


        function IsPC() {
            var flag = 1;
            //平台、设备和操作系统
            var system = {
                win: false,
                mac: false,
                xll: false,
                ipad: false
            };
            //检测平台
            var p = navigator.platform;
            system.win = p.indexOf("Win") == 0;
            system.mac = p.indexOf("Mac") == 0;
            system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
            system.ipad = (navigator.userAgent.match(/iPad/i) != null) ? true : false;
            //跳转语句,如果是PC访问就自动跳转到所要访问的页面http://www.电脑.com
            if (system.win || system.mac || system.xll || system.ipad) {
                //默认访问http://www.电脑.com
            } else {
                //window.location.href = "http://www.手机.com/";
                flag = 0;
            }
            if (isWeiXin()) {
                flag = 2;
            }
            return flag;
        }

        //微信浏览器:Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1 wechatdevtools/1.02.1912261
        //换行MicroMessenger / 7.0.4 Language / zh_CN webview / 15904873695067660 webdebugger port / 47695

        //谷歌浏览器:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36

        //360极速浏览器:Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)
        function isWeiXin() {
            var ua = window.navigator.userAgent.toLowerCase();
            if (ua.match(/MicroMessenger/i) == 'micromessenger') {
                return true;
            } else {
                return false;
            }
        }


    </script>
</body>
</html>

 

 

4.后端

//需要OAuth登录
        [HandlerWX2AuthorizeAttribute(LoginMode.Enforce)]
        public ActionResult JsApi(int? id, string Tel, string Price, string host)
        {
            OrdersEntity ordersEntity = new OrdersEntity()
            {
                TelphoneID = id,
                Tel = Tel,
                Price = Convert.ToDecimal(Price),
                Host = host,
            };

            //创建订单表
            ordersEntity = ordersbll.SaveForm(ordersEntity);

            var openId = (string)Session["OpenId"];
            var sp_billno = ordersEntity.OrderSn;
            var nonceStr = TenPayV3Util.GetNoncestr();
            var timeStamp = TenPayV3Util.GetTimestamp();

            //商品Id,用户自行定义
            var xmlDataInfoH5 = new TenPayV3UnifiedorderRequestData(WeixinConfig.AppID2, tenPayV3Info.MchId, "JSAPI购买靓号", sp_billno,
Convert.ToInt32(ordersEntity.Price * 100),
Request.UserHostAddress, tenPayV3Info.TenPayV3Notify, TenPayV3Type.JSAPI, openId, tenPayV3Info.Key, nonceStr);
            var result = TenPayV3.Unifiedorder(xmlDataInfoH5);//调用统一订单接口
            LogHelper.AddLog(result.ResultXml);//记录日志
            var package = string.Format("prepay_id={0}", result.prepay_id);
            if (result.return_code == "SUCCESS")
            {
                WFTWxModel jsApiPayData = new WFTWxModel()
                {
                    appId = WeixinConfig.AppID2,
                    timeStamp = timeStamp,
                    nonceStr = nonceStr,
                    package = package,
                    paySign = TenPayV3.GetJsPaySign(WeixinConfig.AppID2, timeStamp, nonceStr, package, WeixinConfig.Key),
                    callback_url = "https://shop.jnlxsm.net/webapp/xdd2/paymentFinish/" + ordersEntity.Id
                };
                ViewBag.WxModel = jsApiPayData;
                LogHelper.AddLog(JsonConvert.SerializeObject(jsApiPayData));//记录日志
            }
            return View(ordersEntity);
        }
        

        //需要OAuth登录
        [HttpPost]
        public ActionResult JsApi(OrdersEntity ordersEntity)
        {
            try
            {
                string[] area = ordersEntity.City.Split(' ');
                if (area.Length > 0)
                {
                    ordersEntity.Province = area[0];//
                    ordersEntity.City = area[1];//
                }
                ordersbll.SaveForm(ordersEntity.Id,ordersEntity);
                H5Response root = new H5Response { code = true, status = true, msg = "\u63d0\u4ea4\u6210\u529f\uff01", data = { } };
                return Content(JsonConvert.SerializeObject(root));
            }
            catch (Exception ex)
            {
                var msg = ex.Message;
                msg += "<br>" + ex.StackTrace;
                msg += "<br>==Source==<br>" + ex.Source;

                if (ex.InnerException != null)
                {
                    msg += "<br>===InnerException===<br>" + ex.InnerException.Message;
                }
                return Content(msg);
            }
        }
using System.Web.Mvc;
using HZSoft.Application.Code;
using HZSoft.Util;
using System.Web;
using HZSoft.Application.Web.Utility;

namespace HZSoft.Application.Web
{
    /// <summary>
    /// 版 本 6.1
    /// 
    /// 创建人:佘赐雄
    /// 日 期:2015.11.9 10:45
    /// 描 述:登录认证(会话验证组件)
    /// </summary>
    public class HandlerWX2AuthorizeAttribute : AuthorizeAttribute
    {
        private LoginMode _customMode;
        /// <summary>默认构造</summary>
        /// <param name="Mode">认证模式</param>
        public HandlerWX2AuthorizeAttribute(LoginMode Mode)
        {
            _customMode = Mode;
        }

        /// <summary>
        /// 响应前执行登录验证,查看当前用户是否有效 
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            //登录拦截是否忽略
            if (_customMode == LoginMode.Ignore)
            {
                return;
            }
            //请求地址
            HttpRequest request = HttpContext.Current.Request;
            string RequestUri = request.RawUrl;//AbsoluteUri//FilePath//!string.IsNullOrEmpty(request.Params["urlstr"]) ? request.Params["urlstr"] : 
            if (RequestUri.IndexOf("&amp;")>0)
            {
                //WeChatManage/Liang/Index?organizeId=4da3b884-ac5b-46fb-af10-150beb9e6c69&amp;amp;amp;amp;amp;from=timeline&amp;amp;amp;amp;from=timeline&amp;amp;amp;from=timeline&amp;amp;from=timeline&amp;from=timeline
                //防止提示state参数过长问题,连接转发多次之后会带着一些转发到哪里的冗余信息
                RequestUri = RequestUri.Substring(0, RequestUri.IndexOf("&amp;"));//WeChatManage/Liang/Index?organizeId=4da3b884-ac5b-46fb-af10-150beb9e6c69
            }
            //判断是否微信通过认证
            if (CurrentWxUser.Users == null)
            {
                string url = string.Format(WeixinConfig.GetCodeUrl2, HttpUtility.UrlEncode(RequestUri));
                filterContext.Result = new RedirectResult(url);
                LogHelper.AddLog("filterContext.Result:" + url);
                return;
            }
        }



    }
}
using HZSoft.Application.Busines.BaseManage;
using HZSoft.Application.Busines.WeChatManage;
using HZSoft.Application.Entity.BaseManage;
using HZSoft.Application.Entity.WeChatManage;
using HZSoft.Application.Web.Utility;
using HZSoft.Util;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Net;
using HZSoft.Application.Entity.SystemManage;
using HZSoft.Application.Code;
using HZSoft.Application.Busines.AuthorizeManage;
using HZSoft.Application.Busines.SystemManage;
using HZSoft.Util.Attributes;
using Newtonsoft.Json;
using HZSoft.Application.Entity.CustomerManage;
using HZSoft.Application.Busines.CustomerManage;

namespace HZSoft.Application.Web.Areas.WeChatManage.Controllers
{
    /// <summary>
    /// 微信认证和登录
    /// </summary>
    public class WX2LoginController : Controller
    {
        WeChat_UsersBLL wechatUserBll = new WeChat_UsersBLL();
        UserBLL userBLL = new UserBLL();

        /// <summary>
        /// 微信认证
        /// https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx24e47efa56c2e554&redirect_uri=http%3a%2f%2fmap.lywenkai.cn%2fWeChatManage%2fWeiXinHome%2fRedirect&response_type=code&scope=snsapi_userinfo&state=http%3a%2f%2fmap.lywenkai.cn%2fWeChatManage%2fLogin%2fIndex#wechat_redirect
        /// </summary>
        /// <param name="code">snsapi_userinfo</param>
        /// <param name="state">回调url</param>
        /// <returns></returns>
        public ActionResult Redirect(string code, string state)
        {
            LogHelper.AddLog($"微信认证请求地址:{System.Web.HttpContext.Current.Request.Url.ToString()}  参数code: {code},参数state: {state}");
            //若用户禁止授权,则重定向后不会带上code参数
            if (string.IsNullOrEmpty(code))
            {
                return Redirect(state);
            }
            else
            {
                WeixinToken token = new WeixinToken();
                //判断是否保存微信token,用户网页授权,不限制
                if (Session[WebSiteConfig.WXTOKEN_SESSION_NAME] != null)
                {
                    token = Session[WebSiteConfig.WXTOKEN_SESSION_NAME] as WeixinToken;
                }
                else
                {
                    string tokenUrl = string.Format(WeixinConfig.GetTokenUrl2, code);
                    LogHelper.AddLog($"请求tokenUrl地址: {tokenUrl}");
                    token = AnalyzeHelper.Get<WeixinToken>(tokenUrl);
                    if (token.errcode != null)
                    {
                        return Content("网页授权Error:" + token.errcode + "" + token.errmsg);
                    }
                    Session[WebSiteConfig.WXTOKEN_SESSION_NAME] = token;
                }
                Session["OpenId"] = token.openid;//进行登录
                LogHelper.AddLog($"token.openid: {Session["OpenId"]}");
                //查询用户是否存在
                var userEntity = wechatUserBll.GetEntity(token.openid);
                if (userEntity == null)
                {
                    string userInfoUrl = string.Format(WeixinConfig.GetUserInfoUrl2, token.access_token, token.openid);
                    var userInfo = AnalyzeHelper.Get<WeixinUserInfo>(userInfoUrl);
                    if (userInfo.errcode != null)
                    {
                        Response.Write(userInfo.errcode + ":" + userInfo.errmsg);
                        Response.End();
                    }
                    else
                    {
                        userEntity = new WeChat_UsersEntity()
                        {
                            City = userInfo.city,
                            Country = userInfo.country,
                            HeadimgUrl = userInfo.headimgurl,
                            NickName = userInfo.nickname,
                            OpenId = userInfo.openid,
                            Province = userInfo.province,
                            Sex = userInfo.sex,
                            AppName = Config.GetValue("AppName2")
                        };
                        wechatUserBll.SaveForm("", userEntity);
                    }
                }
                Session[WebSiteConfig.WXUSER_SESSION_NAME] = userEntity;
                return Redirect(state);
            }
        }
        
    }
}

 

 

注意,微信OAuth登录验证是不能通过post提交的

get方式,先获取页面微信model。初始化订单数据

再提交补充客户信息字段

 

商家存在未配置的参数,请联系商家解决

H5支付报错,域名与设置域名不匹配导致

posted on 2020-05-28 20:21  张彦山  阅读(376)  评论(0编辑  收藏  举报