支付宝手机网页支付类解决方法
TP5小程序+公众号一键安装:http://github.crmeb.net/u/crmeb
支付宝手机网页端支付实用类 下载官方手机网站支付SDK&Demo php版本 https://docs.open.alipay.com/203/105910/
1 <?php 2 namespace service; 3 use think\Log; 4 use think\Request; 5 use think\Url; 6 use behavior\wechat\PaymentBehavior; 7 use service\HookService; 8 use service\SystemConfigService; 9 class AlipayTradeWapService 10 { 11 //异步通知地址 12 protected static $notifyUrl; 13 //同步跳转地址 14 protected static $returnUrl; 15 //支付宝公钥 16 protected static $alipayPublicKey; 17 //应用appid 18 protected static $alipayAppId; 19 //应用私钥 20 protected static $alipayPrivateKey; 21 //编码格式 22 protected static $charset='UTF-8'; 23 //请求网管 24 protected static $gatewayUrl='https://openapi.alipay.com/gateway.do'; 25 //加密方式 26 protected static $signType='RSA2'; 27 //是否开启调试模式 28 public static $isDeBug=true; 29 //获取不到配置信息错误次数 30 private static $ErrorCount=0; 31 //获取不到配置信息错误最大次数 32 private static $ErrorSum=3; 33 public function __construct($confing=[]) 34 { 35 self::$ErrorCount++; 36 if(self::$ErrorCount >= self::$ErrorSum) return exception('请配置支付宝公钥私钥APPID'); 37 if((!self::$alipayAppId || !self::$alipayPublicKey || !self::$alipayPrivateKey) && !$confing) self::confing(true); 38 if(isset($confing['returnUrl'])) self::$returnUrl=$confing['returnUrl']; 39 if(isset($confing['notifyUrl'])) self::$returnUrl=$confing['notifyUrl']; 40 if(isset($confing['signType'])) self::$signType=$confing['signType']; 41 if(isset($confing['charset'])) self::$charset=$confing['charset']; 42 if(isset($confing['alipay_public_key'])) self::$alipayAppId=$confing['alipay_public_key']; 43 if(isset($confing['alipay_public_key'])) self::$alipayPublicKey=$confing['alipay_public_key']; 44 if(isset($confing['alipay_private_key'])) self::$alipayPrivateKey=$confing['alipay_private_key']; 45 if(!self::$alipayAppId || !self::$alipayPublicKey || !self::$alipayPrivateKey) exception('请配置支付宝公钥私钥APPID'); 46 self::$ErrorCount=0; 47 } 48 /* 49 * 设置加密方式 50 * */ 51 public function setSignType($signType) 52 { 53 self::$signType=$signType; 54 } 55 /* 56 * 设置同步回调地址 57 * */ 58 public function setReturnUrl($returnUrl) 59 { 60 self::$returnUrl=$returnUrl; 61 } 62 /* 63 * 设置异步回调地址 64 * */ 65 public function setNotifyUrl($notifyUrl) 66 { 67 self::$notifyUrl=$notifyUrl; 68 } 69 /* 70 * 设置业务参数 71 * */ 72 protected static function setBizContent(array $biz_content=[]) 73 { 74 if(isset($biz_content['passback_params'])) $biz_content['passback_params']=urlencode($biz_content['passback_params']); 75 if(isset($biz_content['trade_no']) && empty($biz_content['trade_no'])) unset($biz_content['trade_no']); 76 $bizContent=json_encode($biz_content); 77 //打印业务参数 78 self::$isDeBug && self::WriteLog($bizContent); 79 return $bizContent; 80 } 81 /* 82 * 获取同步回调地址 83 * */ 84 public function getReturnUrl() 85 { 86 return self::$returnUrl; 87 } 88 /* 89 * 获取异步回调地址 90 * */ 91 public function getNotifyUrl() 92 { 93 return self::$notifyUrl; 94 } 95 /* 96 * 读取系统配置赋值给静态变量 并加载支付宝官方支付sdk 97 * */ 98 public static function confing($isReturn=false){ 99 $confing=SystemConfigService::more([ 100 'alipay_public_key', 101 'alipay_app_id', 102 'alipay_private_key', 103 ]); 104 self::$alipayAppId=isset($confing['alipay_app_id']) ? trim($confing['alipay_app_id']) : ''; 105 self::$alipayPublicKey=isset($confing['alipay_public_key']) ? trim($confing['alipay_public_key']) : ''; 106 self::$alipayPrivateKey=isset($confing['alipay_private_key']) ? trim($confing['alipay_private_key']) : ''; 107 self::$returnUrl=SystemConfigService::get('site_url').Url::build('wap/Alipay/alipay_success_synchro'); 108 self::$notifyUrl=SystemConfigService::get('site_url').Url::build('wap/Alipay/alipay_success_notify'); 109 vendor('alipay.AopSdk'); 110 if($isReturn==false) return new self; 111 } 112 /* 113 * 静态调用初始化数据 114 * */ 115 public static function init() 116 { 117 return self::confing(); 118 } 119 /* 120 * 支付宝异步回调 121 * */ 122 public static function handleNotify(){ 123 self::init()->AliPayNotify(function ($data,$result){ 124 HookService::listen('wechat_pay_success',$data,null,true,PaymentBehavior::class); 125 }); 126 } 127 /* 128 * 支付宝异步回调 129 * @param callable $notifyFn 闭包函数 参数1,回调返回的参数,回调结果 130 * @return boole 131 * */ 132 protected function AliPayNotify(callable $notifyFn) 133 { 134 $post=Request::instance()->post(); 135 $result=self::AliPaycheck($post); 136 if($result){ 137 //商户订单号 138 $post['out_trade_no'] =isset($post['out_trade_no']) ? $post['out_trade_no'] : ''; 139 //支付宝交易号 140 $post['trade_no'] =isset($post['trade_no']) ? $post['trade_no'] : '' ; 141 //交易状态 142 $post['trade_status'] =isset($post['trade_status']) ? $post['trade_status'] : ''; 143 //备注 144 $post['attach']=isset($post['passback_params']) ? urldecode($post['passback_params']) : ''; 145 //异步回调成功执行 146 try{ 147 if(is_callable($notifyFn)) $notifyFn((object)$post,$result); 148 }catch (\Exception $e){ 149 self::$isDeBug && self::WriteLog('支付宝支付成功,订单号为:'.$post['out_trade_no'].'.回调报错:'.$e->getMessage()); 150 } 151 echo 'success'; 152 }else{ 153 echo 'fail'; 154 } 155 self::$isDeBug && self::WriteLog($result); 156 return true; 157 } 158 /* 159 * 支付宝同步回调 160 * @param array 161 * */ 162 public function AliPayReturn() 163 { 164 //获取返回参数 165 $get=Request::instance()->get(); 166 //验签成功与否 167 $result=self::AliPaycheck($get); 168 //记录日志 169 self::$isDeBug && self::WriteLog(compact('result','get')); 170 return compact('result','get'); 171 } 172 /** 173 * 验签方法 174 * @param $arr 验签支付宝返回的信息,使用支付宝公钥。 175 * @return boolean 176 */ 177 protected static function AliPaycheck($post){ 178 $aop = new \AopClient(); 179 $aop->alipayrsaPublicKey =self::$alipayPublicKey; 180 return $aop->rsaCheckV1($post,self::$alipayPrivateKey,self::$signType); 181 } 182 /* 183 * 初始化参数 184 * @return object 185 * */ 186 protected static function AopclientRequestExecute($request,$ispage=false){ 187 $aop = new \AopClient (); 188 //网管地址 189 $aop->gatewayUrl =self::$gatewayUrl; 190 //appid 191 $aop->appId =self::$alipayAppId; 192 //私钥 193 $aop->rsaPrivateKey =self::$alipayPrivateKey; 194 //公钥 195 $aop->alipayrsaPublicKey =self::$alipayPublicKey; 196 //版本 197 $aop->apiVersion ="1.0"; 198 //编码格式 199 $aop->postCharset = self::$charset; 200 //内容格式 201 $aop->format= 'JSON'; 202 //加密方式 203 $aop->signType=self::$signType; 204 // 开启页面信息输出 205 $aop->debugInfo=true; 206 if($ispage) { 207 $result = $aop->pageExecute($request, "post"); 208 echo $result; 209 }else 210 $result = $aop->Execute($request); 211 //打开后,将报文写入log文件 212 self::$isDeBug && self::WriteLog($result); 213 return $result; 214 } 215 /** 216 * alipay.trade.wap.pay 下单支付手机网站支付版本 217 * @param $out_trade_no 下单号 218 * @param $total_amount 订单金额 单位元 219 * @param $subject 订单标题 220 * @param $passback_params 订单备注 会原样返回通常用于回调监听函数 221 * @param $product_code 销售产品码,商家和支付宝签约的产品码 222 * @param $ispage 是否直接输出 223 * @return $response 支付宝返回的信息 224 */ 225 public function AliPayWap($out_trade_no,$total_amount,$subject,$passback_params,$product_code='QUICK_MSECURITY_PAY',$ispage=true) { 226 $request = new \AlipayTradeWapPayRequest(); 227 $request->setNotifyUrl(self::$notifyUrl); 228 $request->setReturnUrl(self::$returnUrl); 229 $request->setBizContent(self::setBizContent(compact('out_trade_no','total_amount','subject','passback_params','product_code'))); 230 return self::AopclientRequestExecute($request,$ispage); 231 } 232 /** 233 * alipay.trade.query (统一收单线下交易查询) 234 * @param $out_trade_no 下单号 235 * @param $trade_no 支付宝订单号 236 * @param $passback_params 订单备注 会原样返回通常用于回调监听函数 237 * @return $response 支付宝返回的信息 238 */ 239 public function AliPayQuery($out_trade_no,$trade_no,$passback_params){ 240 $request = new \AlipayTradeQueryRequest(); 241 $request->setBizContent (self::setBizContent(compact('out_trade_no','passback_params','trade_no'))); 242 return self::AopclientRequestExecute($request); 243 } 244 /** 245 * alipay.trade.refund (统一收单交易退款接口) 246 * @param $out_trade_no 下单订单号 247 * @param $trade_no 支付宝订单号 248 * @param $refund_amount 退款金额 249 * @param $refund_reason 退款说明 250 * @param $passback_params 备注 251 * @return $response 支付宝返回的信息 252 */ 253 public function AliPayRefund($out_trade_no,$trade_no,$refund_amount,$refund_reason,$passback_params){ 254 $request = new \AlipayTradeRefundRequest(); 255 $request->setBizContent (self::setBizContent(compact('out_trade_no','trade_no','refund_amount','refund_reason','passback_params','product_code')) ); 256 return self::AopclientRequestExecute($request); 257 } 258 /** 259 * alipay.trade.close (统一收单交易关闭接口) 260 * @param $out_trade_no 订单号 261 * @param $trade_no 支付宝订单号 262 * @return $response 支付宝返回的信息 263 */ 264 public function AliPayClose($out_trade_no,$trade_no){ 265 $request = new \AlipayTradeCloseRequest(); 266 $request->setBizContent (self::setBizContent(compact('out_trade_no','trade_no'))); 267 return self::AopclientRequestExecute($request); 268 } 269 /* 270 * 写入日志 271 * @param $content string | array | object 272 * @return boolen 273 * */ 274 public static function WriteLog($content){ 275 try{ 276 Log::init([ 277 'type' => 'File', 278 'path' => LOG_PATH.'alipay/' 279 ]); 280 if(is_array($content)) $content='response: ' .var_export($content,true); 281 if(is_object($content)) $content='response: '.var_export($content,true); 282 Log::write(date('Y-m-d H:i:s',time()).' '.$content); 283 }catch (\Exception $e){} 284 } 285 }