评论

TinkPHP框架开发的CRMEB小程序商城v4.0二次开发集成支付宝支付

TinkPHP框架开发的CRMEB小程序商城v4.0二次开发集成支付宝支付

大家都知道支付宝支付和微信支付宝都局局在自己的平台,微信内支付宝支付是根本就不能使用,甚至是公众号支付也需要替换到外部浏览器才可以唤起支付宝支付,和QQ浏览器唤起支付宝支付还是问题很多,所以一般在微信生态内的应用一般都不考虑接收支付宝,但仍然有很多用户有这方面的需求,今天就给大家做个详细的接收流程!

开通支付宝支付

开通过程省略,可查看帮助文档:http 😕/help.crmeb.net/crmeb_zsff/1514732 ,

这是crmeb知识关于系统的支付宝支付,不过开通的流程都是一样的。

2.下载支付宝支付SDK

下载地址:https : //opendocs.alipay.com/open/54/103419

说明:新版SDK可用composer安装,当前使用的旧版本,是不能使用composer安装

3.创建aliapay支付类

创建路径:crmeb/services/AlipayService.php,

把下载好的文件解压在vendor目录中目录结构为:/vendor/alipay/

  1. AlipayService

采用单例设计模式,支付宝支付的SDK旧版本不能用composer加载此很不优雅了,不能在类初始化的时候加载,而且第一次加载时非常慢。

<?php
/ **

  • @作者:liaofei <136327134 @qq .com>
  • @day:2020/8/19
  • /

名称空间 crmeb \ services ;

使用 think \ exception \ ValidateException ;
使用 think \ facade \ Route 作为 Url ;
使用 思想\门面\日志;

