. net core wechat applet refund steps – (Unified refund)

Time:2020-5-16

Following the previous “. Net core” Wechat app payment – “after (unified order),” this article will realize the function of unified refund. If you can pay, you should be able to refund. Generally, things involving money will be more sensitive, so when designing the refund process, you must be rigorous and not make any mistakes, otherwise you will face the possibility of paying your own money. Next, we will talk about the realization steps of refund.

Refund scenarios and rules

When a refund is required due to the buyer’s or seller’s reasons within a period of time after the transaction, the seller can return the payment to the buyer through the refund interface, and wechat payment will return the payment to the buyer’s account according to the refund rules after receiving the refund request and verifying successfully.

rule

1. No refund can be submitted for orders with transaction time more than one year;

2. Wechat payment refund supports multiple refunds for a single transaction. Multiple refunds need to submit the merchant order number of the original payment order and set different refund number. The total amount of refund application cannot exceed the order amount. If a refund fails to be submitted again, please do not change the refund number. Please use the original merchant’s refund number.

3. Request frequency limit: 150qps, i.e. no more than 150 normal requests for refund per second

Error or invalid request frequency limit: 6qps, i.e. no more than 6 abnormal or wrong refund request requests per second

4. The number of partial refunds per payment order cannot exceed 50

Interface address

Interface link: https://api.mch.weixin.qq.com/secapi/pay/consult

Relevant parameters

Official refund document

Document address: https://pay.weixin.qq.com/wiki/doc/api/app/app.php? Chapter = 9_ & index = 6

Realize unified refund process

If there are multiple refund processes in the business, you can encapsulate the refund process to facilitate multi location call; if the company has different applets under the same subject, you need the refund function, and you can also encapsulate them to refund for different applets.

Go to the merchant background to download the certificate first, which is required for refund. The following figure is the interface for the merchant background to download the certificate:

Reference package:

Senparc.Weixin.WxOpen

Senparc.Weixin.TenPay

Official account number, applet information


services.AddSenparcGlobalServices(Configuration)
.AddSenparcWeixinServices(Configuration);
IRegisterService register = RegisterService.Start(env, senparcSetting.Value).UseSenparcGlobal(false, null);
register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value)
 .RegisterTenpayV3(senparcWeixinSetting.Value, "appid"); 

Unified refund code implementation

publicbool RefundProduct(OrdOrderProduct ordOrderProduct, PayOrderMstParam payOrderMstParam, OrdOrderPayItem ordOrderPayItem, string appID, DateTime thisTime, ref string errMsg)
{
 try
 {
 OrdOrderPayMst refPay = null;
 if (!PayOrderManager.CreatePayOrderMST(payOrderMstParam, thisTime, ref refPay, ref errMsg))
 {
  Errmsg = "error generating refund form!" + errmsg;
  return false;
 }
 var PayInfo = Senparc.Weixin.Config.SenparcWeixinSetting.Items[appID];
 string AppID = PayInfo.WxOpenAppId;
 string AppSecret = PayInfo.WxOpenAppSecret;
 String MCH? Id = payinfo.tenpayv3? Mchid; // merchant No
 String mch_key = payinfo.tenpayv3_key; // merchant key
 string notifyUrl = string.Format(PayInfo.TenPayV3_TenpayNotify, "RefundNotifyUrl");
 var timeStamp = TenPayV3Util.GetTimestamp();
 var nonceStr = TenPayV3Util.GetNoncestr();
 //Payment source No
 String outtradeno = orderpayitem.payno; // merchant Order No. / payment No
 refPay.PayNoSource = ordOrderPayItem.PayNo;
 //Refund No
 String outrefundno = refpay.payno; // new refund No
 //Total amount at time of payment
 int totalFee = (int)(ordOrderPayItem.PayPrice * 100);
 //Refund amount
 int refundFee = (int)(refPay.PayPrice * 100);
 string opUserId = PayInfo.TenPayV3_MchId;
 var dataInfo = new TenPayV3RefundRequestData(AppID, Mch_id, Mch_key,
  null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null, notifyUrl: notifyUrl);
 //Logger.Info($"PayInfo={PayInfo.SerializeObject()}");
 //Logger.Info($"dataInfo={dataInfo.SerializeObject()}");
 //var basePath = AppContext.BaseDirectory;
 //var certPath = Path.Combine(basePath, "Config/apiclient_cert.p12");
 //Var cert = @ "D: \ projects \ orderapi. Trydou. Com \ config \ apiclient \ cert.p12"; // modify according to your own certificate location
 //Var password = mch_id; // the default is the merchant number, which is recommended to be modified
 //Configure certificate address, V3 automatic identification
 var result = TenPayV3.Refund(dataInfo);
 refPay.PayResult = result.SerializeObject();
 // Logger.Info ("submit refund request:"+ refPay.PayResult );
 if (result.return_code.ToUpper() == "SUCCESS" && result.result_code.ToUpper() == "SUCCESS")
 {
  using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
  {
  //Business processing
  //Commit transaction
  scope.Complete();
  }
  return true;
 }
 else
 {
  errMsg = result.err_code_des;
  Logger. Error (string. Format ("failed to submit refund, refund No. = {0}, associated order No. = {1}, associated product = {2}, refund result = {3}"),
  refPay.PayNo, refPay.RelationNo, refPay.RelationNos, refPay.PayResult));
 }
 }
 catch (Exception ex)
 {
 errMsg = ex.Message;
 Logger. Error (string. Format ("submit refund exception: Message = {0}, stacktrace = {1}", ex.message, ex.stacktrace));
  }
  return false;
 }

