using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Edu.Common.WeChatPayAPIv3.Model.GenerateOrder; using Edu.Common.WeChatPayAPIv3.Model.QueryOrder; using Edu.Common.WeChatPayAPIv3.Model.QueryRefunds; using Edu.Common.WeChatPayAPIv3.Model.Refunds; namespace Edu.Common.WeChatPayAPIv3 { public class WxPayHelper { /// /// 直连商户申请的公众号或移动应用appid。 /// private string _appid { set; get; } /// /// 直连商户的商户号,由微信支付生成并下发。 /// private string _mchid { set; get; } /// /// 证书序列号,查看证书序列号:https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao /// private string _serialNo; /// /// 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY----- /// private string _privateKey; /// /// 构造函数 /// /// 直连商户申请的公众号或移动应用appid /// 直连商户的商户号,由微信支付生成并下发 /// 证书序列号,查看证书序列号:https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao /// 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY----- public WxPayHelper(string appid, string mchid, string serialNo, string privateKey) { _appid = appid; _mchid = mchid; _serialNo = serialNo; _privateKey = privateKey; } /// /// 统一下单接口,只对接了必填的字段 /// /// 商品描述 /// 订单总金额,单位为分 /// 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 /// 通知URL必须为直接可访问的URL,不允许携带查询串。格式:URL /// 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 /// 货币类型,CNY:人民币,境内商户号仅支持人民币 /// public async Task UnionGenerateOrder(string description, int price, string out_trade_no, string notify_url, string attach = "", string currency = "CNY") { var url = "https://api.mch.weixin.qq.com/v3/pay/transactions/native"; var req = new GenerateOrderModelForWxPay { appid = this._appid, mchid = this._mchid, description = description, amount = new WxPayAmountModel { total = price, currency = currency }, out_trade_no = out_trade_no, attach = attach, notify_url = notify_url }; var client = new HttpClient(new WxPayRequestHandler(_mchid, _serialNo, _privateKey)); // var bodyJson = new StringContent(req.ToJson(), Encoding.UTF8, "application/json"); var bodyJson = new StringContent(Common.Plugin.JsonHelper.Serialize(req), Encoding.UTF8, "application/json"); var resp = await client.PostAsync(url, bodyJson); // 注意!!! 这个resp只是http的结果,需要把接口具体返回的值读取出来,如果接口报错的话,这地方可以看到具体的错误信息,我就是在这里入坑的。 var respStr = await resp.Content.ReadAsStringAsync(); // 如果下单成功,就解析返回的结果,把prepay_id解析出来 // var viewModel = respStr.ToObject(); Plugin.LogHelper.WriteInfo(respStr); var viewModel = Common.Plugin.JsonHelper.DeserializeObject(respStr); return viewModel; } /// /// 查询订单 /// /// 商户自己的订单号,不是微信生成的订单号 public async Task QueryOrder(string orderNumber) { var url = $"https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{orderNumber}?mchid={ this._mchid}"; var client = new HttpClient(new WxPayRequestHandler(_mchid, _serialNo, _privateKey)); var resp = await client.GetAsync(url); var respStr = await resp.Content.ReadAsStringAsync(); Plugin.LogHelper.WriteInfo("查询订单的支付结果信息:"+respStr); var payModel = Common.Plugin.JsonHelper.DeserializeObject(respStr);// respStr.ToObject(); return payModel; } ///// ///// 关闭订单 ///// ///// 商户自己的订单号,不是微信生成的订单号 //public async Task ClostOrder(string orderNumber) //{ // var url = $"https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{orderNumber}/close"; // var client = new HttpClient(new WxPayRequestHandler(_mchid, _serialNo, _privateKey)); // var bodyJson = new StringContent(new { mchid = this._mchid }.ToJson(), Encoding.UTF8, "application/json"); // var resp = await client.PostAsync(url, bodyJson); // var respStr = await resp.Content.ReadAsStringAsync(); // var closeModel = new ClostOrderRespModel(); // if (!string.IsNullOrEmpty(respStr)) // closeModel = respStr.ToObject(); // closeModel.StatusCode = resp.StatusCode.ToString(); // return closeModel; //} /// /// 微信支付申请退款接口 /// /// 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一;原支付交易对应的商户订单号。 /// 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 /// 若商户传入,会在下发给用户的退款消息中体现退款原因。 /// 退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。 /// 原支付交易的订单总金额,币种的最小单位,只能为整数。 /// 异步接收微信支付退款结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效,优先回调当前传的这个地址。示例值:https://weixin.qq.com ,必须是https的网址 /// 符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。 /// public async Task Refunds(string out_trade_no, string out_refund_no, string reason, int refund, int total, string notify_url = "", string currency = "CNY") { var req = new RefundsRequestModel { out_refund_no = out_refund_no, out_trade_no = out_trade_no, reason = reason, notify_url = notify_url, amount = new RefundsAmountModel { refund = refund, total = total, currency = currency } }; var url = $"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"; var client = new HttpClient(new WxPayRequestHandler(_mchid, _serialNo, _privateKey)); var bodyJson = new StringContent(Common.Plugin.JsonHelper.Serialize(req), Encoding.UTF8, "application/json"); var resp = await client.PostAsync(url, bodyJson); var respStr = await resp.Content.ReadAsStringAsync(); var payModel = Common.Plugin.JsonHelper.DeserializeObject(respStr);// respStr.ToObject(); return payModel; } /// /// 查询退款结果 /// /// 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 public async Task QueryRefundsOrder(string out_refund_no) { var url = $"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no}"; var client = new HttpClient(new WxPayRequestHandler(_mchid, _serialNo, _privateKey)); var resp = await client.GetAsync(url); var respStr = await resp.Content.ReadAsStringAsync(); Plugin.LogHelper.WriteInfo("查询订单的退款结果信息:" + respStr); var payModel = Common.Plugin.JsonHelper.DeserializeObject(respStr); //respStr.ToObject(); return payModel; } } }