云闪付支付功能流程

14 篇文章 0 订阅

1:云闪付小程序:需要注意一点,他跟支付宝,微信小程序不一样,他没有自己的原生页面 ,是直接在云闪付的小程序后台直接配置跳转站点。如图:

在小程序首页链接上面配置 需要访问的H5站点就可以,不想微信小程序需要有自己的原生页面,然后需要发布到微信的服务器去。

云闪付的小程序的前端也是用户自己的服务器上管理。不需要提交到平台服务器上。

 

2:云闪付支付功能

官网文档:文档中心-中国银联开放平台   https://open.unionpay.com/tjweb/doc/index#skill

支付方式有:这里选择 手机支付控件(含安卓Pay)该支付方式可以用于 APP 手机客户端  和 云闪付小程序

如果是网站页面就需要用手机网页支付,  

手机支付控件(含安卓Pay) 支付是需要唤醒 云闪付 平台的支付控件。如图:

下面那个唤醒页面是云闪付平台的,如果是网页形式是无法唤醒。需要转到到云闪付app平台。跟支付,京东一样。

 

3:这里主要说明   手机支付控件(含安卓Pay)  支付流程跟方式

  注意一:这里默认已经开通了商户号,商户号已经开通了 手机支付控件(含安卓Pay) 该支付方式

注意二:SecureKey  ,signCertPwd 签名秘钥 需要提前准备

注意三:需要下载 签名证书  acp_prod_sign.pfx :一般放入 D/certs 中

 

流程:

第一步:前端点击 云闪付支付 ,获取订单号:orderid  作为参数调用后端API服务。

如下:其实唤醒云闪付的支付功能,只需要有tn单号就可以,tn单号获取方式就是调用平台API接口。https://gateway.95516.com/gateway/api/appTransReq.do

第二步:后端代码:

一个方方法,这个是为了方便后面有其他支付,0是正常订单,  给 早餐,会议室 预留接口

入参:  订单号:

出参: tn单号--云闪付API接口返回的参数

获取订单信息

具体调用API比较复杂:所以这里不做详细解决,在官网文档里没有下载的demo,主要就是参数获取,签名方法

