微信支付

微信支付文档

1、生成二维码 
2、二维码回调 
3、支付成功回调 
4、监听是否成功 
4、错误解决方案

官方上说的这里就不提了。 
官方文档地址

简单理解的流程: 
1、开发者设置微信参数生成二维码 
2、微信公众平台设置 支付回调URL (eg:http://xxx.com/wxpay/return_url.aspx ) 
i.必须外网能够访问,并且有域名和后缀 .xxx,并且回调页面只能直接继承

System.Web.UI.Page

不能间接继承:eg: child:parent,System.Web.UI.Page

3、用户扫描二维码后,微信会请求设置的支付回调地址并传回一个XML文件流数据,其中数据包含了生成二维码时传的参数 
4、在支付回调地址中获取微信传回的XML 文件流,并调用微信的 统一下单接口,设置统一下单接口需要的参数,发送给微信服务器。 
i.统一下单接口为:https://api.mch.weixin.qq.com/pay/unifiedorder 
5、微信服务器进行处理,生成预支付交易,并返回XML文件流,其中包含交易会话标识(prepay_id) 
6、开发者获取到XML 后,将此XML 发送到微信服务器() 
7、微信支付系统根据交易会话标识,发起用户端授权支付流程 
8、用户在微信客户端输入密码,确认支付后,微信客户端提交支付授权 
9、微信支付系统验证后扣款,完成支付交易 
10、微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。 
11、微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况 
i.异步回调地址notify_url

ASP.NET 扫码支付模式一,代码 
1、生成二维码 
a)使用 ThoughtWorks.QRCode 程序集

// 微信提供的类
WxPayData data = new WxPayData();
data.SetValue("appid", WxPayConfig.APPID);//公众帐号id
data.SetValue("mch_id", WxPayConfig.MCHID);//商户号
data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
data.SetValue("product_id", tempPrId.ToString());//商品ID
data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//时间戳
data.SetValue("sign", data.MakeSign());//签名
string str = ToUrlParams(data.GetValues());//转换为URL串
string url = "weixin://wxpay/bizpayurl?" + str;// url
//日志
Log.Info(this.GetType().ToString(), "Get native pay mode 1 url : " + url);
// 生成二维码
CreateQrcode(url);

 

**// 生成二维码函数**
private void CreateQrcode(string nr)
{
        Bitmap bt;
        string enCodeString = nr;
        QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
        qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
        qrCodeEncoder.QRCodeScale = 4;
        qrCodeEncoder.QRCodeVersion = 0;// 超出索引,修改为0
        qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
        bt = qrCodeEncoder.Encode(enCodeString);
        Random dom = new Random();
        int randomnum = dom.Next(0, 999);
        string filename = DateTime.Now.ToString("yyyymmddhhmmssfff") + randomnum;
        string path = Server.MapPath("~/Images/wxpaycode/") + filename + ".jpg";
        // 此处是在服务器上部署时出现 GDI+ XXX的错误而添加的,本地没错误。(效果嘛....呵呵。可以考虑注释掉此段代码)
        Bitmap bmp = new Bitmap(bt);
        bt.Dispose();// 
        bmp.Save(path);
        this.ImageCode.ImageUrl = "~/Images/wxpaycode/" + filename + ".jpg";
}

2、支付回调地址(用户扫码后的回调地址操作)

// 微信返回的是xml 格式的数据,eg:

<xml>
<appid><![CDATA[wx5e9360a3f46f64cd]]></appid>
<openid><![CDATA[o_pncsidC-pRRfCP4zj98h6slREw]]></openid>
<mch_id><![CDATA[1322117501]]></mch_id>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<nonce_str><![CDATA[y4dGR6JxuybgUWUo]]></nonce_str>
<product_id><![CDATA[001]]></product_id>
<sign><![CDATA[89951BAE8796DE7D32E9741E42C35FB4]]></sign>
</xml>

// 2.1获取用户扫描二维码后,微信返回的信息

