CodePay.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Aop.Api.Request;
  8. using Aop.Api.Response;
  9. using BaseModel.Models;
  10. using WayneCloud.PaymentProcessors.Alipay.FromSDK;
  11. namespace Aop.Api.Business
  12. {
  13. public class CodePay
  14. {
  15. private static volatile IAopClient client;
  16. private static volatile Dictionary<AliPayConfig, IAopClient> clients = new Dictionary<AliPayConfig, IAopClient>();
  17. public static IAopClient Clients(AliPayConfig config)
  18. {
  19. //if (config != null)
  20. //{
  21. //if (client == null)
  22. //{
  23. // client = new DefaultAopClient(config.serverUrl,
  24. // config.appId,
  25. // config.merchant_private_key,
  26. // "json",
  27. // config.version,
  28. // config.sign_type,
  29. // config.alipay_public_key,
  30. // config.charset);
  31. //}
  32. //return client;
  33. if (!clients.ContainsKey(config))
  34. {
  35. var newClient = new DefaultAopClient(config.serverUrl,
  36. config.appId,
  37. config.merchant_private_key,
  38. "json",
  39. config.version,
  40. config.sign_type,
  41. config.alipay_public_key,
  42. config.charset);
  43. clients.Add(config, newClient);
  44. return newClient;
  45. }
  46. else
  47. {
  48. return clients[config];
  49. }
  50. }
  51. public static async Task<AopResponse> Run(ElectronicOrderModel order)
  52. {
  53. //set the default trade_status to PAYERROR
  54. order.TradeStatus = TradeStatus.PAYERROR;
  55. //线上联调时,请输入真实的外部订单号。
  56. string out_trade_no = order.BillNumber;
  57. //线上联调时,请输入真实的条码。
  58. string auth_code = order.AuthCode; //扫码枪扫描到的用户手机钱包中的付款条码
  59. string total_amount = order.NetAmount.ToString();
  60. StringBuilder sb = new StringBuilder();
  61. sb.Append("{\"out_trade_no\":\"" + out_trade_no + "\",");
  62. sb.Append("\"scene\":\"bar_code\",");
  63. sb.Append("\"auth_code\":\"" + auth_code + "\",");
  64. sb.Append("\"total_amount\":\"" + total_amount + "\",\"discountable_amount\":\"0.00\",");
  65. sb.Append("\"subject\":\"" + order.Title + "\",\"body\":\"empty_body\",");
  66. sb.Append("\"goods_detail\":[");
  67. var goodsString = (order.FuelOrderDetails.Count == 0) ? "" :
  68. (order.FuelOrderDetails.Select(s => "{\"goods_id\":\"" + s.FuelProductId
  69. + "\",\"goods_name\":\"" + s.FuelProductName
  70. + "\",\"goods_category\":\"" + s.Category
  71. + "\",\"price\":\"" + s.Price
  72. + "\",\"quantity\":\"" + s.Qualtity + "\"}").Aggregate((acc, n) => acc + "," + n));
  73. sb.Append(goodsString);
  74. sb.Append("],");
  75. sb.Append("\"operator_id\":\"" + (order.OperatorId ?? "") + "\",\"store_id\":\"" + order.SiteId + "\",\"terminal_id\":\"" + (order.TerminalId ?? "") + "\",");
  76. string expire_time = System.DateTime.Now.AddHours(1).ToString("yyyy-MM-dd HH:mm:ss");
  77. sb.Append("\"time_expire\":\"" + expire_time + "\"}");
  78. var payResponse = await Pay(sb.ToString(), (AliPayConfig)order.Config);
  79. //支付成功的情形
  80. if (payResponse != null && payResponse.Code == ResultCode.SUCCESS)
  81. {
  82. order.TradeStatus = TradeStatus.SUCCESS;
  83. return payResponse;
  84. }
  85. //如果返回结果是操作失败,或者返回结果不是操作处理中,就直接返回支付失败
  86. if (payResponse == null || payResponse.Code == ResultCode.FAIL || payResponse.Code != ResultCode.INRROCESS)
  87. {
  88. return payResponse;
  89. }
  90. StringBuilder sb1 = new StringBuilder();
  91. sb1.Append("{\"out_trade_no\":\"" + order.BillNumber + "\"}");
  92. //以下是返回操作处理中的情形, 需要进行轮询
  93. AlipayTradeQueryResponse queryResponse = await LoopQuery(sb1.ToString(), (AliPayConfig)order.Config); //用订单号trade_no进行轮询也是可以的。
  94. if (queryResponse !=null)
  95. {
  96. if (string.Compare(queryResponse.Code, ResultCode.SUCCESS, false) == 0)
  97. {
  98. if (queryResponse.TradeStatus == "TRADE_FINISHED"
  99. || queryResponse.TradeStatus == "TRADE_SUCCESS")
  100. {
  101. order.TradeStatus = TradeStatus.SUCCESS;
  102. }
  103. else if (queryResponse.TradeStatus == "TRADE_CLOSED")
  104. {
  105. order.TradeStatus = TradeStatus.CLOSED;
  106. }
  107. return queryResponse;
  108. }
  109. }
  110. return payResponse;
  111. }
  112. private static async Task<AlipayTradePayResponse> Pay(string biz_content, AliPayConfig config)
  113. {
  114. AlipayTradePayRequest payRequst = new AlipayTradePayRequest();
  115. payRequst.BizContent = biz_content;
  116. //payRequst
  117. Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();
  118. //new DefaultAopClient(Config.serverUrl, Config.appId, Config.merchant_private_key);
  119. AlipayTradePayResponse payResponse = await Clients(config).Execute(payRequst);
  120. return payResponse;
  121. }
  122. public static async Task<AlipayTradeCancelResponse> Cancel(string billNumber, AliPayConfig config)
  123. {
  124. StringBuilder sb = new StringBuilder();
  125. sb.Append("{\"out_trade_no\":\"" + billNumber + "\"}");
  126. string biz_content = sb.ToString();
  127. AlipayTradeCancelRequest cancelRequest = new AlipayTradeCancelRequest();
  128. cancelRequest.BizContent = biz_content;
  129. AlipayTradeCancelResponse cancelResponse = await Clients(config).Execute(cancelRequest);
  130. if (null != cancelResponse)
  131. {
  132. if (cancelResponse.Code == ResultCode.FAIL && cancelResponse.RetryFlag == "Y")
  133. {
  134. cancelResponse = await CancelOrderRetry(biz_content, config);
  135. }
  136. }
  137. return cancelResponse;
  138. }
  139. private static async Task<AlipayTradeCancelResponse> CancelOrderRetry(object o, AliPayConfig config)
  140. {
  141. int retryCount = 10;
  142. AlipayTradeCancelResponse cancelResponse = null;
  143. for (int i = 0; i < retryCount; ++i)
  144. {
  145. Thread.Sleep(5000);
  146. AlipayTradeCancelRequest cancelRequest = new AlipayTradeCancelRequest();
  147. cancelRequest.BizContent = o.ToString();
  148. // Dictionary<string, string> paramsDict = (Dictionary<string, string>)cancelRequest.GetParameters();
  149. cancelResponse = await Clients(config).Execute(cancelRequest);
  150. if (null != cancelResponse)
  151. {
  152. if (cancelResponse.Code == ResultCode.FAIL)
  153. {
  154. //if (cancelResponse.Body.Contains("\"retry_flag\":\"N\""))
  155. if (cancelResponse.RetryFlag == "N")
  156. {
  157. break;
  158. }
  159. }
  160. }
  161. if (i == retryCount - 1)
  162. {
  163. // 处理到最后一次,还是未撤销成功,需要在商户数据库中对此单最标记,人工介入处理
  164. }
  165. }
  166. return cancelResponse;
  167. }
  168. private static async Task<AlipayTradeQueryResponse> LoopQuery(string biz_content, AliPayConfig config)
  169. {
  170. AlipayTradeQueryRequest payRequst = new AlipayTradeQueryRequest();
  171. payRequst.BizContent = biz_content;
  172. Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();
  173. AlipayTradeQueryResponse payResponse = null;
  174. for (int i = 1; i <= 6; i++)
  175. {
  176. Thread.Sleep(5000);
  177. payResponse = await Clients(config).Execute(payRequst);
  178. if (string.Compare(payResponse.Code, ResultCode.SUCCESS, false) == 0)
  179. {
  180. if (payResponse.TradeStatus == "TRADE_FINISHED"
  181. || payResponse.TradeStatus == "TRADE_SUCCESS"
  182. || payResponse.TradeStatus == "TRADE_CLOSED")
  183. return payResponse;
  184. }
  185. }
  186. return payResponse;
  187. }
  188. }
  189. }