付出与汲取

APP支付(.NET版)

---恢复内容开始---

APP支付(.NET版)

一、   支付宝支付

1、 有一个支付账号,在蚂蚁金服开放平台中登录账号→选择“管理中心”→在“开发者中心”下选择“网页&移动应用”→然后按步骤创建应用→选择需要的功能进行签约,签约成功后即可使用。

(注意事项:在签约的时候生成的私钥、公钥、还有支付宝公钥记得将文件保存。

支付签约成功会以手机短讯的方式进行通知,这时请查看你的邮箱(在签约时预留的),打开支付发送过来的邮件,通过里面的链接地址进行二次确认,才可正式签约生效)

2、 从官网下载“.NET版”SDK

3、 将SDK添加引用到项目

4、 获取预订单号,返回的预订单号直接给app端请求支付宝,不用做处理---代码如下:

/// <summary>

    /// 获取预订单编号

    /// </summary>

    /// <param name="money">支付金额</param>

    /// <param name="tradeNo">本地订单号</param>

        /// <param name="payment">取卡收费,注册收费</param>这个参数可以不用,是根据自己需要加上的

        public string GetOrderId(string money, string tradeNo, string payment)

        {

            string orderId = string.Empty;

            try

            {

                if (!string.IsNullOrEmpty(payment))

                {

                    //正式环境

                    IAopClient client = new DefaultAopClient(AlPayConfig.payUrl

                        , AlPayConfig.aPPID, AlPayConfig.alipayprivateKey, "json", "1.0", "RSA2"

                        , AlPayConfig.alipaypublicKey, AlPayConfig.charset, false);

                    //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称如:alipay.trade.app.pay

                    AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

                    //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。

                    AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

                    model.Body = "支付宝付款";   //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。

                    model.Subject = payment;//商品的标题/交易标题/订单标题/订单关键字等。

                    model.TotalAmount = money;//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]

                    model.ProductCode = "QUICK_MSECURITY_PAY";//销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY

                    model.OutTradeNo = CommonMethod.StringRemove_(tradeNo);//商户网站唯一订单号

                    model.TimeoutExpress = "30m";//该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。注:若为空,则默认为15d。

                    request.SetBizModel(model);

                    request.SetNotifyUrl(AlPayConfig.notifyUrl);//外网商户可以访问的异步地址

                                                                //这里和普通的接口调用不同,使用的是sdkExecute

                    AlipayTradeAppPayResponse response = client.SdkExecute(request);

                    //HttpUtility.HtmlEncode是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题

                    //Response.Write(HttpUtility.HtmlEncode(response.Body));

                    //页面输出的response.Body就是orderString 可以直接给客户端请求,无需再做处理。

                    string aa = response.TradeNo;

                    orderId = response.Body;

                }

            }

            catch (Exception e)

            {

                Log.Error("AlPay", "App支付支付回调通知:" + e.Message);

            }

            return orderId;

        }

          请求参数请参考“https://docs.open.alipay.com/204/105465/

5、 支付宝异步回调,返回支付结果及参数(参数描述请参考“https://docs.open.alipay.com/204/105301/”)

A、 获取返回的参数信息,并转换成字典

        /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组

        /// request回来的信息组成的数组

       public IDictionary<string, string> GetRequestPost()

        {

            int i = 0;

            IDictionary<string, string> sArray = new Dictionary<string, string>();

            NameValueCollection coll;

            //Load Form variables into NameValueCollection variable.

            coll = Request.Form;

            // Get names of all forms into a string array.

            string[] requestItem = coll.AllKeys;

            for (i = 0; i < requestItem.Length; i++)

            {

                sArray.Add(requestItem[i], Request.Form[requestItem[i]]);

            }

            return sArray;

        }

 

B、确认是否支付成功

/// <summary>

        /// App支付支付回调通知,判断是否支付成功

        /// </summary

        public void AppPayNotify(IDictionary<string, string> strArray)

        {

            //string result = string.Empty;

            try

            {

                //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。

                //bool RSACheckV1(IDictionary<string, string> parameters, string alipaypublicKey, string charset, string signType, bool keyFromFile)

                bool flag = AlipaySignature.RSACheckV1(strArray, AlPayConfig.alipaypublicKey, AlPayConfig.charset, "RSA2", false);

 

                if (!UpdateData(strArray, flag))

                {

                    CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

                                                               new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "支付宝支付回调完成后修改数据失败!"));

                }

 

            }

            catch (Exception e)

            {

                Log.Error("AlPay", "App支付回调通知:" + e.Message);

            }

        }

