• 一文秒懂如何搭建一个最简单的充值系统


         阅读完本文大概需要5分钟。

    目录

    • 移动支付
      • 微信支付
      • 支付宝支付
    • 充值体系
      • 最基础的架构
      • 生产环境应用
    • 总结
    • 参考

         一切都是生意。“天下熙熙皆为利来,天下攘攘皆为利往”。不知从什么时候起,人类社会诞生了公司这样的组织,而这个组织把人们结合在一起,产生了各种行业和商业形态,最后,公司的一切活动都变成了生意。当然,大公司有大公司的生意,小公司有小公司的买卖。

         过去几年saas服务软件大行其道,这其中就有大家熟悉的阿里云服务,客户注册账户+线上支付就能使用软件。

         线上支付,相信大家都不陌生。支付宝,微信,云闪付,苹果支付等,人人都离不开支付通道。我们看到很多大公司都有自己的支付体系和金融体系。大厂,财大气粗,有足够的投入可以自建高可用的支付体系。那么,如何中小微企业想在做点小生意,没有足够的资源自建支付体系,怎么玩?

         借力。这就好比大厂花了大价钱,找到水源,然后挖了一口井,小店也得活不是,给点佣金,分一股“清泉”吧。

    一、移动支付
     

    本文代码示例是基于威富通移动支付(https://www.swiftpass.cn/products/epay/page.html)

    1. 微信支付

         场景介绍

    用户扫描商户展示在各种场景的二维码进行支付。:

         步骤1:商户根据微信支付的规则,为不同商品生成不同的二维码(如图6.1),展示在各种场景,用于用户扫描购买。

         步骤2:用户使用微信“扫一扫”(如图6.2)扫描二维码后,获取商品支付信息,引导用户完成支付(如图6.3)。

         步骤3:用户确认支付,输入支付密码(如图6.4)。

         步骤4:支付完成后会提示用户支付成功(如图6.5),商户后台得到支付成功的通知,然后进行发货处理。

         查看是否安装成功:

         笔者在实际项目中要使用微信扫码付款功能,开发的时候选择的是微信扫码支付的模式一(https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4)

         代码片段

    /// <summary>
            /// 威富通-微信支付
            /// </summary>
            /// <param name="total_fee">订单金额</param>
            /// <param name="orderno">订单号</param>
            /// <param name="productName">产品名称</param>
            private void WebChat(decimal total_fee, string orderno, string productName)
            {
                try
                {
                    total_fee = total_fee * 100;//单位:分
                    PayReqEntity entity = new PayReqEntity();
                    entity.mch_id =“商户ID”
                    string key =“KEY";//您申请的
                    entity.key = key;
                    entity.req_url = "https://pay.swiftpass.cn/pay/gateway";
                    entity.service = "pay.weixin.native";
                    entity.version = "2.0";
                    entity.out_trade_no = orderno;
                    entity.body = productName;
                    entity.attach = "";
                    entity.total_fee = Math.Round(total_fee).ToString();
                    entity.time_start = "";
                    entity.time_expire = "";
                    entity.mch_create_ip = AppUtils.GetIp();
                    entity.notify_url = ChargeHelper.BuildUrl() + "WebChat/Notify.aspx";
                    WeChatPayInterface service = new WeChatPayInterface();
                    PayResEntity result = service.SubmitPay(entity);
                    if (!result.IsSuccess)
                    {
                        string msg = result.Message;
                        if (msg.Contains("订单已存在"))
                        {
                            msg = msg + ",请重新下单!";
                        }
                        Response.Write("<script>alert('" + msg + "')</script>");
                        return;
                    }
                    Session["pavlue"] = result.arr;
                    Response.Redirect("WebChat/Pay.aspx");
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    

         付款完成之后,会回调WebChat/Pay.aspx页面,执行订单业务功能。

    public void callback()
            {
                try
                {
                    WeChatPayInterface service = new WeChatPayInterface();
                    Stream stream = Request.InputStream;
                    string key = "KEY";//你申请的
                    NotifyResEntity result = service.PayResult(key, stream);
                    if (!result.IsSuccess)
                    {
                        Log.Info("[威富通-微信支付回调]:" + result.Message);
                        Response.Write("failure");
                        return;
                    }
                    Hashtable data = result.data;
                    /*-----------交易状态------------
                     SUCCESS—支付成功
                     REFUND—转入退款
                     NOTPAY—未支付
                     CLOSED—已关闭
                     PAYERROR—支付失败(其他原因,如银行返回失败)
                     ------------------------------------ */
                    string out_trade_no = data["out_trade_no"].ToString();//商户订单号
                    int status = Convert.ToInt32(data["status"]);//返回状态码(0表示成功,非0表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断)
                    int result_code = Convert.ToInt32(data["result_code"]);//业务结果(0表示成功,非0表示失败)
                    if (status == 0 && result_code == 0)
                    {
                        string total_fee = data["total_fee"].ToString();//总金额,以分为单位,不允许包含任何字、符号
                        string transaction_id = data["transaction_id"].ToString();//平台交易单号
                        //此处可以在添加相关处理业务 ,更新数据库表中的记录。
                        int proxyid = 0;
                        string bankbill = "";
                        ulong employeeid = 1;
                        string comment = "微信支付";
                        string billtype = "正常订单";
                        int payment = 24;//微信支付
                        string bankname = "";
                        string payer = "";
                        string orderno = out_trade_no;
                        string taobaopayno = transaction_id;
                        decimal amountpaid = 0;
                        if (!string.IsNullOrEmpty(total_fee))
                        {
                            amountpaid = Convert.ToDecimal(total_fee) / 100;
                        }
             
                        //TODO:业务处理部分
                        Response.Write("success");
                        return;
                        
                    }
                    else
                    {
                        Log.Info("[威富通-微信支付回调]:商户订单号out_trade_no=" + out_trade_no + "状态码status=" + status + ",业务结果result_code=" + result_code);
                    }
                }
                catch (Exception ex)
                {
                    Log.Info("[威富通-微信支付回调]异常:" + ex);
                }
                Response.Write("failure");
            }
    
    

    2.支付宝支付

         场景介绍

        扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商户针对每个订单实时生成的订单二维码,并在手机端确认支付。

         调用流程

    https://docs.open.alipay.com/194/105170/

        商户系统调用支付宝预下单接口alipay.trade.precreate,获得该订单二维码图片地址。
        发起轮询获得支付结果:等待5秒后调用交易查询接口alipay.trade.query通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数TRADE_STATUS),如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待5秒后继续查询,直到返回确切的支付结果(成功TRADE_SUCCESS 或 已撤销关闭TRADE_CLOSED),或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用交易撤销接口alipay.trade.cancel将这笔交易撤销,避免用户继续支付。
        除了主动轮询,也可以通过接受异步通知获得支付结果,详见扫码异步通知,注意一定要对异步通知做验签,确保通知是支付宝发出的。

    代码片段:

     private void Alipay(decimal total_fee, string orderno, string productName)
            {
                total_fee = total_fee * 100;//单位:分
                PayReqEntity entity = new PayReqEntity();
                entity.mch_id = "商户ID";
                string key = 商户Key"";
                entity.key = key;
                entity.req_url = "https://pay.swiftpass.cn/pay/gateway";
                entity.service = "pay.alipay.native";
                entity.version = "2.0";
                entity.out_trade_no = orderno;
                entity.body = productName;
                entity.attach = "";
                entity.total_fee = Math.Round(total_fee).ToString();
                entity.time_start = "";
                entity.time_expire = "";
                entity.mch_create_ip = AppUtils.GetIp();
                entity.notify_url = ChargeHelper.BuildUrl() + "Alipay/Notify.aspx";
                WeChatPayInterface service = new WeChatPayInterface();
                PayResEntity result = service.SubmitPay(entity);
                if (!result.IsSuccess)
                {
                    string msg = result.Message;
                    if (msg.Contains("订单已存在"))
                    {
                        msg = msg + ",请重新下单!";
                    }
                    Response.Write("<script>alert('" + msg + "')</script>");
                    return;
                }
                Session["alipay_pavlue"] = result.arr;
                Response.Redirect("Alipay/Pay.aspx");
            }
    

        支付完成,同样回调Alipay/Pay.aspx

    public void callback()
            {
                try
                {
                    WeChatPayInterface service = new WeChatPayInterface();
                    Stream stream = Request.InputStream;
                    string key = "KEY";//填写自己的
                    NotifyResEntity result = service.PayResult(key, stream);
                    if (!result.IsSuccess)
                    {
                        Log.Info("[威富通-支付宝支付回调]:" + result.Message);
                        Response.Write("failure");
                        return;
                    }
                    Hashtable data = result.data;
                    /*-----------交易状态------------
                     SUCCESS—支付成功
                     REFUND—转入退款
                     NOTPAY—未支付
                     CLOSED—已关闭
                     PAYERROR—支付失败(其他原因,如银行返回失败)
                     ------------------------------------ */
                    //string trade_state = data["trade_state"].ToString();
                    string out_trade_no = data["out_trade_no"].ToString();//商户订单号
                    int status = Convert.ToInt32(data["status"]);//返回状态码(0表示成功,非0表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断)
                    int result_code = Convert.ToInt32(data["result_code"]);//业务结果(0表示成功,非0表示失败)
                    if (status == 0 && result_code == 0)
                    {
                        string total_fee = data["total_fee"].ToString();//总金额,以分为单位,不允许包含任何字、符号
                        string transaction_id = data["transaction_id"].ToString();//平台交易单号
                        //此处可以在添加相关处理业务 ,更新数据库表中的记录。
                        int proxyid = 0;
                        string bankbill = "";
                        ulong employeeid = 1;
                        string comment = "支付宝支付";
                        string billtype = "正常订单";
                        int payment = 23;//威富通-支付宝支付
                        string bankname = "";
                        string payer = "";
                        string orderno = out_trade_no;
                        string taobaopayno = transaction_id;
                        decimal amountpaid = 0;
                        if (!string.IsNullOrEmpty(total_fee))
                        {
                            amountpaid = Convert.ToDecimal(total_fee) / 100;
                        }
                        //TODO:业务处理部分
                        Response.Write("success");
                        return;
                    }
                    else
                    {
                        Log.Info("[威富通-支付宝支付回调]:商户订单号out_trade_no=" + out_trade_no + "状态码status=" + status + ",业务结果result_code=" + result_code);
                    }
                }
                catch (Exception ex)
                {
                    Log.Info("[威富通-支付宝支付回调]异常:" + ex);
                }
                Response.Write("failure");
            }
    
    

    二、充值体系

    任何一家公司做生意的都会使用支付业务,这里以SAAS行业支付为例。

    • 最基本的充值业务架构

      满足一下基本需求

      • 用户账户中心
      • 用户可充值,可查看订单和购买商品
      • 代理商、销售等营销部门可以查看业绩报表
    • 订单生成流程

         在实际生产环境中中,订单的流程也是较为重要的一环。

    • 防止重复支付

         支付完成,回调的时候检测订单状态。已支付的就不再执行。

    • 如何保证支付一致性

         在实际生产环境中中,总会发生支付接口支付成功,回调执行订单业务失败的情况,简单的办法是可以增加一个单独检查业务,定时对不一致的订单进行二次执行。

    三、总结

         基本的充值体系是通用的。订单业务量大的可以增加消息队列处理。在保证一致性方面,我们在该架构上还有很多细节可以完善。

    四、参考


         个人微信公众号:

  • 相关阅读:
    poj 1050
    poj 2479 Maximum sum
    Trie树结构(AC自动机前奏)(转)
    poj 3624(zeroonepack)
    poj 3630(Phone List )
    KMP算法(AC自动机前奏)(转)
    AC自动机(转)
    AC自动机模板(hdu2222)
    Running CMD.EXE as Local System
    什么是WPF(Avalon)
  • 原文地址:https://www.cnblogs.com/lucky_hu/p/9823406.html
Copyright © 2020-2023  润新知