• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

.netcore/c#支付宝支付和微信支付

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

前言:最近做了App的支付功能,虽然最后的代码只有巴掌大,但是踩坑的经历真的是异常丰富,问就是官方坑爹的版本升级和core少的可怜的参考资料(望天)。 

阅读本文章您将收获到:1.微信和支付宝支付的保姆级后端教程

                                         2.官方文档解析

                                        3.独家的踩坑提示

                                        4.一个本地可运行的demo

注意事项:1. 仅后端代码部分,不涉及任何前端

                  2.仅APP支付

代码demo:      https://files-cdn.cnblogs.com/files/rulasann/PayUtil.zip  (已重新上传)

 

 


 

 1.官方文档:

    https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay

 2.参数说明(请结合官方文档阅读):

    有两种参数类型,公共参数和请求参数,如果调用官方的SDK,公共参数中的sign不需要自己签。例:

IAopClient client = new DefaultAopClient("https://openapi.alipay.com/gateway.do", "app_id", "merchant_private_key", "json", "1.0", "RSA2", "alipay_public_key", "GBK", false);

    公共参数中的biz_content即为请求参数,这里可不参照官方给的示例写,他们有封装好的model。例:

//以下为发起请求的最简参数
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.TotalAmount = "0.01"; // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] //model.Body = ""; // 商品描述 model.Subject = "交易标题"; // 商品标题/交易标题/订单标题/订单关键字等 model.OutTradeNo = ""; // 商户订单号,由商家自定义,需保证商家系统中唯一。仅支持数字、字母、下划线 model.ProductCode = "QUICK_MSECURITY_PAY"; // 销售产品码,商家和支付宝签约的产品码。QUICK_MSECURITY_PAY:App支付。 request.SetBizModel(model); // 将业务model载入到request

    关于notify_url,非必填,如果需要,可以这样写:

request.SetNotifyUrl(notify_url)

3.完整请求示例,需Nuget引用AlipaySDKNet.Standard,其次建议用一个实体类封装配置信息:

 1 public class AliPayBasicItem
 2     {
 3         /// <summary>
 4         /// 开发者的应用ID , 必填
 5         /// </summary>
 6         public static string app_id = "";
 7 
 8         /// <summary>
 9         /// 请求使用的编码格式
10         /// </summary>
11         public static string charset = "utf-8";
12 
13         /// <summary>
14         /// 仅支持"JSON",非必填
15         /// </summary>
16         public static string format = "json";
17 
18         /// <summary>
19         /// 签名算法
20         /// </summary>
21         public static string sign_type = "RSA2";
22 
23         /// <summary>
24         /// 调用的接口版本 
25         /// </summary>
26         public static string version = "1.0";
27 
28         /// <summary>
29         /// 支付宝请求url
30         /// </summary>
31         public static string url = "https://openapi.alipay.com/gateway.do";
32 
33         /// <summary>
34         /// 商户私钥 (必填)
35         /// </summary>
36         public static string merchant_private_key = "";
37 
38         /// <summary>
39         /// 支付宝公钥 (必填)
40         /// </summary>
41         public static string alipay_public_key = "";
42 
43         /// <summary>
44         /// 支付完成后的通知地址 非必填
45         /// </summary>
46         public static string pay_notify_url = "";
47 
48         /// <summary>
49         /// 币种
50         /// </summary>
51         public static string currency = "CNY";
52 
53         /// <summary>
54         /// 退款完成后的通知地址 非必填
55         /// </summary>
56         //public static string refund_notify_url = "";
57 
58         /// <summary>
59         /// 应用名称
60         /// </summary>
61         public static string app_name = "mc";
62 
63         /// <summary>
64         /// 签约号 (必填)
65         /// </summary>
66         public static string pid = "";
67     }
View Code
 1 public string AppPay()
 2         {
 3             IAopClient client = new DefaultAopClient(AliPayBasicItem.url, AliPayBasicItem.app_id, AliPayBasicItem.merchant_private_key, AliPayBasicItem.format, AliPayBasicItem.version, AliPayBasicItem.sign_type, AliPayBasicItem.alipay_public_key, AliPayBasicItem.charset, false);
 4             AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
 5 
 6             AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
 7             model.TotalAmount = "0.01"; // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
 8             //model.Body = ""; // 商品描述
 9             model.Subject = "交易标题"; // 商品标题/交易标题/订单标题/订单关键字等
10             model.OutTradeNo = ""; // 商户订单号,由商家自定义,需保证商家系统中唯一。仅支持数字、字母、下划线
11             model.ProductCode = "QUICK_MSECURITY_PAY"; // 销售产品码,商家和支付宝签约的产品码。QUICK_MSECURITY_PAY:App支付。
12             request.SetBizModel(model);  // 将业务model载入到request
13             //request.SetNotifyUrl(AliPayBasicItem.pay_notify_url); 
14 
15             AlipayTradeAppPayResponse response = client.SdkExecute(request);
16             var info = response.Body;
17 
18             return info   // 将这里的info直接返给前端          
19         }
View Code

