APP支付
1 组装请求参数
文档地址:opendocs.alipay.com/apis/api_1/ali...
由支付文档可知必填的参数有哪些,以下是组装好的请求参数:
public function getPayData ()
{
// 公共参数
$commonData = [
'app_id' => "支付宝分配给开发者的应用ID", // 应用appid
'method' => "alipay.trade.app.pay", // 接口名称
'charset' => 'utf-8', // 请求使用的编码格式
'sign_type' => 'RSA2', // 签名算法类型
'version' => '1.0', // 调用的接口版本
'notify_url' => "http://your.domain.com/notify", // 支付回调地址
'timestamp' => date("Y-m-d H:i:s", time()), // 发送请求的时间
];
// 非公共参数
$requestData = [
'total_amount' => round((100 / 100), 2), // 订单总金额(元)
'product_code' => 'QUICK_MSECURITY_PAY', // 销售产品码
'subject' => "商品标题", // 商品标题
'out_trade_no' => time(), // 订单号
];
$requestData['biz_content'] = json_encode($requestData); // 非公共参数
// 拼接成字符串
$postStr = $this->concatenationArray(array_merge($commonData, $requestData));
// 格式化商户私钥
$privateKey = $this->formatPrivateKeyInRsa("这里填商户私钥");
// 签名
$postData['sign'] = base64_encode($this->signInRsa($postStr, $privateKey));
// 返回支付链接给前端
return http_build_query($postData);
}
concatenationArray()
:将数组中拼接成字符串,具体代码见 1.1。formatPrivateKeyInRsa()
:格式化商户私钥,具体代码见 1.2。signInRsa()
:对请求参数进行签名,具体代码见 1.3。
1.1 拼接成字符串
public function concatenationArray ($postData)
{
ksort($postData);
$str = urldecode(http_build_query($postData)); // 拼接成字符串
return mb_convert_encoding($str, 'UTF-8'); // 转换成目标字符集
}
1.2 格式化商户私钥
/**
* 格式化私钥
*
* PKCS#1 RSA专用密钥格式:
* -----BEGIN RSA PRIVATE KEY-----
* BASE64 ENCODED DATA
* -----END RSA PRIVATE KEY-----
*/
private function formatPrivateKeyInRsa ($privateKey)
{
$formatedStr = $privateKey;
// 字符串没有以标准格式头开始时,认为是非格式化的
if (false === strpos($formatedStr, '-----BEGIN RSA PRIVATE KEY-----')) {
$formatedStr = "-----BEGIN RSA PRIVATE KEY-----\n";
$formatedStr .= wordwrap($privateKey, 64, "\n", true);
$formatedStr .= "\n-----END RSA PRIVATE KEY-----";
}
$key = openssl_get_privatekey($formatedStr);
return $key;
}
1.3 签名
/**
* RSA签名-使用PKCS#1
*
* @param string $postStr 要被签名的字符串
* @param string $privateKey 私钥
* @return false
*/
public function signInRsa ($postStr, $privateKey)
{
$signature = false;
openssl_sign($postStr, $signature, $privateKey, OPENSSL_ALGO_SHA256);
return $signature;
}
2 支付回调
文档地址:opendocs.alipay.com/open/204/10530...
用户支付完成后,支付宝会通知商户,商户需要在接受数据、处理数据后,返回应答。
回调地址是在步骤1中的notify_url
字段填写的。
public function notify()
{
$signData = request()->post();
// 检查回调参数是否正确
if (!isset($signData['sign']) && $signData['trade_status'] !== "TRADE_FINISHED")
return "false";
// 获取回调传来的签名
$notifySign = base64_decode($signData['sign']);
unset($signData['sign'], $signData['sign_type']); // 不参与验签的字段
// 转换成目标字符集
$str = urldecode(http_build_query($signData));
$toBeVerified = mb_convert_encoding($str, 'UTF-8');
// 格式化公钥
$formatPK = $this->formatPublicKey("这里填支付宝平台公钥");
// 验签
$verify=openssl_verify($toBeVerified,$notifySign,$formatPK,
OPENSSL_ALGO_SHA256);
if (!$verifyRes) return "false";
// TODO:按照业务更新订单支付状态等等
return "success";
}
formatPublicKey()
:格式化公钥,具体代码见 2.1。
2.1 格式化公钥
/**
* 格式化公钥
*
* PKCS#8通用密钥格式:
* -----BEGIN PUBLIC KEY-----
* 64字节长度的 base64 内容
* -----END PUBLIC KEY-----
*/
private function formatPublicKey($publicKey)
{
$formatedStr = $publicKey;
// 字符串没有以标准格式头开始时,认为是非格式化的
if (false === strpos($formatedStr, '-----BEGIN PUBLIC KEY-----')) {
$formatedStr = "-----BEGIN PUBLIC KEY-----\n";
$formatedStr .= wordwrap($publicKey, 64, "\n", true);
$formatedStr .= "\n-----END PUBLIC KEY-----";
}
$key = openssl_pkey_get_public($formatedStr);
return $key;
}
如果文章有帮到你的话,别忘了点赞收藏噢 :smile: