English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

nodejs 微信公众账号 개발

odeJs를 사용하여 微信 공식 계정 기능을 개발했습니다. 모바일 단에서 H5페이지에서 微信 결제 기능을 호출합니다. 최근 몇 일 동안 회사의 필요에 따라 node와 h5페이지에서 微信 결제 기능을 호출하여 결제 요구를 완료합니다. 현재 개발 과정을 다시 정리하여 많은 개발자들이 微信 결제 기능의 개발을 원활하게 완료할 수 있도록 도와줍니다.(微信은 현재 node 결제 기능을 제공하지 않습니다)

1. 코드 요청

request code의 목적은 사용자의 openid(사용자가 현재 공식 계정에 대한 유일한 식별자)과 access_token을 얻는 것입니다. 요청의 API: https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
이 api는 몇 가지 매개변수를 주의해야 합니다:

1. appid는 공식 계정의 appid입니다. 공식 계정에서 확인할 수 있습니다
2. redirect_uri는 사용자 정의된 微信 콜백 주소입니다. 微信는 위의 주소를 요청한 후 사용자 정의된 redirect_uri 주소로 이동합니다. code를 포함하고 있으며, 이处的 redirect_url은 다음과 같아야 합니다 **url_encode** *php*،如果你的程序是 node then you need to use **encodeURLComponent(url)**编码
3. response_type=code로 고정적으로 작성하면 됩니다. 더 이상 설명할 것이 없습니다. 자세한 설명은 微信 공식 웹사이트에서 확인할 수 있습니다
4. scope=snsapi_userinfo로 고정적으로 작성하면 됩니다. 자세한 설명은 微信 공식 웹사이트에서 확인할 수 있습니다
5. state=STATE로 고정적으로 작성하면 됩니다. 자세한 설명은 微信 공식 웹사이트에서 확인할 수 있습니다
6. wechat_redirect로 고정적으로 작성하면 됩니다. 자세한 설명은 微信 공식 웹사이트에서 확인할 수 있습니다
ps: 공식 웹사이트 링크:

2. code를 통해 access_token과 openid 얻기

첫 번째 단계에서 code의 값을 얻었으므로, 다음은 code를 통해 access_token과 openid의 값을 얻어야 합니다. 요청의 api
API https://api.weixin.qq.com/sns/oauth2/access_token#63;appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
이 api의 매개변수 설명은 다음과 같습니다:

1. appid는 微信公众号 id이며, 微信公众号 관리 페이지에서 얻을 수 있습니다.
2. secret은 微信公众号의 키이며, 微信公众号 관리 페이지에서 얻을 수 있습니다.
3. code는 첫 번째 단계에서 사용된 code입니다.
4. grant_type=authorization_code는 고정되어 있습니다.

3. access_token을 통해 인터페이스 호출

access_token을 통해 이후 기능을 호출할 수 있습니다. 공식 예제를 참고하세요:
https://open.weixin.qq.com/cgi-bin/showdocument#63;action=dir_list&t=resource/res_list&verify=1&id=open1419316518&lang=zh_CN

4. 웹 페이지에서 결제 호출 API

이렇게 되면 빨리 끝날 것 같지 않습니까? 웹 페이지에서微信支付 기능을 호출하면 끝납니다? 아니요, 아직 남아 있습니다.
微信浏览器에서 H5웹 페이지에서 JS를 통해 결제를 호출합니다. 인터페이스 입력 출력 데이터 형식은 JSON입니다.
주의: WeixinJSBridge 내장 객체는 다른 브라우저에서는 무효합니다.
아래는 예제 코드입니다:

function onBridgeReady(){
 WeixinJSBridge.invoke(
 'getBrandWCPayRequest', {
  "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入 
  "timeStamp": " 1395712654"  //시간 표시, 자1970년以来的秒数 
  "nonceStr" : "e61463f8efa94090b1f366cccfbbb444" //랜덤 문자열 
  "package" : "prepay_id=u802345jgfjsdfgsdg888" 
  "signType" : "MD5"  //微信簽名 방식: 
  "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 
 },
 function(res){ 
  if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 사용자가 결제 성공한 후에만 res.err_msg에 'ok'이 반환됩니다. 그러나 절대적으로 신뢰할 수 있는 것은 보장되지 않습니다. 
 }
 ); 
}
if (typeof WeixinJSBridge == "undefined"){
 if( document.addEventListener ){
 document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
 }else if (document.attachEvent){
 document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
 document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
 }
}else{
 onBridgeReady();
}

看到上面的代码, 那么想调用微信的支付功能需要传递参数,

