1. 程式人生 > >C#微信支付對接

C#微信支付對接

獲得 rtc none ron 判斷 setting play 提交 display

c#版在pc端發起微信掃碼支付

技術分享圖片

技術分享圖片

主要代碼:

技術分享圖片
/**
        * 生成直接支付url,支付url有效期為2小時,模式二
        * @param productId 商品ID
        * @return 模式二URL
        */
        public string GetPayUrl(string productId, string body, string attach, int total_fee, string goods_tag)
        {
            Log.Info(this.GetType().ToString(), "Native pay mode 2 url is producing...");

            WxPayData data = new WxPayData();
            data.SetValue("body", body);//商品描述
            data.SetValue("attach", attach);//附加數據
            data.SetValue("out_trade_no", productId);//隨機字符串
            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", goods_tag);//商品標記
            data.SetValue("trade_type", "NATIVE");//交易類型
            data.SetValue("product_id", productId);//商品ID

            WxPayData result = WxPayApi.UnifiedOrder(data);//調用統一下單接口
            string url = result.GetValue("code_url").ToString();//獲得統一下單接口返回的二維碼鏈接

            Log.Info(this.GetType().ToString(), "Get native pay mode 2 url : " + url);
            return url;
        }
技術分享圖片

配置信息:

技術分享圖片
public class Config
    {
        //=======【基本信息設置】=====================================
        /* 微信公眾號信息配置
        * APPID:綁定支付的APPID(必須配置)
        * MCHID:商戶號(必須配置)
        * KEY:商戶支付密鑰,參考開戶郵件設置(必須配置)
        * APPSECRET:公眾帳號secert(僅JSAPI支付的時候需要配置)
        */
        public const string APPID = "你的微信公眾號APPID";
        public const string MCHID = "你的微信公眾號的商戶號";
        public const string KEY = "你的微信公眾號的商戶支付密鑰";
        public const string APPSECRET = "你的微信公眾號的APPSECRET";

        //=======【證書路徑設置】===================================== 
        /* 證書路徑,註意應該填寫絕對路徑(僅退款、撤銷訂單時需要)
        */
        public const string SSLCERT_PATH = "cert/apiclient_cert.p12";
        public const string SSLCERT_PASSWORD = "1233410002";



        //=======【支付結果通知url】===================================== 
        /* 支付結果通知回調url,用於商戶接收支付結果
        */
        public const string NOTIFY_URL = "http://你的網站/Pay/ResultNotifyPage.aspx";

        //=======【商戶系統後臺機器IP】===================================== 
        /* 此參數可手動配置也可在程序中自動獲取
        */
        public const string IP = "你的服務器IP";


        //=======【代理服務器設置】===================================
        /* 默認IP和端口號分別為0.0.0.0和0,此時不開啟代理(如有需要才設置)
        */
        public const string PROXY_URL = "";

        //=======【上報信息配置】===================================
        /* 測速上報等級,0.關閉上報; 1.僅錯誤時上報; 2.全量上報
        */
        public const int REPORT_LEVENL = 1;

        //=======【日誌級別】===================================
        /* 日誌等級,0.不輸出日誌;1.只輸出錯誤信息; 2.輸出錯誤和正常信息; 3.輸出錯誤信息、正常信息和調試信息
        */
        public const int LOG_LEVENL = 0;
    }
技術分享圖片

不使用代理要註釋HttpService.cs裏面post和get方法的下面代碼:

//設置代理服務器
                //WebProxy proxy = new WebProxy();                          //定義一個網關對象
                //proxy.Address = new Uri(Config.PROXY_URL);              //網關服務器端口:端口
                //request.Proxy = proxy;

統一下單:

