Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

182 rader
6.7 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Web;
  4. using System.Threading;
  5. namespace WxPayAPI
  6. {
  7. public class MicroPay
  8. {
  9. /**
  10. *
  11. * @param body
  12. * @param total_fee
  13. * @param auth_code
  14. * @throws WxPayException
  15. * @return
  16. */
  17. public static string Run(string body, string total_fee, string auth_code)
  18. {
  19. Log.Info("MicroPay", "Micropay is processing...");
  20. WxPayData data = new WxPayData();
  21. data.SetValue("auth_code", auth_code);//授权码
  22. data.SetValue("body", body);//商品描述
  23. data.SetValue("total_fee", int.Parse(total_fee));//总金额
  24. data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//产生随机的商户订单号
  25. WxPayData result = WxPayApi.Micropay(data, 10); //提交被扫支付,接收返回结果
  26. //如果提交被扫支付接口调用失败,则抛异常
  27. if (!result.IsSet("return_code") || result.GetValue("return_code").ToString() == "FAIL")
  28. {
  29. string returnMsg = result.IsSet("return_msg") ? result.GetValue("return_msg").ToString() : "";
  30. Log.Error("MicroPay", "Micropay API interface call failure, result : " + result.ToXml());
  31. throw new WxPayException("Micropay API interface call failure, return_msg : " + returnMsg);
  32. }
  33. //签名验证
  34. result.CheckSign();
  35. Log.Debug("MicroPay", "Micropay response check sign success");
  36. //刷卡支付直接成功
  37. if(result.GetValue("return_code").ToString() == "SUCCESS" &&
  38. result.GetValue("result_code").ToString() == "SUCCESS")
  39. {
  40. Log.Debug("MicroPay", "Micropay business success, result : " + result.ToXml());
  41. return result.ToPrintStr();
  42. }
  43. /******************************************************************
  44. *
  45. * ****************************************************************/
  46. //1)业务结果明确失败
  47. if(result.GetValue("err_code").ToString() != "USERPAYING" &&
  48. result.GetValue("err_code").ToString() != "SYSTEMERROR")
  49. {
  50. Log.Error("MicroPay", "micropay API interface call success, business failure, result : " + result.ToXml());
  51. return result.ToPrintStr();
  52. }
  53. //2)不能确定是否失败,需查单
  54. //用商户订单号去查单
  55. string out_trade_no = data.GetValue("out_trade_no").ToString();
  56. //确认支付是否成功,每隔一段时间查询一次订单,共查询10次
  57. int queryTimes = 10;//查询次数计数器
  58. while(queryTimes-- > 0)
  59. {
  60. int succResult = 0;//查询结果
  61. WxPayData queryResult = Query(out_trade_no, out succResult);
  62. //如果需要继续查询,则等待2s后继续
  63. if(succResult == 2)
  64. {
  65. Thread.Sleep(2000);
  66. continue;
  67. }
  68. //查询成功,返回订单查询接口返回的数据
  69. else if(succResult == 1)
  70. {
  71. Log.Debug("MicroPay", "Mircopay success, return order query result : " + queryResult.ToXml());
  72. return queryResult.ToPrintStr();
  73. }
  74. //订单交易失败,直接返回刷卡支付接口返回的结果,失败原因会在err_code中描述
  75. else
  76. {
  77. Log.Error("MicroPay", "Micropay failure, return micropay result : " + result.ToXml());
  78. return result.ToPrintStr();
  79. }
  80. }
  81. //确认失败,则撤销订单
  82. Log.Error("MicroPay", "Micropay failure, Reverse order is processing...");
  83. if(!Cancel(out_trade_no))
  84. {
  85. Log.Error("MicroPay", "Reverse order failure");
  86. throw new WxPayException("Reverse order failure!");
  87. }
  88. return result.ToPrintStr();
  89. }
  90. /**
  91. *
  92. *
  93. * @param string out_trade_no
  94. * @param int succCode 012
  95. * @return
  96. */
  97. public static WxPayData Query(string out_trade_no, out int succCode)
  98. {
  99. WxPayData queryOrderInput = new WxPayData();
  100. queryOrderInput.SetValue("out_trade_no",out_trade_no);
  101. WxPayData result = WxPayApi.OrderQuery(queryOrderInput);
  102. if(result.GetValue("return_code").ToString() == "SUCCESS"
  103. && result.GetValue("result_code").ToString() == "SUCCESS")
  104. {
  105. //支付成功
  106. if(result.GetValue("trade_state").ToString() == "SUCCESS")
  107. {
  108. succCode = 1;
  109. return result;
  110. }
  111. //用户支付中,需要继续查询
  112. else if(result.GetValue("trade_state").ToString() == "USERPAYING")
  113. {
  114. succCode = 2;
  115. return result;
  116. }
  117. }
  118. //如果返回错误码为“此交易订单号不存在”则直接认定失败
  119. if(result.GetValue("err_code").ToString() == "ORDERNOTEXIST")
  120. {
  121. succCode = 0;
  122. }
  123. else
  124. {
  125. //如果是系统错误,则后续继续
  126. succCode = 2;
  127. }
  128. return result;
  129. }
  130. /**
  131. *
  132. * 10
  133. * @param string out_trade_no
  134. * @param depth
  135. * @return false表示撤销失败true表示撤销成功
  136. */
  137. public static bool Cancel(string out_trade_no, int depth = 0)
  138. {
  139. if(depth > 10)
  140. {
  141. return false;
  142. }
  143. WxPayData reverseInput = new WxPayData();
  144. reverseInput.SetValue("out_trade_no",out_trade_no);
  145. WxPayData result = WxPayApi.Reverse(reverseInput);
  146. //接口调用失败
  147. if(result.GetValue("return_code").ToString() != "SUCCESS")
  148. {
  149. return false;
  150. }
  151. //如果结果为success且不需要重新调用撤销,则表示撤销成功
  152. if(result.GetValue("result_code").ToString() != "SUCCESS" && result.GetValue("recall").ToString() == "N")
  153. {
  154. return true;
  155. }
  156. else if(result.GetValue("recall").ToString() == "Y")
  157. {
  158. return Cancel(out_trade_no, ++depth);
  159. }
  160. return false;
  161. }
  162. }
  163. }