支付宝公钥证书支付示例

Posted 禹爸爸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了支付宝公钥证书支付示例相关的知识,希望对你有一定的参考价值。

支付宝公钥证书支付示例

支付宝平台仅提供了普通公钥签名方式的电脑支付DEMO(下载),并未提供使用公钥证书的电脑支付DEMO,在阅读了老版的SDK之后,自己编写了这个DEMO。

效果图

支付测试页面
支付测试页面支付宝默认支付页面
支付宝默认支付页面前置支付生成的支付二维码,用于嵌在商品页面。
前置支付二维码

开发前的准备

创建支付应用

登录支付宝开放平台,创建新的应用。依次点击”创建应用“ --> ”网页&移动应用“–>”支付接入“,根据页面提示,补充完整所需信息。
创建支付应用

添加支付能力

支付应用能力列表

生成公钥证书

使用阿里支持提供的公钥证书在线生成工具生成公钥证书。

密钥长度推荐选择RAS2,密钥格式分为JAVA适用非JAVA适用两种,本文中使用的php,所以选择了非JAVA适用
生成密钥点击”生成CSR“按钮,会弹出新的窗口用来填写创建证书文件所需的信息。点击”生成CSR并保存“按钮,会自动下载一个压缩包文件,这其中包含了三个文件:应用公钥应用私钥CSR文件
生成CSR至此,离证书生成还有一步之遥。回到支付宝开放平台,并进入刚刚创建的支付应用,点击左侧的”应用信息“菜单,设置接口加签方式。
修改加签方式在这里选择公钥证书,并上传刚刚通过加密工具生成的CSR文件。
加签CSR证书验通过后,可以看到如下图所示的三个证书下载链接。
在这里插入图片描述
保存好这三份证书文件,以及通过密钥工具生成的应用公钥和私钥

验证密钥证书是否匹配

通常情况下是可以跳过这一步的。在测试阶段如果遇到类似错误提示密钥不匹配时,可以按照支付宝官方文档指导来验证密钥证书是否匹配。

下载服务器端SDK

PHP SDK(老版) 下载

编写DEMO

待上面所有准备工作完成后,我们就可以真刀实枪的开始编写测试DEMO了。

支付测试页面

我们需要先编写效果图中的支付测试页面,用于灵活录入支付所需的一些参数,如商户订单号、订单名称、商品描述、订单金额等。

<body text=#000000 bgColor="#ffffff" leftMargin=0 topMargin=4>
<header class="am-header">
    <h1>支付宝电脑网站支付(公钥证书)支付体验入口页</h1>
</header>
<div id="main">
    <form name=alipayment action=pagepay.php method=post target="_blank">
        <div id="body1" name="divcontent">
            <dl class="content">
                <dt>商户订单号 Out Trade No :</dt>
                <dd>
                    <input type="text" id="WIDout_trade_no" name="WIDout_trade_no" />
                </dd>
                <hr class="one_line">
                <dt>订单名称 Subject :</dt>
                <dd>
                    <input type="text" id="WIDsubject" name="WIDsubject" value="Payment order for Learning Mall course"/>
                </dd>
                <hr class="one_line">
                <dt>付款金额 Amount:</dt>
                <dd>
                    <input type="text" id="WIDtotal_amount" name="WIDtotal_amount" value="0.01"/>
                </dd>
                <hr class="one_line">
                <dt>商品描述 Body:</dt>
                <dd>
                    <input type="text" id="WIDbody" name="WIDbody" value="Payment Testing"/>
                </dd>
                <hr class="one_line">
                <dt>支付网关 Payment Gateway:</dt>
                <dd>
                    <input type="text" id="gateway" name="gateway" value="https://openapi.alipay.com/gateway.do" />
                </dd>
                <hr class="one_line">
                <dt>通知地址 Notify URL</dt>
                <dd>
                    <input type="text" id="notify_url" name="notify_url" value="" />
                </dd>
                <hr class="one_line">
                <dt>回调地址 Return URL</dt>
                <dd>
                    <input type="text" id="return_url" name="return_url" value="" />
                </dd>
                <hr class="one_line">
                <dt>支付宝公钥根路径 Root Cert Path:</dt>
                <dd>
                    <input type="text" id="root_cert_path" name="root_cert_path" value="/Users/cmao/Sites/alipay-sdk-php-all-master/cert/alipayRootCert.crt" />
                </dd>
                <hr class="one_line">
                <dt>支付宝公钥证书路径 Public Cert Path:</dt>
                <dd>
                    <input type="text" id="alipay_cert_path" name="alipay_cert_path"value="/Users/cmao/Sites/alipay-sdk-php-all-master/cert/alipayCertPublicKey_RSA2.crt" />
                </dd>
                <hr class="one_line">
                <dt>应用公钥证书路径 App Public Cert Path:</dt>
                <dd>
                    <input type="text" id="app_cert_path" name="app_cert_path" value="/Users/cmao/Sites/alipay-sdk-php-all-master/cert/appCertPublicKey_2021002142621183.crt" />
                </dd>
                <hr class="one_line">
                <dt>生成支付二维码 Generate QR Code:</dt>
                <dd>
                    <input type="checkbox" id="qr_pay_mode" name="qr_pay_mode" value="4"/>
                    <span class="note-help">如果勾选,表示生成支付二维码,否则会跳转到支付宝默认的支付页面。</span>
                </dd>
                <hr class="one_line">
                <dt></dt>
                <dd id="btn-dd">
                    <span class="new-btn-login-sp">
                        <button class="new-btn-login" type="submit" style="text-align:center;">付 款</button>
                    </span>
                    <span class="note-help">如果您点击“付款”按钮,即表示您同意该次的执行操作。</span>
                </dd>
            </dl>
        </div>
    </form>