6、 根据服务器订单号判断是否支付成功(也可以是根据支付订单号查询支付结果)

     /// <summary>

        /// 根据订单号返回支付结果

        /// </summary>

        public AlipayTradeQueryResponse GetPayResultByPreOrderId(string orderId)

             {

            orderId = CommonMethod.StringRemove_(orderId);

            //正式环境

            IAopClient client = new DefaultAopClient(AlPayConfig.payUrl

                , AlPayConfig.aPPID, AlPayConfig.alipayprivateKey, "json", "1.0", "RSA2",

                 AlPayConfig.alipaypublicKey, AlPayConfig.charset, false);

            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

            request.BizContent = "{\"out_trade_no\":\""+ orderId + "\"," +

                                    "\"trade_no\":\"\"}";

            //string.Format(@"{ut_trade_no:{0},trade_no:""}", orderId);

            AlipayTradeQueryResponse response = client.Execute(request);

            //Console.WriteLine(response.Body);

            return response;

        }

 

       /// <summary>

        /// 根据服务器订单号判断是否支付成功

        /// </summary>

        /// <param name="orderId">服务器订单号</param>

        private void AlTestPayByOrderID(string orderId)

        {

            try

            {

                //根据服务器订单号返回支付结果

                AlipayTradeQueryResponse response = new AlPay().GetPayResultByPreOrderId(orderId);

                T_TMM_RFCardPaymentService rfCardPaymentService = new T_TMM_RFCardPaymentService();

               

                //根据TradeStatus交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)

                //TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)

                if (response.TradeStatus.ToUpper() == "TRADE_SUCCESS")//如果支付成功,则修改数据状态

                {

                    string tradeNoR = response.TradeNo;//支付宝交易号

                    string outTradeNo = CommonMethod.StringToGuidStr(response.OutTradeNo);//商户订单号(服务器订单号)

                    string buyerLogonId = response.BuyerLogonId;//买家支付宝账号

                    string paymentDate = response.SendPayDate;//交易付款时间

                    string payStatus = "1";//支付成功状态为1,失败为2

                    rfCardPaymentService.PaySuccess(outTradeNo, "1", tradeNoR, buyerLogonId, paymentDate, payStatus);

                }

                else

                {

                    //将订单改为失效订单

                    rfCardPaymentService.SetOrderInvalid(orderId);

                }

            }

            catch (Exception ex)

            {

                CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

                                                             new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message));

            }

        }

 

 

二、   微信支付

1、 有微信账号及微信商户号

2、 使用微信账号登录微信开放平台,创建移动应用,根据步骤填写详细信息。等待认证通过,平台认证需要付费。

3、 在微信商户平台创建商户账号,商户账号绑定银行卡,作为APP支付的目标账户。

4、 获取预订单号

  /// <summary>

        /// 取得预支付ID

        /// </summary>

        /// <param name="money">订单金额</param>

        /// <param name="out_trade_no">订单编号</param>

        /// <param name="body">商品描述交易字段</param>

        /// <returns></returns>

        private WxPayData PrepayId(double money, string tradeNo, string body)

        {

            WxPayData data = new WxPayData();

            data.SetValue("body", body);//商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字 - 实际商品名称,天天爱消除 - 游戏充值。

            string out_trade_no = tradeNo.Replace("-", "");//微信要求商户订单号不能超过32位

            data.SetValue("out_trade_no", out_trade_no);//商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。

            data.SetValue("total_fee", (int)(money * 100));//总金额:订单总金额,单位为分,int类型

            string ip = Request.UserHostAddress;

            data.SetValue("spbill_create_ip", ip);//用户端实际ip

            data.SetValue("notify_url", WxPayConfig.NOTIFY_URL);//支付成功回调地址

            data.SetValue("trade_type", "APP");//交易类型

            data.SetValue("attach", body);//附加数据,交易完成,原样返回,body参数不返回,所以用这个代替

            WxPayData result = new WxPayData();

            try

            {

                result = WxPayApi.UnifiedOrder(data);//调用统一下单接口

            }

            catch (System.Exception ex)

            {

                result.SetValue("return_code", "FAIL");

                result.SetValue("return_msg", "下单失败,请返回重试。");

                CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

               new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message));

            }

            //result.SetValue("return_code", "SUCCEED");//返回的结果已经包含当前字段

            //res.Data = result.ToJson();

            return result;

        }