public static CloudPayResponse QueryTN(EnumSetting.OrderType orderType, string orderID, string txnAmt, string txnTime)
        {
            /**
                * 重要:联调测试时请仔细阅读注释!
                * 
                * 产品:跳转网关支付产品<br>
                * 交易:消费:前台跳转,有前台通知应答和后台通知应答<br>
                * 日期: 2015-09<br>
                * 版本: 1.0.0
                * 版权: 中国银联<br>
                * 说明:以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己需要,按照技术文档编写。该代码仅供参考,不提供编码性能规范性等方面的保障<br>
                * 提示:该接口参考文档位置:open.unionpay.com帮助中心 下载  产品接口规范  《网关支付产品接口规范》,<br>
                *              《平台接入接口规范-第5部分-附录》(内包含应答码接口规范,全渠道平台银行名称-简码对照表)<br>
                *              《全渠道平台接入接口规范 第3部分 文件接口》(对账文件格式说明)<br>
                * 测试过程中的如果遇到疑问或问题您可以:1)优先在open平台中查找答案:
                * 							        调试过程中的问题或其他问题请在 https://open.unionpay.com/ajweb/help/faq/list 帮助中心 FAQ 搜索解决方案
                *                             测试过程中产生的7位应答码问题疑问请在https://open.unionpay.com/ajweb/help/respCode/respCodeList 输入应答码搜索解决方案
                *                          2) 咨询在线人工支持: open.unionpay.com注册一个用户并登陆在右上角点击“在线客服”,咨询人工QQ测试支持。
                * 交易说明:1)以后台通知或交易状态查询交易确定交易成功,前台通知不能作为判断成功的标准.
                *       2)交易状态查询交易(Form_6_5_Query)建议调用机制:前台类交易建议间隔(5分、10分、30分、60分、120分)发起交易查询,如果查询到结果成功,则不用再查询。(失败,处理中,查询不到订单均可能为中间状态)。也可以建议商户使用payTimeout(支付超时时间),过了这个时间点查询,得到的结果为最终结果。
                */
            Loger.Write($"云闪付支付接口QueryTN--开始调用云闪付API接口 订单号:"+orderID, LogMessageType.Error);
            CloudPayResponse result = new CloudPayResponse();
            Dictionary<string, string> param = new Dictionary<string, string>();

            //以下信息非特殊情况不需要改动
            param["version"] = SDKConfig.Version;//版本号
            param["encoding"] = "UTF-8";//编码方式
            param["txnType"] = "01";//交易类型
            param["txnSubType"] = "01";//交易子类
            param["bizType"] = "000201";//业务类型
            param["signMethod"] = SDKConfig.SignMethod;//签名方法
            param["channelType"] = "08";//渠道类型
            param["accessType"] = "0";//接入类型
           
            //param["frontUrl"] = SDKConfig.FrontUrl;  //前台通知地址      
            param["backUrl"] = SDKConfig.BackUrl;  //后台通知地址
            param["currencyCode"] = "156";//交易币种

            //TODO 以下信息需要填写
            param["merId"] = SDKConfig.MerId;//商户号,请改自己的测试商户号,此处默认取demo演示页面传递的参数
            param["orderId"] = orderID;//商户订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数,可以自行定制规则
            param["txnTime"] = txnTime;//订单发送时间,格式为YYYYMMDDhhmmss,取北京时间,此处默认取demo演示页面传递的参数,参考取法: DateTime.Now.ToString("yyyyMMddHHmmss")
            param["txnAmt"] = txnAmt;//交易金额,单位分,此处默认取demo演示页面传递的参数

            // 请求方保留域,
            // 透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据。
            // 出现部分特殊字符时可能影响解析,请按下面建议的方式填写:
            // 1. 如果能确定内容不会出现&={}[]"'等符号时,可以直接填写数据,建议的方法如下。
            //param["reqReserved"] = "透传信息1|透传信息2|透传信息3";
            // 2. 内容可能出现&={}[]"'符号时:
            // 1) 如果需要对账文件里能显示,可将字符替换成全角&={}【】“‘字符(自己写代码,此处不演示);
            // 2) 如果对账文件没有显示要求,可做一下base64(如下)。
            //    注意控制数据长度,实际传输的数据长度不能超过1024位。
            //    查询、通知等接口解析时使用System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(reqReserved))解base64后再对数据做后续解析。
            //param["reqReserved"] = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("任意格式的信息都可以"));

            //TODO 其他特殊用法请查看 pages/api_05_app/special_use_purchase.htm
     
            AcpService.Sign(param, System.Text.Encoding.UTF8);  // 签名
            string url = SDKConfig.FrontTransUrl;

            Dictionary<String, String> rspData = CloudHttpClient.Post(param, url, System.Text.Encoding.UTF8);
            //Response.Write(DemoUtil.GetPrintResult(url, param, rspData));
            if (rspData.Count != 0)
            {
                //AppLog.Write("云闪付签名结果2:" + rspData, LogMessageType.Debug);
                //if (Validate(rspData, System.Text.Encoding.UTF8))
                //{
                    //Response.Write("商户端验证返回报文签名成功。<br>\n");
               string respcode = rspData["respCode"]; //其他应答参数也可用此方法获取
                if ("00" == respcode)
                {
                    Loger.Write($"云闪付支付接口QueryTN成功---订单号:{orderID} : TN流水号:{rspData["tn"]}", LogMessageType.Info);
                    //成功
                    //TODO
                    result.Result = "0";
                    result.Message = "成功接收tn";
                    result.TransactionNo = rspData["tn"];
                    result.purchaseOrderNo = orderID;
                }
                else
                {
                    //其他应答码做以失败处理
                    //TODO
                    //Response.Write("失败:" + rspData["respMsg"] + "。<br>\n");
                    //result.Result = "1";
                    //result.Message = "失败:" + rspData["respMsg"];
                }
                //}
                //else
                //{
                //    //Response.Write("商户端验证返回报文签名失败。<br>\n");
                //    //result.Result = "1";
                //    //result.Message = "商户端验证返回报文签名失败";
                //    //AppLog.Write(string.Format("商户端验证返回报文签名失败。<br>\n"), LogMessageType.Info);
                //}
            }
            else
            {
                Loger.Write($"云闪付支付接口QueryTN失败---订单号:{orderID}", LogMessageType.Error);
                //Response.Write("请求失败<br>\n");
                result.Result = "1";
                result.Message = "请求失败,没有获取到TN单号";
            }
            return result;
        }

第三步:获取到云闪付 返回的tn单号,在前端调用  云闪付的 唤醒控件,需要引用一下云闪付的js:

这个js需要在index的页面去引用。在<head>  标签里面

     <script src="https://open.95516.com/s/open/js/upsdk.js" type="text/javascript"></script>  

 var tnNo=res.Data.TransactionNo;
                upsdk.pluginReady (function(){
                upsdk.pay({
                      tn: tnNo,
                      success: function(){
                        console.log("支付成功!");
                          // 支付成功, 开发者执行后续操作。
                      },
                      fail: function(err){
                          console.log("支付失败!");
                          // 支付失败, err.msg 是失败原因描述, 比如TN号不合法, 或者用户取消了交易 等等。
                      }
                  });

第四步:回调方法回写订单状态

这里需要注意

1:取参数信息: NameValueCollection coll = Request.Form;
                             string[] requestItem = coll.AllKeys;

2:验签校验

 if (AcpService.Validate(resData, System.Text.Encoding.UTF8))

{

  注意这里需要区分版本号,一般5.0.0 跟其他版本号是需要区分出来的,目前是使用5.1.0版本。所以不需要用到 certsId 。但是还是需要去读取验签证书信息。

}

protected void Page_Load(object sender, EventArgs e)
        {
            //log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());
            Logger.Log.Info("==============云闪付支付回调开始============");
            // **************演示后台接收银联返回报文交易结果展示***********************
            if (Request.HttpMethod == "POST")
            {
                // 使用Dictionary保存参数
                Dictionary<string, string> resData = new Dictionary<string, string>();
 
                NameValueCollection coll = Request.Form;
                string[] requestItem = coll.AllKeys;
                for (int i = 0; i < requestItem.Length; i++)
                {
                    resData.Add(requestItem[i], Request.Form[requestItem[i]]);
                    Logger.Log.Info(string.Format("{0},{1}", requestItem[i], Request.Form[requestItem[i]]));
                }
                 Logger.Log.Info("回调结果5:");
                //商户端根据返回报文内容处理自己的业务逻辑 ,DEMO此处只输出报文结果
                StringBuilder builder = new StringBuilder();
                Logger.Log.Info("receive back notify: " + SDKUtil.CreateLinkString(resData, false, true, System.Text.Encoding.UTF8));

                Logger.Log.Info(string.Format("回调结果:{0}", resData.ToString()));
                if (AcpService.Validate(resData, System.Text.Encoding.UTF8))
                {
                     Logger.Log.Info(string.Format("验证结果:{0}", resData.ToString()));
                    builder.Append("<tr><td width=\"30%\" align=\"right\">商户端验证银联返回报文结果</td><td>验证签名成功.</td></tr>");

                    string respcode = resData["respCode"]; //00、A6为成功,其余为失败。其他字段也可按此方式获取。
                    Logger.Log.Info(string.Format("验证结果1:{0}", respcode));
                    string reserved = "";
                    if (resData.ContainsKey("reserved"))
                    {
                        reserved = resData["reserved"];
                    }
                    //对reserved值进行解析
                    if (!String.IsNullOrEmpty(reserved))
                    {
                        reserved = SecurityUtil.DecryptFlashPayData(reserved, System.Text.Encoding.UTF8);
                    }

                    if (respcode == "00" || respcode == "A6")
                    {
                        Logger.Log.Info(string.Format("是否成功:{0}", resData.ToString()));
                        if (resData["txnType"] == "04")
                        {
                            Logger.Log.Info("订单退款状态更新操作开始:订单号:" + resData["orderId"].TrimStart('0') + "交易流水号:" + resData["origQryId"]);
                            ReservationClient resv = new ReservationClient();
                            resv.SetOrderRefundStatusNew(new M625OperateInfo() { operatorID = "MOB", ResvSource = "MOB" }, resData["orderId"], resData["origQryId"], 0);//origQryId:原始交易流水号
                        }
                        else //if (resData["txnType"] == "01")
                        {
                            //如果卡号我们业务配了会返回且配了需要加密的话,请按此方法解密
                            //if (resData.ContainsKey("accNo"))
                            //{
                            //    string accNo = SecurityUtil.DecryptData(resData["accNo"], System.Text.Encoding.UTF8);
                            //}
                  
                            bool result = setorder(resData["orderId"], resData["queryId"]);
                            if (result)
                            {
                                Logger.Log.Info(string.Format("支付订单更新订单状态成功:{0}", result.ToString()));
                                //{discountAmt=20}
                                if (!String.IsNullOrEmpty(reserved) && reserved.Contains("{discountAmt="))
                                {
                                    //先注释掉
                                    String discountAmount = reserved.Replace("{discountAmt=", "").Replace("}", "");
                                    ReservationClient resv = new ReservationClient();
                                    resv.SetCloudPayRemark(new M625OperateInfo() { operatorID = "MOB", ResvSource = "MOB" }, resData["orderId"], resData["txnType"],discountAmount);
                                }
                            }
                        }

                        builder.Append("<tr><td align=\"center\" colspan=\"2\"><b>商户端接收银联返回报文并按照表格形式输出结果</b></td></tr>");

                        for (int i = 0; i < requestItem.Length; i++)
                        {
                            builder.Append("<tr><td width=\"30%\" align=\"right\">" + requestItem[i] + "</td><td style='word-break:break-all'>" + Request.Form[requestItem[i]] + "</td></tr>");
                        }
                        builder.Append("<tr><td width=\"30%\" align=\"right\">商户端验证银联返回报文结果</td><td>验证签名成功.</td></tr>");
                        Response.Write(builder.ToString());
                    }
        
                    else
                    {
                        string msg = resData["respMsg"];

                        Response.Write("<tr><td width=\"30%\" align=\"right\">商户端处理银联返回报文结果</td><td>" + msg + "</td></tr>");
                        Logger.Log.Warn("支付信息更新失败,商户端验证银联返回报文结果" + msg);
                    }

                }
                else
                {
                    Response.Write("<tr><td width=\"30%\" align=\"right\">商户端验证银联返回报文结果</td><td>验证签名失败.</td></tr>");
                    Logger.Log.Warn("支付信息更新失败,商户端验证银联返回报文结果,验证签名失败");
                }
                //html = builder.ToString();
            }
            else
            {
                //
            }
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值