- 微信支付回调通知 解密前 如何确定商户的RSAAutoCertificateConfig
官方SDK - 回调通知验签和解密 // 构造 RequestParam RequestParam requestParam = new RequestParam.Builder() .serialNumber(wechatPayCertificateSerialNumber) .nonce(nonce) .signature(signature) .timestamp(timestamp) .body(requestBody) .build(); // 如果已经初始化了 RSAAutoCertificateConfig,可直接使用 // 没有的话,则构造一个 【*****请问这里 未解密前如果能知道是哪个商户号的回调??****】 NotificationConfig config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .apiV3Key(apiV3key) .build(); // 初始化 NotificationParser NotificationParser parser = new NotificationParser(config); // 以支付通知回调为例,验签、解密并转换成 Transaction Transaction transaction = parser.parse(requestParam, Transaction.class);
2023-07-15 - 回调通知验签和解密给的api是不是不太对?
[图片] NotificationParser 的构造方法中的参数是数组呀 [图片] 和示例中的也对不上呀 [图片]
2022-12-28 - 刚收到通知获取手机号收费开始了?
[图片] https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getRealtimePhoneNumber.html https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/paymentManage.html 未来:旧版本接口依然可以使用,只是需要收费而已,不想做改动的交钱就行了。如果想用新API方法就去改吧,多花一分钱。 可能支持的省钱办法: 授权手机号后,服务端将openId、手机号进行绑定。用户onLaunch打开小程序的时候通过wx.login获取code去解密openId,同时由于服务端已经绑定过手机号,所以可以使用该手机号进行登录,并同步返回token、jwtToken等登录态。这样可以做到用户冷启动小程序时自动登录上,减少使用授权的逻辑。业务按钮点击后 先调用wx.login,如果返回token则进行后续业务,如果没返回则弹出自定义弹窗,弹窗内点击按钮再进行手机号授权。(也可以在部分页面onLoad里wx.login),这个场景因为会延长流程,所以产品说不考虑,先直接打开页面就登录上,你们的各自看各自的业务场景吧。然后有四个疑问: 充值购买次数后会,如果小程序被封禁了,充值的金额是否可退款。购买数量是否支持按量付费?如果次数用完了,未购买新的次数,用户端的表现是什么?如果次数用完了,之前文档说的余量20%、10%、5%时会发模板消息提醒,文档相关现在已经删除了,是否还会发?[图片] ———————————————————————————————————————————————— 今天看了下文档做了改动: 退款规则:若购买有误,且未正式开始使用资源包前,可以在支付成功后的7天内申请退款。款项将在3-5个工作日内从原支付路径返回;若资源包已经开始使用(使用1次及以上),则不能申请退款;若支付成功后超过7天,未发起退款申请,亦不能再申请退款。 那么小程序被封了应该是不退的。不确定,等官方回复次数用完了,用户授权不会弹出授权弹窗,会返回一个errNo:1400001,用户判断等于这个errNo的时候跳转到自己的账密登录页面。不确定,等官方回复———————————————————————————————————————————————— 据了解老版本的快速验证组件(获取手机号),180天才会发送短信验证一次,为啥能每次授权都收费0.03元。 社区搜了一张图,180天没验证的应该会弹这个,不是说是短信运营成本么?为啥不是第180天验证那次费用让我们付,而是每次授权都付? [图片] 手机号授权改造后的效果: 打开职位详情页:优先调用接口判断openId是否绑定过。 如果未绑定:使用button的open-type=“getPhoneNumber”,点击报名弹出手机号授权,授权成功后与openId进行绑定落库。 如果已绑定,页面通过变量判断使用wx.login静默授权,同时服务端拿到绑定的手机号后进行登录操作,同步返回登录态(token/jwtToken)。 退出登录页面增加解绑操作(服务端解除openId与手机号的绑定),此时用户再次点击报名,就会弹出手机号授权,方便用户切换手机号。 [视频]
2023-07-27 - 微信:小程序获取手机号要开始收费了!
[图片] 收费说明 自2023年8月26日起,手机号实时验证组件将需要[代码]付费使用[代码]。 [图片] 手机号快速验证组件 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html 新版本组件不再需要提前调用wx.login进行登录。 代码示例 [代码]<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button> Page({ getPhoneNumber (e) { console.log(e.detail.code) } }) [代码] 返回参数说明 code,动态令牌。可通过动态令牌换取用户手机号。使用方法详情phonenumber.getPhoneNumber接口。 请注意: 目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体); 该能力使用时,用户可选择绑定号码,或自主添加号码。平台会基于中国三大运营商提供的短信等底层能力对号码进行验证,但不保证是实时验证; 请开发者根据业务场景需要自行判断并选择是否使用,必要时可考虑增加其他安全验证手段。 开发者需合理使用,若被发现或用户举报开发者不合理地要求用户提供手机号等个人信息,中断了正常的使用流程,影响了用户的使用体验,微信有权依据《微信小程序平台运营管理规范》对该小程序进行处理。常见违规事例和具体解析; 自2023年8月26日起,手机号快速验证组件将需要付费使用。标准单价为:每次组件调用成功,收费0.03元。 手机号快速验证组件(旧版):https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/deprecatedGetPhoneNumber.html 注意 目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。 该能力使用时,用户可选择绑定号码,或自主添加号码。平台会对号码进行验证,但不保证是实时验证; 请开发者根据业务场景需要自行判断并选择是否使用,必要时可考虑增加其他安全验证手段。 手机号实时验证组件 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getRealtimePhoneNumber.html 代码示例 [代码]<button open-type="getRealtimePhoneNumber" bindgetphonenumber="bindgetrealtimephonenumber"></button> Page({ getRealtimePhoneNumber (e) { console.log(e.detail.code) } }) [代码] 该能力与手机号快速验证组件的区别为: 手机号实时验证组件,在每次请求时,平台均会对用户选择的手机号进行实时验证; 手机号快速验证组件,平台会对号码进行验证,但不保证是实时验证。 请注意: 3. 目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体); 4. 该能力使用时,用户可选择绑定号码,或自主添加号码。每次请求时,平台均会基于中国三大运营商提供的短信等底层能力对号码进行实时验证; 5. 请开发者根据业务场景需要自行判断并选择是否使用,必要时可考虑增加其他安全验证手段。 6. 开发者需合理使用,若用户举报或被发现开发者不合理地要求用户提供手机号等个人信息,中断了正常的使用流程,影响了用户的使用体验,微信有权依据《微信小程序平台运营管理规范》对该小程序进行处理。常见违规事例和具体解析; 7. 该能力的bindgetrealtimephonenumber 事件回调中,仅会返回 code,不会返回 encryptedData,开发者仅可通过消费 code的方式换取用户手机号; 自2023年8月26日起,手机号实时验证组件将需要付费使用。标准单价为:每次组件调用成功,收费0.04元。 付费管理 https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/paymentManage.html 修改建议 手机号快速验证组件旧版本接口依然可以使用,只是需要收费而已,不想做改动的交钱就行了。如果想用新接口就去改吧,多花一分钱(增强小程序安全性)。
2023-06-30 - 小程序用户头像昵称获取规则调整公告
更新时间:2022年11月9日由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称。 更新时间:2022年9月28日考虑到近期开发者对小程序用户头像昵称获取规则调整的相关反馈,平台将接口回收的截止时间由2022年10月25日延期至2022年11月8日24时。 调整背景在小程序内,开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录,支持开发者在多个小程序或其它应用间匿名关联同一用户。 同时,为了满足部分小程序业务中需要创建用户的昵称与头像的诉求,平台提供了 wx.getUserProfile 接口,支持在用户授权的前提下,快速使用自己的微信昵称头像。 但实践中发现有部分小程序,在用户刚打开小程序时就要求收集用户的微信昵称头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能。在已经获取用户的 openId 与 unionId 信息情况下,用户的微信昵称与头像并不是用户使用小程序的必要条件。为减少此类不合理的强迫授权情况,作出如下调整。 调整说明自 2022 年 10 月 25 日 24 时后(以下统称 “生效期” ),用户头像昵称获取规则将进行如下调整: 自生效期起,小程序 wx.getUserProfile 接口将被收回:生效期后发布的小程序新版本,通过 wx.getUserProfile 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。自生效期起,插件通过 wx.getUserInfo 接口获取用户昵称头像将被收回:生效期后发布的插件新版本,通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的插件版本不受影响,但如果要进行版本更新则需要进行适配。通过 wx.login 与 wx.getUserInfo 接口获取 openId、unionId 能力不受影响。「头像昵称填写能力」支持获取用户头像昵称:如业务需获取用户头像昵称,可以使用「头像昵称填写能力」(基础库 2.21.2 版本开始支持,覆盖iOS与安卓微信 8.0.16 以上版本),具体实践可见下方《最佳实践》。小程序 wx.getUserProfile 与插件 wx.getUserInfo 接口兼容基础库 2.27.1 以下版本的头像昵称获取需求:对于来自低版本的基础库与微信客户端的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称,开发者可继续使用以上能力做向下兼容。对于上述 3,wx.getUserProfile 接口、wx.getUserInfo 接口、头像昵称填写能力的基础库版本支持能力详细对比见下表: [图片] *针对低版本基础库,兼容处理可参考 兼容文档 请已使用 wx.getUserProfile 接口的小程序开发者和已使用 wx.getUserInfo 接口的插件开发者尽快适配。小游戏不受本次调整影响。 最佳实践小程序可在个人中心或设置等页面使用头像昵称填写能力让用户完善个人资料: [图片] 微信团队 2022年5月9日
2023-09-26 - UserInfo.avatarUrl 字段是被删除了吗?
小程序点击登录无反应,经过查找sourceMap和日志发现报错如下:Cannot read properties of undefined (reading \'avatarUrl\')。 使用的是原来老的获取方式:open-type="getUserInfo" 此小程序已经两年没有更新过。所以比较奇怪是哪里出的问题。
2023-07-10 - 小程序登录、用户信息相关接口调整说明
公告更新时间:2021年04月15日考虑到近期开发者对小程序登录、用户信息相关接口调整的相关反馈,为优化开发者调整接口的体验,回收wx.getUserInfo接口可获取用户授权的个人信息能力的截止时间由2021年4月13日调整至2021年4月28日24时。为优化用户的使用体验,平台将进行以下调整: 2021年2月23日起,若小程序已在微信开放平台进行绑定,则通过wx.login接口获取的登录凭证可直接换取unionID2021年4月28日24时后发布的小程序新版本,无法通过wx.getUserInfo与<button open-type="getUserInfo"/>获取用户个人信息(头像、昵称、性别与地区),将直接获取匿名数据(包括userInfo与encryptedData中的用户个人信息),获取加密后的openID与unionID数据的能力不做调整。此前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。新增getUserProfile接口(基础库2.10.4版本开始支持),可获取用户头像、昵称、性别及地区信息,开发者每次通过该接口获取用户个人信息均需用户确认。具体接口文档:《getUserProfile接口文档》由于getUserProfile接口从2.10.4版本基础库开始支持(覆盖微信7.0.9以上版本),考虑到开发者在低版本中有获取用户头像昵称的诉求,对于未支持getUserProfile的情况下,开发者可继续使用getUserInfo能力。开发者可参考getUserProfile接口文档中的示例代码进行适配。请使用了wx.getUserInfo接口或<button open-type="getUserInfo"/>的开发者尽快适配。开发者工具1.05.2103022版本开始支持getUserProfile接口调试,开发者可下载该版本进行改造。 小游戏不受本次调整影响。 一、调整背景很多开发者在打开小程序时就通过组件方式唤起getUserInfo弹窗,如果用户点击拒绝,无法使用小程序,这种做法打断了用户正常使用小程序的流程,同时也不利于小程序获取新用户。 二、调整说明通过wx.login接口获取的登录凭证可直接换取unionID 若小程序已在微信开放平台进行绑定,原wx.login接口获取的登录凭证若需换取unionID需满足以下条件: 如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用2月23日后,开发者调用wx.login获取的登录凭证可以直接换取unionID,无需满足以上条件。 回收wx.getUserInfo接口可获取用户个人信息能力 4月28日24时后发布的新版本小程序,开发者调用wx.getUserInfo或<button open-type="getUserInfo"/>将不再弹出弹窗,直接返回匿名的用户个人信息,获取加密后的openID、unionID数据的能力不做调整。 具体变化如下表: [图片] 即wx.getUserInfo接口的返回参数不变,但开发者获取的userInfo为匿名信息。 [图片] 此外,针对scope.userInfo将做如下调整: 若开发者调用wx.authorize接口请求scope.userInfo授权,用户侧不会触发授权弹框,直接返回授权成功若开发者调用wx.getSetting接口请求用户的授权状态,会直接读取到scope.userInfo为true新增getUserProfile接口 若开发者需要获取用户的个人信息(头像、昵称、性别与地区),可以通过wx.getUserProfile接口进行获取,该接口从基础库2.10.4版本开始支持,该接口只返回用户个人信息,不包含用户身份标识符。该接口中desc属性(声明获取用户个人信息后的用途)后续会展示在弹窗中,请开发者谨慎填写。开发者每次通过该接口获取用户个人信息均需用户确认,请开发者妥善保管用户快速填写的头像昵称,避免重复弹窗。 插件用户信息功能页 插件申请获取用户头像昵称与用户身份标识符仍保留功能页的形式,不作调整。用户在用户信息功能页中授权之后,插件就可以直接调用 wx.login 和 wx.getUserInfo 。 三、最佳实践调整后,开发者如需获取用户身份标识符只需要调用wx.login接口即可。 开发者若需要在界面中展示用户的头像昵称信息,可以通过<open-data>组件进行渲染,该组件无需用户确认,可以在界面中直接展示。 在部分场景(如社交类小程序)中,开发者需要在获取用户的头像昵称信息,可调用wx.getUserProfile接口,开发者每次通过该接口均需用户确认,请开发者妥善处理调用接口的时机,避免过度弹出弹窗骚扰用户。 微信团队 2021年4月15日
2021-04-15 - 云开发入门
重磅打造的小程序学习路径课,从微信小程序到微信云开发体系化的学习,带来更加顺畅的学习体验。
2021-11-19 - 【新手必看】微信支付V2之傻瓜式1秒接入
微信支付之前也对接过几次,因为时隔久远,每次对接都要挠头一番,可怜了发际线了,我的宝你在哪里,你再不来我头发掉光了😭 这次决定记录下来,以后对接方便新人也方便自己,说真,其实我是看上官方的拉杆箱了🥰 欲练神功,必先挠头,快快乐乐吃西瓜,清清凉凉一夏天👻 如果你是第一次对接支付: 1.你得申请一个服务号,并通过微信认证 2.获取参数看图:往下看 ⬇️ 3.注册微信商户平台并配置API密钥 [图片] [图片] 第一式:随便起个文件名,最好要有特色 //命名为:wwxpay-mini.php 扔到你的微信支付授权目录,就这一个文件已经实现了jsapi支付,无需下载其他sdk 第二式:调试工具 微信公众平台支付接口调试工具:https://pay.weixin.qq.com/wiki/tools/signverify/ (调试错误的时候可以用得上,新手暂时略过) 第三式:上代码 操作方法:将此文件备注位置-【商户参数】/【订单信息】两处的参数,改为你自己的即可,其中订单参数可以为动态获取,如果你只有一个商品那就写死吧 <?php /*下单参数: 公众账号ID 字段: appid 商户号 字段: mch_id 随机字符串 字段: nonce_str 签名 字段: sign 签名类型 字段: sign_type "MD5" 商品描述 字段: body 商户订单号 字段: out_trade_no 标价金额 字段: total_fee 终端IP 字段: spbill_create_ip 通知地址 字段: notify_url 交易类型 字段: trade_type "JSAPI" 转化为以下格式: <xml> <appid>wx2421b1c4370ec43b</appid> <attach>支付测试</attach> <body>JSAPI支付测试</body> <mch_id>10000100</mch_id> <detail><![CDATA[{ "goods_detail":[ { "goods_id":"iphone6s_16G", "wxpay_goods_id":"1001", "goods_name":"iPhone6s 16G", "quantity":1, "price":528800, "goods_category":"123456", "body":"苹果手机" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"苹果手机" } ] }]]></detail> <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str> <notify_url>https://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url> <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid> <out_trade_no>1415659990</out_trade_no> <spbill_create_ip>14.23.150.211</spbill_create_ip> <total_fee>1</total_fee> <trade_type>JSAPI</trade_type> <sign>0CB01533B8C1EF103065174F50BCA001</sign> </xml> 返回值: 返回状态码 字段: return_code 返回值: SUCCESS/FAIL 返回信息 字段: return_msg 返回值: OK 成功的话,在return_code为SUCCESS的时候有返回: 公众账号ID 字段: appid 商户号 字段: mch_id 签名 字段: sign 业务结果 字段: result_code 错误代码 字段: err_code 返回值: SUCCESS/FAIL(错误的时候返回) 错误码解析: INVALID_REQUEST 参数错误 参数格式有误或者未按规则上传 订单重入时,要求参数值与原请求一致,请确认参数问题 NOAUTH 商户无此接口权限 商户未开通此接口权限 请商户前往申请此接口权限 NOTENOUGH 余额不足 用户账号余额不足 用户账号余额不足,请用户充值或更换支付卡后再支付 ORDERPAID 商户订单已支付 商户订单已支付,无需重复操作 商户订单已支付,无需更多操作 ORDERCLOSED 订单已关闭 当前订单已关闭,无法支付 当前订单已关闭,请重新下单 SYSTEMERROR 系统错误 系统超时 系统异常,请用相同参数重新调用 APPID_NOT_EXIST APPID不存在 参数中缺少APPID 请检查APPID是否正确 MCHID_NOT_EXIST MCHID不存在 参数中缺少MCHID 请检查MCHID是否正确 APPID_MCHID_NOT_MATCH appid和mch_id不匹配 appid和mch_id不匹配 请确认appid和mch_id是否匹配 LACK_PARAMS 缺少参数 缺少必要的请求参数 请检查参数是否齐全 OUT_TRADE_NO_USED 商户订单号重复 同一笔交易不能多次提交 请核实商户订单号是否重复提交 SIGNERROR 签名错误 参数签名结果不正确 请检查签名参数和方法是否都符合签名算法要求 XML_FORMAT_ERROR XML格式错误 XML格式错误 请检查XML参数格式是否正确 REQUIRE_POST_METHOD 请使用post方法 未使用post传递参数 请检查请求参数是否通过post方法提交 POST_DATA_EMPTY post数据为空 post数据不能为空 请检查post数据是否为空 NOT_UTF8 编码格式错误 未使用指定编码格式 请使用UTF-8编码格式 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder */ header('Content-type:text/html; Charset=utf-8');//设置网页编码 ini_set('date.timezone', 'Asia/Shanghai'); //商户参数 $appKey = 'xxxxxxxxxxxxxxxxxx';//公众号的APPKey $config = array( 'mch_id' => 'xxxxxxxxxx',//微信支付平台商户号 'appid' => 'xxxxxxxxxxxxxxx',//公众号平台的APPID 'key' => 'xxxxxxxxxxxxxxxxxxxxxxx' //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥V2-设置API密钥 ); //订单信息 $unified = array( 'appid' => $config['appid'],//公众账号ID 'attach' => '饭团',//附加数据 'body' => "饭团子",//商品描述 'mch_id' => $config['mch_id'],//商户号 'nonce_str' => NoStr(),//随机字符串 'notify_url' => "http://pay.xxxxxx.com/wxpay/api/returns.php",//通知地址 'openid' => GetOpenid($config), 'out_trade_no' => strval(date("YmdH").time()),//商户订单号 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//终端IP 'total_fee' => intval(0.01*100), //微信会自己减去两位数*100补回,标价金额 'trade_type' => 'JSAPI',//交易类型 ); $unified['sign'] = getSign($unified, $config['key']);//获取签名 // echo "<pre>";print_r($unified);echo "</pre>";die; // die(arrayToXml($unified)); $responseXml = curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', arrayToXml($unified));//转换为xml并发送 $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);//解析XML为对象 if ($unifiedOrder === false) { die('parse xml error');//解析错误 } if ($unifiedOrder->return_code != 'SUCCESS') { die($unifiedOrder->return_msg);//返回成功结果 } if ($unifiedOrder->result_code != 'SUCCESS') { die($unifiedOrder->err_code->des);//返回失败结果 } $arr = array( "appId" => $config['appid'],//公众账号ID "timeStamp" => strval(time()),//这里是字符串的时间戳 "nonceStr" => NoStr(),//随机字符串 "package" => "prepay_id=" . $unifiedOrder->prepay_id,//订单详情扩展字符串 "signType" => 'MD5',//声明加密类型 ); $arr['paySign'] = getSign($arr, $config['key']);//获取调起支付的签名 $jsApiParameters=json_encode($arr); ?> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>FT-收银台</title> <script type="text/javascript"> /* JSAPI调起支付 公众号id appId 时间戳 timeStamp 随机字符串 nonceStr String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串,32位。推荐随机数生成算法 订单详情扩展字符串 package String(128) prepay_id=123456789 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=*** 签名方式 signType MD5 签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致 签名 paySign 是 String(64) C380BEC2BFD727A4B6845133519F3AD6 签名,详见签名生成算法:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 */ function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, function(res){ WeixinJSBridge.log(res.err_msg); alert(res.err_code+res.err_desc+res.err_msg); } ); } function callpay() { if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } } </script> </head> <body> <br/> <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">0.01元</span>钱</b></font><br/><br/> <div align="center"> <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >立即支付</button> </div> </body> </html> <?php //所有的函数都在这里了 function GetOpenid(array $config){ //通过code获得openid if (!isset($_GET['code'])){ //触发微信返回code码 $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://'; $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']); $url = __CreateOauthUrlForCode($baseUrl,$config); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = GetOpenidFromMp($code,$config); return $openid; } } function GetOpenidFromMp($code,array $config){ $url = __CreateOauthUrlForOpenid($code,$config); $res = curlGet($url); //取出openid $data = json_decode($res,true); // $this->data = $data; $openid = $data['openid']; return $openid; } function __CreateOauthUrlForOpenid($code,array $config){ $urlObj["appid"] = $config['appid']; $urlObj["secret"] = $GLOBALS['appKey']; $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = toparams2($urlObj); return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } /** * 构造获取code的url连接 * @param string $redirectUrl 微信服务器回跳的url,需要url编码 * @return 返回构造好的url */ function __CreateOauthUrlForCode($redirectUrl,array $config){ $urlObj["appid"] = $config['appid']; $urlObj["redirect_uri"] = "$redirectUrl"; $urlObj["response_type"] = "code"; $urlObj["scope"] = "snsapi_base"; $urlObj["state"] = "STATE"."#wechat_redirect"; $bizString = toparams2($urlObj); return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; } function getSign($params, $key){ //生成签名 ksort($params, SORT_STRING);//把值作为字符串来排序 $unSignParaString = toparams1($params, false); $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));//拼接字符并转换为大写 return $signStr; } 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 toparams1($paraMap, $urlEncode = false){ //签名数组排序并拼接 $buff = ""; ksort($paraMap);//对数组进行排序:ABCDEFG…… foreach ($paraMap as $k => $v) { if (null != $v && "null" != $v) { if ($urlEncode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } } $reqPar = false; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1);//移除多余的& } return $reqPar; } function toparams2($urlObj){ //把数组转成URL参数:appid=123456&sign=xxxxxxxxxxxxxxxxx $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign") $buff .= $k . "=" . $v . "&"; } $buff = trim($buff, "&");//移除多余的& return $buff; } function curlGet($url = '', $options = array()){ //get访问 $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } function curlPost($url = '', $postData = '', $options = array()){ //post访问 if (is_array($postData)) { $postData = http_build_query($postData);//把数组转成URL参数:appid=123456&sign=xxxxxxxxxxxxxxxxx } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL超时为30秒 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } function NoStr($length = 16){ //随机字符串默认16位 $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } ?> 我喜欢面向过程emm,别笑话我🤣 别问为啥这么多备注,因为怕你笨🤣 总结: 1. 申请服务号,注册微信商户平台,获取:Appid Key Api密钥 商户号 2. 创建wxpay-mini.php【名称随意,但是一定放到授权目录】 3.【商户参数】/【订单信息】两处的参数,改为你自己的参数 4.运行支付测试结果 这你还不会的话,来找我,看我怎么揍你🤪 我还没对象,拉杆箱可以不要,官方给我介绍个对象呗,别说给我New一个😭 还没有用过微信云托管的朋友可以看我另一篇教程:https://developers.weixin.qq.com/community/minihome/article/doc/000068648fcae81db5fd0f17e58413 暂时就写这么多,再熬天就要亮了😇
2022-05-27 - 【新手必看】微信云托管PHP+Nginx配置使用教程
注册登录就不用讲了,自行领悟 官方提供的一键部署并不怎么实用,我把demo部署上去有什么用,又不能修改,干瞪眼🤣 因为没用过Docker之后查了又查,并没有关于PHP的部署,全是Python Nodejs Java的教程,是PHP不香了吗🥵 第一步创建实例,我们需要先了解下管官方要的Dockerfile文件的写法: Dockerfile ,也别了解了直接复制就行😂 # 不建议更换alpine3.13之后会有问题,什么问题我也不知道,不要动就对了 FROM alpine:3.13 # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 #RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 设置国内镜像源并安装PHP+Nginx+Zip RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache \ php7 \ php7-json \ php7-ctype \ php7-exif \ php7-pdo \ php7-pdo_mysql \ php7-fpm \ php7-curl \ nginx \ zip \ && rm -f /var/cache/apk/* # 设置网站目录,这个名字你喜欢就好 WORKDIR /app # 将当前目录下所有文件拷贝到/app (.dockerignore中文件除外) COPY . /app # 替换nginx、fpm、php配置并赋予777权限,不赋予权限修改或写日志有问题,配置文件放到本地根目录conf目录下 RUN cp /app/conf/nginx.conf /etc/nginx/conf.d/default.conf \ && cp /app/conf/fpm.conf /etc/php7/php-fpm.d/www.conf \ && cp /app/conf/php.ini /etc/php7/php.ini \ && mkdir -p /run/nginx \ && chmod -R 777 /app \ && chmod -R 777 /etc \ && mv /usr/sbin/php-fpm7 /usr/sbin/php-fpm # 暴露端口 # 此处端口必须与「服务设置」-「流水线」以及「手动上传代码包」部署时填写的端口一致,否则会部署失败。 EXPOSE 80 # 执行启动命令. # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["sh", "run.sh"] run.sh 直接复制,不要改,不要改,不要改 #!/bin/sh # 后台启动 php-fpm -D # 关闭后台启动,hold住进程 nginx -g 'daemon off;' 有了这俩万能配置文件,你只需要: 放到你的项目 ➡️ 根目录 ➡️ 打包Zip压缩包 ➡️ 微信云托管登录 ➡️ 创建实例 ➡️ 手动上传代码 ➡️ 选定压缩包 ➡️ 提交部署 ➡️ 等待项目启动 如果想要在线编辑,创建目录:manager,然后下载它:https://github.com/657258535/Great-Linux-Manager ,把它扔到manager目录就可以在线编辑了,不过只能用于测试,正式版请通过发布部署完成 如果实例会自动停止,解决办法看图: [图片] 其他的问题暂时没遇到,至此记录结束🇨🇳
2022-05-24 - 【特约商进件】请按最新的接口文档要求进件,怎么解?
之前做了一个特约商进件的功能,原来是没问题的; 现在突然,告诉我,有问题。 {"code":"PARAM_ERROR","message":"请按最新的接口文档要求进件"} 这个怎么解,有遇到这个问题的朋友么,给点思路! 特约商户进件,提交申请单 请求URL:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/ End === update at 2022.07.08 === 文档更新日志 , 可以看这个更新日志,了解最新的改动! 1、超级管理员,contact_info 增加 contact_type 字段,【必填】 2、若主体类型是个体户(非企业),不要传递 subject_info/identity_info/owner 字段 3、最终受益人现在改为 Array , ubo_info_list [图片] End
2022-07-08 - 小程序搜索优化指南(SEO)
2019年上半年微信发布了基于小程序页面的搜索,为了让我们更好地发现及理解小程序的页面,结合过去一段时间来我们遇到的各种情况,我们强烈建议各位开发者花一些宝贵的时间认真阅读本文:) 爬虫访问小程序内页面时,会携带特定的 user-agent "mpcrawler" 及场景值:1129 1. 小程序里跳转的页面 (url) 可被直接打开。 小程序页面内的跳转url是我们爬虫发现页面的重要来源,且搜索引擎召回的结果页面 (url) 是必须能直接打开,不依赖上下文状态的。特别的:建议页面所需的参数都包含在url 2. 页面跳转优先采用navigator组件。 小程序提供了两种页面路由方式: a.navigator 组件 b. 路由 API,包括 navigateTo / redirectTo / switchTab / navigateBack / reLaunch 建议使用 navigator 组件,若不得不使用API,可在爬虫访问时屏蔽针对点击设置的时间锁或变量锁。 3.清晰简洁的页面参数。 结构清晰、简洁、参数有含义的 querystring 对抓取以及后续的分析都有很大帮助,但是将 JSON 数据作为参数的方式是比较糟糕的实现。 4. 必要的时候才请求用户进行授权、登录、绑定手机号等。 建议在必须的时候才要求用户授权(比如阅读文章可以匿名,而发表评论需要留名)。 5. 我们不收录 web-view 中的任何内容。 我们暂时做不到这一点,长期来看,我们可能也做不到。 6. 利用 sitemap 配置引导爬虫抓取,同时屏蔽无搜索价值的路径。 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html 7. 设置一个清晰的标题和页面缩略图。 页面标题和缩略图对于我们理解页面和提高曝光转化有重要的作用。 通过wx.setNavigationBarTitle或 自定义转发内容onShareAppMessage对页面的标题和缩略图设置,另外也为 video、audio 组件补齐 poster /poster-for-crawler属性。 8. 使用页面路径推送能力 可极大丰富微信可以收录的内容,进而提高小程序内容的曝光机会。请参考: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/search/search.submitPages.html
2020-01-14