4.响应:

有坑注意:官方给的响应示例是个json,实际上我们拿到的(即上面示例中的info)并不长这样,如下图所示,是加密过的,看不懂没关系,不需要处理,直接返给前端就好,由前端拿着那长串去唤起支付,至此支付过程结束。

 5.支付结果处理:

如果notify_url 赋了值,支付宝会将支付结果post给这个接口,处理一下接收数据

② 可主动调用查询接口去获取支付结果 https://opendocs.alipay.com/apis/api_1/alipay.trade.query ,写法跟支付类似,封装的model为AlipayTradeQueryModel

 


 

 part2:微信App支付

 1.官方文档:

   https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml

   有坑注意:微信支付接口已经升级到v3版本,网上找的示例可能还是老版本,区别是,老版本为MD5加密,参数格式为XML,新版本为SHA2加密,参数格式为json

 2.参数说明:

   官方给的请求参数如下图,没什么好说的,就一个json:

   

   *金额total是int类型;

   *notify_url与支付宝不同,微信是必填,官方建议是https且无端口号,实际上http加有端口号也是可以的(不建议哈);

3.签名:

   需手动对接口参数签名,签名过程参考:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml ,以下以微信支付为例:

①拼接待签名字符串:请求方法\n+URL\n+时间戳\n+随机字符串\n+请求参数\n

TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string time_str = Convert.ToInt64(ts.TotalSeconds).ToString();
string sign_url = "/v3/pay/transactions/app";
string nonce_str = Guid.NewGuid().ToString().Replace("-", "");
string body_str = "";  // 上面的参数
string to_sign = "POST" + "\n" + sign_url + "\n" + time_str + "\n" + nonce_str + "\n" + body_str + "\n";

②使用商户私钥对待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值

byte[] keyData = Convert.FromBase64String(key);
using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
using (RSACng rsa = new RSACng(cngKey))
{
    byte[] data = System.Text.Encoding.UTF8.GetBytes(to_sign);
    string sign = Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
}

③设置请求头:Authorization: 认证类型 签名信息

    认证类型为:WECHATPAY2-SHA256-RSA2048

    签名信息为:商户号mchid+商户API证书serial_no+请求随机串nonce_str+时间戳timestamp+签名值sign

string value = $"WECHATPAY2-SHA256-RSA2048 " + "mchid=\"" + mch_id + "\",serial_no=\"" + serial_no + "\",nonce_str=\"" + nonce_str + "\",timestamp=\"" + time_str + "\",signature=\"" + sign + "\"";
request.Headers.Add("Authorization", value);

   有坑注意:请求头还需有以下设置,不然会报400

request.ContentType = "application/json;charset=utf-8";
request.Headers.Add("Accept", "application/json");
request.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

4.返回值处理:

  请参考https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml

  以上是前端调起支付要用到的字段,由后端通过返回值拼接处理而成

5.完整代码示例:

①要用到的实体类 

  1  public class WxPayBasicItem
  2     {
  3         /// <summary>
  4         /// 小程序ID
  5         /// </summary>
  6         public static string appid = "";
  7 
  8         /// <summary>
  9         /// 商户号
 10         /// </summary>
 11         public static string mch_id = "";
 12 
 13         /// <summary>
 14         /// 商户证书序列号
 15         /// </summary>
 16         public static string serial_no = "";
 17 
 18         /// <summary>
 19         /// 商户私钥
 20         /// </summary>
 21         public static string private_key = "";
 22 
 23         /// <summary>
 24         /// 小程序支付请求url
 25         /// </summary>
 26         //public static string order_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
 27 
 28         /// <summary>
 29         /// app支付请求url
 30         /// </summary>
 31         public static string app_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
 32 
 33         /// <summary>
 34         /// 预支付完成后的通知地址
 35         /// </summary>
 36         public static string order_notify_url = "https://weixin.qq.com/"; 
 37 
 38         /// <summary>
 39         /// 交易类型 小程序取值"JSAPI"
 40         /// </summary>
 41         //public static string trade_type = "JSAPI";
 42 
 43         /// <summary>
 44         /// 查询订单请求url
 45         /// </summary>
 46         public static string query_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/id";
 47 
 48         /// <summary>
 49         /// 应用密钥 
 50         /// </summary>
 51         //public static string secret = "";
 52 
 53         /// <summary>
 54         /// 授权登录url
 55         /// </summary>
 56         public static string auth_login_url = "https://api.weixin.qq.com/sns/oauth2/access_token";
 57 
 58         /// <summary>
 59         /// 微信获取用户信息url
 60         /// </summary>
 61         public static string wx_user_url = "https://api.weixin.qq.com/sns/userinfo";
 62     }
 63 
 64     /// <summary>
 65     /// App预支付参数
 66     /// </summary>
 67     public class AppPaymentData
 68     {
 69         /// <summary>
 70         /// 小程序ID
 71         /// </summary>
 72         //[Required]
 73         public string appid { get; set; }
 74 
 75         /// <summary>
 76         /// 商户号
 77         /// </summary>
 78         public string mchid { get; set; }
 79 
 80         /// <summary>
 81         /// 商品描述 商品简单描述,不超过128字节
 82         /// </summary>
 83         public string description { get; set; }
 84 
 85         /// <summary>
 86         /// 商户订单号
 87         /// </summary>
 88         public string out_trade_no { get; set; }
 89 
 90         /// <summary>
 91         /// 交易结束时间 yyyyMMddHHmmss,非必填
 92         /// </summary>
 93         //public string time_expire { get; set; }
 94 
 95         /// <summary>
 96         /// 附加数据 非必填
 97         /// </summary>
 98         //public string attach { get; set; }
 99 
100         /// <summary>
101         /// 异步通知地址 通知url必须为外网可访问的url,不能携带参数。
102         /// </summary>
103         public string notify_url { get; set; }
104 
105         /// <summary>
106         /// 订单优惠标记
107         /// </summary>
108         //public string goods_tag { get; set; }
109 
110         /// <summary>
111         /// 订单金额信息
112         /// </summary>
113         public PaymentDataAmount amount { get; set; }
114 
115         /// <summary>
116         /// 场景信息
117         /// </summary>
118         //public PaymentDataScene scene_info { get; set; }
119 
120         /// <summary>
121         /// 结算信息
122         /// </summary>
123         //public PaymentDataSettle settle_info { get; set; }
124     }
125 
126     /// <summary>
127     /// 订单金额
128     /// </summary>
129     public class PaymentDataAmount
130     {
131         /// <summary>
132         /// 总金额 订单总金额,单位为分
133         /// </summary>
134         public int total { get; set; }
135 
136         /// <summary>
137         /// 货币类型 非必填,默认"CNY"
138         /// </summary>
139         public string currency { get; set; }
140     }
141 
142     /// <summary>
143     /// App调起支付参数
144     /// </summary>
145     public class AppPayBackItem
146     {
147         /// <summary>
148         /// 应用id
149         /// </summary>
150         public string appid { get; set; }
151 
152         /// <summary>
153         /// 商户号
154         /// </summary>
155         public string partnerid { get; set; }
156 
157         /// <summary>
158         /// 预支付交易会话ID
159         /// </summary>
160         public string prepayid { get; set; }
161 
162         /// <summary>
163         /// 订单详情扩展字符串
164         /// </summary>
165         public string package { get; set; }
166 
167         /// <summary>
168         /// 随机字符串
169         /// </summary>
170         public string noncestr { get; set; }
171 
172         /// <summary>
173         /// 时间戳
174         /// </summary>
175         public string timestamp { get; set; }
176 
177         /// <summary>
178         /// 签名
179         /// </summary>
180     

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
c#自适应窗体的实现发布时间:2022-07-13
下一篇:
C#将字符串格式化为Json发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap