Yii2 微信支付扩展 [ 2.0 版本 ]
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018-12-04
* Time: 11:07 AM
* Author: 王称意
* QQ/Email: 984008813/wondely@126.com
*/
namespace app\service;
class WechatPay {
public $key = '********************';
public function createSign($params)
{
$sign = $this->MakeSign($params);
return $sign;
}
public function unifiedorder($params)
{
$xml = $this->ToXml($params);
return $xml;
}
public function ToXml($params)
{
$xml = "<xml>";
foreach ($params as $key=>$val)
{
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
public function XmlToArray($xml)
{
if(!$xml){
return "xml数据异常!";
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $data;
}
public function ToUrlParams($params)
{
$buff = "";
foreach ($params as $k => $v)
{
if($k != "sign" && $v !="" && !is_array($v)){
$buff .=$k."=".$v."&";
}
}
$buff = trim($buff, "&");
return $buff;
}
public function MakeSign($params, $sign_type = 'MD5')
{
//签名步骤一:按字典序排序参数
ksort($params);
$string = $this->ToUrlParams($params);
//签名步骤二:在string后加入KEY
$string = $string."&key=".$this->key;
//签名步骤三:MD5加密或者HMAC-SHA256
if($sign_type == "MD5"){
$string = md5($string);
} else if($sign_type == "HMAC-SHA256") {
$string = hash_hmac("sha256",$string ,$this->key);
}
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
public function getNonceStr($length = 31)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
public function postXmlCurl($xml, $url, $useCert = false, $second = 30)
{
$ch = curl_init();
$curlVersion = curl_version();
$ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']."1518495571";
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
$proxyHost = "0.0.0.0";
$proxyPort = 0;
//$config->GetProxy($proxyHost, $proxyPort);
//如果有配置代理这里就设置代理
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,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
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 = "";
$sslKeyPath = "";
//$config->GetSSLCertPath($sslCertPath, $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 Exception("curl出错,错误码:$error");
return "curl出错,错误码:$error";
}
}
}
?>
在根目录下面 建一个 service目录 复制上面的内容到一个文件。
<?php
class PayController extends AppController {
public function actionIndex()
{
$good_id = \Yii::$app->request->post('good_id');
$pay_type = \Yii::$app->request->post('pay_type');
if(empty($good_id)){
$this->msg['msg'] = '购买的商品不能为空';
return $this->asJson($this->msg);
}
if(empty($pay_type)){
$this->msg['msg'] = '请选择支付方式';
return $this->asJson($this->msg);
}
$good_info = Goods::findOne($good_id);
$user_info = $this->getUserInfo();
$date_time = date('YmdHis');
$order_id = 'wechat'.$good_id.$date_time;
$orderModel = new BookOrder();
$orderModel->order_id = $order_id;
$orderModel->user_id = $user_info['id'];
$orderModel->user_name = $user_info['username'];
$orderModel->good_id = $good_id;
$orderModel->agent_id = $user_info['source_id'];
$orderModel->order_money = $good_info['goods_money'];
$orderModel->pay_type = $pay_type;
$orderModel->order_status = 0;
$orderModel->create_time = time();
$orderModel->save();
//todo wechatSDk 微信支付的sdk
if($pay_type == 2){
$param = [
'appid' =>'*******',
'mch_id'=> '*******',
'body'=> '嘻嘻嘻嘻嘻-充值中心',
'out_trade_no'=> $order_id,
'total_fee'=> 1, //$good_info['goods_money']*100,
'spbill_create_ip'=> $_SERVER['REMOTE_ADDR'],
'notify_url'=>'http://xxxxx.com/callback/wechat',
'trade_type'=>'MWEB',
'scene_info'=>'{"h5_info":{"type":"Wap","wap_url":"http://xxxxx.com","wap_name":"嘻嘻嘻嘻嘻"}}',
];
$wechatPay = new WechatPay();
$param['nonce_str'] = $wechatPay->getNonceStr();
$param['sign'] = $wechatPay->createSign($param);
$xml = $wechatPay->unifiedorder($param); //统一下单
$data = $wechatPay->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder');
$data = $wechatPay->XmlToArray($data);
//var_dump($data);
if($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS'){
$this->msg['msg'] = '订单下单成功';
$this->msg['order_id'] = $order_id;
$this->msg['data'] = $data;
}else{
$this->msg['msg'] = $data['return_msg'];
}
return $this->asJson($this->msg);
}
}
}
?>
下单页面,调起微信支付。
<?php
class CallbackController extends Controller{
public $enableCsrfValidation = false;
public function actionWechat(){
$msg = [
'success' => "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>",
'fail' =>"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>"
];
$xml = file_get_contents('php://input');
if(empty($xml)){
Yii::info('回调异常','paylog');
echo $msg['fail'];exit;
}
//Yii::info($xml,'paylog');
$wechatPay = new WechatPay();
$call_back = $wechatPay->XmlToArray($xml);
//var_dump($call_back);
if(empty($call_back)){
Yii::info('数据非法请求','paylog');
echo $msg['fail'];exit;
}
if($call_back['result_code'] == 'SUCCESS' && $call_back['return_code'] == 'SUCCESS'){
$sign = $wechatPay->createSign($call_back);
if($sign !== $call_back['sign']){
//todo 返回信息签名异常的处理
Yii::info('该订单签名异常'.$call_back['out_trade_no'],'paylog');
echo $msg['fail'];
exit;
}
$order_id = $call_back['out_trade_no'];
$time = time();
$order_info = BookOrder::find()->where(['order_id'=>$order_id])->one();
$good_info = Goods::findOne($order_info['good_id']);
if($order_info){
if($order_info['order_status'] == 1){
Yii::info('该订单已支付,请勿重复支付'.$order_id,'paylog');
echo $msg['success'];
exit;
}
$ts = Yii::$app->db->beginTransaction();
if($good_info['goods_type'] ==1){
$condition = ['user_id' =>$order_info['user_id']];
$userVip = UserVip::find()->where($condition)->one();
$end_time = 3600*24*30*$good_info['goods_num'];
if($userVip){
if($userVip['end_time'] > $time){
$plus_time = $userVip['end_time']+$end_time;
}else{
$plus_time = $time+$end_time;
}
$userVip->end_time = $plus_time;
$userUpdate = $userVip->save();
}else{
$userVip = new UserVip();
$userVip->user_id = $order_info['user_id'];
$userVip->begin_time = $time;
$userVip->end_time = $time+$end_time;
$userUpdate = $userVip->save();
}
$consumeCoin = new CoinConsume();
$consumeCoin->user_id = $order_info['user_id'];
$consumeCoin->consume_type = 3;
$consumeCoin->consume_msg = 'xxxxxxx';
$consumeCoin->consume_time = $time;
$consumeCoinUpdate = $consumeCoin->save();
}else{
$userInfo = User::findOne($order_info['user_id']);
$consumeCoin = new CoinConsume();
$consumeCoin->user_id = $order_info['user_id'];
$consumeCoin->consume_type = 2;
$consumeCoin->coin_before = $userInfo['coin'];
$consumeCoin->consume_coin = $good_info['goods_num'];
$consumeCoin->coin_after = $userInfo['coin']+$good_info['goods_num'];
$consumeCoin->consume_msg = 'xxxxxxxx';
$consumeCoin->consume_time = $time;
$consumeCoinUpdate = $consumeCoin->save();
$userInfo->coin = $userInfo['coin']+$good_info['goods_num'];
$userUpdate = $userInfo->save();
}
$order_info->order_status = 1;
$order_info->update_time = $time;
$orderPayUpdate = $order_info->save();
if($userUpdate && $consumeCoinUpdate && $orderPayUpdate){
$ts->commit();
Yii::info('该订单已支付成功,本地业务处理成功'.$order_id,'paylog');
echo $msg['success'];
exit;
}else{
$ts->rollBack();
Yii::info('该订单已支付成功,本地业务操作失败,请在后台补单'.$order_id,'paylog');
echo $msg['fail'];
exit;
}
}else{
Yii::info('该订单不存在,微信已经支付成功'.$order_id,'paylog');
echo $msg['fail'];
exit;
}
}
echo $msg['fail'];
exit;
}
public function actionAli(){
}
}
wonderwong 深圳
注册时间:2012-03-21
最后登录:2024-06-01
在线时长:10小时29分
最后登录:2024-06-01
在线时长:10小时29分
- 粉丝8
- 金钱290
- 威望70
- 积分1090
共 0 条评论