using System; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using WayneCloud.Models; using WayneCloud.Models.Models; namespace Wechat.PayAPI { public class Refund { private const int MAX_REFUND_RETRY_TIMES = 5; /*** * 申请退款完整业务流程逻辑 * @param transaction_id 微信订单号(优先使用) * @param out_trade_no 商户订单号 * @param total_fee 订单总金额 * @param refund_fee 退款金额 * @return 退款结果 */ public static async Task Run(string transaction_id, ElectronicOrderModel order) { // string out_trade_no, string total_fee, string refund_fee //set the default trade_status to PAYERROR order.TradeStatus = TradeStatus.PAYERROR; string out_refund_no = WxPayApi.GenerateOutTradeNo((WxPayConfig)order.Config); Log.Info("Refund", "Refund is processing, out_refund_no = " + out_refund_no); int retry_count = 0; bool use_unsettled_fund = true; while (true) { WxPayData result = await RequestRefund(transaction_id, order.BillNumber, order.TotalAmount.ToString(), order.NetAmount.ToString(), out_refund_no, use_unsettled_fund, (WxPayConfig)order.Config, (X509Certificate2)order.Certification); //如果提交退款接口调用失败,则抛异常 if (!result.IsSet("return_code") || result.GetValue("return_code").ToString() == "FAIL") { string returnMsg = result.IsSet("return_msg") ? result.GetValue("return_msg").ToString() : ""; Log.Error("MicroPay", "Micropay API interface call failure, result : " + result.ToXml()); throw new WxPayException("Micropay API interface call failure, return_msg : " + returnMsg); } //签名验证 result.CheckSign((WxPayConfig)order.Config); Log.Debug("MicroPay", "Micropay response check sign success"); //退款成功 if (result.GetValue("return_code").ToString() == "SUCCESS" && result.GetValue("result_code").ToString() == "SUCCESS") { Log.Debug("MicroPay", "Micropay refund success, result : " + result.ToXml()); order.TradeStatus = TradeStatus.SUCCESS; return result; } /****************************************************************** * 剩下的都是接口调用成功,业务失败的情况 * ****************************************************************/ //1)业务结果明确失败 if (result.GetValue("err_code").ToString() != "BIZERR_NEED_RETRY" && result.GetValue("err_code").ToString() != "SYSTEMERROR" && result.GetValue("err_code").ToString() != "NOTENOUGH") { Log.Error("MicroPay", "micropay API interface call success, business failure, result : " + result.ToXml()); return result; } //2) 使用相同退款单号重试 if (result.GetValue("err_code").ToString() == "NOTENOUGH") { use_unsettled_fund = !use_unsettled_fund; Log.Debug("MicroPay", "Switched to use the other fund source for refund, use_unsettled_fund = " + use_unsettled_fund); } retry_count++; if (retry_count <= MAX_REFUND_RETRY_TIMES) { Log.Debug("MicroPay", "Micropay refund retry, retry_count : " + retry_count); } else { Log.Error("MicroPay", "Micropay refund max retry times exceeded! Result : " + result.ToXml()); return result; } } } private static async Task RequestRefund( string transaction_id, string out_trade_no, string total_fee, string refund_fee, string out_refund_no, bool use_unsettled_fund, WxPayConfig config, X509Certificate2 certification ) { if (config == null) { throw new WxPayException("微信支付,缺少WxPayConfig!"); } WxPayData data = new WxPayData(); if (!string.IsNullOrEmpty(transaction_id))//微信订单号存在的条件下,则已微信订单号为准 { data.SetValue("transaction_id", transaction_id); } else//微信订单号不存在,才根据商户订单号去退款 { data.SetValue("out_trade_no", out_trade_no); } data.SetValue("total_fee", Convert.ToInt32(Decimal.Parse(total_fee) * 100));//订单总金额 data.SetValue("refund_fee", Convert.ToInt32(Decimal.Parse(refund_fee) * 100));//退款金额 data.SetValue("out_refund_no", out_refund_no);//商户退款单号 data.SetValue("op_user_id", config.MCHID);//操作员,默认为商户号 if (use_unsettled_fund) { data.SetValue("refund_account", "REFUND_SOURCE_UNSETTLED_FUNDS"); } else { data.SetValue("refund_account", "REFUND_SOURCE_RECHARGE_FUNDS"); } WxPayData result = await WxPayApi.Refund(data, config, certification);//提交退款申请给API,接收返回数据 return result; } } }