技術分享圖片
/**
        * 
        * 統一下單
        * @param WxPaydata inputObj 提交給統一下單API的參數
        * @param int timeOut 超時時間
        * @throws WxPayException
        * @return 成功時返回,其他拋異常
        */
        public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //檢測必填參數
            if (!inputObj.IsSet("out_trade_no"))
            {
                throw new WxPayException("缺少統一支付接口必填參數out_trade_no!");
            }
            else if (!inputObj.IsSet("body"))
            {
                throw new WxPayException("缺少統一支付接口必填參數body!");
            }
            else if (!inputObj.IsSet("total_fee"))
            {
                throw new WxPayException("缺少統一支付接口必填參數total_fee!");
            }
            else if (!inputObj.IsSet("trade_type"))
            {
                throw new WxPayException("缺少統一支付接口必填參數trade_type!");
            }

            //關聯參數
            if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
            {
                throw new WxPayException("統一支付接口中,缺少必填參數openid!trade_type為JSAPI時,openid為必填參數!");
            }
            if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
            {
                throw new WxPayException("統一支付接口中,缺少必填參數product_id!trade_type為JSAPI時,product_id為必填參數!");
            }

            //異步通知url未設置,則使用配置文件中的url
            if (!inputObj.IsSet("notify_url"))
            {
                inputObj.SetValue("notify_url", Config.NOTIFY_URL);//異步通知url
            }

            inputObj.SetValue("appid", Config.APPID);//公眾賬號ID
            inputObj.SetValue("mch_id", Config.MCHID);//商戶號
            inputObj.SetValue("spbill_create_ip", Config.IP);//終端ip              
            inputObj.SetValue("nonce_str", GenerateNonceStr());//隨機字符串

            //簽名
            inputObj.SetValue("sign", inputObj.MakeSign());
            string xml = inputObj.ToXml();

            var start = DateTime.Now;

            Log.Debug("WxPayApi", "UnfiedOrder request : " + xml);
            string response = HttpService.Post(xml, url, false, timeOut);
            Log.Debug("WxPayApi", "UnfiedOrder response : " + response);

            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxPayData result = new WxPayData();
            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//測速上報

            return result;
        }
技術分享圖片

看我的調用例子:

技術分享圖片

MakeQRCode.aspx頁面照抄:

技術分享圖片
public partial class Pay_MakeQRCode : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(base.Request.QueryString["data"]))
        {
            string str = base.Request.QueryString["data"];
            Bitmap image = new QRCodeEncoder
            {
                QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
                QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M,
                QRCodeVersion = 0,
                QRCodeScale = 4
            }.Encode(str, Encoding.Default);
            MemoryStream ms = new MemoryStream();
            image.Save(ms, ImageFormat.Png);
            base.Response.BinaryWrite(ms.GetBuffer());
            base.Response.End();
        }
    }
}
技術分享圖片

這個頁面是用來生成二維碼的,需要引入ThoughtWorks.QRCode.dll組件。

我使用模式二,回調頁面是ResultNotifyPage.aspx,就是在配置信息那裏填寫的那個回調頁面。

技術分享圖片
protected void Page_Load(object sender, EventArgs e)
    {
        ResultNotify resultNotify = new ResultNotify(this);
        WxPayData res = resultNotify.ProcessNotify2();
        if (res.GetValue("return_code") == "SUCCESS")
        {
            //查詢微信訂單信息
            string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString();
            string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString();
            string appId = ConfigurationManager.AppSettings["AppId"].ToString();

            QueryOrder queryorder = new QueryOrder();
            queryorder.appid = appId;
            queryorder.mch_id = mch_id;
            queryorder.transaction_id = res.GetValue("transaction_id").ToString();
            queryorder.out_trade_no = "";
            queryorder.nonce_str = TenpayUtil.getNoncestr();

            TenpayUtil tenpay = new TenpayUtil();
            OrderDetail orderdeatil = tenpay.getOrderDetail(queryorder, paySignKey);
            //寫微信記錄
            (new vinson()).WriteReturnWXDetail(orderdeatil);
            //寫充值記錄
            FilliedOnline(orderdeatil.out_trade_no);
        }


        Response.Write(res.ToXml());
        Response.End();
    }
技術分享圖片

掃碼支付成功後會異步到這個頁面執行代碼,我們自己的業務邏輯就要寫在這裏。使用微信官方的ProcessNotify()函數可不行,我們稍微修改下就好了。增加ProcessNotify2函數:

