一、小总结
二、服务层
2:特别需要注意的是
如果是支付成功后立马调用分账的话需要 sleep(60) :等待60秒(这个大家在测试时可以缩短,比如30秒试一下看能成功调用不)
如果支付成功后没有等待直接调用会失败:提示订单正在处理中
二、服务层
// 分账
public function profitsharing()
{
// 分账金额
$nMoney = 1; // 添加分账接收方
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';
// 接收方信息
$receiver = [
// 分账接收方类型
"type" => "PERSONAL_OPENID",
// 分账接收方账号 (个人:openid)
"account" => "个人:openid",
// 关系
"relation_type" => 'SUPPLIER',
];
// 公共参数
$oValues = [
"mch_id" => "商户号",
"appid" => "公众账号ID",
"nonce_str" => $this->getNonceStr(), // 随机字符串
"receiver" => json_encode($receiver),// 接收方信息
];
// 产生签名
ksort($oValues);
$oValues["sign"] = $this->MakeSign($oValues);
// 参数转ml
$postXML = $this->ToXml($oValues); // 请求
$timeOut = 6;
$response = self::postXmlCurl($postXML, $url, true, $timeOut);
// 结果转数组
$ret = $this->FromXml($response);
if ($ret["return_code"] == "SUCCESS" && $ret["result_code"] == "SUCCESS") { // 添加分账接收方成功 // 请求单次分账
$receivers = [
"type" => "PERSONAL_OPENID", // 分账接收方类型
"account" => "个人:openid", // 分账接收方账号
"amount" => $nMoney * 100, // 分账金额 分
"description" => "分到个人" // 分账描述
]; $aData = [
"mch_id" => "商户号",
"appid" => "公众账号ID",
"nonce_str" => $this->getNonceStr(), // 随机字符串
"sign_type" => "跟下单类型保持一致", // 签名类型
"transaction_id" => $transaction_id, // 微信订单号:根据你的业务场景来获取
"out_order_no" => "自定义", // 商户分账单号
"receivers" => json_encode($receivers, 256)// 分账接收方列表 json格式 中文不转码
];
// 签名
ksort($aData);
$aData['sign'] = $this->MakeSign($aData);
// 请求单次分账
$url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
// 参数转ml
$postXML = $this->ToXml($oValues); // 结果
$timeOut = 6;
$response = self::postXmlCurl($postXML, $url, true, $timeOut);
// 结果转数组
$ret = $this->FromXml($response);
// 保存分账订单状态或者别的操作 if ($ret["return_code"] == "SUCCESS" && $ret["result_code"] == "SUCCESS")
{
dump("分账成功") // 保存分账订单状态或者别的操作 } else {
dump("分账失败")
}
} else {
dump("添加分账接收方失败")
}
}
// 查询分账结果
public function profitsharingquery()
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingquery';
$aWxpayParam = $this->get_wxpay_param();
$aData = [
"mch_id" => "商户号",
"transaction_id" => $transaction_id, // 微信订单号:根据你的业务场景来获取
"out_order_no" => "请求分账中自定义的单号",// 商户分账单号
"nonce_str" => $this->getNonceStr(), // 随机字符串
"sign_type" => "跟下单类型保持一致", // 签名类型
];
// 签名
ksort($aData);
$aData['sign'] = $this->MakeSign($aData);
$postXML = $this->ToXml($aData); // 结果
$timeOut = 6;
$response = self::postXmlCurl($postXML, $url, true, $timeOut);
$ret = $this->FromXml($response);
return json($ret);
}
<--------------------------------------------------------------------------> /**
*
* 产生随机字符串,不长于32位
* @param int $length
* @return 产生的随机字符串
*/
public static function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
} return $str;
} /**
* 输出xml字符
**/
public function ToXml($values)
{
if (!is_array($values) || count($values) <= 0) {
return "数组数据异常!";
} $xml = "<xml>"; foreach ($values as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>"; return $xml;
} /**
* 将xml转为array
* @param string $xml
* @throws WxPayException
*/
public function FromXml($xml)
{
if (!$xml) {
return "xml数据异常!";
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$res = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $res;
} /**
* 生成签名
* @param bool $needSignType 是否需要补signtype
* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function MakeSign($values, $needSignType = true)
{
if ($needSignType) {
// $this->SetSignType($config->GetSignType());
$sSignType = self::SIGNTYPE;
} $sKey = $this->get_wxpay_param()['key']; // 签名步骤一:按字典序排序参数
ksort($values);
$string = $this->ToUrlParams($values); // 签名步骤二:在string后加入KEY
$string = $string . "&key=" . $sKey; // 签名步骤三:MD5加密或者HMAC-SHA256
if ($sSignType == "MD5") {
$string = md5($string);
} else if ($sSignType == "HMAC-SHA256") {
$string = hash_hmac("sha256", $string, $sKey);
} else {
return "签名类型不支持!";
} // 签名步骤四:所有字符转为大写
$result = strtoupper($string); return $result;
} /**
* 以post方式提交xml到对应的接口url
*
* @param WxPayConfigInterface $config 配置对象
* @param string $xml 需要post的xml数据
* @param string $url url
* @param bool $useCert 是否需要证书,默认不需要
* @param int $second url执行超时时间,默认30s
*/
private function postXmlCurl($xml, $url, $useCert = false, $second = 30)
{
$ch = curl_init();
$curlVersion = curl_version();
$ua = "WXPaySDK/" . self::VERSION . " (" . PHP_OS . ") PHP/" . PHP_VERSION . " CURL/" . $curlVersion['version'] . " " . $aWxpayParam['mchid'];
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
$proxyHost = "0.0.0.0";
$proxyPort = 0;
// 如果有配置代理这里就设置代理
if ($proxyHost != "0.0.0.0" && $proxyPort != 0) {
curl_setopt($ch, CURLOPT_PROXY, $proxyHost);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxyPort);
}
curl_setopt($ch, CURLOPT_URL, $url);
// curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
// curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
curl_setopt($ch, CURLOPT_USERAGENT, $ua);
// 设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
// 要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if ($useCert == true) {
// 设置证书
// 使用证书:cert 与 key 分别属于两个.pem文件
// 证书文件请放入服务器的非web目录下
$sslCertPath = 'sslCertPath'; // 证书路径
$sslKeyPath = 'sslKeyPath'; // 证书路径
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, $sslCertPath);
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, $sslKeyPath);
}
// post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
// 运行curl
$data = curl_exec($ch);
// 返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
throw new WxPayException("curl出错,错误码:$error");
}
}
发表评论 取消回复