</div>
</body>
<script language="javascript">
	function GetDateNow() {
		var vNow = new Date();
		var sNow = "";
		sNow += String(vNow.getFullYear());
		sNow += String(vNow.getMonth() + 1);
		sNow += String(vNow.getDate());
		sNow += String(vNow.getHours());
		sNow += String(vNow.getMinutes());
		sNow += String(vNow.getSeconds());
		sNow += String(vNow.getMilliseconds());
		document.getElementById("WIDout_trade_no").value =  sNow;
	}
	GetDateNow();
</script>

网页支付

整个代码分为三部分内容:

  1. 创建AopClient实例并初始化。
  2. 创建API请求对象并设置request参数。
  3. 发起请求并处理响应或异常。
<?php

require_once '../aop/AopCertClient.php';
require_once '../aop/request/AlipayTradePagePayRequest.php';

//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = trim($_POST['WIDout_trade_no']);
//订单名称,必填
$subject = trim($_POST['WIDsubject']);
//付款金额,必填
$total_amount = trim($_POST['WIDtotal_amount']);
//商品描述,可空
$body = trim($_POST['WIDbody']);
//支付宝根证书路径
$rootCertPath = trim($_POST['root_cert_path']);
//支付宝公钥证书路径
$alipayCertPath = trim($_POST['alipay_cert_path']);
//应用证书路径
$appCertPath = trim($_POST['app_cert_path']);
// 阿里支付网关
$gateway = $_POST['gateway'] ? trim($_POST['gateway']): 'https://openapi.alipay.com/gateway.do';


$aop = new AopCertClient ();
// 支付应用APP ID
$aop->appId = '2021002142621183';
// 阿里支付网关
$aop->gatewayUrl = $gateway;
//返回数据格式
$aop->format='json';
//签名类型
$aop->signType='RSA2';
//是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内
$aop->isCheckAlipayPublicCert = true;
//调用getCertSN获取证书序列号
$aop->appCertSN = $aop->getCertSN($appCertPath);
//调用getRootCertSN获取支付宝根证书序列号
$aop->alipayRootCertSN = $aop->getRootCertSN($rootCertPath);
//调用getPublicKey从支付宝公钥证书中提取公钥
$aop->alipayrsaPublicKey = $aop->getPublicKey($alipayCertPath);
//应用私钥
$aop->rsaPrivateKey = 'YOUR PRIVATE KEY';

//实例化具体API对应的request类
$request = new AlipayTradePagePayRequest();
//通知地址
$request->setNotifyUrl(trim($_POST['notify_url']));
//回调地址
$request->setReturnUrl(trim($_POST['return_url']));
//设置业务参数
$request->setBizContent("{" .
    ($_POST['qr_pay_mode'] ? "\\"qr_pay_mode\\":\\"4\\",\\"qrcode_width\\":\\"100\\"," : "") .
    "\\"out_trade_no\\":\\"" . $out_trade_no ."\\"," .
    "\\"total_amount\\":\\"" . $total_amount . "\\"," .
    "\\"subject\\":\\"" . $subject . "\\"," .
    "\\"body\\":\\"" . $body . "\\",".
    "\\"product_code\\": \\"FAST_INSTANT_TRADE_PAY\\"".
    "}");
//生成签名
$aop->generateSign($request);

echo $aop->pageExecute($request);

完成支付测试页面和网页支付的代码后,如果你的证书、私钥都正确的话,应该是可以跳转到支付宝默认支付页面进行扫码支付了(如下图)。
支付宝默认支付页面
这种PC扫码支付的方式为跳转支付,阿里开放平台同时还提供了前置支付。

前置支付

前置模式是将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体分为以下几种:

  • 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;
  • 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px;
  • 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px;
  • 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。
//设置业务参数
$request->setBizContent("{" .
    ($_POST['qr_pay_mode'] ? "\\"qr_pay_mode\\":\\"4\\",\\"qrcode_width\\":\\"100\\"," : "") .
    "\\"out_trade_no\\":\\"" . $out_trade_no ."\\"," .
    "\\"total_amount\\":\\"" . $total_amount . "\\"," .
    "\\"subject\\":\\"" . $subject . "\\"," .
    "\\"body\\":\\"" . $body . "\\",".
    "\\"product_code\\": \\"FAST_INSTANT_TRADE_PAY\\"".
    "}");

这里的qr_pay_mode参数指定了支付方式,更多电脑网页支付参数看这里

以下是qr_pay_mode参数设置为4的支付二维码截图,开发者可以将这个二维码嵌到商品页面中。
前置支付二维码

遇到的问题

alipay_root_cert_sn为空

在确保证书路径配置正确的情况下,这个问题极大可能是因为www-data对存放证书的目录没有正确访问权限造成的。通过修改目录访问权限可解决此问题。

以上是关于支付宝公钥证书支付示例的主要内容,如果未能解决你的问题,请参考以下文章

支付宝公钥证书支付示例

支付宝公钥证书支付示例

支付宝线上支付示例

支付宝支付对接过程

PHP 转账到支付宝账户

PHP 转账到支付宝账户