新手问题 微信支付 统一支付接口 appid and openid not match

naitnix · 2015年06月12日 · 最后由 xinggu 回复于 2019年06月03日 · 68011 次阅读

最近在搞微信公众号支付,即用户在 h5 页面通过 jssdk 发起支付请求,看了下文档

wx.chooseWXPay({
    timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
    nonceStr: '', // 支付签名随机串,不长于 32 
    package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***
    signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
    paySign: '', // 支付签名
    success: function (res) {
        // 支付成功后的回调函数
    }
});

这里的 package 需要从统一支付接口拿到,所以在代码里按照文档要求先去请求了统一支付接口

def self.random_string
    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
    newpass = ""
    1.upto(16) { |i| newpass << chars[rand(chars.size-1)] }
    return newpass
end

def self.generate_sign(hash)
    stringA        = hash.sort.map{|e| e.join('=')}.join('&')
    stringSignTemp = stringA + "&key=#{Wechart.apikey}"
    sign           = Digest::MD5.hexdigest(stringSignTemp).upcase
    return   sign 
end

def self.unifiedorder(opt)
    param   = {
        appid:self.appid,
        mch_id:self.mch_id,
        nonce_str:self.random_string,
        body:opt[:body],
        out_trade_no:opt[:trade],
        total_fee:opt[:total_fee].to_i * 100,
        spbill_create_ip:opt[:ip],
        notify_url:self.notify_url,
        trade_type:'JSAPI',
        openid:opt[:openid]
    }

    sign     = generate_sign(param)
    param.merge!({sign:sign})

    builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
        xml.root {
            xml.appid param[:appid]
            xml.mch_id param[:mch_id]
            xml.nonce_str self.random_string
            xml.sign sign
            xml.body param[:body]
            xml.out_trade_no param[:out_trade_no]
            xml.total_fee param[:total_fee]
            xml.spbill_create_ip param[:spbill_create_ip]
            xml.notify_url param[:notify_url]
            xml.trade_type param[:trade_type]
            xml.openid param[:openid]
        }
    end

    uri = URI.parse("https://api.mch.weixin.qq.com/pay/unifiedorder")
    Net::HTTP.start(uri.host,uri.port,use_ssl:true) do |http|
        request  = Net::HTTP::Post.new(uri.path)
        request.body = builder.to_xml
        response = http.request(request)
        res      = Nokogiri::XML(response.body,nil,'UTF-8')
    end
end

上述方法的入口是 unifiedorder 这个函数,在 console 里面测试,一直返回错误信息:

#<Nokogiri::XML::Document:0x2d42798 name="document" children=[#<Nokogiri::XML::Element:0x2d41244 name="xml" children=[#<Nokogiri::XML::Element:0x2d4072c name="return_code" children=[#<Nokogiri::XML::CDATA:0x2d3db94 "FAIL">]>, #<Nokogiri::XML::Text:0x2d3ce24 "\n">, #<Nokogiri::XML::Element:0x2d3c820 name="return_msg" children=[#<Nokogiri::XML::CDATA:0x2d33cd4 "appid and openid not match">]>, #<Nokogiri::XML::Text:0x2d33310 "\n">]>]>

看错误提示很明显 appid 和 openid 不匹配,但是没明白是什么意思,不知道 appid 和 openid 怎么扯上关系了,于是各种 google,无果,发到这里请大家帮忙,看 api,支付需要三个步骤:

* 步骤1:网页授权获取用户openid
* 步骤2:使用统一支付接口,获取prepay_id
* 步骤3:使用jsapi调起支付

现在我已经知道了我的个人 openid,所以,第一步省略了,上面的代码直接列出的是第二步,一直是这个错误,不知道各路高手是怎么解决的,求答案

用我的 gem 吧。。。就是楼上的链接,之前刚好有朋友已经踩过 APP 支付的坑了...

使用 wxpay 成功。支付功能 需要 appid openid mch_id mch_key, 还要在微信公众号里 配几个地方。有一个地方有问题都不能成功。。。从坑里爬出来的飘过

appid 和 openid 有关系的,按微信支付的文档,不同 app 下面的授权用户,openid 不一样的

这里有一些 App 支付接入的文档,希望能有一些帮助:https://pingxx.com/guidance

要介绍一下支付返点的故事么?谁掌握了这个入口,谁就是坐着收钱

#5 楼 @pingplusplus ping++ 里面貌似没有和本问题相关的微信支付内容,有广告嫌疑@lgn21st

#2 楼 @jasl gem 中为什么没有获取 code,用 code 获取 openid 的过程?

#8 楼 @caiqinghua 因为有 omniauth-wechat-oauth2 这种更专业的 gem 解决呀

#8 楼 @caiqinghua 另一方面,微信的 openid 获取是和系统的业务和技术耦合非常紧密的,所以没法单纯通过 Gem 层面抽象

#10 楼 @jasl node 处理还是挺简单的,可以抽取出来