{
 "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入 
 "timeStamp": " 1395712654"  //시간 표시, 자1970년以来的秒数 
 "nonceStr" : "e61463f8efa94090b1f366cccfbbb444" //랜덤 문자열 
 "package" : "prepay_id=u802345jgfjsdfgsdg888" 
 "signType" : "MD5"  //微信簽名 방식: 
 "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 
}

参数说明:

1. appId //公众号名称,由商户传入
2. timeStamp //시간 표시, 자1970年以来的秒数  此处需要特别的注意一下,需要是字符串的时间戳格式, 意思就是必须就“” 引号
3. nonceStr //랜덤 문자열    32位的, 随后会提供方法
4. signType // 微信签名方式: MD5
5. paySign //微信签名, 随后说
6. **package**   //这个最重要, 充哪里获取到的呢? 接下来说。
ps: 官网接口说明
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

五.获取package, 从微信的 统一下单 接口获取prepay_id

官方 api:
https://api.mch.weixin.qq.com/pay/unifiedorder

请求参数一堆, 但是有一些不是必须的,下面是必须参数

{
 appid : APPID,
 attach : ATTACH,
 body : BODY,
 mch_id : MCH_ID,
 nonce_str: NONCE_STR,
 notify_url : NOTIFY_URL,// 微信付款后的回调地址
 openid : OPENID,
 out_trade_no : OUT_TRADE_NO ,//new Date().getTime(), //주문 번호
 spbill_create_ip : SPBILL_CREATE_IP , //客户端的 ip
 total_fee : TOTAL_FEE, //商品的价格, 此处需要注意的是这个价格是以分算的, 那么一般是元, 你需要转换为 RMB 的元
 trade_type : 'JSAPI',
}

微信的统一下单接口要求传递的是 xml 的数据, 而且数据还需要签名, 那么首先吧数据签名。
签名规则可以参考微信给出的签名规则(签名方法一会给出)
微信官方签名规则:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3

生成签名后需要吧数据组装为xml 的格式:

var body = '<xml> ' +
 <appid>'+config.wxappid+</appid> ' +
 <attach>'+obj.attach+</attach> ' +
 <body>'+obj.body+</body> ' +
 <mch_id>'+config.mch_id+</mch_id> ' +
 <nonce_str>'+obj.nonce_str+</nonce_str> ' +
 <notify_url>'+obj.notify_url+</notify_url>' +
 <openid>'+obj.openid+</openid> ' +
 <out_trade_no>'+obj.out_trade_no+</out_trade_no>'+
 <spbill_create_ip>'+obj.spbill_create_ip+</spbill_create_ip> ' +
 <total_fee>'+obj.total_fee+</total_fee> ' +
 <trade_type>'+obj.trade_type+</trade_type> ' +
 <sign>'+obj.sign+</sign> ' + // 此处必带签名, 否则微信在验证数据的时候是不通过的
 </xml>';

接下来就是请求 api 获取prepay_id的值了, 将上面得到的 xml 数据请求下面的 api 发送给微信, 微信验证数据没问题后会放回你想要的值。
api : https://api.mch.weixin.qq.com/pay/unifiedorder

六. 获取到了prepay_id是不是就可以在 h5 段直接调用微信的支付了么? 答案是还不可以。

获取到了prepay_id那么现在h5 呼起微信的支付功能的参数是这样的:

{
 "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入 
 "timeStamp": " 1395712654"  //시간 표시, 자1970년以来的秒数 
 "nonceStr" : "e61463f8efa94090b1f366cccfbbb444" //랜덤 문자열 
 "package" : "prepay_id=u802345jgfjsdfgsdg888" 
 "signType" : "MD5"  //微信簽名 방식:
}

有了这样的参数,那么你还需要吧所有参与的参数做签名。签名规跟上面的一样,生成了签名后需要吧签名的参数 paySign 赋给h5 呼起微信的支付功能的参数(也就是微信的签名不参与签名的生成)
最后的参数是这样子的:

{
 "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入 
 "timeStamp": " 1395712654"  //시간 표시, 자1970년以来的秒数 
 "nonceStr" : "e61463f8efa94090b1f366cccfbbb444" //랜덤 문자열 
 "package" : "prepay_id=u802345jgfjsdfgsdg888" 
 "signType" : "MD5"  //微信簽名 방식:
 "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
}

만약 모든 단계가 잘못되지 않았다면, 이 파라미터를 받으면 微信 결제 기능을 정상적으로 호출할 수 있습니다. 원생 기능과는 차이가 없습니다. (당신의 마음이 정말 기쁘다면, 앱이 없이도 앱 기능을 사용할 수 있습니다. 이렇게 신비롭습니다).

7. 결제 완료 리턴