Note: pay attention to the parameters of the refund interface, such as: amount, refund address, etc., to ensure that the parameters are correct. Generally, wechat will receive the refund request instruction. After wechat processing is successful, it will asynchronously call back the refund interface to the server.

Refund unified callback processing

The direct code is as follows:

/// <summary>
///Refund callback
/// </summary>
[HttpPost("RefundNotifyUrl")]
public ActionResult RefundNotifyUrl()
{
 ResponseResult result = new ResponseResult();
 ResponseHandler resHandler = new ResponseHandler(HttpContext);
 string return_code = resHandler.GetParameter("return_code");
 string return_msg = resHandler.GetParameter("return_msg");
 try
 {
 var mch_key = Senparc.Weixin.Config.SenparcWeixinSetting.TenPayV3_Key;
 if (return_code.ToUpper() == "SUCCESS")
 {
  //string result_code = resHandler.GetParameter("result_code");
  //string appId = resHandler.GetParameter("appid");
  //string mch_id = resHandler.GetParameter("mch_id");
  //string nonce_str = resHandler.GetParameter("nonce_str");
  string req_info = resHandler.GetParameter("req_info");
  var decodeReqInfo = TenPayV3Util.DecodeRefundReqInfo(req_info, mch_key);
  var decodeDoc = XDocument.Parse(decodeReqInfo);
  var refundNotifyXml = decodeDoc.SerializeObject();
  //Get the information needed in the interface
  string out_trade_no = decodeDoc.Root.Element("out_trade_no").Value;
  string out_refund_no = decodeDoc.Root.Element("out_refund_no").Value;
  string transaction_id = decodeDoc.Root.Element("transaction_id").Value;
  string refund_id = decodeDoc.Root.Element("refund_id").Value;
  int total_fee = int.Parse(decodeDoc.Root.Element("total_fee").Value);
  int refund_fee = int.Parse(decodeDoc.Root.Element("refund_fee").Value);
  RefundNotifyParam param = new RefundNotifyParam()
  {
  Payno = out trade no, // merchant order number
  Payprice = ((float) refund_fee. Toint() / 100). Todecimal(), // refund amount
  Out ` refund ` no = out ` refund ` No, // merchant refund No 
  Transactionno = transaction_id, // wechat Order No
  Refund UU id = refund UU ID, // wechat refund No 
  };
  Logger.info (string. Format ("refund callback parameter, return ﹐ code = {0}, return ﹐ MSG = {1}, refundnotifyxml = {2}", return ﹐ code, return ﹐ MSG, refundnotifyxml));
  result = Service.RefundNotifyUrl(param);
  if (result.errno != 0)
  {
  //Callback processing logic failed
  Logger.Error ( string.Format ("refund callback business processing failed: refund No. {0}, {1}", param.Out_ refund_ no,  result.errmsg );
  }
  else
  {
  Logger.info (string. Format ("refund callback business processed successfully, refund doc No.: {0}", param. Out_refund_no));
  string xml = string.Format(@"<xml>
    <return_code><![CDATA[{0}]]></return_code>
    <return_msg><![CDATA[{1}]]></return_msg>
    </xml>", return_code, return_msg);
  return Content(xml, "text/xml");
  }
 }
 else
 {
  //Wrong order processing
  Logger. Error (string. Format ("refund callback failed, return ﹐ code = {0}, return ﹐ MSG = {1}", return ﹐ code, return ﹐ MSG));
 }
 }
 catch (Exception ex)
 {
 Logger. Error (string. Format ("refund callback exception: Message = {0}, stacktrace = {1}", ex.message, ex.stacktrace));
 }
 return Content("fail", "text/xml");
}

Note: if the refund is processed successfully, please return the result to wechat success. Otherwise, wechat will send the refund callback to the server continuously according to the rules until the number of times is used up. Check the above rule documents.

summary

The above is the refund procedure of the. Net core wechat applet introduced by Xiaobian to you (Unified refund). I hope it can help you. If you have any questions, please leave a message to me, and Xiaobian will reply you in time. Thank you very much for your support of the developepaer website!
If you think this article is helpful to you, welcome to reprint, please indicate the source, thank you!

Recommended Today

IView, upload component beforeupload compress image

critical code <Upload multiple :format=”[‘jpg’,’jpeg’,’png’]” :beforeUpload=”beforeUpload” action=”” :on-success=”upload” > < button icon = “IOS cloud upload outline” > upload picture < / button > </Upload> import Compressor from “compressorjs” beforeUpload(file) { return new Promise((resolve, reject) => { let isLt1M = file.size / 1024 / 1024 < 1; if (isLt1M) { resolve(file); } new Compressor(file, { […]