1、增加微信支付分帐功能
官方文档:https://pay.weixin.qq.com/doc/v3/partner/4012690944
分帐商户的来源为供应商,另外的问题,不赘述,在供应商信息修改的页面引用支付操作。
//引用服务
use crmeb\services\pay\Pay;
//相关代码段
//添加分账接收方
$pay = new Pay('v3_wechat_pay');
$res = $pay->receiversAdd($data['transfer_type'], $account, $name, 'SUPPLIER');
if (!array_key_exists('message', $res)){
$data['is_sign'] = 1;
}else{
throw new AdminException($res['message']);
}
相应的服务文件增加入口,开启V3支付时,文件为:\crmeb\services\pay\storage\V3WechatPay.php,添加函数:
/**
* 添加分帐用户
* @author yi716
*/
public function receiversAdd($type, string $account, string $name, string $relation_type)
{
return $this->instance->v3pay->receiversAdd($type, $account, $name, $relation_type);
}
在上面的文件中,因为新增了部分的字段,所以需要把常量增加上去,在initialize函数中增加以下:
$config['v3_payment']['mer_type'] = $merType = sys_config('mer_type');
if ($merType) { // by yi716
$config['v3_payment']['sub_mch_id'] = trim(sys_config('pay_sub_merchant_id'));
$config['v3_payment']['sp_appid'] = trim(sys_config('sp_appid'));
$config['v3_payment']['sub_cert_path'] = public_path() . $this->getPemPath(sys_config('pay_sub_weixin_client_cert'));
$config['v3_payment']['sub_key_path'] = public_path() . $this->getPemPath(sys_config('pay_sub_weixin_client_key'));
$config['v3_payment']['sub_serial_no'] = trim(sys_config('pay_pub_weixin_serial_no'));
$config['v3_payment']['sub_key'] = trim(sys_config('pay_sub_weixin_key_v3'));
}
在具体操作文件中添加处理函数,如\crmeb\services\easywechat\v3pay\PayClient.php中,添加函数:
//增加接口常量
//添加分帐接收方-服务商模式 by yi716
const API_PROFITSHAREING_RECEIVERS_ADD_URL = 'v3/profitsharing/receivers/add';
//删除分帐接收方-服务商模式 by yi716
const API_PROFITSHAREING_RECEIVERS_DEL_URL = 'v3/profitsharing/receivers/delete';
//请求分帐-服务商模式 by yi716
const API_PROFITSHAREING_ORDERS_URL = 'v3/profitsharing/orders';
//查询分帐结果-服务商 by yi716
const API_PROFITSHAREING_ORDERS_SHOW_URL = 'v3/profitsharing/orders/{out_order_no}';
//请求分帐退回-服务商模式 by yi716
const API_PROFITSHAREING_RETURN_URL = 'v3/profitsharing/return-orders';
/*
* 添加分帐接收方-服务商模式 by yi716
* type 1:用户,子商户OPENID 2:商户号
*/
public function receiversAdd($type = 1, $account = '', $name='', $relation_type = 'SUPPLIER'){
$type == 1 ? 'PERSONAL_SUB_OPENID' : 'MERCHANT_ID';
//$this->app['config']['v3_payment']['mer_type'];
$data = [
'appid' => $this->app['config']['v3_payment']['sp_appid'],
'sub_appid' => $this->app['config']['miniprog']['appid'],
'sub_mchid' => $this->app['config']['v3_payment']['sub_mch_id'],
'type' => ($type == 1) ? 'PERSONAL_SUB_OPENID' : 'MERCHANT_ID',
'account' => $account,
'relation_type' => $relation_type,
];
if ($type == 2){
$data['name'] = self::getEncrypt($name);
}
$datas = ['json' => $data];
$res = $this->request(self::API_PROFITSHAREING_RECEIVERS_ADD_URL, 'POST', $datas);
if (array_key_exists('message', $res)) {
throw new PayException($res['message']);
}
return $res;
}
private function getEncrypt($str) {
//$str是待加密字符串
$public_key_path = $this->app['config']['v3_payment']['sub_key_path'];
$public_key = file_get_contents($public_key_path);
//$public_key = file_get_contents($this->app['config']['v3_payment']['cert_path']);
$encrypted = '';
if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
$sign = base64_encode($encrypted);
} else {
throw new PayException('encrypt failed');
}
return $sign;
}
相关的坑:
1、当用户角色为商户时,需要上报name字段。
2、name字段需要加密,官方文档是可采用【微信支付公钥ID】或【微信支付平台证书序列号】进行加密,但是微信支付公钥ID功能在V3环境下已不存在,所以需要采用微信支付平台证书序列号,服务商模式下,是需要以服务端的证书和密钥来产生的。
证书下载文档地址:平台证书简介及使用说明_平台证书|微信支付商户文档中心