接上篇 服务商模式特约商户支付
服务商(银行、支付机构、电商平台不可用)使用该接口提交商家资料,帮助商家入驻成为微信支付的特约商户。服务商通过该接口让提交商家资料去申请入驻,不必要让特约商户繁琐的去微信支付平台填写申请资料。
本人开发语言:php;版本:7.4
开发框架 Laravel 5.x
微信特约商户进件需要使用APIv3 版本
引入类库
使用composer 在项目根目录下执行
composer require wechatpay/wechatpay
准备配置参数
证书序列号:
登陆商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号
或
到证书文件夹,执行一下命令
openssl x509 -in apiclient_cert.pem -noout -serial
生成平台证书:
使用composer安装的软件包,可以通过如下命令下载:
composer exec CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}
注: 示例命令行上的
是
变
量
表
达
方
法
,
运
行
时
请
替
换
(
包
括
{}是变量表达方法,运行时请替换(包括
是变量表达方法,运行时请替换(包括{})为对应的实际值。
参数说明:
注:当前默认服务商支付的参数已生成好
开发接入
v2 与 v3 的区别
V3 | 规则差异 | v2 |
---|---|---|
JSON | 参数格式 | XML |
POST、GET 或 DELETE | 提交方式格式 | POST |
AES-256-GCM加密 | 回调加密 | 无需加密 |
RSA 加密 | 敏感加密 | 无需加密 |
UTF-8 | 编码方式 | UTF-8 |
非对称密钥SHA256-RSA | 签名方式 | MD5 或 HMAC-SHA256 |
通过 WeChatPay\Builder::factory 工厂方法构建一个实例
$merchantId = config("wechat.payment.default.mch_id");
$merchantPrivateKeyFilePath = "file://" . config("wechat.payment.default.key_path");
// 加载商户私钥
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
$merchantCertificateSerial = config("wechat.payment.default.serial");// API证书不重置,商户证书序列号就是个常量
//$apiV3key = config("wechat.payment.default.api_v3_key");
$platformCertificateFilePath = 'file://' . config("wechat.payment.default.platform_key_path");
// 加载「平台证书」公钥
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 解析「平台证书」序列号,「平台证书」当前五年一换,缓存后就是个常量
$this->platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
// 工厂方法构造一个实例
$this->instance = Builder::factory([
'mchid' => $merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$this->platformCertificateSerial => $platformPublicKeyInstance,
],
]);
敏感数据加密
public function getEncrypt($str)
{
//$str是待加密字符串
//平台证书
$publicKeyPath = config("wechat.payment.default.platform_key_path");
$publicKey = file_get_contents($publicKeyPath);
$encrypted = '';
if (openssl_public_encrypt($str, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING)) {
//base64编码
$sign = base64_encode($encrypted);
} else {
\Log::error("微信商户支付开通敏感字符加密失败,str=" . $str);
return false;
}
return $sign;
}
图片上传,预先上传图片生成好的MediaID
public function imageUpload($file)
{
$media = new MediaUtil($file);
$resp = $this->instance
->v3->merchant->media->upload
->postAsync([
'body' => $media->getStream(),
'headers' => [
'Content-Type' => $media->getContentType(),
]
])
->then(static function ($response) {
// echo $response->getBody(), PHP_EOL;
return $response;
})
->otherwise(static function ($e) {
// 异常错误处理
\Log::error($e->getMessage());
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
\Log::error($r->getStatusCode() . ' ' . $r->getReasonPhrase());
\Log::error($r->getBody());
}
return false;
})
->wait();
if ($resp) {
return json_decode($resp->getBody(), true);
}
return false;
}
提交申请进件,可获取微信支付申请单号applyment_id
public function apply($request)
{
try {
$resp = $this->instance
->chain('v3/applyment4sub/applyment/')
->post([
'json' => $request,
'headers' => [
// $platformCertificateSerial 见初始化章节
'Wechatpay-Serial' => $this->platformCertificateSerial,
],
]);
} catch (\Exception $e) {
// 异常错误处理
\Log::error("message_error:" . $e->getMessage());
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
\Log::error("response_error:" . $r->getStatusCode() . ' ' . $r->getReasonPhrase());
\Log::error("body_error:" . $r->getBody());
}
return false;
}
if ($resp->getStatusCode() == 200) {
return json_decode($resp->getBody(), true);
}
}
查询申请进度,通过申请单号applyment_id,查询申请结果、进度
public function getApplyProgress($applymentId)
{
$resp = $this->instance
->v3->applyment4sub->applyment->applyment_id->{'{applyment_id}'}
->getAsync([
// 查询参数结构
'applyment_id' => $applymentId,
])
->then(static function ($response) {
// 正常逻辑回调处理
// echo $response->getBody(), PHP_EOL;
return $response;
})
->otherwise(static function ($e) {
// 异常错误处理
echo $e->getMessage(), PHP_EOL;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
\Log::error($r->getStatusCode() . ' ' . $r->getReasonPhrase());
\Log::error($r->getBody());
}
})
->wait();
if ($resp) {
return json_decode($resp->getBody(), true);
}
return false;
}
提交申请进件的参数,根据官方文档结合自身商户、服务商实际业务场景自行组装