/ **
*类支付宝服务

  • @package crmeb \ services

  • /
    类 AlipayService
    {
    / **

    • @var静态
    • /
      受保护的 静态$ instance;

    / **

    • @var字符串
    • /
      受保护的$ alipayAppId;

    / **

    • @var字符串
    • /
      受保护的$ alipayPublicKey;

    / **
    *支付宝

    • @var字符串
    • /
      受保护的$ alipayPrivateKey;

    / **
    *同步同步地址

    • @var字符串
    • /
      受保护的$ returnUrl;

    / **
    *初步输入地址

    • @var字符串
    • /
      受保护的$ notifyUrl;

    / **
    *请求网关

    / **
    *是否开启日志

    • @var bool
    • /
      protected $ isLog = false ;

    / **

    • AlipayService构造函数。
    • /
      受保护的 函数 __construct ()
      {
      $ this- > initialize();
      $ this- > options();
      }

    / **

    • @参数$ name
    • @参数$参数
    • /
      public function __call ($ name,$ arguments)
      {
      if(strstr($ name,‘set’)!== false){
      $ name = ucwords(substr($ name,3,-1));
      if(in_array($ name,[ ‘returnUrl’,‘isLog’,‘notifyUrl’,‘alipayPrivateKey’,‘alipayAppId’,‘alipayPublicKey’ ])){
      $ this- > {$ name} = $ arguments [ 0 ];
      }
      } else {
      throw new ValidateException(‘访问方法不存在’);
      }
      }

    / **
    *初始化加载阿里云pay

    • /
      受保护的 函数 initialize ()
      {
      $ dir = app()-> getRuntimePath()‘支付宝’ ;
      如果(!file_exists($ dir)){
      mkdir($ dir,0775,true);
      }
      define(‘AOP_SDK_WORK_DIR’,$ dir);
      包括app()-> getRootPath()。DS。“供应商”。DS。“支付宝”。DS。‘AopSdk.php’ ;
      }

    / **
    *获取参数配置

    • /
      受保护的 功能 选项()
      {
      $ this-> alipayAppId = sys_config(‘alipay_app_id’);
      $ this-> alipayPublicKey = sys_config(‘alipay_public_key’);
      $ this-> alipayPrivateKey = sys_config(‘alipay_private_key’);
      $ this-> returnUrl = Url :: buildUrl(’/ api / alipay / synchro ‘)-> domain(true)-> build();
      $ this-> notifyUrl = Url :: buildUrl(’/ api / alipay / notify’)-> domain(true)-> build();
      }

    / **

    • @返回静态
    • /
      公共 静态 函数 实例()
      {
      if(is_null(self :: $ instance)){
      self :: $ instance = new static();
      }
      返回 self :: $ instance;
      }

    / **
    *支付宝支付同步重组

    • /
      公共 静态 函数 aliPayReturn ()
      {

    }

    / **
    *支付支付同步预算

    • /
      公共 静态 函数 handleNotify ()
      {

    }

    / **
    *下单支付手机网站支付版本

    • @param string $ outTradeNo下单号
    • @param string $ totalAmount订单金额单位元
    • @param string $ subject订单标题
    • @param string $ passbackParams订单备注会原样返回通常用于替换监听函数
    • @param string $ productCode销售产品码,商家和支付宝签约的产品码
    • @param bool $ isView是否直接输出
    • @return $ response支付宝返回的信息
    • /
      公共 函数 aliPayWap (字符串$ outTradeNo,字符串$ totalAmount,字符串$ subject,字符串$ passbackParams,字符串$ productCode = ‘QUICK_MSECURITY_PAY’,bool $ isView = true)
      {

    }

    / **
    *统一收单交易重置接口

    • @param string $ outTradeNo下单订单号
    • @param string $ tradeNo支付宝订单号
    • @param string $ refundAmount兑换金额
    • @param string $ refundReason替换说明
    • @param string $ passbackParams备注
    • @return $ response支付宝返回的信息
    • /
      公共 职能 aliPayRefund (字符串$ outTradeNo,字符串$ tradeNo,字符串$ refundAmount,字符串$ refundReason,字符串$ passbackParams)
      {

    }

    / **
    *设置业务参数

    • @参数数组$ biz_content
    • @返回字符串
    • /
      受保护的 函数 setBizContent (数组$ bizContent = [])
      {
      if(isset($ bizContent [ ’ passback_params ’ ]))$ bizContent [ ’ passback_params ’ ] = urlencode($ bizContent [ ’ passback_params ’ ]);
      if(isset($ bizContent [ ‘trade_no’ ])&&空($ bizContent [ ‘trade_no’ ]))未设置($ bizContent [ ‘trade_no’ ]));
      $ bizContent = json_encode($ bizContent);
      //打印业务参数
      $ this-> isLog && $ this- > writeLog($ bizContent);
      返回$ bizContent;
      }

    / **
    *撰写日志

    • @param $ content字符串| 数组| 目的
    • @返回日志
    • /
      受保护的 函数 writeLog ($ content)
      {
      if(is_array($ content))$ content = ‘response:’。var_export($ content,true);
      如果(is_object($内容))$含量= ‘响应:’。var_export($ content,true);
      返回Log :: write(date(‘Ymd H:i:s’,time())。’’。$ content);
      }

}

首先要把从数据库中获取到的参数放入支付配置里

创建aopclientRequestExecute()方法把options()方法获取到的参数赋值给支付宝此方法会输出或直接返回HTML的文本,前分离分离可直接用返回提交数据。

/ **
 *初始化参数
 * @param $请求
 * @参数布尔$ isView
 * @return mixed | \ SimpleXMLElement | string | \提交表单HTML文本
 *抛出: \异常
 * /
