<?php

namespace app\api\controller\v1;

use think\Request;
use app\api\exception\weappay\lib\WxPayConfig;
use app\common\model\StoreMessages as Smsg; //消息
use app\common\model\StoreSpecial as Ss; // 特价商品
use app\common\model\StoreGroup as SG; //拼团
use app\common\model\StoreMgroup as SM; //用户团购
use app\common\model\StoreMspecial as SMs; //用户限量
use app\common\model\StoreOrder as StoreOd; //订单
use app\common\model\StoreCart as shopCart; //购物车
use app\common\model\StoreProducts as StorePro; //普通商品
use think\facade\Log;
use app\api\controller\v1\PayConfig; //微信支付管理
class Wxpay extends PayConfig
{
public function wxappay() //微信app支付
{
$oid = input('oid'); //商家id
$orsid = input('orsid'); //订单号
$price = input('price');
$appid = PayConfig::get_wx_config_info('wxappid', $oid);
$mchid = PayConfig::get_wx_config_info('wxmch_id', $oid);
//$price = $price * 100;
$price = 1;
$nonce_str = self::getNonceStr(); //自己做个随机字符串 $data = [
'appid' => $appid, //appid T
'mch_id' => $mchid, //商户号T
'nonce_str' => $nonce_str,
'body' => '可待商城系统-商品购买', //商品信息
'out_trade_no' => $orsid, //订单号
'total_fee' => $price, //价格,微信支付价格会处以一百
'spbill_create_ip' => self::getip(),
'notify_url' => config('api_url') . '/wxnotify',
'trade_type' => 'APP', //小程序,app,之类的选项不一样
]; $data['sign'] = self::makeSign($data, $oid); //制作签名 $xmldata = self::array2xml($data); //传入参数转换成xml格式
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
$res = self::curl_post_ssl($url, $xmldata); //curl发出请求 if (!$res) {
return ['status' => 1, 'msg' => "服务器连接失败"];
} $content = self::xml2array($res); //签名失败时,打印该数据 //
if (strval($content['return_code']) == 'FAIL') {
return json(['status' => 1, 'msg' => strval($content['return_msg'])]);
} if (strval($content['result_code']) == 'FAIL') {
return json(['status' => 1, 'msg' => strval($content['err_code']), ':' . strval($content['err_code_des'])]);
} //第二次签名,把第一次签名成功微信传过来的数据参数加入第二次签名,prepayid
$timest = (string)time(); $resdata = [
'appid' => $appid,
'partnerid' => $mchid,
'prepayid' => strval($content['prepay_id']),
'package' => 'Sign=WXPay',
'noncestr' => self::getNonceStr(),
'timestamp' => $timest,
]; $resdata['sign'] = self::makeSign($resdata, $oid); //T同第一次,使用当前时间和随机字符串获取签名
return json(['data' => $resdata, 'code' => 1]); //把数据传给前端,调起支付 } //回调地址(逻辑处理)
public function wxnotify()
{
$notify = file_get_contents("php://input");
$array = $this->xml2array($notify); //微信回调数据是xml格式,转化成数组
$order_num = $array['out_trade_no'];
$paynumber = $array["transaction_id"]; //交易流水号
$price = $array["total_amount"]; //支付金额
//$price = 0.01; //支付金额
}
//制作字符串
public 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;
} //制作签名,需要支付密钥
public function makeSign($data, $oid = 0)
{
//获取微信支付秘钥
$key = PayConfig::get_wx_config_info('wxkey', $oid);;
// 去空
$data = array_filter($data);
//签名步骤一:按字典序排序参数
ksort($data);
$string_a = http_build_query($data);
$string_a = urldecode($string_a);
//签名步骤二:在string后加入KEY
//$config=$this->config;
$string_sign_temp = $string_a . "&key=" . $key;
//签名步骤三:MD5加密
$sign = md5($string_sign_temp);
// 签名步骤四:所有字符转为大写
$result = strtoupper($sign);
return $result;
} //获得用户IP
public function getip()
{
static $ip = '';
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['HTTP_CDN_SRC_IP'])) {
$ip = $_SERVER['HTTP_CDN_SRC_IP'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] as $xip) {
if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
$ip = $xip;
break;
}
}
}
return $ip;
} /**
* 将一个数组转换为 XML 结构的字符串
* @param array $arr 要转换的数组
* @param int $level 节点层级, 1 为 Root.
* @return string XML 结构的字符串
*/
public function array2xml($arr, $level = 1)
{
$s = $level == 1 ? "<xml>" : '';
foreach ($arr as $tagname => $value) {
if (is_numeric($tagname)) {
$tagname = $value['TagName'];
unset($value['TagName']);
}
if (!is_array($value)) {
$s .= "<{$tagname}>" . (!is_numeric($value) ? '<![CDATA[' : '') . $value . (!is_numeric($value) ? ']]>' : '') . "</{$tagname}>";
} else {
$s .= "<{$tagname}>" . $this->array2xml($value, $level + 1) . "</{$tagname}>";
}
}
$s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
return $level == 1 ? $s . "</xml>" : $s;
} /**
* 将xml转为array
* @param string $xml xml字符串
* @return array 转换得到的数组
*/
public function xml2array($xml)
{
//禁止引用外部xml实体
libxml_disable_entity_loader(false);
$result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $result;
} //用于支付
public function curl_post_ssl($url, $xmldata, $second = 30, $aHeader = array())
{
$ch = curl_init();
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
if (count($aHeader) >= 1) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
} curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);
$data = curl_exec($ch);
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "call faild, errorCode:$error\n";
curl_close($ch);
return false;
}
} //数组转xml
function arrayToXml($arr)
{
$xml = "<root>";
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
} else {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
}
}
$xml .= "</root>";
return $xml;
}
}

  

最新文章

  1. jquery实现&quot;跳到底部&quot;,&quot;回到顶部&quot;效果
  2. Xcode + Swift 制作动态原型
  3. 分享一个基于EF5.0封装的BaseDAL
  4. SpatiaLite 各版本数据库差异
  5. 在Android应用中实现Google搜索的例子
  6. C趣味100道之58.拉丁方的一些想法。
  7. HDU 5765 Bonds(状压DP)
  8. hive------ Group by、join、distinct等实现原理
  9. oracle 中 某个字段的长度不够的sql 语句
  10. svg中实现文字随曲线走向,HTML直接写和JavaScript创建对象两种方式
  11. CRM项目之stark组件(2)
  12. node通过http.request向其他服务器上传文件
  13. eclipse spring 配置文件xml校验时,xsd报错
  14. Dom操作注意事项
  15. Java性能调优:利用JMC分析性能
  16. javascript对象使用总结
  17. rim
  18. 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)
  19. ACM-ICPC 2018 徐州赛区网络预赛 Solution
  20. 1029 C语言文法翻译(2)

热门文章

  1. 【Spring】事务
  2. CentOS 7.3 安装 libsodium 1.0.18
  3. TensorFlow读取数据的三种方法
  4. FreeSql (二十一)查询返回数据
  5. android 百度地图入门01 (史上最详没有之一)
  6. Yum未完成事务问题
  7. hbase 修复 hbase hbck
  8. Charles 下载
  9. java动态代理之CGLIB实现
  10. Java Synchronized Method This Static Class Object 区别