草庐IT

PHP接口微信支付

康康糖糖 2023-03-28 原文
PHP后台调用微信支付下单
function wx_getPayRequest($openid, $orderid, $rmb, $title,$appoids)
{
$nonce = $orderid.mt_rand(10000,99999);
$orderid=$orderid.'_'.$nonce;//str_replace(",","_",$appoids);
//Log::write('\n ================'.$orderid,'notice');
$srct='0x'.md5(config('app.environment')['paykey'].$orderid);
$notify = '';//回调地址,自己写,支付成功回调,在回调页面进行更改与用户金钱相关的代码
$url= 'https://api.mch.weixin.qq.com/pay/unifiedorder';//统一接口prepay_id
// post data
$now = time().'';//时间
$appid ='';//小程序ID 写到一个类里面了 方便后期修改 当然也可以在这里直接写
$mchid ='';//商户号
// Log::write('\n $mchid================'.json_encode($mchid),'notice');
// Log::write('\n $appid================'.json_encode($appid),'notice');
$data = array(
'appid' => $appid,
'mch_id' => $mchid,
'spbill_create_ip' => '127.0.0.1',//终端ip Y
'nonce_str' => $nonce, //随机字符串Y
'openid' => $openid, //用户标识 N
'body' => $title, //商品描述 Y
// 'detail' => $body, //商品详情 N
'attach' => $appoids, //附加数据 N
'out_trade_no' => $orderid, //商户订单号 Y
'total_fee' => $rmb, //总金额 单位分 int Y
'notify_url' => $notify, //通知地址 Y
'trade_type' => 'JSAPI',
);

$data[ 'sign' ] = self::MakeSign($data);
//echo $data[ 'sign' ];
// Log::write('\n sign================'.json_encode($data[ 'sign' ]),'notice');

$xml=self::wx_toXML($data);
$ret = $this->http_request($url,$xml);
$json = self::wx_parseXML( $ret );
//Log::write('\n ================'.json_encode($json),'notice');
if( !$json || !isset($json[ 'prepay_id' ]) )
{
return array( 'payCode'=>1,'ret' => 'fail', 'tip' => $json[ 'return_msg' ] );
}

$prepayid = $json[ 'prepay_id' ];
$req = array(
'appId' => $appid,
'timeStamp' => $now,
'nonceStr' => $nonce,
'package' => 'prepay_id='.$prepayid,
'signType' => 'MD5',
);
$req[ 'paySign' ] = self::wx_getPkgSign($req);
//$req[ 'notify' ] = $notify;
return $req;
}

///作用:格式化参数,签名过程需要使用
private function formatBizQueryParaMap($paraMap, $urlencode) {
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
$reqPar;
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}


