支付宝当面付自行实现签名及整个流程(php)

一直不太喜欢用官方的sdk。因为如果有更新,还要重新下载sdk,还要修改一些东西。感觉挺不方便的。所以我一般都是调用api生撸。但是支付宝的文档真的很生涩,调试半天终于弄好了。记录一下吧。

直接上代码:

$time = time();
            try{
                $order = self::$db->table('scanpay_order')->add(array('amount' => $amount, 'marketid' => $marketid, 'deskid' => $cashier_desk, 'cashier_uid' => $cashier_uid, 'dateline' => $time, 'pay_type' => 2));
                //上面这一行,是往数据库写一条记录。根据你的业务逻辑,这一步也可以省略。对你来说语法可能并不完全熟悉,因为我用的是我自己写的一个php框架。
            }catch(\Exception $e){
                return array('code' => -101, 'message' => $e->getMessage());
            }
            vendor('WXSdk/WXSdk');
            $wxsdk = new \WXSdk("", "");
            //上面这2行,是为了后面调用curl准备的。你也可以不用管它。它也是我自己写的一个小工具。
            $appid = '2021004104687588';
            $method = 'alipay.trade.pay';
            $charset = 'utf-8';
            $sign_type = 'RSA2';
            $timestamp = date('Y-m-d H:i:s', $time);
            $version = '1.0';
            
            $out_trade_no = 'scanpay_ali_' . $order;  
            //上面这行是商户自已的订单号,这个你自己定。方便使用就好。
            $total_amount = $amount;//这个是订单金额。单位是元
            $subject = 'WormJan的商品'; //商品标题
            $auth_code = $code;    //这个就是扫描到的用户的支付条码了
            $scene = 'bar_code';  //固定
            
            $arr = array('out_trade_no' => $out_trade_no, 'total_amount' => $total_amount, 'subject' => $subject, 'auth_code' => $auth_code, 'scene' => $scene);

            $biz_content = json_encode($arr);

            $arr_final = array('app_id' => $appid, 'method' => $method, 'charset' => $charset, 'sign_type' => $sign_type, 'timestamp' => $timestamp, 'version' => $version, 'biz_content' => $biz_content);

            $str = $wxsdk->order_str($arr_final);   
            //上面这个是按键值排序,然后生成 a=b&c=d 这样的字符串。后面我把这个方法贴出来吧。这个是我小工具里的一个方法。可以自己写
            $str = urldecode($str);

            $signature = '';
            $priv_key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/cert_alipay/app_private_key.txt');   //应用私钥。这个要注意了。从支付宝工具中生成的私钥,是纯base64的,你要在内容前面加上一行 -----BEGIN RSA PRIVATE KEY-----,在后面另起一行加上 -----END RSA PRIVATE KEY-----  ,私钥内容要在一行里面。那么也就是说,密钥文件里一共三行内容。
            $priv_key = wordwrap($priv_key, 64, "\n", true);  //从网上找的,说必须这么整一下。我就听了。
            $key = openssl_pkey_get_private($priv_key);
            if($key === false){
                debug("openssl_get_privatekey失败" . openssl_error_string()); 
                //debug我自己写的一个函数。这个随便你了,可以不用。
            }
            openssl_sign($str, $signature, $key, 'SHA256');
            openssl_free_key($key);
            $sign = base64_encode($signature);   //这个就是最终的sign了。

            $post_final = $str . "&sign=" . urlencode($sign);  //传递的时候,要encode一下

            $url = 'https://openapi.alipay.com/gateway.do';

            $result = $wxsdk->curl_post_ssl($url, $post_final); 
            //curl向支付宝网关提交数据。这个是我小工具里的方法。大家可以自行写一下。后面我传上来也行
            $result = (array)json_decode($result, true); 
            //上面这一行将返回结果由json转为数组,方便取值
            $result['out_trade_no'] = $out_trade_no;    
            //根据业务逻辑,上面这一行不要也可以
            return($result);

下面是我的curl函数

public function curl_post_ssl($url, $vars, $cert = '', $key = ''){
			$ch = curl_init();
			curl_setopt($ch,CURLOPT_TIMEOUT, 30);
			curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch,CURLOPT_URL, $url);
			curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);

			//以下两种方式需选择一种
			if($cert != ''){
				curl_setopt($ch, CURLOPT_SSLCERT, $cert);
			}
			if($key != ''){
				curl_setopt($ch, CURLOPT_SSLKEY, $key);
			}

			curl_setopt($ch,CURLOPT_POST, true);
			curl_setopt($ch,CURLOPT_POSTFIELDS, $vars);
			$data = curl_exec($ch);
			if($data){
				curl_close($ch);
				return $data;
			} else {
				$error = curl_errno($ch);
				echo "call faild, errorCode:$error\n";
				curl_close($ch);
				return false;
			}
		}
//vars 就是要传递的参数。这里是字符串。 cert 和key用不到。因为我们用的是密钥方式。

下面是我的字符串排序的函数

function order_str($param){
            if(!$param){
				return false;
			}
			//按键排序
			ksort($param);
			
			//拿到待签名字符串
			$str = http_build_query($param);
            return $str;
        }
//param 参数是一个数组。就是你要排序的那些内容。
/*例如:
array("b" => 2, "a" => 1)
会给你弄成  a=1&b=2
*/

你可能感兴趣的:(php,开发语言)