受保护的 函数 aopclientRequestExecute (\ AlipayTradeWapPayRequest $ request,bool $ isView = false)
 {
    $ aop = new \ AopClient();
    //网管地址
    $ aop-> gatewayUrl = $ this-> gatewayUrl;
    // appid 
    $ aop-> appId = $ this-> alipayAppId;
    //私钥
    $ aop-> rsaPrivateKey = $ this-> alipayPrivateKey;
    //公钥
    $ aop-> alipayrsaPublicKey = $ this-> alipayPublicKey;
    //版本
    $ aop-> apiVersion = “ 1.0” ;
    //编码格式
    $ aop-> postCharset = 'UTF-8' ;
    //内容格式
    $ aop-> format = 'JSON' ;
    //加密方式
    $ aop-> signType = 'RSA2' ;
    //开启页面信息输出
    $ aop-> debugInfo = false ;
    如果($ isView){
        $ result = $ aop-> pageExecute($ request,“ post”);
        回声$结果;
    }其他{
        $ result = $ aop-> Execute($ request);
    }
    //打开后,将报文写入log文件
    $ this-> isLog && $ > writeLog($ result);
    返回$ result;
}

创建订单

上面已经创建好aliPayWap()方法,接下来我们来完成它,aliPayWap()方法的逻辑也非常简单,只需要支付订单号,支付金额,订单标题,订单备注。订单备注一般会原样返回的,这样可以利用订单备注来让初步相对执行对应的方法

例如有用户下单支付和用户充值替代方法为一个,为一个替代方法处理的逻辑就比较混乱。

/ **
 *下单支付手机网站支付版本
 * @参数 string $ outTradeNo下单号
 * @参数 string $ totalAmount订单金额单位元
 * @参数 string $ subject订单标题
 * @参数 string $ passbackParams订单备注会原样返回通常用于替换监听函数
 * @参数 string $ productCode销售产品码,商家和支付宝签约的产品码
 * @参数 bool $ isView是否直接输出
 * @返回 $ response支付宝返回的信息
 * /
公共 函数 aliPayWap (字符串$ outTradeNo,字符串$ totalAmount,字符串$ subject,字符串$ passbackParams,字符串$ productCode = 'QUICK_MSECURITY_PAY',bool $ isView = true)
 {
    $ request = new \ AlipayTradeWapPayRequest();
    //设置初始域名地址
    $ request-> setNotifyUrl($ this-> notifyUrl);
    //设置同步异步地址
    $ request-> setReturnUrl($ this-> returnUrl);
    //用内置方法格式化参数
    $ content = $ this-> setBizContent([
         'out_trade_no' => $ outTradeNo,
         'total_amount' => $ totalAmount,'subject' => $ subject,
         ' passback_params' => $ passbackParams
         ,
         'product_code' => $ productCode,
    ]);
    //设置下单参数
    $ request-> setBizContent($ content);
    //执行请求进行下单,返回对应的支付参数
    return  $ this this-> aopclientRequestExecute($ request,$ isView);
}

订单退款

aliPayRefund()方法负责退款处理,需要参数下单订单号,支付宝订单号,退款金额,替换说明,备注。支付宝订单号需要在支付支付替代中或者同步替换中获取更新在数据库中,方便替换处理。

/ **
*统一收单交易重置接口
* @参数 string $ outTradeNo下单订单号
* @参数 string $ tradeNo支付宝订单号
* @参数 string $ refundAmount兑换金额
* @参数 string $ refundReason替换说明
* @参数 string $ passbackParams备注
* @返回 $ response支付宝返回的信息
* /
公共 功能 aliPayRefund (字符串$ outTradeNo,字符串$ tradeNo,字符串$ refundAmount,字符串$ refundReason,字符串$ passbackParams)
{
$ request = new \ AlipayTradeRefundRequest();
$含量= $这- > setBizContent([
‘out_trade_no’ => $ outTradeNo,
‘trade_no’ => $ tradeNo,
‘REFUND_AMOUNT’ => $ REFUNDAMOUNT,
‘passback_params’ => $ passbackParams,
‘REFUND_REASON’ => $ refundReason,
‘product_code’ => $ passbackParams,
]);
$ request-> setBizContent($ content);
返回 $ this-> aopclientRequestExecute($ request);
}