//接收并读取POST过来的XML文件流
StreamReader reader = new StreamReader(Request.InputStream);
String xmlData = reader.ReadToEnd();
WxPayData obj = new WxPayData();
SortedDictionary<string, object> dic = obj.FromXml(xmlData);
//此处获取产品id
int rankid = Convert.ToInt32(dic["product_id"].ToString());
Rank rankobj = new Rank();
RankEntity entity = rankobj.Select(rankid);
if (entity != null)
{
    //dic["openid"]
    //统一下单接口
    WxPayData wxdata = new WxPayData();// 微信提供的类
    wxdata.SetValue("appid", WxPayConfig.APPID);//公众帐号id
    wxdata.SetValue("mch_id", WxPayConfig.MCHID);//商户号
    wxdata.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
    wxdata.SetValue("product_id", dic["product_id"]);//商品ID
    wxdata.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//时间戳
    wxdata.SetValue("body", "测试");// 商品描述
    wxdata.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//订单号
    wxdata.SetValue("total_fee", entity.Price * 100);//金额*100为真正金额,测试使用 1 为 1 分钱
    wxdata.SetValue("spbill_create_ip", ValidateHelper.GetHostAddress());//终端IP
    wxdata.SetValue("notify_url", WxPayConfig.NOTIFY_URL);//支付回调地址
    wxdata.SetValue("trade_type", "NATIVE");//交易类型(--原生扫码支付)
    wxdata.SetValue("openid", dic["openid"]);// 用户标识,当(trade_type=JSAPI)时,为必填参数
    // 附加数据(订单号,金额,rank id(级别ID)),类似于支付宝的公共回传参数
    wxdata.SetValue("attach", wxdata.GetValue("out_trade_no") + "_" + wxdata.GetValue("total_fee") + "_" + rankid);
    Log.Info(this.GetType().ToString(), "wxdata:wxdata=true");
    WxPayData returnData = WxPayApi.UnifiedOrder(wxdata);// 请求微信微信服务器统一下单接口,生成预处理订单(微信demo 类方法)
    Response.Write(returnData.ToXml());// 回发给微信
    Response.End();
}

3、支付成功异步回调(用户支付成功后的回调地址操作)

//接收并读取POST过来的XML文件流
StreamReader reader = new StreamReader(Request.InputStream);
String xmlData = reader.ReadToEnd();
WxPayData obj = new WxPayData();
SortedDictionary<string, object> dic = obj.FromXml(xmlData);
Log.Info(this.GetType().ToString(), "return_code:back=" + dic["return_code"]);//日志
Log.Info(this.GetType().ToString(), "公共回传参数:attach=" + dic["attach"]);

if (Equals(dic["return_code"].ToString(), "SUCCESS") && Equals(dic["result_code"].ToString(), "SUCCESS"))
{
    // 判断SUCCESS 后,可以修改数据信息
    string[] parmaArr = dic["attach"].ToString().Split('_');
    int uid = ValidateHelper.GetNullableInt(Session["uid"] ?? "0");
    // 支付记录
    PayRecord pr = new PayRecord();
    PayRecordEntity pre = new PayRecordEntity();
    pre.UserId = uid;
    pre.PayOrder = parmaArr[0];// 订单号
    pre.RankId = Convert.ToInt32(parmaArr[2]);
    pre.PayType = 2;// 微信
    pre.PayDate = DateTime.Now;
    pre.PayAmount = Convert.ToDecimal(parmaArr[1]);
    int res = pr.Save(pre);
    if (res > 0)
    {
        // 用户信息更改
        User user = new User();
        UserEntity ue = user.Select(uid);
        ue.RankId = ue.RankId > pre.RankId ? ue.RankId : pre.RankId;
        int ures = user.Save(ue);
        if (ures > 0)
        {
            Response.Redirect("../index.aspx");
        }
    }
}

4、二维码页面监听是否完成(根据需求) 
利用 jquery 定时请求一个地址,这个地址内查询数据库的订单状态。 
如果订单状态更改为成功,则二维码页面提示支付成功并跳转。

    <script type="text/javascript">
        setInterval("CheckStatus()", 3000);
        function CheckStatus() {
            $.post("../Handler/GetDataHandler.ashx", { status: $("#HiddenField1").val(), flag: 19 }, function (data) {
                if (data) {
                    var json = JSON.parse(data);
                    layer.msg(json.result, {
                        icon: 1,
                        time: 2000
                    }, function () {
                        window.location.href = json.url;
                    });
                }
            });
        }
    </script>

// 出现的错误和解决方案 
1、原生支付URL参数错误 
解决方案:检查生成二维码的参数,校验签名是否正确(微信提供的sign签名算法生成的签名不正确(我是测试了不正确,然后我自己写的MD5加密的sign)) 
微信提供的签名校验工具地址:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1
  •  

2、获取商户订单信息超时或者商户返回的httpcode非200 
在用户扫码二维码后,在二维码回调页面获取微信数据的同时也需要将数据再重新回发给微信(见:2.1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值