微信支付开发有两种类型,一种是扫码支付,公众号支付的,还有一种是微信App支付,如果两种需求都有,需要申请两个微信支付商户号。

这边主要介绍下微信App支付开发步骤

第一步,申请微信开放平台账号,创建应用

创建成功之后,会生成一个appid

第二步,在开放平台应用详情那边,申请微信支付能力获取

申请成功之后微信会发送邮件到申请邮箱,包含微信支付管理平台登录账号密码,登录微信支付平台,设置api密钥

第三步,接入代码

开发文档参考

这边分享一个写好的微信app支付服务端代码

示例代码

<?php 

/**
 * 微信app支付
 */
class Wxapp
{

private $_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
private $_appid = '';
private $_appkey = '';
private $_mchid = '';
	private $_keyPath = 'apiclient_key.pem';
private $_certPath = 'apiclient_cert.pem';


/**
 * 支付
 * @param  [type] $params [description]
 * @return [type]         [description]
 */
public function pay(array $params)
{
    $result = $this->createPreOrder($params);

    return $result;
}

protected function createPreOrder($params)
{
    $request = array();
    $request['appid'] = $this->_appid;
    $request['mch_id'] = $this->_mchid;
    $request['nonce_str'] = $this->randomStr(32);
    $request['body'] = ''; //商品描述自行填写
    $request['out_trade_no'] = $params['out_trade_no'];
    $request['total_fee'] = strval($params['total_fee']*100);
    $request['spbill_create_ip'] = get_client_ip();
    $request['notify_url'] = 'http://example.com/notify.html';//微信异步通知地址
    $request['trade_type'] = 'APP';
    $request['sign'] = $this->sign($request);

    $xml_str = $this->arrayToXml($request);
    $response = $this->curlRequest($xml_str);
    $response_data = $this->xmlToArray($response);
    if ($response_data['return_code'] != 'SUCCESS' || $response_data['result_code'] != 'SUCCESS') {
        echo $response_data['return_msg'];
        exit;
    }

    
    if (!$this->verifySign($response_data)) {
        echo 'Fail';
        exit;
    }

    $pay_params = $this->createResponse($response_data);
    return $pay_params;
}


/**
 * 生成支付参数
 * @param  [type] $data [description]
 * @return [type]       [description]
 */
protected function createResponse($data)
{
    $response = array();
    $response['appid'] = $this->_appid;
    $response['partnerid'] = $this->_mchid;
    $response['prepayid'] = $data['prepay_id'];
    $response['package'] = 'Sign=WXPay';
    $response['noncestr'] = $this->randomStr(21);
    $response['timestamp'] = time();
    $response['sign'] = $this->sign($response);

    return $response;
}
	
	public function refund(array $params)
{
    $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
    $request = array();
    $request['appid'] = $this->_appid;
    $request['mch_id'] = $this->_mchid;
    $request['nonce_str'] = $this->randomStr(32);
    $request['out_refund_no'] = $params['refund_sn'];
    $request['transaction_id'] = $params['transaction_id'];
    $request['total_fee'] = strval($params['pay_money']*100);
    $request['refund_fee'] = strval($params['refund_money']*100);
    $request['sign'] = $this->sign($request);
     $xml_str = $this->arrayToXml($request);
    $response = $this->curlRequest($xml_str,$url,true);

    $response_data = $this->xmlToArray($response);
    $result['status'] = 0;
    if ($response_data['return_code'] != 'SUCCESS' || $response_data['result_code'] != 'SUCCESS') {
       $result['msg'] = $response_data['return_msg'];
       return $result;
    }

    if ($response_data['result_code'] == 'SUCCESS') {
        $result['status'] = 1;
    }
    return $result;
}
	
/**
 * 发起支付请求
 * @param  [type] $request [description]
 * @return [type]          [description]
 */
protected function curlRequest($request)
{
    $ch = curl_init ();
    curl_setopt ( $ch, CURLOPT_URL, $this->_url);
    curl_setopt ( $ch, CURLOPT_POST, 1 );
    curl_setopt ( $ch, CURLOPT_HEADER, 0 );
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $request );
    $return = curl_exec ( $ch );
    if ($return === false) {
        $error = curl_error($ch);
    }
    curl_close ( $ch );
    return $return;
}



/**
 * 随机数生成函数
 * @param  [type] $length [description]
 * @return [type]         [description]
 */
protected function randomStr($length)
{
    $random_arr = array_merge(range(0,9),range('a','z'),range('A','Z'));
    $str = '';
    $counts = count($random_arr);
    for ($i=0;$i<$length;$i++) {
        $rand = mt_rand(0,$counts-1);
        $str .= $random_arr[$rand];
    }

    return $str;
}


/**
 * 验证签名
 * @param  [type] $sign     [description]
 * @param  [type] $response [description]
 * @return [type]           [description]
 */
protected function verifySign($response)
{
    if ($response['sign'] != $this->sign($response)) {
        return false;
    }

    return true;
}


/**
 * 签名函数
 * @param  [type] $params [description]
 * @return [type]         [description]
 */
protected function sign($params)
{   
    //字典升序
    ksort($params);
    //生成签名字符串
    $sign_str = $this->createSignParams($params);
    //拼接key
    $sign_str .= '&key='.$this->_appkey;
    //md5加密
    $sign_str = md5($sign_str);
    //转换为大写
    $result = strtoupper($sign_str);

    return $result;
}


/**
 * 数组转xml数据函数
 * @return [type] [description]
 */
protected function arrayToXml($data)
{
    $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;
}


/**
 * xml转换为数组
 * @param  [type] $xml [description]
 * @return [type]      [description]
 */
protected function xmlToArray($xml)
{
    libxml_disable_entity_loader(true);
    $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        

    return $result;
}



protected function createSignParams($request)
{
    $buff = "";
    foreach ($request as $k => $v)
    {
        if($k != "sign" && $v != "" && !is_array($v)){
            $buff .= $k . "=" . $v . "&";
        }
    }
    
    $buff = trim($buff, "&");
    return $buff;
}


}

appid,appkey,mchid,body(商品描述),notify_url(回调地址),spbill_create_ip(支付ip) 根据开发的框架和业务自行填写

开发过程中遇到问题,可以通过微信提供的接口进行测试比对测试地址