准备
需求
需求就是最简单的对接微信H5支付接口
方案心路历程
- 之前直接用http对接过,不过这次想用官方提供的SDK
- 一方面SDK提供的接口比较完整,二方面感觉应该使用别人辛苦写下来的封装
- 百度了一下官方文档
注:上述的上个文档下面姑且成为D1 D2 D3
实操
微信商户平台配置
注:这里是后面回忆编写,可能有点出入,后续有再进行实操时再截图回来进行完善 一下会获取几个关键信息 标注为kn
获取基本配置
登录微信商户平台—进入后台—我忘了[狗头] k1 mchId 商户id k2 appid 商户appid
API证书
进入后台—点击账户中心—API安全—API证书管理—申请证书—按照指示操作 k3 API证书序列号 k4 API证书KEY 文件名是apiclient_key.pem ,其他文件在v3 接口中暂时没有使用到 拿到的证书中有一个文件为apiclient_cert.pem 注意这个是API证书,并不是下面使用到的平台证书
v3key
API安全—申请v3key—申请证书 k5 v3key
编码
这里我们使用的是laravel框架为例 接口是H5支付,使用的是v3接口对接
查看 D2 引入SDK
composer require wechatpay/wechatpay
微信商户服务类-引入SDK
<?php
namespace App\Services\Support\Wechat;
use App\Utils\Common\HttpC;
use Illuminate\Support\Facades\Log;
use WeChatPay\Builder;
use WeChatPay\Util\PemUtil;
class Mch
{
private $merchantId = '';
private $instance = null;
public function baseUrl()
{
return config('wechat.mch.base_url');
}
public function __construct()
{
$this->merchantId = config('wechat.mch.id');
$merchantPrivateKeyFilePath = config('wechat.mch.ssl_key');
$merchantPrivateKeyInstance = PemUtil::loadPrivateKey($merchantPrivateKeyFilePath);
$merchantCertificateSerial = config('wechat.mch.serial');
$platformCertificateFilePath = config('wechat.mch.wechatpay_cert');
$platformCertificateInstance = PemUtil::loadCertificate($platformCertificateFilePath);
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateInstance);
$this->instance = Builder::factory([
'mchid' => $this->merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformCertificateInstance,
],
]);
}
public function pay($data)
{
try {
$resp = $this->instance
->v3->pay->transactions->h5
->post(['json' => [
'mchid' => $this->merchantId,
'out_trade_no' => $data['out_trade_no'],
'appid' => config('wechat.mch.appid'),
'description' => $data['description'],
'notify_url' => $data['notify_url'],
'amount' => [
'total' => $data['amount'],
'currency' => 'CNY'
],
'scene_info' => [
"payer_client_ip" => $data['ip'],
"h5_info" => [
"type" => $data['h5_type'] ?? "Wap"
]
]
]]);
$code = $resp->getStatusCode();
$message = $resp->getReasonPhrase();
$body = $resp->getBody();
Log::info(sprintf("Wechat/Mch->pay statusCode: %s, reasonPhrase: %s, body: %s", $code, $message, $body));
$res = [
'code' => $code,
'data' => json_decode($body, true) ?? [],
'message' => $message
];
} catch (\Exception $e) {
Log::error("Fail to Wechat/Mch->pay: " . $e->getMessage() . "\n");
$code = 500;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
Log::error("" . $r->getStatusCode() . ' ' . $r->getReasonPhrase() . "\n");
Log::error("" . $r->getBody()->getContents() . "\n\n\n");
$code = $r->getStatusCode();
}
Log::error("getTraceAsString: " . $e->getTraceAsString() . "\n");
$res = [
'code' => $code,
'data' => json_decode($body, true) ?? [],
'message' => $e->getMessage() ?? '请稍后重试'
];
}
return $res;
}
}
引用封装后的支付方法
use Mch;
$mch= new Mch();
$options = [
'out_trade_no' => $data['order_id'],
"description" => $data['subject'],
"amount" => $data['amount'],
'return_url' => config('ali.alipay.returnUrl'),
'notify_url' => config('ali.alipay.notifyUrl') . $data['pay_type'],
'ip' => config('ali.alipay.quitUrl'),
];
$res = $mch->pay($options);
前端使用-微信的H5支付前端对接起来比较方便-拿到后端返回的h5_url 之后直接跳转即可 后端异步处理-可参考另一篇支付宝手机网站支付&实战踩坑
踩坑
SDK文档
平台证书,可由下载器 ./bin/CertificateDownloader.php 生成并假定保存为 /path/to/wechatpay/cert.pem 这句话特别关键 这里的平台证书 与API证书 是两个不同的证书,以上的下载器与API证书的下载器也是两个不同的下载器 平台证书需要通过SDK中的./bin/CertificateDownloader.php 使用命令行生成
查看 D3 生成命令-这里我们是使用composer安装的软件包,可以通过如下命令下载
vendor/bin/CertificateDownloader.php -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}
${mchId} = k1 ${apiV3key} = k5 ${mchPrivateKeyFilePath} = k4 ${mchSerialNo} = k3 ${outputFilePath} 生成后的平台证书的所在目录,不需要带文件名
|