[微信支付]C# .net 微信掃碼Native支付模式二以及成功回調

0x0001 前言

經過一週的摧殘,終於完成了微信支付,做完總結一下,覺得其實並不難,主要是網上沒有一個明確的教程.
本文是基於C#語言上進行開發,其實本人是做java的,但由於最近接手維護的項目是C#的,所以也強制讓自己簡單的熟悉一遍C#(偷偷的說,我C# .net .asp都還沒清楚,不過最重要的是思路,語言只是一種工具~~~)

0x0002 項目背景(可略過)

  1. 項目類型:在線考試系統;
  2. 項目要求:讓之前全部免費的試卷部分收費,故選用微信支付 (PS:早知道微信支付官方文檔這麼坑,就選型支付寶了)
  3. 項目業務:系統暫時要求點擊支付時網站彈出生成的微信支付二維碼,由用戶進行掃描購買,購買完成後用戶可使用已購買的商品(試卷);
  4. 微信支付產品選型:微信有多種支付模式,如下:
    在這裏插入圖片描述
    根據實際情況需求,推薦使用Native支付,此種方式簡單也能完成我們的需求.(一開始選的JSAPI,但是後來實在做不動了,就換了Native支付,不過現在看來,都差不多,只是JSAPI需要多獲取幾個微信指定的屬性)

Native支付是指商戶系統按微信支付協議生成支付二維碼,用戶再用微信“掃一掃”完成支付的模式。該模式適用於PC網站、實體店單品或訂單、媒體廣告支付等場景。

0x0003 開發思路

  • 簡單來說:微信掃碼支付就是我們把需要的信息生成二維碼,然後用戶掃描二維碼就出現了我們想要展示的信息.
  • 稍複雜來說:微信掃碼支付就是我們把部分重要信息(商品價格\商品id等)發送給微信服務端,微信返回生成包含我們提交數據且加密的微信支付協議的URL,我們接收此URL並將其生成一個二維碼圖片,用戶通過微信掃一掃,發起支付。
  • 總體來說:
    1.註冊微信商戶號,接入微信支付,配置微信支付平臺的 支付授權目錄掃碼回調鏈接;
    2.用戶點擊支付時,前端向服務端傳遞相關數據id;
    3.服務端接收id後查詢覈對,按照微信掃碼支付規則調用微信支付接口;
    4.微信支付接口根據一系列數據比如(商品價格\商品id)加密生成簽名後返回一個帶微信支付協議的URL;
    5.使用相關生成二維碼的工具(QRCode.js)將URL生成二維碼圖片;
    6.用戶掃碼跳到支付界面,點擊支付後,微信服務端調用我們的掃碼回調鏈接;
    7.需要提前寫好掃碼回調鏈接的類或方法,根據微信傳來的詩句在此覈對數據,通過則更改自己系統的某狀態,並返給微信服務端成功.

0x0004 開發過程

0.準備工作

  • 申請 微信商戶號 微信公衆號 (這裏具體步驟不描述,因爲這屬於公司申請):
  • 開通 Native支付(點擊開通,很簡單,但需要管理員賬號)
  • 安裝 微信認證證書

1.下載官方工具類(Native 模式二)

官方文檔地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
先下載官方提供的工具類Demo
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
在這裏插入圖片描述

2.解壓並進入WxPayAPI文件夾,將 business example lib 三個文件夾複製到咱們項目的工程中(本項目使用VS ,如果不會添加 ,VS將複製過來的文件或文件夾顯示到解決方案管理)

在這裏插入圖片描述
在這裏插入圖片描述

3.雖然是三個文件夾,但對於我們Native開發模式二,僅需改3個文件,也就是每個文件夾下一個,就可以完美運行]

(1)business文件夾 NativePay.cs 推薦其他文件不刪除

在這裏插入圖片描述

(2)example文件夾 ResultNotifyPage.aspx,推薦刪除其他文件,並將此文件放在工程根目錄下

在這裏插入圖片描述
如:
在這裏插入圖片描述

(3)lib文件夾全部保留,因爲這裏面是所依賴的工具類。

4.後端進行頁面配置

(1)對於lib文件夾,僅需修改DemoConfig.cs[作用:配置微信商戶號和公衆號、回調地址等相關信息];

在這裏插入圖片描述
對於這個頁面,我們僅需要修改4個地方:

在這裏插入圖片描述
在這裏插入圖片描述
將內容寫在 return 後面的引號裏

以下是這4個的介紹
①Appid:綁定支付的APPID(必須配置) 登錄微信公衆號可以查到 (商戶號必須綁定一個公衆號纔可以,這個APPID是微信公衆號的);
在這裏插入圖片描述
②Mchid:商戶號(必須配置) 登錄 微信商戶平臺 可以查到在這裏插入圖片描述
③ Key:商戶支付密鑰,參考開戶郵件設置(必須配置),請妥善保管,避免密鑰泄露 ;
在這裏插入圖片描述
④NotifyUrl: 支付結果通知回調url,用於商戶接收支付結果
在這裏插入圖片描述

注:a.這個鏈接必須外網,如需內網開發測試可參考微信支付-使用Natapp實現本地內網進行開發測試以及解決webpack "Invalid Host header"問題
\b.ResultNotifyPage.aspx爲剛纔 **3(2)**中所保留的那個文件

(2)對於business文件夾,僅需修改NativePay.cs文件[作用:用來調用微信接口根據我們提供的數據生成二維碼鏈接]

下拉代碼找到模式二,僅需修改模式二的代碼
在這裏插入圖片描述
①可修改方法參數列表 product_id不要動,其他的可隨意修改,傳遞值時,將主鍵傳到product_id中
②可修改data.SetValue(鍵,值)的值

鍵可參考 官方文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
我這裏只給出上面圖片顯示的鍵對應的內容:
在這裏插入圖片描述

注1:body商品描述 是用戶在掃碼後顯示的標題,如下

在這裏插入圖片描述
微信支付-C# .net 微信掃碼支付Body含有中文導致出現“簽名錯誤”

注2:total_fee商品金額 單位是分!!!單位是分!!!單位是分!!!推薦傳值或在當前頁面直接根據商品id直接查金額,防止被篡改;
注3:trade_type交易類型 一定爲NATIVE. product_id商品ID不要改,接收傳遞的ID即可;
注4:其他屬性可保持原來的或自己添加 .

(2)對於ResultNotifyPage.aspx文件,僅需修改ResultNotifyPage.aspx.cs文件[作用:用戶支付成功後,微信服務端發送信息到這個頁面提醒我們覈對信息並更新狀態]

原版代碼爲:
在這裏插入圖片描述
我們要獲取微信服務端返回來的數據使用上述代碼的這個方法 resultNotify.ProcessNotify();
此方法有返回值,原版代碼沒寫,在這裏我們需要寫上返回值.

WxPayData notifyData = resultNotify.ProcessNotify();

然後開始寫邏輯:關於我係統的代碼如下:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
using TeachAssis.Model;

