支付宝条码支付
最近在做第三方支付功能,其中支付宝用了条码支付这种高大上的新支付方式,话说还有比较常见的是支付宝扫码支付,这两种有什么区别呢,很简单,就是扫码支付是消费者用手机主动扫码再支付,条码支付是商家用扫码枪主动扫码再支付。那么为何选择条码支付呢,因为这个速度快,从扫消费者手机上的条码或二维码,到支付完成,那是瞬间的事,不过要是触发了需要密码的时候,还是需要消费者在手机上输入支付密码后才能完成消费的。
介绍完了条码支付后,给个文档接口吧:支付宝条码支付。条码支付整个流程主要需要的API包含:支付接口alipay.trade.pay,查询订单接口alipay.trade.query,撤销订单接口alipay.trade.cancel,申请退款接口alipay.trade.refund。这些东西都在支付宝提供的SDK里面包含了,我们就不用重新造轮子了,支付宝已经提供了很好很强大的SDK了,只是这个生成的dll有点大。
那么要想使用这个功能,首先是需要一个支付宝商家账号的,这个是前置条件。然后需要设置好APPID,这个可以到这个网址获取支付宝APPID,获取好之后,还需要用OPENSSL软件生成RSA公钥和私钥,OPENSSL软件下载地址我也贴出来吧:OPENSSL的Windows版,32位的和64位的系统都可以用Win32 OpenSSL v1.0.2d Light。安装完之后先用genrsa -out {0} 1024生成私钥,其中{0}填私钥名称,可以携带绝对路径,再用rsa -in {0} -pubout -out {1}生成对应的公钥,其中{0}对应先生成的私钥,{1}对应要生成的公钥。生成完之后再到这个网址配置公钥:配置支付宝公钥。
大致流程就是这样,现在贴出各API我的调用示例吧:
条码支付请求:
/// <summary> /// 扣款 /// </summary> /// <param name="payLog">支付日志</param> /// <returns></returns> public void Pay(Mall_PayLog payLog) { //参考API列表-条码支付请求API https://app.alipay.com/market/document.htm?name=tiaomazhifu#page-11 var bizContent = new JsonObject(); //商户订单号 bizContent.Put("out_trade_no", payLog.OrderMain.OrderNum); //场景:条码支付 bizContent.Put("scene", "bar_code"); //条码 bizContent.Put("auth_code", payLog.Summary); //支付金额 bizContent.Put("total_amount", payLog.Money.ToString("F")); //订单标题 bizContent.Put("subject", "当面付条码支付"); //商户操作员编号 bizContent.Put("operator_id", LoginContext.AuthSession.Emp.RealName); //过期时间,默认5分钟后自动取消支付 bizContent.Put("time_expire", DateTime.Now.AddMinutes(5).ToString("yyyy-MM-dd HH:mm:ss")); var payRequest = new AlipayTradePayRequest { BizContent = bizContent.ToString() }; var result = GetAopClient(payLog.PayType.PaySetting).Execute(payRequest); switch (result.Code) { //支付成功 case ResultCode.SUCCESS: payLog.IDNum = result.TradeNo; payLog.PayedMoney = payLog.Money; payLog.PayState = Mall_EnumPayLogState.Payed; payLog.Update(); break; //支付中 case ResultCode.INRROCESS: payLog.IDNum = result.TradeNo; payLog.Update(); throw new MallException(ExceptionCode.PAY_PAYING, "请在手机端确认支付"); //支付失败 default: //payLog.IDNum = result.TradeNo; //payLog.Update(); new Loger().Info(string.Format("支付宝支付失败,PayLogID:{0},交易号{1},错误信息:{2}", payLog.ID, result.TradeNo, result.SubMsg)); throw new MallException(ExceptionCode.PAY_NOTCOMPLETED, "支付宝条码支付失败:" + result.SubMsg); } }
查询订单:
/// <summary> /// 服务端查询支付状态 /// </summary> /// <returns>0:进行中,1:已完成,2:已取消</returns> public int GetServicePayState(Mall_PayLog payLog) { var bizContent = new JsonObject(); //商户订单号(也可以只传支付宝交易号trade_no) bizContent.Put("out_trade_no", payLog.OrderMain.OrderNum); var payRequest = new AlipayTradeQueryRequest { BizContent = bizContent.ToString() }; var result = GetAopClient(payLog.PayType.PaySetting).Execute(payRequest); switch (result.Code) { //处理成功 case ResultCode.SUCCESS: if (result.TradeStatus == "TRADE_SUCCESS") { if (payLog.PayState == Mall_EnumPayLogState.Paying) { //更新支付状态 payLog.PayedMoney = payLog.Money; payLog.PayState = Mall_EnumPayLogState.Payed; payLog.Update(); } return 1; } return 0; default: //备注保存失败信息 payLog.Summary = result.SubMsg; payLog.Update(); return 2; } }
撤销订单:
/// <summary> /// 撤销支付(撤销还未支付的付款) /// </summary> /// <param name="payLog"></param> /// <returns></returns> public void ReversePay(Mall_PayLog payLog) { var bizContent = new JsonObject(); //商户订单号 bizContent.Put("out_trade_no", payLog.OrderMain.OrderNum); var payRequest = new AlipayTradeCancelRequest { BizContent = bizContent.ToString() }; var result = GetAopClient(payLog.PayType.PaySetting).Execute(payRequest); switch (result.Code) { //撤销订单成功 case ResultCode.SUCCESS: break; default: throw new MallException(ExceptionCode.PAY_NOTCOMPLETED, "撤销订单失败:" + result.SubMsg); } }
申请退款:
/// <summary> /// 退款 /// </summary> /// <param name="tradeNo">支付宝交易号</param> /// <param name="refundAmount">退款金额</param> /// <param name="appId">支付宝APPID</param> /// <returns></returns> public void RefundPay(string tradeNo, decimal refundAmount, string appId) { if (string.IsNullOrEmpty(tradeNo)) { throw new MallException(ExceptionCode.COMMON_BASE_CODEERROR, "未找到支付宝交易号"); } if (refundAmount < 0) { throw new MallException(ExceptionCode.COMMON_BASE_CODEERROR, "退款金额不能小于0"); } if (string.IsNullOrEmpty(appId)) { throw new MallException(ExceptionCode.COMMON_BASE_CODEERROR, "未找到支付宝AppId"); } var bizContent = new JsonObject(); //支付宝交易号 bizContent.Put("trade_no", tradeNo); //退款金额 bizContent.Put("refund_amount", refundAmount.ToString("F")); //退款原因 bizContent.Put("refund_reason", "O2O当面付退款"); var payRequest = new AlipayTradeRefundRequest { BizContent = bizContent.ToString() }; var result = GetAopClient(appId).Execute(payRequest); switch (result.Code) { //退款成功 case ResultCode.SUCCESS: break; //退款失败 default: throw new MallException(ExceptionCode.PAY_NOTCOMPLETED, "退款失败:" + result.SubMsg); } }
需要特殊处理的是,当需要消费者在手机端输入支付密钥时,必须等待消费者输完密码完成支付后手动查询支付的最新状态,这个也可以做成自动刷新状态,我是做成手动刷新的,还有就是密钥的生成需要四个dll,在安装的openssl目录里找到
这四个dll放到你的程序根目录下就可以了,然后生成密钥就用这个函数:
/// <summary> /// 执行OpenSsl命令 /// </summary> /// <param name="commands">命令</param> public void ExecuteOpenSslCommand(params string[] commands) { using (var openssl = new Process { StartInfo = { //设定程序名 FileName = _openSslPath, //关闭Shell的使用 UseShellExecute = false, //重定向标准输入 RedirectStandardInput = true, //重定向标准输出 RedirectStandardOutput = true, //重定向错误输出 RedirectStandardError = true, //设置不显示窗口 CreateNoWindow = true } }) { openssl.Start(); commands.Each(o => openssl.StandardInput.WriteLine(o)); } }
至此,支付宝条码支付功能就已经介绍完了,其他支付宝支付的调用也是类似的。觉得不错请点赞支持我喔,下篇将介绍微信扫码支付的示例。