public function wx_getPkgSign($req )
{
foreach ($req as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//签名步骤二:在string后加入KEY
$String = $String . "&key=" . config('app.environment')['paykey'];
//签名步骤三:MD5加密
$String = md5($String);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}

public function wx_toXML( $data )
{
$xml = '<xml>';
foreach( $data as $key => $val )
{
$xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
}
$xml .= '</xml>';
return $xml;
}

/**
* 输出xml字符
* @param $data
* @return string
*/
public function ToXml($data)
{
if(!is_array($data)
|| count($data) <= 0)
{
throw new WxPayException("数组数据异常!");
}

$xml = "<xml>";
foreach ($data as $key=>$val)
{
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}

/**
* 格式化参数格式化成url参数
*/
public function ToUrlParams($data)
{
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}

$buff = trim($buff, "&");
return $buff;
}

/**
* 生成签名
* @param $data
* @return string 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function MakeSign($data)
{
//签名步骤一:按字典序排序参数
ksort($data);
$string = $this->ToUrlParams($data);
//签名步骤二:在string后加入KEY
$string = $string . "&key=".config('app.environment')['paykey'];
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}

public function wx_parseXML( $str )
{
$rsp = array();
$xml = @simplexml_load_string( $str );
if( $xml && $xml->children() )
{
foreach( $xml->children() as $node )
{
if( $node->children() )
{
$k = $node->getName();
$nodeXml = $node->asXML();
$v = substr( $nodeXml, strlen($k)+2, strlen($nodeXml)-2*strlen($k)-5 );
}
else
{
$k = $node->getName();
$v = (string)$node;
}
$rsp[ $k ] = $v;
}
}
return $rsp;
}

public function payRefund($wxtranid,$order_childid, $ordertotalrmb,$refundrmb){
$appid = config('environment')[config('current_environment')]['appid'];//小程序ID 写到一个类里面了 方便后期修改 当然也可以在这里直接写
$mchid = config('environment')[config('current_environment')]['mchid'];//商户号
$nonce = $order_childid.mt_rand(10000,99999);

Log::write('取消预约单申请退款中===$ordertotalrmb='.$ordertotalrmb.'=======$refundrmb='.$refundrmb,'notice');

//统一下单退款参数构造
$unifiedorder = array(
'appid' => $appid,
'mch_id' => $mchid,
'nonce_str' => $nonce,
'transaction_id' => $wxtranid,
'out_refund_no' => $order_childid,
'total_fee' => intval($ordertotalrmb),
'refund_fee' => intval($refundrmb),
'notify_url'=>'https://wxcon.drmpsy.com.cn/api/appo/payBackSuccess'
);
$unifiedorder['sign'] = self::wx_getPkgSign($unifiedorder);
Log::write('$content111111================'.json_encode($unifiedorder),'notice');
//请求数据
$xmldata = self::wx_toXml($unifiedorder);
$opUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//$res = $this->http_request($opUrl, $xmldata);
$res = $this->postXmlSSLCurl($xmldata,$opUrl);
Log::write($res,'notice');
if (!$res) {
return "Can't connect the server";
}
$content = self::xmlToArray($res);
Log::write('$content================'.json_encode($content),'notice');
try{
if (strval($content['result_code']) == 'FAIL') {
return strval($content['err_code_des']);
}
}
catch (Exception $err){

}
try{
if ($content['return_code']&&strval($content['return_code']) == 'FAIL') {
return strval($content['return_msg']);
}
}
catch (Exception $err){

}
return $content;
}

public function xmlToArray($xml){
$array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $array_data;
}

//需要使用证书的请求
private function postXmlSSLCurl($xml,$url,$second=30)
{
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置header
curl_setopt($ch,CURLOPT_HEADER,FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, '/nfs/website/wx.drmpsy.com.cn/api/cert/apiclient_cert.pem');
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,'/nfs/website/wx.drmpsy.com.cn/api/cert/apiclient_key.pem');
//post提交方式
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
echo "curl出错,错误码:$error"."<br>";
curl_close($ch);
return false;
}
}
//curl请求
public function http_request($url,$data = null,$headers=array())
{
$curl = curl_init();
if( count($headers) >= 1 ){
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}

有关PHP接口微信支付的更多相关文章

  1. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  2. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

  3. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  4. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  5. ruby-on-rails - 与 ActiveMerchant 一起使用的最佳支付网关是什么? - 2

    我需要使用ActiveMerchant库在我们的一个Rails应用程序中设置支付解决方案。尽管这个问题非常主观,但人们对主要网关(BrainTree、Authorize.net等)的体验如何?它必须:处理定期付款。有能力记入个人帐户。能够取消付款。有办法存储用户的付款详细信息(例如Authotize.netsCIM)。干杯 最佳答案 ActiveMerchant很棒,但在过去一年左右的时间里,我在使用它时发现了一些问题。首先,虽然某些网关可能会得到“支持”——但并非所有功能都包含在内。查看功能矩阵以确保完全支持您选择的网关-http

  6. Ubuntu20.04系统WineHQ7.0安装微信 - 2

    提供3种Ubuntu系统安装微信的方法,在Ubuntu20.04上验证都ok。1.WineHQ7.0安装微信:ubuntu20.04安装最新版微信--可以支持微信最新版,但是适配的不是特别好;比如WeChartOCR.exe报错。2.原生微信安装:linux系统下的微信安装(ubuntu20.04)--微信适配的最好,反应最快,但是微信版本只到2.1.1,版本太老,很多功能都没有。3.深度deepin-wine6安装微信:ubuntu20.04+系统deepin-wine6安装新版微信--综合比较好,当前个人使用此种方法1个月,微信版本3.4;没什么大问题,尚可。一、WineHQ7.0安装微信

  7. 微信小程序订餐系统 - 2

    对传统的餐饮商家来说,小程序很好地解决了餐厅线下线上连接的问题,在引流获客、节约人力、营销宣传、塑造会员体系、改善消费体验等方面都有很大帮助。小程序点餐可以帮助餐饮企业节省一大把人力开支。一个包含扫码点单、菜品管理、优惠券推送、外卖配送的小程序,商家花几万元就能完成开发测试并投入。商家为什么要开通“扫码点餐”1.解决服务员不够用的问题。2.不怕顾客跑单漏单。3.在微信就能管理菜品、查看营业额。4.订单小票显示顾客桌号和已点菜品。5.可在“附近的小程序”找到您的门店。如今餐饮业常用的三种经营模式:1堂食点单模式客人通过小程序堂食点单。商家可以在微信扫码点餐小程序管理后台根据自己店内情况来设置不同

  8. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  9. ruby-on-rails - 如何在 RubyOnRails 中使用 'acts as nested set' 创建一个可排序的接口(interface) - 2

    我一直在为使用acts_as_list的模型实现一些不错的交互界面,这些界面可以对我的mRails应用程序中的列表进行排序。我有一个排序函数,在每次拖放之后使用sortable_elementscript.aculo.us函数调用并设置每条记录的位置。这是在拖放完成后处理排序的Controller操作示例:defsortparams[:documents].each_with_indexdo|id,index|Document.update_all(['position=?',index+1],['id=?',id])endend现在我正在尝试对嵌套集模型(acts_as_nested

  10. 你真正了解什么是接口测试么?接口实战一“篇”入魂 - 2

    最近在工作中,看到一些新手测试同学,对接口测试存在很多疑问,甚至包括一些从事软件测试3,5年的同学,在聊到接口时,也是一知半解;今天借着这个机会,对接口测试做个实战教学,顺便总结一下经验,分享给大家。计划拆分成4个模块跟大家做一个分享,(接口测试、接口基础知识、接口自动化、接口进阶)感兴趣的小伙伴记得关注,希望对你的日常工作和求职面试,带来一些帮助。注:文章较长有5000多字,希望小伙伴们认真看完,当然有些内容对小白同学不是太友好,如果你需要详细了解其中的一些概念或者名词,请在文章之后留言,后续我将针对大家的疑问,整理输出一些大家感兴趣的文章。随着开发模式的迭代更新,前后端分离已不是新的概念,

随机推荐