namespace WxPayAPI
{
    public partial class ResultNotifyPage : System.Web.UI.Page
    {
        private TeachAssis.Service.OrderService orderService = new TeachAssis.Service.OrderService();//項目所用的業務邏輯層
        private TeachAssis.Service.StuExamService stuExamService = new TeachAssis.Service.StuExamService();//項目所用的業務邏輯層
        protected void Page_Load(object sender, EventArgs e)
        {
            ResultNotify resultNotify = new ResultNotify(this);
            WxPayData notifyData = resultNotify.ProcessNotify();//添加上返回值;
            if (notifyData != null)//判斷微信傳遞的數據是否爲空,不爲空則可以進入
            {
                //支付回調,微信連續發送8次請求,result_code此字段是通信標識,非交易標識,交易是否成功需要查看result_code來判斷,可參考 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
                if (notifyData.IsSet("result_code"))//成功返回 SUCCESS 則進入判斷
                {
                    //1.通過傳遞的訂單號先查詢是否存在此訂單,如果訂單存在則進行下一步 這一步已經在 resultNotify.ProcessNotify()方法中自行完成
                    //2.覈對系統訂單金額與微信訂單中金額是否一致
                    //2.1 先通過傳遞的考試訂單id從訂單表查詢訂單金額
                    String order_id=(String)notifyData.GetValue("attach");
                    Orders ord = orderService.GetModel(order_id);
                    if (ord!=null) {
                        //2.2 將查出的金額單位由元變爲分
                        int money = (int)(ord.ExamMoney * 100);
                        //2.3 與微信訂單中金額進行對比,不一致,返回非法操作
                        int WXMoney = Convert.ToInt32(notifyData.GetValue("total_fee"));
                        if (money == WXMoney)
                        {
                            //簽名
                            String sign = ((String)notifyData.GetValue("sign")).ToUpper();
                            if (sign!=null&&!"".Equals(sign))
                            {
                                ord.Test3 = sign;
                                //3.覈對其他信息是否正確
                                String sign2 = notifyData.MakeSign().ToUpper();

                                if (sign.Equals(sign2))
                                {
                                    //將結束時間存到當前訂單中
                                    String time_end = (String)notifyData.GetValue("time_end");
                                    ord.EndTime = time_end;
                                    //將微信給商戶生成的訂單號存在當前訂單中Test1 
                                    String out_trade_no = (String)notifyData.GetValue("out_trade_no");
                                    ord.Test1 = out_trade_no;
                                    //將微信訂單號存在當前訂單中PayID 
                                    String transaction_id = (String)notifyData.GetValue("transaction_id");
                                    ord.PayID = transaction_id;
                                    //將微信用戶用戶標識(用戶在商戶appid下的唯一標識)存在當前訂單中Test2
                                    String openid = (String)notifyData.GetValue("openid");
                                    ord.Test2 = openid;
                                    //將是否關注公衆賬號存在當前訂單中Test3(用戶是否關注公衆賬號,Y-關注,N-未關注)
                                    String is_subscribe = (String)notifyData.GetValue("is_subscribe");
                                    ord.Test3 = is_subscribe;
                                    //在Orders表中修改訂單的狀態爲2,已支付
                                    ord.PayStatus = 2;
                                    b = orderService.Save(ord);
                                    //在StuExam表中新建一條記錄
                                    StuExam stuExam = new StuExam { StuID = ord.StuID, CreatTime = DateTime.Now, ExamID = ord.ExamID, Status = 1 };
                                    if (stuExamService.IsExsit(ord.StuID, ord.ExamID)) {
                                        //如果存在記錄,則只需要更改狀態
                                        String[] strPK = { ord.StuID, ord.ExamID };
                                        StuExam stu = stuExamService.GetModel(strPK);
                                        stu.Status = 1;
                                        stuExamService.Save(stu);
                                    }
                                    else {
                                        //如果不存在記錄
                                        stuExamService.Add(stuExam);
                                    }
                                }
                            }                           
                        }
                        else
                        {
                            //暫無操作
                        }
                    }
                    
                }
            }
        }       
    }
}

其實代碼很簡單,就是將 notifyData裏的數據,通過 notifyData.GetValue("XXXX")方法獲取出來,然後和訂單中比一下,再調用微信生成簽名的工具重新生成簽名對比一下,保證安全性,如果通過,則修改訂單狀態即可.

到這裏所有後臺需要修改的微信代碼全部完成,還缺一個接收通過微信接口生成的微信支付協議的鏈接,通過這個鏈接我們在前臺轉換成二維碼即可.

5.前端進行頁面配置

本系統前端使用vue,生成二維碼的工具爲QRCode.js
QRCode在一般項目中引入可參考 http://www.runoob.com/w3cnote/javascript-qrcodejs-library.html
在vue中
0.在項目文件夾中的打開cmd命令窗口輸入npm install qrcodejs2 --save 安裝qrcode
1.在使用的界面導入 import QRCode from 'qrcodejs2' 使用qrcode
2.在使用的位置放入div <div id="qrcode"></div> //生成二維碼的位置
3.在js中(vue項目中) methods:{} 中寫以下方法,先獲取元素節點,然後將節點內容清空,使用new QRCode(qr,Xxx);
Xxx是微信接口返給我們的URL地址
在這裏插入圖片描述
4.調用此方法:我的調用流程爲,點擊報名(在點擊事件中將想要購買的商品id通過路由傳到微信支付接口)
在這裏插入圖片描述
,然後彈出模態窗口(微信支付接口生成url鏈接,QRCode根據url生成圖片展示在頁面上),
在這裏插入圖片描述
附部分代碼和邏輯:(這裏其實可以很簡單的寫,看自己的習慣)
在這裏插入圖片描述
這裏使用了延時加載,因爲有時候頁面刷新太快,導致加載跟不上.

到這裏就寫完了,雖然內容很多,總結一下很少
1.下載微信demo,將那三個文件夾加入工程
2.修改那3個文件
3.前端向微信接口傳值,返回URL
4.QRCode根據URL生成二維碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章