5、 微信回调修改本地数据库

      /// <summary>

        /// 微信支付支付结果通知处理

        /// </summary>

        //[HttpPost, ValidateInput(false)]

        [HttpPost]

        public void ProcessNotify()

        {

            try

            {

                WxResultNotify resultNotify = new WxResultNotify(this.Request, this.Response);

                bool bPayRs = resultNotify.ProcessNotify();

                WxPayData notifyData = resultNotify.NotifyData;

                string id = string.Empty;//服务器订单号

                string paymentOrderNo = string.Empty;//微信订单号

                string paymentStatus = string.Empty;//支付状态

                string paymentMethod = CommonConst.PayTypeWX;//支付方式

                string paymentAccount = string.Empty;//用户编号

                string payDate = string.Empty;//支付时间

                //支付id

                if (notifyData.IsSet("out_trade_no"))

                {

                    string out_trade_no = notifyData.GetValue("out_trade_no").ToString();

                    if (string.IsNullOrEmpty(out_trade_no) || out_trade_no.Length != 32)//订单编号不正确

                    {

                        id = string.Empty;

                        return;

                    }

                    else

                    {

                        //还原订单号

                        StringBuilder sb = new StringBuilder();

                        sb.Append(out_trade_no.Substring(0, 8));

                        sb.Append("-");

                        sb.Append(out_trade_no.Substring(8, 4));

                        sb.Append("-");

                        sb.Append(out_trade_no.Substring(12, 4));

                        sb.Append("-");

                        sb.Append(out_trade_no.Substring(16, 4));

                        sb.Append("-");

                        sb.Append(out_trade_no.Substring(20, 12));

                        id = sb.ToString();

                    }

                }

                else

                {

                    CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

             new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "订单号不存在!"));

                    return;

                }

                //微信支付订单号

                if (notifyData.IsSet("transaction_id"))

                {

                    paymentOrderNo = notifyData.GetValue("transaction_id").ToString();

                }

                //用户编号

                if (notifyData.IsSet("openid"))

                {

                    paymentAccount = notifyData.GetValue("openid").ToString();

                }

                //支付时间

                if (notifyData.IsSet("time_end"))

                      {

                    payDate = DateTime.ParseExact(notifyData.GetValue("time_end").ToString()

            , "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture).ToString("yyyy-MM-dd HH:mm:ss");

                }

              //判断交易是否成功

              if (notifyData.IsSet("result_code") && notifyData.GetValue("result_code").ToString() == "SUCCESS")//交易成功

                {

                    paymentStatus = "1";//支付状态“成功”

                }

                else//交易失败

                {

                    paymentStatus = "2"; //支付状态“失败”

                    CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

                    new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "交易失败!"));

                }

                //判断是取卡支付还是注册支付

                if (notifyData.IsSet("attach") && notifyData.GetValue("attach").ToString().Contains(CommonConst.PaymentQK))//取卡支付

                {

                    //支付完成修改数据

                    new T_TMM_RFCardPaymentService().PaySuccess(id, paymentMethod, paymentOrderNo, paymentAccount, payDate, paymentStatus);

                }

                else

                      {

                    //支付完成修改数据

                    new T_TMM_RegisterPaymentService().PaySuccess(id, paymentMethod, paymentOrderNo, paymentAccount, payDate, paymentStatus);

                    new AlPay().GreateLoginAuthorityByOrderId(id);

                }

            }

            catch (Exception ex)

            {

                CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

                new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message));

            }

        }

6、 根据服务器订单号查询是否支付成功(也可以根据支付订单号查询支付结果)

