Apple Pay 支付集成
交易步骤:
1、浏览并选购商品:用户通过手机客户端与商户系统交互浏览选购商品,客户端向商户系统发送
购买商品请求数据。
2、生成并推送订单信息请求数据:商户系统根据选购商品请求数据生成订单数据集,把构造完成
的订单信息数据集合按照移动支付系统的订单信息推送接口,通过商户后台提交(POST)的方式传递
给移动支付系统。
3、移动支付系统对请求数据进行处理:移动支付系统得到这些集合后,会先进行安全校验等验证,
一系列验证通过后便会处理这次发送过来的数据请求。
4、返回交易流水号:移动支付系统返回商户系统交易流水号应答。
5、转发交易流水号:商户系统转发交易流水号至手机客户端。
6、调用支付控件,发起支付请求数据:手机客户端收到交易流水号等要素,调起支付控件,用户
输入支付信息后,客户端按照移动支付系统的支付接口规则组装并发送支付请求数据至移动支付系统。
7、移动支付系统对请求数据进行处理:移动支付系统得到这些集合后,会先进行安全校验等验证,
一系列验证通过后便会处理这次发送过来的数据请求。
8、返回支付结果:移动支付系统返回结果至手机客户端。
9、返回支付结果:支付控件返回商户客户端支付结果(目前为了兼容控件第一期,未采用frontEndUrl
方式来返回结果)。
10、移动支付系统后台异步返回处理的结果数据:对于成功处理完成的交易,移动支付系统服务器
主动发起通知,调用商户在请求时设定好的后台通知地址路径(参数backEndUrl), 把支付结果数据反
馈给商户。
11 商户对获取的返回结果数据进行处理:商户在前台通知处理页面(参数frontEndUrl 指定页面)
或服务器后台通知页面(参数backEndUrl 指定页面)获取移动支付返回的结果数据后,可以结合自身
网站的业务逻辑进行数据处理(如:订单更新等操作)。以后台通知为准。若未收到后台通知,需要发
起交易信息查询请求。相关说明:
商户后台接收到移动支付系统支付成功通知交易后,需返回全渠道系统后台确认已收到应答。
生成TN
- /// <summary>
- /// ApplePay支付接口服务
- /// </summary>
- [RoutePrefix("api/applepay")]
- public class ApplePayController : ApiController
- {
- private static readonly Logger logger = LogManager.GetCurrentClassLogger();
- /// <summary>
- /// ApplePay支付接口服务
- /// </summary>
- private readonly IApplePayService _applePayService;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="applePayService">ApplePay支付接口服务</param>
- public ApplePayController(IApplePayService applePayService)
- {
- _applePayService = applePayService;
- }
- /// <summary>
- /// 生成交易流水号[即TN]
- /// </summary>
- /// <param name="payTradeNo">参数</param>
- /// <returns></returns>
- [HttpPost]
- [Route("generate_trade_no")]
- public async Task<IHttpActionResult> GenerateTradeNoAsync(PayPalData payPal)
- {
- var data = await _applePayService.GenerateTradeNoAsync(payPal);
- return Ok(new { IsError = data.IsError, Msg = data.Msg, Data = data.Data });
- }
- }
- /// <summary>
- /// 生成交易流水号[即TN]
- /// </summary>
- /// <param name="payPal">参数</param>
- /// <returns></returns>
- public async Task<WebAPIResponse> GenerateTradeNoAsync(PayPalData payPal)
- {
- try
- {
- var param = new Dictionary<string, string>();
- //版本号
- param["version"] = "5.0.0";
- //编码方式
- param["encoding"] = "UTF-8";
- //交易类型
- param["txnType"] = "";
- //交易子类
- param["txnSubType"] = "";
- //业务类型
- param["bizType"] = "";
- //签名方法
- param["signMethod"] = "";
- //渠道类型
- param["channelType"] = "";
- //接入类型
- param["accessType"] = "";
- //前台通知地址
- //param["frontUrl"] = SDKConfig.FrontUrl;
- //后台通知地址
- param["backUrl"] = SDKConfig.BackUrl;
- //交易币种
- param["currencyCode"] = "";
- //商户号
- param["merId"] = SDKConfig.MerId;
- //商户订单号,8-32位数字字母,不能含“-”或“_”
- param["orderId"] = payPal.OutTradeNO;
- //订单发送时间,参考取法: DateTime.Now.ToString("yyyyMMddHHmmss")
- param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");
- //交易金额,单位分
- param["txnAmt"] = payPal.TotalFee;
- //请求方保留域,透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据
- param["reqReserved"] = payPal.Resv;
- //签名
- AcpService.Sign(param, System.Text.Encoding.UTF8);
- string url = SDKConfig.AppRequestUrl;
- var rspData = AcpService.Post(param, url, System.Text.Encoding.UTF8);
- if (rspData.Count == )
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "请求失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- if (!AcpService.Validate(rspData, System.Text.Encoding.UTF8))
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "商户端验证返回报文签名失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- string respcode = rspData["respCode"];
- if (respcode != "")
- {
- logger.Error("失败:" + rspData["respMsg"] + "。<br>\n");
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "失败:" + rspData["respMsg"] + "。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = false,
- Msg = "后续请将此tn传给手机开发,由他们用此tn调起控件后完成支付",
- Data = rspData["tn"]
- };
- }).ContinueWith(t => t.Result);
- }
- catch (Exception ex)
- {
- logger.Fatal(ex, "GenerateTradeNoAsync Exception: " + ex.Message);
- return new WebAPIResponse
- {
- IsError = false,
- Msg = "GenerateTradeNoAsync Exception: " + ex.Message,
- Data = string.Empty
- };
- }
- }
异步通知
- /// <summary>
- /// 苹果支付
- /// </summary>
- public class ApplePayController : Controller
- {
- private static readonly Logger logger = LogManager.GetCurrentClassLogger();
- /// <summary>
- /// 支付服务
- /// </summary>
- private readonly IPayPalService _payPalService;
- /// <summary>
- /// ApplePay支付服务
- /// </summary>
- private readonly IApplePayService _applePayService;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="payPalService">整合支付服务</param>
- /// <param name="applePayService">ApplePay支付服务</param>
- public ApplePayController(IPayPalService payPalService, IApplePayService applePayService)
- {
- _payPalService = payPalService;
- _applePayService = applePayService;
- }
- /// <summary>
- /// ApplePay支付异步回调
- /// </summary>
- /// <returns></returns>
- public async Task<ActionResult> Notify()
- {
- var param = new Dictionary<string, string>();
- //param = @"accessType=0&bizType=000301&certId=69597475696¤cyCode=156&encoding=UTF-8&merId=301310048990295&orderId=000098393411&queryId=201512280008212498278&reqReserved=041601&respCode=00&respMsg=Success!&respTime=20151228000822&settleAmt=10400&settleCurrencyCode=156&settleDate=1228&traceNo=249827&traceTime=20151228000821&txnAmt=10400&txnSubType=01&txnTime=20151228000821&txnType=01&version=3.0.0&signature=cQHM+yW2G34Clkv5zm56XDnd8VhnC1aly5kmjfQ0mUyZb9mN79DJPvC5a98GXwPn7EBn7e1DUNs0J8Nr6FGIXc4A50QltH6njNsiSZMtIR6wlwPqqhga/AprJ4JulL2h6uv0ITPw9b5oHZx81oMpblzM+ZTamP8ZMWmH65ctrl4Qog+U09bXIGOEnezwHYG7Nz8/TumZeSch0TvR0S/vw61u6u45e81FmZ1oarE165QZ+jIfkiRnqI7/iGy4Xa2iSV7qCnNusTgMUg0JVZroBEfr5rA60+0FEzOFzLvae8yVLbsJ454hB4IyaltX34gQJAjpgBZ66dvJo2lGMCe1QQ==".ConvertStringToDictionary();
- var item = Request.Form.AllKeys;
- for (int i = ; i < item.Length; i++)
- {
- param.Add(item[i], Request.Form[item[i]]);
- }
- //判断是否有带返回参数
- if (param.Count <= )
- {
- return Json(new { IsError = true, ErrorMsg = "NO DATA !!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
- }
- logger.Info("【 ApplePayController Notify SDKUtil.ConvertDictionaryToString : 请求报文=[" + param.ConvertDictionaryToString() + "]\n");
- //验证签名
- if (!AcpService.Validate(param, System.Text.Encoding.UTF8))
- {
- logger.Error("ApplePayController Notify VERIFY FAIL SDKUtil.ConvertDictionaryToString : " + param.ConvertDictionaryToString());
- return Json(new { IsError = true, ErrorMsg = "DATA VERIFY FAIL !!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
- }
- //验证数据 [重要!!!!]
- if (!param.ContainsKey("orderId") || !param.ContainsKey("respCode") || !param["respCode"].Equals(""))
- {
- return Json(new { IsError = true, ErrorMsg = "DATA VERIFY FAIL !!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
- }
- //查询支付参数【确保来源是合并支付】
- var payPal = _payPalService.Query(param["orderId"]);
- if (payPal.IsNull() || payPal.NotifyUrl.IsNullOrEmpty() || payPal.OutTradeNO.IsNullOrEmpty())
- {
- logger.Error("ApplePayController Notify NOT FIND ORDER SDKUtil.ConvertDictionaryToString : " + param.ConvertDictionaryToString());
- return Json(new { IsError = true, ErrorMsg = "NOT FIND ORDER !!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
- }
- //记录日志
- payPal.TradeNO = param["queryId"];
- //支付金额分转换元
- payPal.TotalFee = (Convert.ToInt32(param["txnAmt"]) / 100M).ToStringSafe();
- payPal.Service = payPal.Service + "_Notify";
- payPal.CreateTime = DateTime.Now;
- payPal.Memo = param.ConvertDictionaryToJson();
- payPal.Resv = param["reqReserved"];
- payPal.Memo = param.ConvertDictionaryToJson();
- bool flag = _payPalService.Save(payPal);
- if (!flag)
- {
- logger.Error("ApplePayController Notify SAVE PayPalData FAIL SDKUtil.ConvertDictionaryToString : " + param.ConvertDictionaryToString());
- return Json("DATA SAVE PayPalData FAIL !!!", JsonRequestBehavior.AllowGet);
- }
- try
- {
- //调用业务接口
- logger.Info("ApplePayController PostJsonAsync req: " + payPal.SerializeJson(System.Text.Encoding.UTF8));
- var data = await payPal.NotifyUrl.PostJsonAsync(payPal).ReceiveJson<WebAPIResponse>();
- logger.Info("ApplePayController PostJsonAsync resp: " + data.SerializeJson(System.Text.Encoding.UTF8) + " 】");
- if (data.IsError)
- {
- logger.Fatal("!!! ApplePayController PostJsonAsync : " + payPal.SerializeJson(System.Text.Encoding.UTF8));
- return Json("DATA PostJsonAsync FAIL FAIL !!!", JsonRequestBehavior.AllowGet);
- }
- }
- catch (Exception ex)
- {
- logger.Fatal(ex, "ApplePayController PostJsonAsync Exception : " + ex.Message + " payPal : " + payPal.SerializeJson(System.Text.Encoding.UTF8));
- return Content("exception: " + ex.Message);
- }
- return await Task.Run(() =>
- {
- return Content("success");
- }).ContinueWith(t => t.Result);
- }
- }
交易状态查询
- /// <summary>
- /// 交易状态查询
- /// </summary>
- /// <param name="orderNo">订单号</param>
- /// <returns></returns>
- public async Task<WebAPIResponse> QueryTradeStatusAsync(string orderNo)
- {
- try
- {
- var param = new Dictionary<string, string>();
- //版本号
- param["version"] = "5.0.0";
- //编码方式
- param["encoding"] = "UTF-8";
- //证书ID
- param["certId"] = CertUtil.GetSignCertId();
- //签名方法
- param["signMethod"] = "";
- //交易类型
- param["txnType"] = "";
- //交易子类
- param["txnSubType"] = "";
- //业务类型
- param["bizType"] = "";
- //接入类型
- param["accessType"] = "";
- //渠道类型
- param["channelType"] = "";
- //商户号
- param["merId"] = SDKConfig.MerId;
- //商户订单号,8-32位数字字母,不能含“-”或“_”
- param["orderId"] = orderNo;
- //订单发送时间,参考取法: DateTime.Now.ToString("yyyyMMddHHmmss")
- param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");
- // 签名
- AcpService.Sign(param, System.Text.Encoding.UTF8);
- string url = SDKConfig.SingleQueryUrl;
- var rspData = AcpService.Post(param, url, System.Text.Encoding.UTF8);
- if (rspData.Count == )
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "请求失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- if (!AcpService.Validate(rspData, System.Text.Encoding.UTF8))
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "商户端验证返回报文签名失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- string respcode = rspData["respCode"];
- if (respcode != "")
- {
- logger.Error("失败:" + rspData["respMsg"] + "。<br>\n");
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "失败:" + rspData["respMsg"] + "。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- string origRespCode = rspData["origRespCode"];
- if (origRespCode != "")
- {
- logger.Error("稍后查询:" + rspData["origRespMsg"] + "。<br>\n");
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "稍后查询:" + rspData["origRespMsg"] + "。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = false,
- Msg = "交易成功!!!",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- catch (Exception ex)
- {
- logger.Fatal(ex, "QueryTradeStatusAsync Exception: " + ex.Message);
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "QueryTradeStatusAsync Exception: " + ex.Message,
- Data = string.Empty
- };
- }
- }
退货
- /// <summary>
- /// 退货交易
- /// </summary>
- /// <param name="orderNo">订单号</param>
- /// <param name="origQryId">原消费的queryId</param>
- /// <param name="txnAmt">交易金额</param>
- /// <returns></returns>
- public async Task<WebAPIResponse> RefundTradeNoAsync(string orderNo, string origQryId, string txnAmt)
- {
- try
- {
- var param = new Dictionary<string, string>();
- //商户号
- param["merId"] = SDKConfig.MerId;
- //版本号
- param["version"] = "5.0.0";
- //编码方式
- param["encoding"] = "UTF-8";
- //签名方法
- param["signMethod"] = "";
- //交易类型
- param["txnType"] = "";
- //交易子类
- param["txnSubType"] = "";
- //业务类型
- param["bizType"] = "";
- //接入类型
- param["accessType"] = "";
- //渠道类型
- param["channelType"] = "";
- //后台通知地址
- //param["backUrl"] = SDKConfig.BackUrl;
- //商户订单号,8-32位数字字母,不能含“-”或“_”
- param["orderId"] = orderNo;
- //原消费的queryId,可以从查询接口或者通知接口中获取
- param["origQryId"] = origQryId;
- //订单发送时间
- param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");
- //交易金额,退货总金额需要小于等于原消费
- param["txnAmt"] = txnAmt;
- //请求方保留域,透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据
- //param["reqReserved"] = "透传信息";
- // 签名
- AcpService.Sign(param, System.Text.Encoding.UTF8);
- string url = SDKConfig.BackTransUrl;
- var rspData = AcpService.Post(param, url, System.Text.Encoding.UTF8);
- if (rspData.Count == )
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "请求失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- if (!AcpService.Validate(rspData, System.Text.Encoding.UTF8))
- {
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "商户端验证返回报文签名失败。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- string respcode = rspData["respCode"];
- if (respcode != "")
- {
- logger.Error("失败:" + rspData["respMsg"] + "。<br>\n");
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "失败:" + rspData["respMsg"] + "。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- return await Task.Run(() =>
- {
- return new WebAPIResponse
- {
- IsError = false,
- Msg = "订单号:" + orderNo + " 退货受理成功。<br>\n",
- Data = string.Empty
- };
- }).ContinueWith(t => t.Result);
- }
- catch (Exception ex)
- {
- logger.Fatal(ex, "RefundTradeNoAsync Exception: " + ex.Message);
- return new WebAPIResponse
- {
- IsError = true,
- Msg = "RefundTradeNoAsync Exception: " + ex.Message,
- Data = string.Empty
- };
- }
- }
Apple Pay 支付集成的更多相关文章
- 集成 Apple Pay
作者感言 在中秋过后终于把国内的三大支付平台SDK集成都搞定了, 现在我们终于可以来研究Apple自家的支付Apple Pay最后:如果你有更好的建议或者对这篇文章有不满的地方, 请联系我, 我会参考 ...
- iOS App集成Apple Pay教程(附示例代码)
苹果在本周一发布了iOS 8.1版本,并正式开放了Apple Pay支付系统.Apple Pay是一个基于NFC的支付系统,不久将被数以万计的线下零售商店予以支持.即便这项科技并不是彻底的突破性进展, ...
- Swift # Apple Pay集成
苹果正式开放了Apple Pay支付系统.Apple Pay是一个基于NFC的支付系统,不久将被数以万计的线下零售商店予以支持.即便这项科技并不是彻底的突破性进展,但它足以推动许多公司和零售商来支持这 ...
- 【转】iOS开发 -- Apple Pay
技术博客原地址:http://www.cnblogs.com/dashunzi/p/ApplePay.html#top 原技术博客中有源码和视频,有感兴趣的朋友可以研究一下! 一.什么是Apple P ...
- 开发apple pay碰到的问题总结
本来想简单总结一下Apple Pay 开发过程中的几个问题, 结果被下面这篇文章全碰上了, 干脆全文转载, 作者对相关资源整理得比较详细, 比较有参考价值 总的来说, 我们做过 APNs 推送的话, ...
- iOS开发 Apple Pay
一.什么是Apple Pay? 1. 概念 Apple Pay,简单来说, 就是一种移动支付方式.通过Touch ID/ Passcode,用户可使用存储在iPhone 6, 6p等设备上的信用卡和借 ...
- Apple Pay的实现
首先是搜到的大神写的全套知识点:http://www.jianshu.com/p/8d7b86f1d142 http://www.cnblogs.com/dashunzi/archive/2016/0 ...
- 装B技能GET起来!Apple Pay你会用了吗?
科技圈儿有一个自带光环的品牌 它每次一有任何动静 不用宣传 也不用刻意营销 消息还是能传天下 2月18日 你敢说你的朋友圈儿没有被下面这个词儿刷屏? Apple Pay 这不,我就跟着凑凑热闹,开个小 ...
- Apple Pay(转)
Apple Pay 是在 iOS 8 中第一次被介绍,它可以为你的应用中的实体商品和服务,提供简单.安全.私密的支付方式.它使得用户支付起来非常简便,只需按一下指纹就可以授权进行交易. Apple P ...
随机推荐
- 安卓 build/core/Makefile 以及main.mk
android make 系统总共分为四层 arch board device product 在各个字android.mk文件中引用的定义都存放在./build/core/下!比如android.m ...
- Linux中的sleep、usleep、nanosleep、poll和select
在进行Linux C/C++编程时,可调用的sleep函数有好多个,那么究竟应当调用哪一个了?下表列出了这几个函数间的异同点,可作为参考: 性质 精准度 线程安全 信号安全 sleep libc库函数 ...
- winSockets编程(三)最简单的C/S形式
功能:向服务器端发送一个字符串,属于最简易的形式,一共需要4个主要步骤,初始化-建立套接字-连接服务器-发送数据 /****************************************** ...
- spring 事务的传播特性
1.声明式事物中,一个类serviceA的方法test1()调用另一个类serviceB的方法test2() 要是serviceB的test2()事务配置在xml文件中为REQUIRED,又在此方法上 ...
- 在64位win10下安装32位oracle
乱试,居然搞定了. 1 下载个32位的驱动包,解压拷贝到C:\Windows\SysWOW64 其实这样就能用了:)不过如果人家只提供一个tsname的文件给你,或某些程序跑配置的,读取的配置是一个t ...
- FPGA之初认识
什么是FPGA FPGA(Field-Programmable Gate Array),即现场可编程门阵列 .看到编程两个字码农就笑了,不就是编程嘛,那可是我们的强项 .且慢,此编程非彼编程 .一定要 ...
- 6、GNU makefile工程管理学习的一个例子
在之前我们已经学习了一个文件的编译过程,但是做过项目的都知道,一个工程中的源文件不计其数,其按类型.功能.模块会分别放在若干个目录中,而这些文件如何编译就需要有一个编译规则,虽然现在很多大型的项目都是 ...
- MAC系统下用Idea创建spring boot工程 基于maven
1.创建项目 打开idea编辑器,选择file -> new -> project 点击next 依次填入group,artifact 填写完成之后再点击“next” 根据自己的需求在最 ...
- How do I convert an IIR filter into a FIR filter in digital signal processing?
Maybe you were asking if there is some kind of design tool allowing to convert an IIR filter into an ...
- Java基础巩固——反射
什么是反射 反射机制就是指程序运行时能够获取自身的信息.在Java中,只要给出类的名字,就可以通过反射机制来获取类的信息 哪里用的到反射机制 在jdbc中就是使用的反射来实例化对象,比如:Class. ...