C#完成JSAPI支付(一)

C#完成JSAPI支付


一、为什么要写JSAPI微信支付的文章


  1. 最近有微信H5支付的相关业务,希望下次遇到类似业务时不迷路
  2. 微信H5支付配置纷繁复杂,对关键点进行记录,加强记忆

二、准备资料


  • 微信商户号

      登录微信商户,进入账户中心,点击个人信息,查看商户号

      

  • 微信支付API密钥

       登录微信商户,进入账户中心,点击API安全,然后在该页的API密钥部分,查看微信支付API密钥

      

  • 配置支付目录

      登录微信支付商户平台(pay.weixin.qq.com)-->产品中心-->开发配置。支付授权目录校验规则说明:

  1. 如果支付授权目录设置为顶级域名(例如:https://www.weixin.com/ ),那么只校验顶级域名,不校验后缀;
  2. 如果支付授权目录设置为多级目录,就会进行全匹配,例如设置支付授权目录为https://www.weixin.com/abc/123/,则实   际请求页面目录不能为https://www.weixin.com/abc/,也不能为https://www.weixin.com/abc/123/pay/,必须为             https://www.weixin.com/abc/123/;
  • 配置微信公众号IP白名单

     将我们服务器的IP地址配置到微信公众号IP地址白名单,登录微信公众号,安全中心-->Ip白名单

     

    点击Ip白名单,配置我们的服务器地址。

     

    

  • 下载JSAPI支付SDK。

      下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

       进入页面之后,选择.NET C#的SDK下载

      

  解压后的目录如下,其实在开发过程中,我们主要使用两部分,分别为Lib跟business文件夹中的对象。故仅需要将这两部分代码Copy至我们项目工程中即可。

 三、开发工作


       关于微信H5开发,分两部分完成。

  • 后端C#代码
  • 前端Jquery代码

     我认为,我在完成微信H5支付之前,需要先了解微信支付的执行步骤。

  1. 调用微信统一下单接口
  2. Html页,前端发起支付
  3. 支付成功,微信回调我们服务器完成支付。

     C#代码


     第一步:赋值WxPayConfig对象

     微信支付的所有配置信息都在Lib文件中的WxPayConfig对象中,我们在调用统一下单接口前,需将我们实际支付环境中的配置信息更新至WxPayConfig对象。WxPayConfig类的结构如下:

public class WxPayConfig
    {
        #region 微信支付信息

        /// <summary>
        /// 微信公众号AppId
        /// </summary>
        public static string APPID
        {
            get;set;
        }


        /// <summary>
        /// MCHID:商户号(必须配置)
        /// </summary>
        public static string MCHID
        {
            get; set;
        }

        /// <summary>
        /// 商户系统后台机器IP,此参数可手动配置也可在程序中自动获取
        /// </summary>
        public static string IP
        {
            get; set;
        }


        /// <summary>
        /// 支付结果通知回调url,用于商户接收支付结果
        /// </summary>
        public static string NOTIFY_URL
        {
            get; set;
        }

        /// <summary>
        /// 微信支付统一下单接口地址
        /// </summary>
        public static string UnifiedorderUrl
        {
            get; set;
        }

        #endregion



        /// <summary>
        /// 微信支付有效时间
        /// </summary>
        public static string Time_expire
        {
            get; set;
        }

        /// <summary>
        /// APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)
        /// </summary>
        public static string APPSECRET
        {
            get; set;
        }


        /// <summary>
        /// KEY:商户支付密钥,参考开户邮件设置(必须配置)
        /// </summary>
        public static string KEY
        {
            get; set;
        }

        /// <summary>
        /// 【日志级别】,日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息
        /// </summary>
        public static int LOG_LEVENL
        {
            get; set;
        }

        //=======【证书路径设置】===================================== 
        /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
        */
        public static string SSLCERT_PATH
        {
            get; set;
        }
        public static string SSLCERT_PASSWORD
        {
            get; set;
        }

        //=======【代理服务器设置】===================================
        /* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)
        */
        public const string PROXY_URL = "http://10.152.18.220:8080";

        //=======【上报信息配置】===================================
        /* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报
        */
        public const int REPORT_LEVENL = 1;

        /// <summary>
        /// 证书路径
        /// </summary>
        public static string WxSSLPath { get; set; }
        
        /// <summary>
        /// 证书秘钥
        /// </summary>
        public static string WxSSLPwd { get; set; }
    }

 我们需要更新的配置信息如下:

 //统一下单请求地址
 WxPayConfig.UnifiedorderUrl = https://api.mch.weixin.qq.com/pay/unifiedorder; 
//微信支付成功后的回调地址
 WxPayConfig.NOTIFY_URL = "回调地址";
//微信公众号的AppId
 WxPayConfig.APPID = "公众号AppId";
//微信商户的商户号
 WxPayConfig.MCHID = "微信商户号";
//服务器的Ip地址
 WxPayConfig.IP = "Ip地址";
//微信商户的支付密钥
 WxPayConfig.KEY = "支付密钥";

     第二步:创建JsApiPay对象,并赋值

   JsApiPay对象中有四个属性,三个方法,一个空构造函数

   三个属性分别为:

 /// <summary>
 /// openid用于调用统一下单接口【支付者的OpenId】
 /// </summary>
 public string openid { get; set; }

 /// <summary>
 /// access_token用于获取收货地址js函数入口参数【该参数我们不会用到】
 /// </summary>
 public string access_token { get; set; }

 /// <summary>
 /// 商品金额,用于统一下单【支付金额】
 /// </summary>
 public int total_fee { get; set; }

 /// <summary>
 /// 统一下单接口返回结果【统一下单返回结果】
 /// </summary>
 public WxPayData unifiedOrderResult { get; set; }

 声明JsApiPay对象, 并依次为我们需要赋值的参数赋值。

//声明JsApiPay对象
JsApiPay jsApiPay = new JsApiPay();
//微信支付金额是以分为单位,所以我们需对钱数进行转换,*100为最终支付金额
string strFee = (data.pay_price * 100).ToString("0");
//支付人的OpenId
jsApiPay.openid = data.openid;
//为支付金额赋值
jsApiPay.total_fee = Convert.ToInt32(strFee);

第三步:调用JsApiPay对象中的统一下单方法

 调用jsApiPay中的方法GetUnifiedOrderResult()获取统一下单结果。

 WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult();

微信提供的示例中,GetUnifiedOrderResult的方法体如下:

/**
 * 调用统一下单,获得下单结果
* @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() == "")
    {
       throw new WxPayException("UnifiedOrder response error!");
    }
    unifiedOrderResult = result;
    return result;
}

 我们需要做的就是替换方法体中的body,attach,goods_tag参数。

 请注意:如果我们没有任何优惠券信息,goods_tag参数可为空,我们可以不赋值或者无需拼接该参数。

第四步:调用JsApiPay中的方法GetJsApiParameters().获取Js支付参数完成支付。

 如果统一下单方法调用成功,我们还需调用JsApiPay中的方法GetJsApiParameters()。完成最终支付。微信提供的GetJsApiParameters方法体示例如下,我们无需修改。

 /**
        *  
        * 从统一下单成功返回的数据中获取微信浏览器调起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()
        {

            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();

            return parameters;
        }

  将GetJsApiParameters方法的结果返回至前端Html代码即可。就这样我们的C#部分代码就完成了。

Html代码


第一步 判断是否为微信浏览器内完成支付

根据微信要求,微信支付必须在微信浏览器内完成,我们如何判断当前客户打开该页面时是否启用了微信浏览器,微信提供了对象以及方法

 if (typeof WeixinJSBridge == "undefined") {
      // 提交支付信息
      if (document.addEventListener) {
           document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
      } else if (document.attachEvent) {
          document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
          document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
      }
     // 提交支付信息
     onBridgeReady();           
} else {         
    // 提交支付信息
    onBridgeReady();
}

在onBridgeReady方法内,我们调用统一下单的ajax请求,并使用返回的jsApiParam对象完成支付。

function onBridgeReady() {
   $.ajax({
      url: "统一下单请求Url",
      data: {"请求的业务数据"},
      type: "post",
      dataType: "json",
      success: function (data) {
         var resultData = "返回的jsApiParam的Json数据结果";
         WeixinJSBridge.invoke(
            'getBrandWCPayRequest',
             JSON.parse(resultData),
             function (res) {
                 switch (res.err_msg) {
                    case "get_brand_wcpay_request:ok":
                         //支付成功
                          break;
                     case "get_brand_wcpay_request:cancel":
                          //支付取消
                          break;
                      default:
                          //支付失败
                          break;
                        }
                    }
                );
            },
            error: function () {
               
            }
        });
    }

至此我们JSAPI完成H5支付的全部过程就已经完成。下一篇,我会着重写一下我们应该如何处理微信的支付回调请求。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值