阿珏酱Blog因为我是活在二次元的女孩

支付宝当面付对接

阿珏酱·2024-05-21 10:28·87 次阅读

支付宝当面付对接

Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解`

支付宝当面付对接

日期:2020-4-4 阿珏 折腾代码 浏览:2186次 评论:10条

当面付顾名思义,面对面付款,帮助商家在线下消费场景下实现快速收款;当面付产品支持条码支付和扫码支付两种付款方式。


我们这里对接的就是扫码支付


扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。业务流程如下图所示:





由于当面付的签约非常简单,允许个体工商户/个人商户签约。所以该方式也被大量用于线上的扫码支付,由于该方式违反了支付宝的相关条款,有一定风险,咱作为技术交流,暂且先抛开这个问题。




作为技术对接,即使你没有签约当面付产品,也是可以进行开发的。


支付能力直接涉及到交易与资金,为了方便开放者调试支付能力,开放平台已经准备好沙箱环境,包括沙箱环境账号和沙箱版支付宝钱包,这样开发者就可以在沙箱环境调试了。点击了解

如何接入沙箱



接入沙箱环境







所以我这边开发使用的是沙箱环境,毕竟里面好多钱,随便用。





首先先下载相应的开发语言的sdk 下载:https://docs.open.alipay.com/194/105201/


扫码支付文档:https://docs.open.alipay.com/194/106078/






配置密钥




为了保证交易双方(商户和支付宝)的身份和数据安全,开发者在调用接口前,需要配置双方密钥,对交易数据进行双方校验。



下载



支付宝开放平台开发助手

进行密钥生成。




生成密钥后,开发者需要在开放平台开发者中心进行密钥配置,配置完成后可以获取支付宝公钥








设计接入




由于我这边的设计不需要用到轮询(后面会说),所以没有加上


以下是我业务中的相关代码


Copy
public function pay(){

Copy
if (request()-&gt;isPost()) { // (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线, // 需保证商户系统端不能重复,建议通过数据库sequence生成, $uid = Session::get('sq.uid'); $outTradeNo = order_num() . $uid; // (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费” $subject = '聚合平台用户积分充值'; // (必填) 订单总金额,单位为元,不能超过1亿元 // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】 $totalAmount = input('post.pay_money/f'); if($totalAmount &lt; 1){ return ['status' =&gt; 1, 'msg' =&gt; '最低充值金额1元']; } if($totalAmount &gt; 9999999){ return ['status' =&gt; 1, 'msg' =&gt; '充值最大金额不能超过9999999元']; } // (不推荐使用) 订单可打折金额,可以配合商家平台配置折扣活动,如果订单部分商品参与打折,可以将部分商品总价填写至此字段,默认全部商品可打折 // 如果该值未传入,但传入了【订单总金额】,【不可打折金额】 则该值默认为【订单总金额】- 【不可打折金额】 //String discountableAmount = "1.00"; // // (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】 // $undiscountableAmount = "0.01"; // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号) // 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID //$sellerId = ""; // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元" $body = "聚合平台用户积分充值" . $totalAmount . '元'; //商户操作员编号,添加此参数可以为商户操作员做销售统计 // $operatorId = ""; // (可选) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持 // $storeId = ""; // 支付宝的店铺编号 // $alipayStoreId= ""; // 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),系统商开发使用,详情请咨询支付宝技术支持 // $providerId = ""; //系统商pid,作为系统商返佣数据提取的依据 // $extendParams = new ExtendParams(); // $extendParams-&gt;setSysServiceProviderId($providerId); // $extendParamsArr = $extendParams-&gt;getExtendParams(); // 支付超时,线下扫码交易定义为5分钟 $timeExpress = "5m"; // 商品明细列表,需填写购买商品详细信息, // $goodsDetailList = array(); // // 创建一个商品信息,参数含义分别为商品id(使用国标)、名称、单价(单位为分)、数量,如果需要添加商品类别,详见GoodsDetail // $goods1 = new GoodsDetail(); // $goods1-&gt;setGoodsId("apple-01"); // $goods1-&gt;setGoodsName("iphone"); // $goods1-&gt;setPrice(3000); // $goods1-&gt;setQuantity(1); // //得到商品1明细数组 // $goods1Arr = $goods1-&gt;getGoodsDetail(); // // 继续创建并添加第一条商品信息,用户购买的产品为“xx牙刷”,单价为5.05元,购买了两件 // $goods2 = new GoodsDetail(); // $goods2-&gt;setGoodsId("apple-02"); // $goods2-&gt;setGoodsName("ipad"); // $goods2-&gt;setPrice(1000); // $goods2-&gt;setQuantity(1); // //得到商品1明细数组 // $goods2Arr = $goods2-&gt;getGoodsDetail(); // $goodsDetailList = array($goods1Arr,$goods2Arr); //第三方应用授权令牌,商户授权系统商开发模式下使用 $appAuthToken = "";//根据真实值填写 // 创建请求builder,设置请求参数 $qrPayRequestBuilder = new AlipayTradePrecreateContentBuilder(); $qrPayRequestBuilder-&gt;setOutTradeNo($outTradeNo); $qrPayRequestBuilder-&gt;setTotalAmount($totalAmount); $qrPayRequestBuilder-&gt;setTimeExpress($timeExpress); $qrPayRequestBuilder-&gt;setSubject($subject); $qrPayRequestBuilder-&gt;setBody($body); // $qrPayRequestBuilder-&gt;setUndiscountableAmount($undiscountableAmount); // $qrPayRequestBuilder-&gt;setExtendParams($extendParamsArr); // $qrPayRequestBuilder-&gt;setGoodsDetailList($goodsDetailList); // $qrPayRequestBuilder-&gt;setStoreId($storeId); // $qrPayRequestBuilder-&gt;setOperatorId($operatorId); // $qrPayRequestBuilder-&gt;setAlipayStoreId($alipayStoreId); $qrPayRequestBuilder-&gt;setAppAuthToken($appAuthToken); // 调用qrPay方法获取当面付应答 require ROOT_PATH.'extend/f2fpay/config/config.php'; $qrPay = new AlipayTradeService($config); $qrPayResult = $qrPay-&gt;qrPay($qrPayRequestBuilder); // 根据状态值进行业务处理 switch ($qrPayResult-&gt;getTradeStatus()){ case "SUCCESS": $response = $qrPayResult-&gt;getResponse(); Db::name('order') -&gt;insert([ 'uid' =&gt; $uid, 'pay_id' =&gt; $outTradeNo, 'money' =&gt; $totalAmount, 'creat_time' =&gt; time(), 'subject' =&gt; $subject ]); return ['status' =&gt; 0, 'msg' =&gt; '支付宝创建订单二维码成功!!!"','data' =&gt; [ 'qr_code' =&gt; $response-&gt;qr_code, 'outTradeNo' =&gt; $outTradeNo ]]; // $qrcode = $qrPay-&gt;create_erweima($response-&gt;qr_code); // echo $qrcode; // print_r($response); break; case "FAILED": return ['status' =&gt; 1, 'msg' =&gt; '支付宝创建订单二维码失败!!!"']; // if(!empty($qrPayResult-&gt;getResponse())){ // print_r($qrPayResult-&gt;getResponse()); // } break; case "UNKNOWN": return ['status' =&gt; 1, 'msg' =&gt; '系统异常,状态未知!!!"']; // echo "系统异常,状态未知!!!"."&lt;br&gt;--------------------------&lt;br&gt;"; // if(!empty($qrPayResult-&gt;getResponse())){ // print_r($qrPayResult-&gt;getResponse()); // } break; default: return ['status' =&gt; 1, 'msg' =&gt; '不支持的返回状态,创建订单二维码返回异常!!!']; break; } return ; } }</pre> 以上就是当面付预下单代码 <br/> 关于这个SDK,我非常有必要吐槽一下,哪个货写的demo,还在PHP例子里引入了个lotusphp框架,一大堆没有用的东西,完全没有考虑我们开发者能不能接受的了。 <br/> 我也是花了点时间,把SDK给精简了一下,只拿出我需要的部分,放入了我自己的框架中,加上了namespace,自动加载。 <br/> <img src="https://img2023.cnblogs.com/blog/3441070/202405/3441070-20240526174145251-551273636.jpg"/> <br/> 扫码支付有一个独有的功能----异步通知 <br/> 这个也正是线上支付最为需要的功能 <br> 当收银台调用预下单请求 API 生成二维码展示给用户后,用户通过手机扫描二维码进行支付,支付宝会将该笔订单的变更信息,沿着商户调用预下单请求时所传入的异步通知地址 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商户系统。 <br/> <img src="https://img2023.cnblogs.com/blog/3441070/202405/3441070-20240526174146216-407474224.jpg"/> <br/> 记住这个异步通知地址需要在应用那设置一下。 <br/> <pre class="prettyprint lang-php linenums"> // 异步回调 public function notify() { if (request()-&gt;isPost()) { require ROOT_PATH.'extend/f2fpay/config/config.php'; $aop = new AopClient; $aop-&gt;alipayrsaPublicKey = $config['alipay_public_key']; $flag = $aop-&gt;rsaCheckV1($_POST, null, "RSA2"); if ($flag) { //异步SIGN验证成功, 可以进行下一步动作。例如验证订单金额 然后完成订单。之类的。。 //需要验证的就是 订单号 与 订单金额是否一致,验证成功 就可以对数据库中的订单进行操作了。 //TRADE_SUCCESS 对于当面付来说,已经到账了。详情可以看这里 https://www.cnblogs.com/tdalcn/p/5956690.html if ($_POST['trade_status'] === "TRADE_SUCCESS") { //订单处理模板 $res = Db::name('order') -&gt;where('pay_id', $_POST['out_trade_no']) -&gt;where('money', $_POST['total_amount']) -&gt;where('status', 0) -&gt;find(); if($res){ Db::name('order') -&gt;where('id',$res['id']) -&gt;update([ 'status' =&gt; 1, 'buyer_logon_id' =&gt; $_POST['buyer_logon_id'], 'pay_time' =&gt; $_POST['gmt_payment'], 'pay_no' =&gt; $_POST['trade_no'] ]); Db::name('user') -&gt;where('uid',$res['uid']) -&gt;setInc('integral', floatval($_POST['total_amount']) * 1000); } } } echo 'success'; //接口必须返回success 不然阿里会一直发送校验验证。 } }</pre> <strong> <span style="font-size:18px;"> 轮询 </span> </strong> <br> 其中如果需要页面支付成功后同步跳转,则需要添加轮询,由于当面付是没有同步通知这个功能,所以需要用到轮询,并且这个方法也是在当面付的文档中所提及到的。 <br/> 以下代码摘自Bty付费版 <br/> <pre class="prettyprint lang-php linenums">public function query() { if (input('post.no')) { $out_trade_no = input('post.no'); $queryContentBuilder = new AlipayTradeQueryContentBuilder(); $queryContentBuilder-&gt;setOutTradeNo($out_trade_no); $queryResponse = new AlipayTradeService($this-&gt;alipay_config); $queryResult = $queryResponse-&gt;queryTradeResult($queryContentBuilder); $res['status'] = $queryResult-&gt;getTradeStatus(); $res['buyer'] = isset($queryResult-&gt;getResponse()-&gt;buyer_logon_id) ? $queryResult-&gt;getResponse()-&gt;buyer_logon_id : ''; $res['amount'] = $queryResult-&gt;getResponse()-&gt;buyer_pay_amount; if ($res['status'] == 'SUCCESS') { $this-&gt;paySuccess('', $out_trade_no); } exit(json_encode($res)); } else { $this-&gt;error('非法请求'); } }</pre> 由于我们对接的并不是类似商城一般的系统,所以暂时用不到类似退款这些的复杂操作。 <br/> <img src="https://img2023.cnblogs.com/blog/3441070/202405/3441070-20240526174147080-1313678268.jpg"/> <br/> 当面付的基础对接就到此结束。 <br/> 完结撒花! </br> </br> </br> </img> </br> </br>


网友评论:

自考院校 5个月前 (2020-11-14)
可以可以

深圳自考院校 6个月前 (2020-10-06)
博主大大着实是厉害啊,偷偷薅羊毛。。

小艾 10个月前 (2020-06-23)
。。。。。个人就能用几十天。

成人之美 11个月前 (2020-06-01)
当面付就是额度太小了。

北挽_ 1年前 (2020-04-08)
这个输入qq可以自动填写怎么搞,好6啊[#aru_17]

阿珏 1年前 (2020-04-09)
@北挽_:这个现在不是很场常的见吗,就那样那样写

北挽_ 1年前 (2020-04-09)
@阿珏:我的也搞上了,感觉好好玩,谢谢博主![#aru_17]

阿珏 1年前 (2020-04-14)
@北挽_:[#aru_53]

-- 1年前 (2020-04-07)
前排围观[#aru_8]

御神装-勿忘 1年前 (2020-04-04)
完结撒花[#aru_8]

posted @   阿珏酱  阅读(108)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示