#7 楼 @caiqinghua 确有嫌疑,广告贴

#10 楼 @jasl 理解。为了 gem 包的完备性,建议在 readme 中说明,为什么不在这个 gem 中获取 openid。另外建议加上调试的注意点。

@jasl ,试了你的 gem,一样的问题,所以我觉得可能是微信的某些地方配置有问题,这里要请教一下,需要做哪些配置

@fresh_fish ,没明白你说的是啥意思,我的理解是 openid 只不过是需要支付人的 id,只要我有这个 id 并且,账户金额足够,那么就可以充值,跟绑定与否没多大关系,不知道这么理解是否正确,望指教

#15 楼 @naitnix 我的意思是你这个 openid 是从你现在这个应用下面获取的吗?

@fresh_fish ,不是,我是已知了自己微信账号的 openid, 然后作为一个参数直接传递的,难道必须要先授权然后再做支付申请?

#17 楼 @naitnix 就是刚才说的问题,即使同一个用户,不用应用下授权获取到的 openid 是不一样的,所以才会不匹配,你试试从你自己的应用下面授权拿一下 openid 看看

#17 楼 @fresh_fish 如果授权时 scope 选择 snsapi_userinfo,可以拿到 unionid,这个对同一个帐号下面的应用是唯一的

#18 楼 @fresh_fish 请问 只要 openid 是这个应用对应的就可以不是吗?支付好像不用授权,获取个人信息需要授权。不知道是不是这样

@fresh_fish ,谢谢,问题得到解决,看来授权的那一步是不可少的,之前一直天真的以为只要有 openid 就可以了,现在看来这是错误的

@pathbox, @fresh_fish 请问怎样判断某个 openid 是不是和某个应用对应

#23 楼 @naitnix 自己记录下来。。。

。。。。。。自己录?用户授权的时候会录一次,或者关注的时候会录一次,貌似只有这两处

@pathbox @fresh_fish ,刚刚测试了一下,只要 openid 是这个应用对应的就可以不用去授权了,如果不是的话,就会报"appid and openid not match"这个错误了,这个时候是需要先授权获取 openid 的,至于怎么判断 openid 是不是和某个应用对应,这个应该是在授权的时候微信那边有过记录了

#22 楼 @fresh_fish 我理解对了哈哈

#26 楼 @naitnix 所有的 openid 都是微信给你的,微信帮你管理了

#26 楼 @naitnix 如果我有多个公众号,想在 A 里面使用 B 的微信支付。这里的 openid 是传 A 下面授权获取的,还是 B 下面?传 unionid 是否可以呢?

#2 楼 @jasl 我用的时候,提示签名错误,使用了你的 WxPay::Service.invoke_unifiedorder 方法,得到的这个提示

#30 楼 @greatbody 应该是你的配置问题,去后台再确认一下

#31 楼 @jasl 后来去检查,发现是 key 长度超过了微信的限制。

#32 楼 @greatbody 嗯,微信支付这块,出现问题,先排查下配置,我之前还遇到过很多莫名其妙极具误导性的错误信息,最后发现都是因为配置错误造成的

#33 楼 @jasl 现在已经成功了。微信神坑,已经写了一个简单的配置总结贴。

我也碰到这样的错误。仔细检查代码后解决了:

  • 确保获取 openid 时所用的公众号 appid 与发起支付时所用的公众号 appid 一致。

我分别为测试环境和生产环境申请了两个公众号,测试通过后发布上线。然后在上线后碰到这个错误,仔细检查了代码,反思了为什么测试环境能成功,而生产环境不行。最终发现区别在于获取 openid 时,写死了使用测试环境的公众号。也就是说,在向生产环境的公众号支付之前,用了测试环境公众号去拿 openid。

确保改一致之后,问题解决!

@naitnix 你好,我也遇到同样的问题,我检查 openid 和 appid 都应该是对的,不知道你说的授权后获得 openid 是什么意思,能否帮忙详细说明下,我的 QQ 27779611

自己搞了个微信公众号接的第三方平台,微信支付开通后,测试定单,我自己可以支付,其他人都不行,研究了几天不得要领,总是报错:Appid and opened not match,也不知道哪里设置出了问题,求大神解惑

这个我开发 https://xorpay.com 支付平台 的时候也碰到过。微信每个产品 公众号、小程序 下面的用户都对应一个 openid,并且还不一样,你这个问题应该是用来获取用户 openid 的 appid 和你用来发起支付的 appid 不一致导致的。

注意,发起支付的时候 paySign 签名的 appid 要和你获取 openid 时候用的 appid 一致 大部分问题都是出在这里

  1. 如果你是 js 用 jsapi 发起支付,https://api.weixin.qq.com/sns/oauth2/access_token 需要用到这个来获取 openid
  2. 如果是小程序里面发起支付,用 wx.login 获得 code 以后,需要用 https://api.weixin.qq.com/sns/jscode2session 这个接口来获取 openid
需要 登录 后方可回复, 如果你还没有账号请 注册新账号