富友支付AS微信支付

    刚好公司有个需求,需要把公众号的微信支付,改成富友AS微信支付(我自己起的名字),而且是要用C#去写。对于只用过PHP和Python的我来说,那是一脸懵逼。最后研究了一下富友开放平台的文档,折腾了一天终于还是把问题解决了。C#的代码有点略多,简单点我还是贴个PHP代码出来,主要是流程和踩坑点,也是做个记录,省的下次再去折腾。

PS:富友官方的Demo有点坑,和文档不匹配,不过按照文档去修改下Demo其实也很简单就能实现了。

富友AS微信支付:起这个名字的原因是,通过调用富友的统一下单接口,然后在返回数据中取到调起微信支付所需要的参数去调起微信支付。

这里我只说实现的流程和注意的地方,最后代码封装什么的自己去做吧,不管用什么语言都差不多。

微信公众号/服务窗统一下单接口:https://fundwx.fuiou.com/wxPreCreate

富友开放平台:https://open.fuioupay.com/partner/

首先自然是定义报文了,报文如下:

$data=array();
$data['version']="1.0";
$data['ins_cd']="08A9999999";//机构号,接入机构在富友的唯一代码
$data['mchnt_cd']="0002900F0370542";//商户号, 富友分配给二级商户的商户号
$data['term_id']="88888888";//终端号
$data['random_str']='abcdefg';//随机字符串
$data['goods_des']="描述";//商品描述
$data['mchnt_order_no']= time();//内部订单号
$data['order_amt']=2000;//金额单位 fen
$data['term_ip']="127.0.0.1";
$data['txn_begin_ts']=date('YmdHis',time());//订单生成时间
$data['notify_url']="wx.test.com";//回调URL
$data['trade_type'] = 'JSAPI';//订单类型
$data['sub_appid'] = '';//wx2308b45bb46d7592
$data['sub_openid'] = "";//obrYV5uNkmBXZhLrEibWlLn0AbUg
$data['addn_inf']="";
$data['curr_type']="CNY";
$data['goods_detail']="";
$data['goods_tag']="";
$data['limit_pay'] = "";
$data['openid'] = "";
$data['product_id'] = "";

  这里是所有签名要用到的字段,按照文档所说:

1.将接口中每一个字段(sign 及 reserved 开头字段除外),以字典顺序排 序之后,按照 key1=value1&key2=value2.....的顺序,进行拼接。

2.对得到的字符串进行 RSA 签名/验签 注:sign 及 reserved 开头字段除外的其他非必填字段也需要参与验签。 我司会根据后期业务需求,新增 reserved 开头字段,请提前做好兼容 (简而言之,我们会新增 reserved 开头字段的字段,这些字段都不参与验 签)。

    菜鸟如我,在这个简单的地方就踩了一个坑,而踩坑的原因在于没有认真的去阅读文档,想当然的用微信支付的签名方式去处理了报文:微信支付中字段为空的不参与签名,而富友支付这里,除了sign和reserved打头的字段外都是需要参与签名的,这就导致了之后我的验签无法通过。

参数有了,现在进行字典排序

function signSort( $params){
    if (!is_array($params)){
        $params = array();
    }
    ksort($params);
    $signStr = "";
    foreach ($params as $k => $v) {
        $signStr .= $k.'='.$v."&";
    }
    //var_dump(substr($signStr,0,-1));
    return substr($signStr,0,-1);
}
$sign = signSort($data);

很简单,直接使用ksort()这个自带函数就好了,然后拼接成key1=value1&key2=value2……的格式,貌似大部分接口都是这么搞的。

现在是关键的一步:签名,这里直接贴上Demo中的类方法,下面直接用了

class A2Xml {
  private $xml    = null;
  function __construct() {
    $this->xml = new XmlWriter();
  }
  //数组转xml
  function toXml($data, $eIsArray=FALSE) {
    if(!$eIsArray) {
      $this->xml->openMemory();
    }
    foreach($data as $key => $value){
      if(is_array($value)){
        $this->xml->startElement($key);
        $this->toXml($value, TRUE);
        $this->xml->endElement();
        continue;
      }
      $this->xml->writeElement($key, $value);
    }
    if(!$eIsArray) {
      $this->xml->endElement();
      return $this->xml->outputMemory(true);
    }
  }
  //签名加密流程
  function sign($data){
      //读取密钥文件
     $pem = file_get_contents(dirname(__FILE__).'/keypem.pem');
      //获取私钥
      $pkeyid = openssl_pkey_get_private($pem);
      //var_dump($pkeyid);
      //MD5WithRSA私钥加密
      openssl_sign($data,$sign,$pkeyid,OPENSSL_ALGO_MD5);
      //返回base64加密之后的数据
      //echo($sign);
      $t=base64_encode($sign);
      //解密-1:error验证错误 1:correct验证成功 0:incorrect验证失败
       //$pubkey = openssl_pkey_get_public($pem);
       //$ok = openssl_verify($data,base64_decode($t),$pubkey,OPENSSL_ALGO_MD5);
      // var_dump($ok);
      return $t;
  }
  //通过curl模拟post的请求;
  function SendDataByCurl($url,$data){
      //对空格进行转义
      $url = str_replace(' ','+',$url);
      $ch = curl_init();
      //设置选项,包括URL
      curl_setopt($ch, CURLOPT_URL, "$url");
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_HEADER, 0);
      curl_setopt($ch,CURLOPT_TIMEOUT,3); //定义超时3秒钟
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
       // POST数据
      curl_setopt($ch, CURLOPT_POST, 1);
      // 把post的变量加上
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  //所需传的数组用http_bulid_query()函数处理一下,就ok了
      //执行并获取url地址的内容
      $output = curl_exec($ch);
      $errorCode = curl_errno($ch);
      //释放curl句柄
      curl_close($ch);

      if(0 !== $errorCode) {
        return $errorCode;
      }
      return $output;
    }

  }
//签名加密流程
  $xml = new A2Xml();
  function sign($data){
      //读取密钥文件
     $pem = file_get_contents(dirname(__FILE__).'/keypem.pem');
      //获取私钥
      $pkeyid = openssl_pkey_get_private($pem);
      //var_dump($pkeyid);
      //MD5WithRSA私钥加密
      openssl_sign($data,$sign,$pkeyid,OPENSSL_ALGO_MD5);
      //返回base64加密之后的数据
      //echo($sign);
      $t=base64_encode($sign);
      //解密-1:error验证错误 1:correct验证成功 0:incorrect验证失败
       //$pubkey = openssl_pkey_get_public($pem);
       //$ok = openssl_verify($data,base64_decode($t),$pubkey,OPENSSL_ALGO_MD5);
      // var_dump($ok);
      return $t;
  }

$data['sign'] = $xml->sign($sign);

  接下来需要转化数组为XML格式

//完整的xml格式
$requestXml = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?><xml>".$xml->toXml($data)."</xml>";

  CURL模拟发送post请求

 

//经过两次urlencode()之后的字符串
$requestParam = "req=".urlencode(urlencode($requestXml ));
//通过curl的post方式发送接口请求 
$url = "https://fundwx.fuiou.com/wxPreCreate";

//返回的xml字符串        
$resultXml = URLdecode(URLdecode($xml->SendDataByCurl($url,$requestParam )));
//将xml转化成对象
$ob= simplexml_load_string($resultXml);

//输出结果
echo '<pre>';
var_dump($ob);
echo '</pre>';

  整个过程很简单,用C#实现流程也一样的,官方Demo中的问题也就是报文的字段不全,以及订单类型字段不对,其他的按照官方Demo运行就OK了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值