技術分享圖片
public WxPayData ProcessNotify2()
        {
            WxPayData notifyData = GetNotifyData();

            //檢查支付結果中transaction_id是否存在
            if (!notifyData.IsSet("transaction_id"))
            {
                //若transaction_id不存在,則立即返回結果給微信支付後臺
                WxPayData res = new WxPayData();
                res.SetValue("transaction_id", "");
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "支付結果中微信訂單號不存在");
                return res;
            }

            string transaction_id = notifyData.GetValue("transaction_id").ToString();

            //查詢訂單,判斷訂單真實性
            if (!QueryOrder(transaction_id))
            {
                //若訂單查詢失敗,則立即返回結果給微信支付後臺
                WxPayData res = new WxPayData();
                res.SetValue("transaction_id", transaction_id);
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "訂單查詢失敗");
                return res;
            }
            //查詢訂單成功
            else
            {
                WxPayData res = new WxPayData();
                res.SetValue("transaction_id", transaction_id);
                res.SetValue("return_code", "SUCCESS");
                res.SetValue("return_msg", "OK");
                return res;
            }
        }
技術分享圖片

返回WxPayData對象,這樣一判斷



if (res.GetValue("return_code") == "SUCCESS")

表示支付成功,就可以進入我們的業務邏輯。

然後我們還要對當前訂單查單,獲取訂單的相關信息,之前微信未出demo的時候我自己寫了個查單的,就直接用了,關鍵WxPayData對象會返回微信的訂單號:res.GetValue("transaction_id").ToString()。

完事後還要發送信息回給微信,通知微信後臺不要繼續發送異步請求了:

        Response.Write(res.ToXml());
        Response.End();

這個代碼比較重要了。

再說說放置二維碼的頁面:

技術分享圖片
<div class="g-body">
    <div class="g-wrap">
        <div class="m-weixin">
            <div class="m-weixin-header">
                <p><strong>請您及時付款,以便訂單盡快處理!訂單號:<asp:Label ID="trade_no" runat="server" Text="Label"></asp:Label></strong></p>
                <p>請您在提交訂單後1小時內支付,否則訂單會自動取消。</p>
            </div>
            <div class="m-weixin-main">
                <h1 class="m-weixin-title">
                    <img alt="微信支付" src="../images/wxlogo_pay.png"/>
                </h1>
                <p class="m-weixin-money"><font>掃一掃付款</font><br/><strong>¥<asp:Label ID="money" runat="server" Text="Label"></asp:Label></strong></p>
                <p>
                    <img id="payQRImg" width="260" height="260" class="m-weixin-code" style="position: absolute;" src="<%=ImageUrl %>" alt="二維碼" style="border-width:0px;" />
                    <img class="m-weixin-demo" src="../images/wxwebpay_guide.png" alt="掃一掃" />
                    <img style="margin-top:300px;" src="../images/weixin_1.png" alt="請使用微信掃描二維碼以完成支付" />
                </p>
                <p id="we_ok" style="display:none;">
                    <input value="完成" style="width: 300px; height: 50px; background: rgb(21, 164, 21) none repeat scroll 0% 0%; color: white; font-size: 30px; border: medium none; cursor: pointer;" type="button" />
                </p>
            </div>
        </div>
    </div>
</div>   
技術分享圖片

寫個js查單支付情況進行顯示:

技術分享圖片
    $(function () {
        var success = "<%=success %>";
        if (success == "error") {
            $(".g-body").hide();
        }
    })

    var iCount = setInterval(check, 2000);  //每隔2秒執行一次check函數。

    function check() {
        $.ajax({
            contentType: "application/json",
            url: "/WebService/vinson.asmx/queryWeiXin",
            data: "{OrderID:‘" + $("#trade_no").text() + "‘}",
            type: "POST",
            dataType: "json",
            success: function (json) {
                json = eval("(" + json.d + ")");
                if (json.success == "success") {
                    clearInterval(iCount);
                    $(".m-weixin-money font").html("已成功付款");
                    $("#payQRImg").remove();
                    $(".m-weixin-demo").before(‘<img  src="../images/wx_ok.jpg" width="200">‘);
                    $(".m-weixin-demo").next().remove();
                    $("#we_ok").show();
                }
            },
            error: function (err, ex) {
            }
        });
    }
技術分享圖片

是的,我又寫了個給ajax使用的查單函數queryWeiXin。

我這裏才是生成訂單和二維碼:

技術分享圖片

恩,還有啥呢,恩,看看效果吧:

技術分享圖片

支付成功後:

技術分享圖片

恩,完事。

C#微信支付對接