微信 결제가 끝나면 h5 페이지의 微信 결제 리턴 함수에 값을 넣습니다.
res.err_msg == "get_brand_wcpay_request:ok" 이렇게 되면 성공했습니다. 하지만 그게 끝인건 아닙니다. 왜 그런지요? 微信이 실제로 돈을 받았습니까? 받은 돈이 微信에 전달한 값과 일치합니까? 또한, 결제 결과를 데이터베이스에 쓰는 등이 모두 알 수 없습니다. 또한, 단일 주문 인터페이스에서는 notify_url : NOTIFY_URL와 같은 필수 매개변수가 있습니다.// 微信 결제 후의 리턴 주소 이 주소는 사용자가 微信에 전달하는 주소이며, 微信이 사용자의 결제를 받으면 이 인터페이스를 post 방식으로 요청합니다. 微信은 사용자 결제 정보를 전달합니다. 하지만 xml 형식입니다.
이런 xml 형식입니다:

<xml>
 <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
 <attach><![CDATA[支付测试]]></attach>
 <bank_type><![CDATA[CFT]]></bank_type>
 <fee_type><![CDATA[CNY]]></fee_type>
 <is_subscribe><![CDATA[Y]]></is_subscribe>
 <mch_id><![CDATA[10000100]]></mch_id>
 <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
 <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
 <out_trade_no><![CDATA[1409811653]]></out_trade_no>
 <result_code><![CDATA[SUCCESS]]></result_code>
 <return_code><![CDATA[SUCCESS]]></return_code>
 <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
 <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
 <time_end><![CDATA[20140903131540]]></time_end>
 <total_fee>1</total_fee>
 <trade_type><![CDATA[JSAPI]]></trade_type>
 <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>

根据自己的业务逻辑解析这个 xml 格式的数据就好了。
注意:这里你在获取到数据后微信需要得到你的回应, 如果你一直不回应微信, 微信会请求你好几次, 这样估计你的逻辑会有问题吧,所以你需要给微信返回 xml 的格式的 回应。

<xml>
 <return_code><![CDATA[SUCCESS]]></return_code>
 <return_msg><![CDATA[OK]]></return_msg>
</xml>

小坑:node ,express 框架开发, 如果你在微信的支付成功后的回调中没有获取到任何 xml 的值, 那么你需要安装一组件:body-parser-xml, 你可以使用 npm install body-parser-xml --save 安装, 在 app.js 里面require('body-parser-xml')(bodyParser);,使用中间件的方式

// 解决微信支付通知回调数据
app.use(bodyParser.xml({
 limit: '2MB', // Reject payload bigger than 1 MB
 xmlParseOptions: {
 normalize: true, // Trim whitespace inside text nodes
 normalizeTags: true, // Transform tags to lowercase
 explicitArray: false // Only put nodes in array if >1
 }
});

이렇게 하면 위챗의 xml 데이터를 정상적으로 가져올 수 있습니다.

사용 방법:

pay.getAccessToken({
 notify_url : 'http://demo.com/', //위챗 결제가 완료된 후의 콜백
 out_trade_no : new Date().getTime(), //주문 번호
 attach : '이름',
 body : '구매 정보',
 total_fee : '1', // 이곳의 한도는 분입니다
 spbill_create_ip : req.connection.remoteAddress,
 }, function (error, responseData) {
 res.render('payment', {
  title : '위챗 결제',
  wxPayParams : JSON.stringify(responseData),
  //userInfo : userInfo
 });
 });

이제 그쳐도 괜찮습니다. 잘못된 부분이 있다면 지적해 주세요.

저의 코드를 추가합니다:https://git.oschina.net/anziguoer/wechatPay

본문은 《JavaScript 위챗 개발 기술 요약》에 정리되었습니다. 배우고 읽어 주세요.

지금 잘 관심이 많은 위챗小程序 튜토리얼 한편을 추천드립니다:《위챗小程序 개발 튜토리얼》에디터가 정성껏 정리한 것입니다. 좋아해 주시길 바랍니다.

이것이 본문의 전부입니다. 여러분의 학습에 도움이 되길 바라며, 많이 지지해 주시길 바랍니다.

성명서: 본문은 인터넷에서 가져왔으며, 저작권은 원작자에게 있으며, 인터넷 사용자가 자발적으로 기여하고 자체적으로 업로드한 내용으로, 이 사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 문제가 있는 내용을 발견한 경우 notice#w로 이메일을 보내 주시기 바랍니다。3codebox.com(보내는 이메일에서 #을 @으로 변경하시오)를 통해 신고하시고 관련 증거를 제공하시면, 확인된 경우 이 사이트는 즉시 저작권 침해 내용을 삭제할 것입니다。

좋아하는 것