话说微信自从和支付宝大战之后,微信支付被逼得上线了,不然微信浏览器里是无法正常完成支付宝支付的,特别是做过授权登录的网站,如果想用第三方浏 览器打开链接去调用支付宝支付的话,可能还会出现各种奇葩问题。而且一旦这些问题和钱搭上关系后,处理起来就必须谨慎再谨慎了。
被逼无奈下,加上手机版的微信支付接口,下面给出接口文件源码,其他文件,例如语言包啊,就自己写写吧。
<?php
/* 微信支付 */
/* V 1.0 */
/* by tiandi */
/* www.tiandiyoyo.com */
/* 2015.3.23 */
if (!defined('IN_ECTOUCH'))
{
die('Hacking attempt');
}
$payment_lang = ROOT_PATH . 'lang/' .$GLOBALS['_CFG']['lang']. '/payment/wxpay.php';
if (file_exists($payment_lang))
{
global $_LANG;
include_once($payment_lang);
}
/* 模块的基本信息 */
if (isset($set_modules) && $set_modules == TRUE)
{
$i = isset($modules) ? count($modules) : 0;
/* 代码 */
$modules[$i]['code'] = basename(__FILE__, '.php');
/* 描述对应的语言项 */
$modules[$i]['desc'] = 'wxpay_desc';
/* 是否支持在线支付 */
$modules[$i]['is_online'] = '1';
/* 作者 */
$modules[$i]['author'] = 'tiandi';
/* 网址 */
$modules[$i]['website'] = 'http://www.tiandiyoyo.com';
/* 版本号 */
$modules[$i]['version'] = '1.0';
/* 配置信息 */
$modules[$i]['config'] = array(
array('name' => 'wxpay_appid', 'type' => 'text', 'value' => ''),
array('name' => 'wxpay_mchid', 'type' => 'text', 'value' => ''),
array('name' => 'wxpay_apikey', 'type' => 'text', 'value' => '')
);
return;
}
class wxpay {
var $para;
var $openid;
function wxpay()
{
}
function __construct()
{
}
function set_para($key,$value){
$this->para[$key] = $value;
}
function get_code($order, $payment){
$sql = "SELECT wxid FROM " .$GLOBALS['ecs']->table('users'). " WHERE user_id = ".$_SESSION['user_id'];
$wxid = $GLOBALS['db']->getOne($sql);
$apikey = $payment['wxpay_apikey'];
$appid = $payment['wxpay_appid'];
$callback_url = $GLOBALS['ecs']->url() . 'respond.php?code=wxpay';
$ip = getIPaddress();
$timestamp = time();
$noncestr = $this->create_noncestr();
$this->set_para("nonce_str", $noncestr); //随机字符串
$this->set_para("appid", $appid); //公众号
$this->set_para("mch_id", $payment['wxpay_mchid']); //商户号
//$this->set_para("device_info", 'WEB'); //终端设备号(商户的门店号或设备ID),注意:PC网页或公众号内支付请传"WEB"
$this->set_para("body", $order['order_sn']); //商品或支付单简要描述
$this->set_para("out_trade_no", $order['order_sn'] . 'O' . $order['log_id']); //商户订单号
$this->set_para("total_fee", floor($order['order_amount']*100)); //付款金额,单位分
$this->set_para("spbill_create_ip", $ip); // 终端地址
$this->set_para("notify_url", $callback_url); //异步通知地址
$this->set_para("trade_type", 'JSAPI'); //交易类型 JSAPI,NATIVE,APP
$this->set_para("openid", $wxid); //用户openid
$postxml = $this->create_xml($apikey);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$response = $this->curl_post_ssl($url, $postxml);
$responseObj = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA);
//print_r($responseObj);
$prepay_id = "prepay_id=".$responseObj->prepay_id;
$signkey = getkey($noncestr,$prepay_id,$timestamp,$appid,$apikey);
$button = '<div style="text-align:center"><input type="button" value="' .$GLOBALS['_LANG']['pay_button']. '" class="c-btn3" /></div>';
$js = "<script>function onBridgeReady(){".
"WeixinJSBridge.invoke(".
"'getBrandWCPayRequest', {".
"'appId' : '".$payment['wxpay_appid']."', ".
"'timeStamp':'".$timestamp."',".
"'nonceStr' : '".$noncestr."',".
"'package': '".$prepay_id."',".
"'signType' : 'MD5',".
"'paySign' : '".$signkey."'".
"},".
"function(res){ ".
"if(res.err_msg == 'get_brand_wcpay_request:ok' ) ".
"{".
"alert('支付成功!');".
"window.location.href='user.php?act=order_list';".
"}".
"else {".
"alert('支付失败!');".
"} });} ".
" </script>";
return $button.$js;
}
function respond($postStr) {
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
$responseObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$json = json_encode($responseObj);
$res = json_decode($json, true);
if($this->check_respond_date($res)) {
$out_trade_no = $res['out_trade_no'];
$out_trade_no = explode('O', $out_trade_no);
$order_sn = $out_trade_no[0];//订单号
$log_id = $out_trade_no[1];//订单号log_id
if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') {
// by tiandi 改变子订单状态
sub_order_paid($order_sn, $log_id, 2);
/* 改变订单状态 */
order_paid($order_sn, $log_id, 2);
echo "success";
} else {
echo "fail";
}
}
else
echo "fail";
}
function check_respond_date($res) {
$sql = "SELECT pay_config FROM " .$GLOBALS['ecs']->table('touch_payment'). " WHERE pay_code = '".$res['code']."'";
$result = $GLOBALS['db']->getOne($sql);
$config = $this->unserialize_config($result);
$apikey = $config['wxpay_apikey'];
ksort($res);
$tempsign = "";
foreach ($res as $k => $v){
if (null != $v && "null" != $v && "sign" != $k && "code" != $k) {
$tempsign .= $k . "=" . $v . "&";
}
}
$tempsign = substr($tempsign, 0, strlen($tempsign)-1); //去掉最后的&
$tempsign .="&key=". $apikey; //拼接APIKEY
$sign = strtoupper(md5($tempsign));
if($sign == $res['sign']) {
return true;
}
else {
return false;
}
}
function unserialize_config($cfg){
if (is_string($cfg) && ($arr = unserialize($cfg)) !== false)
{
$config = array();
foreach ($arr AS $key => $val)
{
$config[$val['name']] = $val['value'];
}
return $config;
}
else
{
return false;
}
}
function create_noncestr( $length = 24 ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
function check_sign_para(){
if($this->para["appid"] == null ||
// $this->para["device_info"] == null ||
$this->para["mch_id"] == null ||
$this->para["nonce_str"] == null ||
$this->para["body"] == null ||
$this->para["out_trade_no"] == null ||
$this->para["total_fee"] == null ||
$this->para["spbill_create_ip"] == null ||
$this->para["notify_url"] == null ||
$this->para["trade_type"] == null ||
$this->para["openid"] == null
)
{
return false;
}
return true;
}
function create_sign($apikey){
if($this->check_sign_para() == false) {
echo "签名参数错误!";
}
ksort($this->para);
$tempsign = "";
foreach ($this->para as $k => $v){
if (null != $v && "null" != $v && "sign" != $k) {
$tempsign .= $k . "=" . $v . "&";
}
}
$tempsign = substr($tempsign, 0, strlen($tempsign)-1); //去掉最后的&
$tempsign .="&key=". $apikey; //拼接APIKEY
return strtoupper(md5($tempsign));
}
function create_xml($apikey){
$this->set_para('sign', $this->create_sign($apikey));
return $this->ArrayToXml($this->para);
}
function ArrayToXml($arr)
{
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val))
{
$xml.="<".$key.">".$val."</".$key.">";
}
else
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml.= "</xml>";
return $xml;
}
function curl_post_ssl($url, $vars, $second=30)
{
$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);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
$data = curl_exec($ch);
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
curl_close($ch);
return false;
}
}
}
function getIPaddress()
{
$IPaddress='';
if (isset($_SERVER)){
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
$IPaddress = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
$IPaddress = $_SERVER["HTTP_CLIENT_IP"];
} else {
$IPaddress = $_SERVER["REMOTE_ADDR"];
}
} else {
if (getenv("HTTP_X_FORWARDED_FOR")){
$IPaddress = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("HTTP_CLIENT_IP")) {
$IPaddress = getenv("HTTP_CLIENT_IP");
} else {
$IPaddress = getenv("REMOTE_ADDR");
}
}
return $IPaddress;
}
function getkey($noncestr,$prepay_id,$timestamp,$appid,$apikey) {
$tempsign = "appId=".$appid."&nonceStr=".$noncestr."&package=".$prepay_id."&signType=MD5&timeStamp=".$timestamp."&key=".$apikey;
return strtoupper(md5($tempsign));