移动应用端的支付宝支付php开发流程
1、https://openhome.alipay.com/ 支付宝开放平台并创建应用,审核通过后并签约app支付拿到pid
2、按照官方文档用 【RSA签名验签工具.bat】生成应用公钥和私钥
3、下载支付宝官方demo(https://docs.open.alipay.com/54/106370/根据自己的开发语言下载)包整合到项目中(说实话这个php的demo着实有些坑)
整合好开始写支付宝支付类代码如下:
<?php namespace data\extend; use data\extend\alipay_app\aop\AopClient; use data\extend\alipay_app\aop\request\AlipayTradeAppPayRequest as AlipayTradeAppPayRequest; /** * 功能说明:自定义支付宝支付接入类 */ class AliPayApp { protected $aop; /** * 初始化 */ public function __construct() { $this->aop = new AopClient(); $this->aop->gatewayUrl = "https://openapi.alipay.com/gateway.do"; $this->aop->appId = "步骤一中拿到的应用appid"; $this->aop->rsaPrivateKey = "*******";//私有密钥(步骤二中生成的商户私有秘钥) $this->aop->format = "JSON"; $this->aop->charset = "utf-8"; $this->aop->signType = "RSA2"; $this->aop->alipayrsaPublicKey = "****";//商户公钥(步骤二中生成的商户公钥) $this->aop->alipayPublicKey = "*****";//支付宝公钥 } /** * 创建APP支付订单 * * @param string $body 对一笔交易的具体描述信息。 * @param string $subject 商品的标题/交易标题/订单标题/订单关键字等。 * @param string $order_sn 商户网站唯一订单号 * @return array 返回订单信息 */ public function createAppPay($order_sn,$body, $subject, $total_amount) { //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay $request = new AlipayTradeAppPayRequest(); //SDK已经封装掉了公共参数,这里只需要传入业务参数 $bizcontent = [ 'body' => $body, 'subject' => $subject, 'out_trade_no' => $order_sn, 'timeout_express' => '1d',//失效时间为 1天 'total_amount' => $total_amount,//价格 'product_code' => 'QUICK_MSECURITY_PAY', ]; //商户外网可以访问的异步地址 (异步回掉地址,根据自己需求写) $request->setNotifyUrl("http://".$_SERVER['HTTP_HOST']."/此处为回调通知地址"); $request->setBizContent(json_encode($bizcontent)); //这里和普通的接口调用不同,使用的是sdkExecute $response = $this->aop->sdkExecute($request); return $response; //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题 } /** * 异步通知验签 * * @param string $params 参数 * @param string $signType 签名类型:默认RSA * @return bool 是否通过 */ public function rsaCheck($params, $signType) { return $this->aop->rsaCheckV1($params, NULL, $signType); } }
上面代码注意在调用 data\extend\alipay_app\aop\AopClient 这个类需要注意回调验签的过程调用 $this->aop->rsaCheckV1()这个类进行通知的sign和post回来的参数(此处需要主要验签过程按照官方要求去掉sign和sign_type后)重新组装+支付宝公钥($this->aop->alipayPublicKey切记不是应用公钥)代码稍作调整如下
/** rsaCheckV1 & rsaCheckV2 * 验证签名 * 在使用本方法前,必须初始化AopClient且传入公钥参数。 * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。 **/ public function rsaCheckV1($params, $rsaPublicKeyFilePath,$signType='RSA') { $sign = $params['sign']; $params['sign_type'] = null; $params['sign'] = null; return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath,$signType); } function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA') { if($this->checkEmpty($this->alipayPublicKey)){ $pubKey= $this->alipayrsaPublicKey; $res = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; //logWrite("商户RSA公钥".$res); }else { //读取公钥文件(注释部分为原来) //$pubKey = file_get_contents($rsaPublicKeyFilePath); //转换为openssl格式密钥 //$res = openssl_get_publickey($pubKey);
//此处更改为支付宝公钥验签 $pubKey= $this->alipayPublicKey; $res = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; // logWrite("支付宝RSA公钥".$res); } ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确'); //调用openssl内置方法验签,返回bool值 //logWrite("签名:".$sign); if ("RSA2" == $signType) { $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256); } else { $result = (bool)openssl_verify($data, base64_decode($sign), $res); } if(!$this->checkEmpty($this->alipayPublicKey) && is_file($this->alipayPublicKey)) { //释放资源 openssl_free_key($res); } //logWrite("验签结果:".var_export($result,true)); return $result; }
至此基本大功告成,最后一步是APP端的调用代码如下:
public function aliPayApp() { $out_trade_no = $this->GetReqArgc('out_trade_no'); if (empty($out_trade_no)) { $this->error("没有获取到支付信息"); } $data = $this->getPayInfo($out_trade_no); if($data < 0) { return $data; } $ali_pay = new AliPayApp(); $retval = $ali_pay->createAppPay($out_trade_no, $data['pay_body'], $data['pay_detail'], $data['pay_money']); if($res){ $this->ExitMessage(SUCCESS,"",array("out_trade_no"=>$out_trade_no,"retData"=>$res)); }else{ $this->ExitMessage(ERROR_CODE,"支付宝参数错误",0); } }
以上接口返回给APP端后唤起快捷SDK创建订单并支付的参数后即可调起支付宝APP进行支付操作,最后就是通知处理支付结果的业务逻辑如下代码:
public function payCallback(){ $request = input('post.'); $pay = new AliPayApp(); $verify = $pay->rsaCheck($params,$signType); if ($verify_result) { // 验证成功 $out_trade_no = $request['out_trade_no']; // 支付宝交易号 $trade_no = $request['trade_no']; // 交易状态 $trade_status = $request['trade_status']; //logWrite("支付成功了"); if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') { //此处支付成功后的业务逻辑处理根据自己需求 echo "success"; // 请不要修改或删除 } } else { // 验证失败 echo "fail"; } }
ok大功告成!说实话支付宝支付还是比微信支付要好许多虽然也有坑,但微信支付的坑是比较多的!
一个人静静坐在电脑面前写代码的感觉,那是什么感觉?那是武林高手闭关修炼的感觉。