App.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using Edge.Core.Processor;
  2. using Edge.Core.Processor.Dispatcher.Attributes;
  3. using Edge.Core.UniversalApi;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.Extensions.Logging;
  6. using PaymentGateway.GatewayApp;
  7. using Gateway.Payment.Shared;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Globalization;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using System.Linq;
  14. namespace Gateway.Payment
  15. {
  16. [MetaPartsDescriptor(
  17. "lang-zh-cn:支付网关Applang-en-us:Payment gateway App",
  18. "lang-zh-cn:用于支持移动支付功能lang-en-us:Used for support mobile payment, like QR code scan payment and etc.",
  19. new[] { "lang-zh-cn:支付网关lang-en-us:PaymentGateway" })]
  20. public class App : IAppProcessor
  21. {
  22. private IServiceProvider services;
  23. private ILogger logger;
  24. private AppConfigV1 appConfig;
  25. public string MetaConfigName { get; set; }
  26. public void Init(IEnumerable<IProcessor> processors)
  27. {
  28. //throw new NotImplementedException();
  29. }
  30. public class AppConfigV1
  31. {
  32. public TongLianPayConfigAndCertificationV1 TongLianPayV1Config { get; set; }
  33. public TongLianPayConfigAndCertificationV2 TongLianPayV2Config { get; set; }
  34. public AliPayConfigAndCertification AliPayConfig { get; set; }
  35. public WxPayConfigAndCertification WxPayConfig { get; set; }
  36. }
  37. [ParamsJsonSchemas("appCtorParamsJsonSchema")]
  38. public App(AppConfigV1 appConfig, IServiceProvider services)
  39. {
  40. //<?xml version="1.0" encoding="utf-8"?>
  41. //<TongLianPayConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  42. // <appId>00191280</appId>
  43. // <cusId>561599055417A40</cusId>
  44. // <appKey>eabd7016a0bddd25dd339e0aefc665e0</appKey>
  45. // <apiVersion>11</apiVersion>
  46. // <apiUrl>https://vsp.allinpay.com/apiweb/unitorder</apiUrl>
  47. // <notifyUrl></notifyUrl>
  48. // <queryInterval>3</queryInterval>
  49. // <queryTimeout>120</queryTimeout>
  50. //</TongLianPayConfig>
  51. if (appConfig?.TongLianPayV1Config?.Config?.notifyUrl?.Contains("showmethemoney", StringComparison.OrdinalIgnoreCase) ?? false)
  52. appConfig.TongLianPayV1Config = new TongLianPayConfigAndCertificationV1()
  53. {
  54. Config = new TongLianPayConfigV1()
  55. {
  56. appId = "00191280",
  57. cusId = "561599055417A40",
  58. appKey = "eabd7016a0bddd25dd339e0aefc665e0",
  59. apiVersion = "11",
  60. apiUrl = "https://vsp.allinpay.com/apiweb/unitorder",
  61. notifyUrl = "",
  62. queryInterval = 3,
  63. queryTimeout = 120,
  64. }
  65. };
  66. //<? xml version="1.0" encoding="utf-8"?>
  67. //<TongLianPayConfigV2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  68. // <appId>M00000005</appId>
  69. // <sysId>1323455910784892929</sysId>
  70. // <key>3dab2c7911b74f3cb3241c083a0e055e</key>
  71. // <oilStationNo>S0049</oilStationNo>
  72. // <shiftsMask>01</shiftsMask>
  73. // <version>1.0</version>
  74. // <charset>utf-8</charset>
  75. // <signType>MD5</signType>
  76. // <apiUrl>https://cloud.aipgd.com/gateway</apiUrl>
  77. // <notifyUrl></notifyUrl>
  78. // <queryInterval>10</queryInterval>
  79. // <queryTimeout>90</queryTimeout>
  80. //</TongLianPayConfigV2>
  81. if (appConfig?.TongLianPayV2Config?.Config?.notifyUrl?.Contains("showmethemoney", StringComparison.OrdinalIgnoreCase) ?? false)
  82. appConfig.TongLianPayV2Config = new TongLianPayConfigAndCertificationV2()
  83. {
  84. Config = new TongLianPayConfigV2()
  85. {
  86. appId = "M00000005",
  87. sysId = "1323455910784892929",
  88. key = "3dab2c7911b74f3cb3241c083a0e055e",
  89. oilStationNo = "S0049",
  90. shiftsMask = "01",
  91. version = "1.0",
  92. charset = "utf-8",
  93. signType = "MD5",
  94. apiUrl = "https://cloud.aipgd.com/gateway",
  95. notifyUrl = "",
  96. queryInterval = 10,
  97. queryTimeout = 90
  98. }
  99. };
  100. this.appConfig = appConfig;
  101. this.services = services;
  102. var loggerFactory = services.GetRequiredService<ILoggerFactory>();
  103. this.logger = loggerFactory.CreateLogger("DynamicPrivate_Gateway.Payment");
  104. }
  105. private static Aop.Api.Request.AlipayOpenOperationOpenbizmockBizQueryRequest GetAlipayRequest()
  106. {
  107. // 初始化Request,并填充Model属性。实际调用时请替换为您想要使用的API对应的Request对象。
  108. Aop.Api.Request.AlipayOpenOperationOpenbizmockBizQueryRequest request = new Aop.Api.Request.AlipayOpenOperationOpenbizmockBizQueryRequest();
  109. Aop.Api.Domain.AlipayOpenOperationOpenbizmockBizQueryModel model = new Aop.Api.Domain.AlipayOpenOperationOpenbizmockBizQueryModel
  110. {
  111. BizNo = "123456789"
  112. };
  113. request.SetBizModel(model);
  114. return request;
  115. }
  116. [UniversalApi]
  117. public async Task<PaymentOrder> StartPayment(PaymentOrderDto input)
  118. {
  119. var mapper = this.services.GetRequiredService<AutoMapper.IMapper>();
  120. var order = mapper.Map<PaymentOrder>(input);
  121. order.ServerSideTimestamp = DateTime.Now;
  122. order.PayResults = new List<PaymentOrderPayResult>();
  123. if (!input.IsForRefund)
  124. {
  125. var billNumber = SequenceNumber.Next();
  126. order.BillNumber = billNumber;
  127. }
  128. this.logger.LogInformation("New PaymentOrder received for start a payment: " + order.ToFullJsonLogString());
  129. try
  130. {
  131. var returnCode = ClientSideReturnCode.PAY_ERROR;
  132. switch (order.PaymentMethod)
  133. {
  134. case "WX_SCAN":
  135. {
  136. //https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1
  137. WechatPaymentProcessor processor = new WechatPaymentProcessor();
  138. //Get WxPayConfig and Certifiction File
  139. WxPayConfigAndCertification wxPayConfigAndCertification = null;// ConfigHelper.WxConfigInstances(currentBuId, configServiceUrl, wxPayConfigName);
  140. //if (wxPayConfigAndCertification != null)
  141. //{
  142. // input.Config = wxPayConfigAndCertification.ConfigInfo?.Config;
  143. // order.Certification = wxPayConfigAndCertification.CertificationInfo?.Certification;
  144. //}
  145. var genericResponseWeChat = order.IsForRefund ?
  146. await processor.Return(order).ConfigureAwait(false) :
  147. await processor.Process(order).ConfigureAwait(false);
  148. var wechatResponse = genericResponseWeChat.WeChatResponse;
  149. if (order.TradeStatus == TradeStatusEnum.SUCCESS)
  150. {
  151. returnCode = ClientSideReturnCode.OK;
  152. }
  153. else
  154. {
  155. returnCode = ClientSideReturnCode.PAY_ERROR;
  156. if (!order.IsForRefund)
  157. {
  158. logger.LogInformation("Mark order(WeChat): " + order.ToFullJsonLogString() + " to cancel since returnCode is: " + returnCode);
  159. processor.Cancel(order);
  160. }
  161. }
  162. order.PayResults.Add(new PaymentOrderPayResult()
  163. {
  164. PaymentResultCode = ((int)returnCode).ToString(CultureInfo.InvariantCulture),
  165. PaymentResultMessage = returnCode.ToString(),
  166. PaymentResultErrorDetail = wechatResponse.IsSet("err_code") ? wechatResponse.GetValue("err_code").ToString() : "",
  167. PaymentResultRawResult = wechatResponse.ToXml()
  168. });
  169. break;
  170. }
  171. case "ALI_SCAN":
  172. {
  173. //https://opendocs.alipay.com/open/54/103419
  174. try
  175. {
  176. // 1. 创建IAopClient实例
  177. Aop.Api.IAopClient client = new Aop.Api.DefaultAopClient(
  178. "https://openapi.alipay.com/gateway.do",
  179. "2019091767145019", //请更换为您的AppId
  180. "MIIEowIBAAKCAQ ... ...", //请更换为您的PKCS1格式的应用私钥
  181. "json", "1.0", "RSA2",
  182. "utf-8", //请更换为您使用的字符集编码,推荐采用utf-8
  183. false, new Aop.Api.CertParams
  184. {
  185. //请更换为您的应用公钥证书文件路径
  186. AlipayPublicCertPath = "/home/foo/alipayCertPublicKey_RSA2.crt",
  187. //请更换您的支付宝公钥证书文件路径
  188. AppCertPath = "/home/foo/appCertPublicKey_2019090366875133.crt",
  189. //请更换为支付宝根证书文件路径
  190. RootCertPath = "/home/foo/alipayRootCert.crt"
  191. });
  192. // 2. 创建使用的Open API对应的Request请求对象
  193. Aop.Api.Request.AlipayOpenOperationOpenbizmockBizQueryRequest request = GetAlipayRequest();
  194. // 3. 发起请求并处理响应
  195. Aop.Api.Response.AlipayOpenOperationOpenbizmockBizQueryResponse response = client.CertificateExecute(request);
  196. if (!response.IsError)
  197. {
  198. Console.WriteLine("调用成功。");
  199. }
  200. else
  201. {
  202. Console.WriteLine("调用失败,原因:" + response.Msg + "," + response.SubMsg);
  203. }
  204. }
  205. catch (Exception e)
  206. {
  207. Console.WriteLine("调用遭遇异常,原因:" + e.Message);
  208. throw e;
  209. }
  210. break;
  211. }
  212. case "ALL_IN_SCAN":
  213. var v1Processor = new TongLianAllInPayV1Processor(services);
  214. var tongLianPayConfigV1 = this.appConfig.TongLianPayV1Config;
  215. if (tongLianPayConfigV1 != null)
  216. order.Config = tongLianPayConfigV1.Config;
  217. var v1GenericResponse = order.IsForRefund ?
  218. await v1Processor.Return(order).ConfigureAwait(false) :
  219. await v1Processor.Process(order).ConfigureAwait(false);
  220. var v1Response = v1GenericResponse.AllInPayResponse;
  221. if (v1Response != null && order.TradeStatus == TradeStatusEnum.SUCCESS)
  222. {
  223. returnCode = ClientSideReturnCode.OK;
  224. }
  225. else
  226. {
  227. returnCode = ClientSideReturnCode.PAY_ERROR;
  228. if (!order.IsForRefund)
  229. {
  230. logger.LogInformation("Mark order(AllInpay): " + order.ToFullJsonLogString() + " to cancel since payment returnCode is: " + returnCode);
  231. await v1Processor.Cancel(order);
  232. }
  233. }
  234. order.PayResults.Add(new PaymentOrderPayResult()
  235. {
  236. BillNumber = order.BillNumber,
  237. PaymentResultCode = ((int)returnCode).ToString(CultureInfo.InvariantCulture),
  238. PaymentResultMessage = returnCode.ToString(),
  239. PaymentResultErrorDetail = v1Response != null && v1Response.ContainsKey("retmsg") ? v1Response["retmsg"] : "",
  240. PaymentResultRawResult = v1Response != null && v1Response.ContainsKey("errmsg") ? v1Response["errmsg"] : ""
  241. });
  242. break;
  243. case "ALL_IN_SCAN_V2":
  244. {
  245. var v2Processor = new TongLianAllInPayV2Processor(services);
  246. TongLianPayConfigAndCertificationV2 tongLianPayConfig = this.appConfig.TongLianPayV2Config;
  247. if (tongLianPayConfig != null)
  248. order.Config = tongLianPayConfig.Config;
  249. var v2GenericResponse = order.IsForRefund ?
  250. await v2Processor.Return(order).ConfigureAwait(false) :
  251. await v2Processor.Process(order).ConfigureAwait(false);
  252. var v2Response = v2GenericResponse.AllInPayResponseV2;
  253. if (order.TradeStatus == TradeStatusEnum.SUCCESS)
  254. {
  255. returnCode = ClientSideReturnCode.OK;
  256. }
  257. else
  258. {
  259. returnCode = ClientSideReturnCode.PAY_ERROR;
  260. if (!order.IsForRefund)
  261. {
  262. logger.LogInformation($"Mark an order(AllInpayV2) to cancel since payment returnCode is: { returnCode}, the raw order is: { order.ToFullJsonLogString() }");
  263. await v2Processor.Cancel(order);
  264. }
  265. }
  266. order.PayResults.Add(new PaymentOrderPayResult()
  267. {
  268. PaymentResultCode = ((int)returnCode).ToString(CultureInfo.InvariantCulture),
  269. PaymentResultMessage = returnCode.ToString(),
  270. PaymentResultErrorDetail = v2Response.bizMsg + "|" + (v2Response.payStatusMsg ?? ""),
  271. PaymentResultRawResult = v2Response.bizCode
  272. });
  273. break;
  274. }
  275. default:
  276. {
  277. logger.LogError("Unsupport PaymentMethod: " + order.PaymentMethod + " received.");
  278. throw new ArgumentException("Unsupport PaymentMethod: " + order.PaymentMethod);
  279. }
  280. }
  281. }
  282. catch (Exception ex)
  283. {
  284. logger.LogError("Error occured in StartPayment, detail: " + ex);
  285. order.PayResults.Add(new PaymentOrderPayResult()
  286. {
  287. PaymentResultCode = "XX4XX4XX",
  288. PaymentResultMessage = "订单支付失败于本地",
  289. PaymentResultErrorDetail = "本地内部错误"
  290. });
  291. }
  292. return order;
  293. }
  294. }
  295. }