'系统错误', 'PARAM_ERROR' => '请求参数未按指引进行填写', 'SIGNERROR' => '参数签名结果不正确', 'OP_USER_PASSWD_ERROR' => '操作员密码校验失败', 'OP_USER_AUTH_ERROR' => '操作员权限错误', 'TRANSFER_FEE_LIMIT_ERROR' => '转账限额错误', 'TRANSFER_FAIL' => '收款用户的账户不支持收款,收款失败', 'NOTENOUGH' => '商户营销账户的余额不足', 'ORDERNOTEXIST' => '转账订单不存在', 'APPID_OR_OPENID_ERR' => 'appid 或 openid 非法', 'TOTAL_FEE_OUT_OF_LIMIT' => '单笔限额检查失败', 'SPID_NOT_ALLOW' => '当前商户不支持企业付款', 'REALNAME_CHECK_ERROR' => '实名检查失败', 'RE_USER_NAME_CHECK_ERROR' => '用户真实姓名校验失败', 'INVALID_CERTIFICATE' => '证书非法', ]; private $_requestParams = []; /** * @param $value */ public function setOpUserId($value) { $this->_requestParams['op_user_id'] = $value; } /** * @param $value */ public function setOpUserPassword($value) { $this->_requestParams['op_user_passwd'] = $value; } /** * @param $value */ public function setSpbillCreateIp($value) { $this->_requestParams['spbill_create_ip'] = $value; } /** * @param $mch_billno * @param $openId * @param $price * @return mixed * @throws Exception */ public function mch_send($mch_billno, $openId, $price) { $client = new Client('api.qpay.qq.com', 443, true); $client->withHeader(['Content-Type' => 'application/json']); $client->withSslCertFile($this->getConfig()->getSslCert()); $client->withSslKeyFile($this->getConfig()->getSslKey()); $client->withCa($this->getConfig()->getSslCa()); $client->post($this->_cash, $this->orderConfig($mch_billno, $openId, $price)); $client->close(); if (!in_array($client->getStatusCode(), [101, 200, 201])) { return new Result(code: 505, message: 'network error.'); } $json = json_decode($client->getBody(), true); if (isset($json['return_code']) && $json['return_code'] != 'SUCCESS') { return new Result(code: 500, data: $json['return_msg'] ?? $json['retmsg']); } else if ($json['result_code'] != 'SUCCESS') { return new Result(code: 500, data: $this->_errors[$json['err_code']] ?? $json['err_code_desc']); } else { return new Result(code: 0, data: $json); } } /** * @param $mch_billno * @param $openId * @param $price * @return array */ private function orderConfig($mch_billno, $openId, $price): array { $requestParam['input_charset'] = 'UTF-8'; $requestParam['nonce_str'] = Help::random(32); $requestParam['out_trade_no'] = $mch_billno; $requestParam['mch_id'] = $this->getConfig()->getMchId(); $requestParam['appid'] = $this->getConfig()->getAppid(); $requestParam['openid'] = $openId; $requestParam['fee_type'] = 'CNY'; $requestParam['total_fee'] = $price * 100; $requestParam['memo'] = $this->getConfig()->getBody(); $requestParam['notify_url'] = $this->getConfig()->getNotifyUrl(); $requestParam['spbill_create_ip'] = $this->getConfig()->getNotifyUrl(); if (!empty($this->_requestParams) && is_array($this->_requestParams)) { $requestParam = array_merge($requestParam, $this->_requestParams); } $requestParam['sign'] = Help::sign($requestParam, $this->getConfig()->getKey(), 'MD5'); return $requestParam; } /** * @return string * @throws Exception */ public function mchOrderNo(): string { return implode([ $this->getConfig()->getMchId(), date('Ymd'), random_int(11, 99), date('His'), random_int(11, 99) ]); } /** * @param array $requestParams * @return bool */ public function validator(array $requestParams): bool { $notifySign = $requestParams['sign']; unset($requestParams['sign']); $sign = Help::sign($requestParams, $this->getConfig()->getKey(), 'MD5'); if ($sign !== $notifySign) { return false; } return true; } }