初步验签

主要给初步和同步重新验证签名和数据处理方便调用

/ **
 *验签方法
 * @param array $ post验签支付宝返回的信息,使用支付宝公钥。
 * @返回布尔值
 * /
受保护的 函数 aliPaycheck (数组$ post)
 {
    $ aop =新 \ AopClient();
    $ aop-> alipayrsaPublicKey = $ this-> alipayPublicKey;
    return $ aop-> rsaCheckV1($ post,$ this-> alipayPrivateKey,'RSA2');
}

初步理论

创建最初的路由,修改文件:app / api / route / v1.php,在顶部中增加以下代码,别忘了创建对应的AlipayController文件

路线:: any(’ alipay / notify’,‘v1.alipay.AlipayController / notify’); //支付宝支付某些

首先需要处理支付包初始化返回的数据,再添加aliPayNotify()方法来解析处理异步替换返回的参数。

/ **
 *支付宝初步重新
 * @param callable $ notifyFn闭包函数参数1,替换返回的参数,实际结果
 * @返回布尔
 * /
受保护的 函数 aliPayNotify (可调用$ notifyFn)
 {
    $ post = app()->请求-> post();
    $ result = $ this-> aliPaycheck($ post);
    if($ result){
         //商户订单号
        $ post [ 'out_trade_no' ] = isset($ post [ 'out_trade_no' ])吗?$ post [ 'out_trade_no' ]:'' ;
        //支付宝交易号
        $ post [ 'trade_no' ] = isset($ post [ 'trade_no' ])?$ post [ 'trade_no' ]:'' ;
        //交易状态
        $ post [ 'trade_status' ] = isset($ post [ '])?$ post [ 'trade_status' ]:'' ;
        //评论
        $ post [ 'attach' ] = isset($ post [ 'passback_params' ])吗?urldecode($ post [ 'passback_params' ]):'' ;
        //如果初始化是成功执行
        try {
             if(is_callable($ notifyFn))$ notifyFn((object)$ post,$ result);
        } catch(\例外$ e){
             $ this-> isLog && $ this- > writeLog('支付宝支付成功,订单号为:'。$ post [ 'out_trade_no' ]。'。某些报错:'。$ e- > getMessage());
        }
        回声 “成功”;
    } else {
         echo'fail  ' ;
    }
    $ this-> isLog && $ this- > writeLog($ result);
    返回 true ;

}

执行instance()方法实例本类调用aliPayNotify()方法

/ **
 *支付宝支付同步重组
 * / 
public  static  function  aliPayReturn ()
 {
     self :: instance()-> aliPayNotify(function  ($ data,$ result)  {
         // $ data为支付宝重新返回通过解析后重组的数据
        // $ result为验签结果
        //这里要写异步初始化的逻辑
        //可根据$ data-> attach来判断需要执行的逻辑
        //可以调用TP6中的事件来执行对应的业务逻辑
        // event($ data-> attach,$ data )
    });
}

同步双向

同步替换使用在支付成功后替换回去的页面一遍验证下返回的数据是否正常,记录下支付宝订单号,或者其他逻辑

/ **
 *支付支付同步预算
 * /
公共 静态 函数 handleNotify ()
 {
     //获取返回参数
    $ get = app()-> request-> get();
    //验签成功与否
    $ result = self :: instance()-> aliPaycheck($ get);
    //记录日志
    self :: instance()-> isLog && self :: instance()-> writeLog(compact('result','get'));
    return compact('result','get');
}

其他的业务逻辑可根据自身需求编写,以上就是支付宝支付的下单,转换,异步同步转换

记得进入后台增加对应的支付宝配置。

作者:CRMEB

最后一次编辑于  10-14  
点赞 1
收藏
评论

1 个评论

  • 拎包哥
    拎包哥
    10-15

    你这是有后台服务器的玩法

    10-15
    赞同
    回复
登录 后发表内容