一、前言
经过两三天的琢磨总算完成了微信扫码支付功能,不得不感叹几句:
微信提供的DEMO不错,直接复制粘贴就可以跑起来了;
微信的配置平台我真是服了。公众平台、商户平台、开放平台,一个平台一套账户密码,大写的恶心
DEMO地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
.NET版DEMO中的Lib文件夹是关键,直接复制到自己的代码里,或者打成dll随个人意愿。
二、正文
Step1:肯定是产生商户订单号,然后传给微信后台,由微信去组成二维码字符串,然后返给你,你再把字符串做成图片;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/// <summary>
/// 获取二维码
/// </summary>
/// <param name="orderNumber"></param>
/// <returns></returns>
public string GetCodeUrl( string orderNumber)
{
var result = string .Empty;
if (! string .IsNullOrEmpty(orderNumber))
{
var matchedItem = db.OrderInfoForProducts.FirstOrDefault(x => x.OrderNumber == orderNumber);
if (matchedItem != null && matchedItem.IsPaid == false )
{
WxPayData data = new WxPayData();
data.SetValue( "body" , "productBody" ); //商品描述
data.SetValue( "attach" , "attach data" ); //附加数据
data.SetValue( "out_trade_no" , WxPayApi.GenerateOutTradeNo()); //随机字符串
data.SetValue( "total_fee" , price); //总金额
data.SetValue( "time_start" , DateTime.Now.ToString( "yyyyMMddHHmmss" )); //交易起始时间
data.SetValue( "time_expire" , DateTime.Now.AddMinutes(10).ToString( "yyyyMMddHHmmss" )); //交易结束时间
data.SetValue( "goods_tag" , "tag" ); //商品标记
data.SetValue( "trade_type" , "NATIVE" ); //交易类型
data.SetValue( "product_id" , WxPayApi.GenerateOutTradeNo()); //商品ID
result = WxPayApi.UnifiedOrder(data).GetValue( "code_url" ).ToString(); //调用统一下单接口
}
}
return result;
}
|
在这里,我是把公司的商户订单号放在了attach字段上,因为公司的商户订单号比较长,超过了32位。out_trade_no与product_id字段最多32位,请慎重!
微信中的价格不能带小数,所以0.01元要写成100。
Step2: 成功返回二维码字符串之后就可以在生成图片了,我这边使用了ThoughtWorks.QRCode.dll来生成图片:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/// <summary>
/// 根据字符串得到相应的二维码
/// </summary>
/// <param name="qrInfo"></param>
/// <param name="productName"></param>
/// <param name="version"></param>
/// <returns></returns>
public static Image CreateQRCodeImage( string qrInfo, string productName, string version)
{
try
{
if (! string .IsNullOrEmpty(qrInfo))
{
QRCodeEncoder encoder = new QRCodeEncoder
{
QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
QRCodeScale = 4,
QRCodeVersion = 0,
QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
};
//编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字)
//大小(值越大生成的二维码图片像素越高)
//版本(注意:设置为0主要是防止编码的字符串太长时发生错误)
//错误效验、错误更正(有4个等级)
Image image = encoder.Encode(qrInfo, Encoding.GetEncoding( "utf-8" ));
string filename = $ "{productName}_{version}.png" ;
var userLocalPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var docPath = Path.Combine(userLocalPath, @"Your Product\QRCode" );
if (!Directory.Exists(docPath))
{
Directory.CreateDirectory(docPath);
}
string filepath = Path.Combine(docPath, filename);
using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
{
image.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
fs.Close();
image.Dispose();
}
return image;
}
}
catch (Exception)
{
return null ;
}
return null ;
}
|
Step3: 当用户扫完二维码之后,微信会发起回调,这时候我们就可以处理自己的业务逻辑了。这里我的UpdatePayStatus返回的是一个空页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/// <summary>
/// 回调函数
/// </summary>
public ActionResult UpdatePayStatus()
{
//接收从微信后台POST过来的数据
System.IO.Stream s = Request.InputStream;
int count = 0;
byte [] buffer = new byte [1024];
StringBuilder builder = new StringBuilder();
while ((count = s.Read(buffer, 0, 1024)) > 0)
{
builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
}
s.Flush();
s.Close();
s.Dispose();
//转换数据格式并验证签名
WxPayData data = new WxPayData();
try
{
data.FromXml(builder.ToString());
}
catch (WxPayException ex)
{
//若签名错误,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue( "return_code" , "FAIL" );
res.SetValue( "return_msg" , ex.Message);
LogEntity signErrorLog = new LogEntity();
signErrorLog.errorMessage = ex.Message;
LogHelper.WriteLog(signErrorLog, null );
Response.Write(res.ToXml());
Response.End();
}
ProcessNotify(data);
return View();
}
/// <summary>
/// 处理回调数据
/// </summary>
/// <param name="data"></param>
public void ProcessNotify(WxPayData data)
{
WxPayData notifyData = data;
//检查支付结果中transaction_id是否存在
if (!notifyData.IsSet( "transaction_id" ))
{
//若transaction_id不存在,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue( "return_code" , "FAIL" );
res.SetValue( "return_msg" , "支付结果中微信订单号不存在" );
LogEntity orderLog = new LogEntity();
orderLog.errorMessage = "支付结果中微信订单号不存在" ;
LogHelper.WriteLog(orderLog, null );
Response.Write(res.ToXml());
Response.End();
}
string transaction_id = notifyData.GetValue( "transaction_id" ).ToString();
//查询订单,判断订单真实性
if (!QueryOrder(transaction_id))
{
//若订单查询失败,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue( "return_code" , "FAIL" );
res.SetValue( "return_msg" , "订单查询失败" );
LogEntity orderqueryLog = new LogEntity();
orderqueryLog.errorMessage = "订单查询失败" ;
LogHelper.WriteLog(orderqueryLog, null );
Response.Write(res.ToXml());
Response.End();
}
//查询订单成功
else
{
WxPayData res = new WxPayData();
res.SetValue( "return_code" , "SUCCESS" );
res.SetValue( "return_msg" , "OK" );
SetPaymentResult(data); //这里的参数是 data !!! 不是 res !!!
Response.Write(res.ToXml());
Response.End();
}
}
/// <summary>
/// 商户后台更新
/// </summary>
/// <param name="res"></param>
private void SetPaymentResult(WxPayData res)
{
var isSucessFlagOne = res.GetValue( "return_code" ).ToString();
var isSuccessFlagTwo = res.GetValue( "result_code" ).ToString();
if (isSucessFlagOne == "SUCCESS" && isSuccessFlagTwo == "SUCCESS" )
{
//自己的业务逻辑 !!!!
}
}
//查询订单
private bool QueryOrder( string transaction_id)
{
WxPayData req = new WxPayData();
req.SetValue( "transaction_id" , transaction_id);
WxPayData res = WxPayApi.OrderQuery(req);
if (res.GetValue( "return_code" ).ToString() == "SUCCESS" &&
res.GetValue( "result_code" ).ToString() == "SUCCESS" )
{
return true ;
}
else
{
return false ;
}
}
|
三、结尾
做完支付宝与微信扫码支付发现支付宝的接入要比微信方便很多,还有一个同步请求。而且吐槽个其它的,微信开放平台的审批速度要比支付宝的审批慢很多。还有微信支付最后上线前不需要非得用沙箱测试,做完之后直接一分钱一分钱测试即可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/lovecsharp094/archive/2017/10/12/7650112.html