/// <summary>

        /// 根据服务器订单号判断是否支付成功

        /// </summary>

        /// <param name="orderId">服务器订单号</param>

        private void WXTestPayByOrderID(string orderId)

        {

            try

            {

                T_TMM_RFCardPaymentService rfCardPaymentService = new T_TMM_RFCardPaymentService();

                //根据服务器订单号返回支付结果

                WxPayData payData = new WxPayData();

                payData.SetValue("out_trade_no", CommonMethod.StringRemove_(orderId));//服务器订单号

                //返回查询结果

                WxPayData payResult = WxPayApi.OrderQuery(payData);

                //根据支付状态判断是否支付成功SUCCESS—支付成功REFUND—转入退款NOTPAY—未支付CLOSED—已关闭REVOKED—已撤销(刷卡支付)USERPAYING--用户支付中PAYERROR--支付失败(其他原因,如银行返回失败)

                if (payResult.IsSet("trade_state") && payResult.GetValue("trade_state").ToString() == "SUCCESS")//支付成功

                {

                    string tradeNoR = payResult.GetValue("transaction_id").ToString();//微信支付订单号

                    string outTradeNo = CommonMethod.StringToGuidStr(payResult.GetValue("out_trade_no").ToString());//商户订单号(服务器订单号)

                    string buyerLogonId = payResult.GetValue("openid").ToString();//买家支付宝账号

                    string paymentDate = DateTime.ParseExact(payResult.GetValue("time_end").ToString(),"yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture).ToString("yyyy-MM-dd HH:mm:ss"); //交易付款时间

                    string payStatus = "1";//支付成功状态为1,失败为2

                    rfCardPaymentService.PaySuccess(outTradeNo, "2", tradeNoR, buyerLogonId, paymentDate, payStatus);

                }

                else//支付失败

                {

                    //将订单改为失效订单

                    rfCardPaymentService.SetOrderInvalid(orderId);

                }

            }

            catch (Exception ex)

            {

                CommonMethod.WriteErrorLog(string.Format(CommonMethod.LOG_ERROR_FORMAT, this.GetType().FullName,

               new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message));

            }

        }

 

注:微信开放平台创建移动应用时,开发信息中的以下信息是固定值,不能随意更换。

(如需修改,则必须通知APP开发人员,对APP作出相对应的修改)

 

iOS平台

iPhone

应用下载地址:未填写

Bundle ID:moon.SundyApp

测试版本Bundle ID:moon.SundyApp

 

iPad 无

Android平台

应用下载地址:未填写

应用签名:478c16ede90213492d8ea8eda87d1ada

包名:com.sundy.android

 

 

 

三、  所有与支付相关的配置信息,都在web.config文件中配置(重要)

1、 支付宝需配置的信息有

a)       AL_APPID 在支付宝的管理平台“创建应用”成功后,对于已经创建的应用会生成一个APPID,这个编号是唯一的,相当于应用的身份证号。

b)       AL_PUBLIC_KEY(支付宝公钥)在支付宝的管理平台“创建应用”成功后,在应用信息里面,有查看支付宝公钥的链接,将这个链接复制替换到config文件中,注意:不能出现换行和空格。

c)       AL_PRIVATE_KEY(应用私钥)在支付宝“创建应用”的时候,在使用“生成密钥”的工具生成时会生成两个txt文件,分别为“应用公钥”和“应用私钥”。这里使用的就是应用私钥。(注:“应用私钥”在“应用信息”中看不到)。

d)       CHARSET(编码格式)一般使用UTF-8。

e)       NOTIFY_URL回调地址(服务器地址)。

f)        AL_PAY_URL(支付宝-URL) 正式地址:https://openapi.alipay.com/gateway.do,沙箱环境:https://openapi.alipaydev.com/gateway.do

2、 微信需配置的信息有

a)  WX_URL_UNIFIEDORDER(统一下单url):https://api.mch.weixin.qq.com/pay/unifiedorder

b)  WX_URL_ORDERQUERY(订单查询url):https://api.mch.weixin.qq.com/pay/orderquery

c)  WX_URL_REPORT(测速上报url):https://api.mch.weixin.qq.com/payitil/report

d)  WX_APPID 在微信开放平台创建好应用后,生成的一个APPID。

e)  WX_MCHID(商户号)在微信商户平台注册的微信商户编号,用来指定收款帐户。

f)  WX_APIKEY(商户支付密钥)在微信商户平台注册的时间可以得到。

g)  WX_REPORT_LEVENL(上报信息配置 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报)。

h)  WX_LOG_LEVENL(日志级别 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息)。

3、 NOTIFY_URL(共用的回调URL,回调地址(服务器地址))

---恢复内容结束---

posted on 2018-01-25 10:03  付出与汲取  阅读(475)  评论(0编辑  收藏  举报

导航