元觉乡微信支付统一下单,用PHP怎么实现?(代码全)
阅读 25677 · 发布日期 2020-08-24 17:26 · 温州优光网络科技有限公司|建站|APP小程序制作|做网站SEO推广优化
H5支付时出现“签名错误”怎么办?注意调用微信“统一下单”接口后返回pre_pay_id后,需要用户再次进行签名返回给HTML; “支付目录没有授权”,进入微信商家管理后台设置即可。
一、Model层,Wxpay.php
class Wxpay
{
private $appid = '
wxe8*****d4'
;
//微信公众号appid
private $secret = '
37c4*******5f0'
;
//微信公众号appsecret
private $mchid = '
13******02'
;
//商家号
private $key = '
5363e******49e8'
;
//支付密钥
private $sslcert_path = '
apiclient_cert.pem'
;
//证书所在绝对路径
private $sslkey_path = '
apiclient_key.pem'
;
//证书所在绝对路径
public function __construct($appid = '
'
, $secret = '
'
, $mchid = '
'
, $key = '
'
)
{
if(!empty($appid)) $this->appid = $appid;
if(!empty($secret)) $this->secret = $secret;
if(!empty($mchid)) $this->mchid = $mchid;
if(!empty($key)) $this->key= $key;
}
/*
* 微信内H5调起支付
* @params string $openid : 微信用户openid
* @params string $out_trade_no : 商家生成的订单号(唯一性)
* @params int $total_fee : 支付金额,单位分
* return array $ret : 返回支付时所需要的数据
* */
public function payForWeixin($openid,$out_trade_no,$total_fee,$attach='
微信支付'
,$body='
微信支付'
)
{
//支付数据
$data['
openid'
] = $openid;
$data['
out_trade_no'
] = $out_trade_no;
$data['
total_fee'
] = $total_fee*100;
$data['
spbill_create_ip'
] = $_SERVER["REMOTE_ADDR"];
$data['
attach'
] = $attach;
$data['
body'
] = $body;
$data['
appid'
] = $this->appid;
$data['
mch_id'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
trade_type'
] = "JSAPI";
$data['
notify_url'
] = "http://****.com/home/wxpaynofiy/notify.html";
$sign = $this->getParam($data);
$dataXML = "
appid'
]."
".$data['
attach'
]."
".$data['
body'
]."
mch_id'
]."
nonce_str'
]."
notify_url'
]."
openid'
]."
out_trade_no'
]."
spbill_create_ip'
]."
total_fee'
]."
trade_type'
]."
$url = '
https://api.mch.weixin.qq.com/pay/unifiedorder'
;
$result = $this->https_post($url,$dataXML);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
] == '
SUCCESS'
&& $ret['
return_msg'
] == '
OK'
) {
return array(
'
appId'
=> $this->appid,
'
timeStamp'
=> time(),
'
nonceStr'
=> $data['
nonce_str'
],
'
package'
=> '
prepay_id='
.$ret['
prepay_id'
],
'
signType'
=> '
MD5'
,
'
paySign'
=> $sign
);
}
else {
$this->errorLog("微信支付失败,",$ret);
return null;
}
}
/*
* 微信二维码支付
* @params string $openid : 用户的openid
* @params string $out_trade_no : 商户订单号
* @params number $total_fee : 订单金额,单位分
* return string $code_url : 二维码URL链接
*/
public function payForQrcode($out_trade_no,$total_fee,$body="魔盒CMS",$attach="微信支付")
{
//支付数据
$data['
out_trade_no'
] = $out_trade_no;
$data['
total_fee'
] = $total_fee*100;
$data['
spbill_create_ip'
] = $_SERVER["REMOTE_ADDR"];
$data['
attach'
] = $attach;
$data['
body'
] = $body;
$data['
appid'
] = $this->appid;
$data['
mch_id'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
trade_type'
] = "NATIVE";
$data['
notify_url'
] = "http://****.com/home/wxpaynofiy/notify.html";
$sign = $this->getParam($data);
$dataXML = "
appid'
]."
".$data['
attach'
]."
".$data['
body'
]."
mch_id'
]."
nonce_str'
]."
notify_url'
]."
out_trade_no'
]."
spbill_create_ip'
]."
total_fee'
]."
trade_type'
]."
$url = '
https://api.mch.weixin.qq.com/pay/unifiedorder'
;
$result = $this->https_post($url,$dataXML);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
] == '
SUCCESS'
&& $ret['
return_msg'
] == '
OK'
) {
return $ret['
code_url'
];
}
else {
$this->errorLog("获取微信支付二维码失败,",$ret);
return null;
}
}
/*
* 订单查询
* @params string $transaction_id : 微信订单号
* @params string $out_trade_no : 商家订单号(与微信订单号二选一)
* */
public function findOrder($out_trade_no)
{
$data['
appid'
] = $this->appid;
$data['
mch_id'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
out_trade_no'
] = $out_trade_no;
$sign = $this->getParam($data);
$dataXML = "
appid'
]."
mch_id'
]."
nonce_str'
]."
out_trade_no'
]."
$url = '
https://api.mch.weixin.qq.com/pay/orderquery'
;
$result = $this->https_post($url,$dataXML);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
] == '
SUCCESS'
&& $ret['
return_msg'
] == '
OK'
) {
return $ret;
}
else {
$this->errorLog("查询微信支付订单失败,",$ret);
return null;
}
}
/*
* 退款订单查询
* @params string $transaction_id : 微信订单号
* @params string $out_trade_no : 商家订单号(与微信订单号二选一)
* */
public function findRefundOrder($out_trade_no)
{
$data['
appid'
] = $this->appid;
$data['
mch_id'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
out_trade_no'
] = $out_trade_no;
$sign = $this->getParam($data);
$dataXML = "
appid'
]."
mch_id'
]."
nonce_str'
]."
out_trade_no'
]."
$url = '
https://api.mch.weixin.qq.com/pay/refundquery'
;
$result = $this->https_post($url,$dataXML);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
] == '
SUCCESS'
&& $ret['
return_msg'
] == '
OK'
) {
return $ret;
}
else {
$this->errorLog("查询微信支付退款订单失败,",$ret);
return $ret['
err_code_des'
];
}
}
/*
* 申请退款
* @params string $out_trade_no : 商户订单号
* @params string $out_refund_no : 商户退款单号
* @params int $total_fee : 订单金额
* @params int $refund_fee : 退款金额
* @params string $refund_desc : 退款原因
* */
public function refund($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$refund_desc='
退款'
)
{
$data['
appid'
] = $this->appid;
$data['
mch_id'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
out_trade_no'
] = $out_trade_no;
$data['
out_refund_no'
] = $out_refund_no;
$data['
total_fee'
] = $total_fee*100;
$data['
refund_fee'
] = $refund_fee*100;
$data['
refund_desc'
] = $refund_desc;
$data['
notify_url'
] = "http://*****.com/home/wxpaynofiy/refund.html";
$sign = $this->getParam($data);
$dataXML = "
appid'
]."
mch_id'
]."
nonce_str'
]."
out_trade_no'
]."
out_refund_no'
]."
total_fee'
]."
refund_fee'
]."
refund_desc'
]."
notify_url'
]."
$url = '
https://api.mch.weixin.qq.com/secapi/pay/refund'
;
$result = $this->https_post($url,$dataXML,true);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
] == '
SUCCESS'
&& $ret['
return_msg'
] == '
OK'
) {
return $ret;
}
else {
$this->errorLog("微信退款失败,",$ret);
return null;
}
}
/*
* 企业付款至用户零钱
* @params string $openid : 用户openid
* @params int $total_fee : 付款金额,单位分
* @params string $out_trade_no : 商家订单号
* @params string $username : 微信用户名称(注意微信昵称若为空时支付会出错)
* @params string $desc : 付款描述
* @params string $check_name : 是否检测用户名
* */
public function payForUser($openid,$total_fee,$out_trade_no,$username='
魔盒CMS'
,$desc='
魔盒CMS付款给用户'
,$check_name='
NO_CHECK'
)
{
$data['
amount'
] = $total_fee*100;
$data['
check_name'
] = $check_name;
$data['
desc'
] = $desc;
$data['
mch_appid'
] = $this->appid;
$data['
mchid'
] = $this->mchid;
$data['
nonce_str'
] = random(12);
$data['
openid'
] = $openid;
$data['
partner_trade_no'
] = $out_trade_no;
$data['
re_user_name'
] = $username;
$data['
spbill_create_ip'
] = $_SERVER["REMOTE_ADDR"];
$sign = $this->getParam($data);
$dataXML="
mch_appid'
]."
mchid'
]."
nonce_str'
]."
partner_trade_no'
]."
openid'
]."
check_name'
]."
re_user_name'
]."
amount'
]."
desc'
]."
spbill_create_ip'
]."
$url = '
https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'
;
$result = $this->https_post($url,$dataXML,true);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
]=='
SUCCESS'
&& $ret['
result_code'
] == '
SUCCESS'
)
{
//支付成功返回商户订单号、微信订单号、微信支付成功时间
$result['
partner_trade_no'
] = $ret['
partner_trade_no'
];
$result['
payment_no'
] = $ret['
payment_no'
];
$result['
payment_time'
] = $ret['
payment_time'
];
return $ret;
}
else {
$this->errorLog('
付款给用户失败'
,$ret);
return null;
}
}
/*
* 普通红包
* @params string $out_trade_no : 商家订单号
* @params string $openid : 接收红包用户的openid
* @params int $total_fee : 红包金额,单位分
* @params int $total_num : 红包发放总人数
* @params string $wishing : 红包祝福语
* @params string $act_name : 活动名称
* @params string $remark : 备注
* @params string $scene_id :
场景值ID。
发放红包使用场景,红包金额大于200或者小于1元时必传。
PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖
* */
public function redPack($openid,$total_fee,$out_trade_no,$total_num = 1,$wishing = '
感谢您光临***平台进行购物'
,$act_name='
***购物发红包'
,$remark = '
购物领红包'
)
{
$data['
mch_billno'
] = $out_trade_no;
$data['
mch_id'
] = $this->mchid;
$data['
wxappid'
] = $this->appid;
$data['
send_name'
] = '
发送红包者的名称'
;
$data['
re_openid'
] = $openid;
$data['
total_amount'
] = $total_fee;
$data['
total_num'
] = $total_num;
$data['
wishing'
] = $wishing;
$data['
client_ip'
] = $_SERVER["REMOTE_ADDR"];
$data['
act_name'
] = $act_name;
$data['
remark'
] = $remark;
$data['
nonce_str'
] = random(12);
$sign = $this->getParam($data);
$dataXML="
mch_billno'
]."
mch_id'
]."
wxappid'
]."
send_name'
]."
re_openid'
]."
total_amount'
]."
total_num'
]."
wishing'
]."
client_ip'
]."
act_name'
]."
remark'
]."
nonce_str'
]."
$url = '
https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack'
;
$result = $this->https_post($url,$dataXML,true);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
]=='
SUCCESS'
&& $ret['
result_code'
] == '
SUCCESS'
)
{
return $ret;
}
else {
$this->errorLog('
发放普通红包失败'
,$ret);
return $ret['
err_code_des'
];
}
}
/*
* 裂变红包:
一次可以发放一组红包。
首先领取的用户为种子用户,种子用户领取一组红包当中的一个,并可以通过社交分享将剩下的红包给其他用户。
* 裂变红包充分利用了人际传播的优势。
* @params string $out_trade_no : 商家订单号
* @params string $openid : 接收红包用户的openid
* @params int $total_fee : 红包金额,单位分
* @params int $total_num : 红包发放总人数
* @params string $wishing : 红包祝福语
* @params string $act_name : 活动名称
* @params string $remark : 备注
* @params string $scene_id :
场景值ID。
发放红包使用场景,红包金额大于200或者小于1元时必传。
PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖
* */
public function redPackGroup($openid,$total_fee,$out_trade_no,$total_num,$wishing = '
感谢您光临***进行购物'
,$act_name='
**购物发红包'
,$remark = '
购物领红包'
)
{
$data['
mch_billno'
] = $out_trade_no;
$data['
mch_id'
] = $this->mchid;
$data['
wxappid'
] = $this->appid;
$data['
send_name'
] = '
发送红包者的名称'
;
$data['
re_openid'
] = $openid;
$data['
total_amount'
] = $total_fee;
$data['
amt_type'
] = '
ALL_RAND'
;
//ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
$data['
total_num'
] = $total_num;
$data['
wishing'
] = $wishing;
$data['
client_ip'
] = $_SERVER["REMOTE_ADDR"];
$data['
act_name'
] = $act_name;
$data['
remark'
] = $remark;
$data['
nonce_str'
] = random(12);
$sign = $this->getParam($data);
$dataXML="
mch_billno'
]."
mch_id'
]."
wxappid'
]."
send_name'
]."
re_openid'
]."
total_amount'
]."
amt_type'
]."
total_num'
]."
wishing'
]."
client_ip'
]."
act_name'
]."
remark'
]."
nonce_str'
]."
$url = '
https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack'
;
$result = $this->https_post($url,$dataXML,true);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
]=='
SUCCESS'
&& $ret['
result_code'
] == '
SUCCESS'
)
{
return $ret;
}
else {
$this->errorLog('
发放裂变红包失败'
,$ret);
return $ret['
err_code_des'
];
}
}
/*
* 查询红包记录
* @params string $out_trade_no : 商家订单号
* */
public function findRedPack($out_trade_no)
{
$data['
mch_billno'
] = $out_trade_no;
$data['
mch_id'
] = $this->mchid;
$data['
appid'
] = $this->appid;
$data['
bill_type'
] = '
MCHT'
;
//MCHT:通过商户订单号获取红包信息。
$data['
nonce_str'
] = random(12);
$sign = $this->getParam($data);
$dataXML="
mch_billno'
]."
mch_id'
]."
appid'
]."
bill_type'
]."
nonce_str'
]."
$url = '
https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo'
;
$result = $this->https_post($url,$dataXML,true);
$ret = $this->xmlToArray($result);
if($ret['
return_code'
]=='
SUCCESS'
&& $ret['
result_code'
] == '
SUCCESS'
)
{
return $ret;
}
else {
$this->errorLog('
查询红包记录失败'
,$ret);
return $ret['
err_code_des'
];
}
}
/*
* 获取用户微信的OPENID
* */
public function openid($c=false)
{
if($_GET['
state'
]!="zgm"){
$t = $c ? "snsapi_userinfo" : "snsapi_base";
$url=urlencode(get_url());
$url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=".$url."&response_type=code&scope=".$t."&state=zgm#wechat_redirect";
echo "";
exit;
}
if($_GET['
code'
]){
$url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$_GET['
code'
]."&grant_type=authorization_code";
$wx_db=json_decode($this->https_get($url));
if($c){
$url_2="https://api.weixin.qq.com/sns/userinfo?access_token=".$wx_db->access_token."&openid=".$wx_db->openid."&lang=zh_CN";
$db=json_decode($this->https_get($url_2));
return $db;
}
else{
return $wx_db->openid;
}
}
}
/*
* 发起网络GET请求
* @params string $url : URL链接
*/
private function https_get($url)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_HEADER, FALSE) ;
curl_setopt($curl, CURLOPT_TIMEOUT,60);
if (curl_errno($curl)) {
return '
Errno'
.curl_error($curl);
}
else{
$result=curl_exec($curl);
}
curl_close($curl);
return $result;
}
//对参数排序,生成MD5加密签名
private function getParam($paramArray, $isencode=false)
{
$paramStr = '
'
;
ksort($paramArray);
$i = 0;
foreach ($paramArray as $key => $value)
{
if ($key == '
Signature'
){
continue;
}
if ($i == 0){
$paramStr .= '
'
;
}
else{
$paramStr .= '
&'
;
}
$paramStr .= $key . '
='
. ($isencode?urlencode($value):$value);
++$i;
}
$stringSignTemp=$paramStr."&key=".$this->key;
$sign=strtoupper(md5($stringSignTemp));
return $sign;
}
//POST提交数据
private function https_post($url,$data,$ssl = false)
{
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
if($ssl) {
curl_setopt ( $ch,CURLOPT_SSLCERT,$this->sslcert_path);
curl_setopt ( $ch,CURLOPT_SSLKEY,$this->sslkey_path);
}
curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
$result = curl_exec($ch);
if (curl_errno($ch)) {
return '
Errno: '
.curl_error($ch);
}
curl_close($ch);
return $result;
}
/*
* XML转array
* @params xml $xml : xml 数据
* return array $data : 转义后的array数组
*/
private function xmlToArray($xml)
{
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, '
SimpleXMLElement'
, LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring),true);
return $val;
}
/*
* 记录日志
* @params string $msg : 提示语句
* @params array $ret : 错误结果
*/
private function errorLog($msg,$ret)
{
file_put_contents(ROOT_PATH . '
runtime/error/wxpay.log'
, "[" . date('
Y-m-d H:i:s'
) . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND);
}
}
二、Controller层,Test.php
use appcommonmodelWxpay;
class Test
{
/*
* 调用微信支付
* 一、获取微信用户的openid;
* 二、调用微信支付接口
* 三、生成H5中使用的签名内容
*/
public function wx()
{
$wxpay = new Wxpay();
$openid = $wxpay->openid();
$pay = $wxpay->payForWeixin($openid,date('
YmdHis'
).rand(1,5),'
0.1'
);
$paySign =strtoupper(MD5('
appId='
.$pay['
appId'
].'
&nonceStr='
.$pay['
nonceStr'
].'
&package='
.$pay['
package'
].'
&signType=MD5&timeStamp='
.$pay['
timeStamp'
].'
&key=536*****9e8'
));
$h5 = array(
'
appId'
=> $pay['
appId'
],
'
timeStamp'
=> $pay['
timeStamp'
],
'
nonceStr'
=> $pay['
nonceStr'
],
'
package'
=> $pay['
package'
],
'
signType'
=> $pay['
signType'
],
'
paySign'
=> $paySign
);
$this->assign('
wxpay'
,$h5);
return view();
}
}
三、HTML中调用微信支付,wx.html
wxpaynofiy.php class Wxpaynofiy {
public function notify() {
$xml = isset($GLOBALS["HTTP_RAW_POST_DATA"]) ? $GLOBALS['
HTTP_RAW_POST_DATA'
] : file_get_contents("php://input");
$data = xmlToArray($xml);
if($data['
return_code'
] == '
SUCCESS'
&& $data['
result_code'
] == '
SUCCESS'
){
if($this->checkSign($data)) {
$transaction_id = $data['
transaction_id'
];
//微信支付订单号 $out_trade_no = $data['
out_trade_no'
];
//商家订单号 $this->errorLog('
微信支付返回结果,微信支付订单号:
'
.$transaction_id.'
,商家订单号:
'
.$out_trade_no,[]);
}
else {
$this->errorLog('
微信支付返回结果签名验证失败'
,$data);
}
}
else {
$this->errorLog('
微信支付返回结果'
,$data);
}
echo '
;
}
/* * 验证签名 * @params array $result : 微信支付成功返回的结果数组 * return bool $ret : 成功true,失败false * */ private function checkSign(array $data) {
$str = '
'
;
ksort($data);
foreach ($data as $k => $v) {
if($k != '
sign'
) $str .= $k.'
='
.$v.'
&'
;
}
$temp = $str . '
key=5363******49e8'
;
//key:
商户支付密钥 $sign = strtoupper(md5($temp));
return $sign == $data['
sign'
] ? true : false;
}
private function errorLog($msg,$ret) {
file_put_contents(ROOT_PATH . '
runtime/error/wxpaynofiy.log'
, "[" . date('
Y-m-d H:i:s'
) . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND);
}
}
相关推荐:
微信支付与支付宝支付整合 PHP实现PHP如何实现微信支付视频教程 :
php微信接口开发实战项目聊天机器人+微信支付以上就是微信支付统一下单,用PHP怎么实现?(代码全)的详细内容,更多请关注php中文网其它相关文章!
微信
分享相关标签:
php 微信 微信支付本文原创发布php中文网,转载请注明出处,感谢您的尊重!
上一篇:
还是代码好用,几步就能判断用户是否已关注公众号
下一篇:
关于微信自定义分享功能的实现代码相关文章相关视频修改微信号有什么影响吗?微信中共享实时位置什么意思数据库设计的基本原则是什么?微信小程序调用图片安全API微信支付统一下单,用PHP怎么实现?(代码全)PHP开发基础教程之简介PHP新手入门之简介PHP开发基础教程之环境搭建php学习路线介绍php环境配置 [温州做微信公众号]