WeChat支払い関連
20494 ワード
Androidアプリケーション統合微信決済商戸応用アクセス微信支払い申請、略、具体的には公式サイトの手順を参照してください(https://open.weixin.qq.com/cgi-bin/frame?t=resource/res_main_tmpl&verify=1&lang=zh_CNモバイルアプリケーション開発->微信支払い機能->微信APP支払いアクセス業者サービスセンター、中には1が含まれている.申請プロセスガイド2.開放類目及び料金基準3.一般的なビジネスアクセスの問題) シーン紹介 ユーザーがモバイル端末アプリに微信決済機能を統合するのに適しています.
商戸APPは微信が提供するSDKを呼び出して微信支払いモジュールを呼び出し、商戸APPは微信にジャンプして支払いを完了する.
支払いが終わったら、商家アプリに戻り、最後に支払い結果を表示します.
インタラクションの詳細は次のとおりです.
手順1:ユーザーは商家アプリに入り、商品の注文を選択し、購入を確認し、支払いの一環に入る.取引先サービスバックグラウンドは支払い注文を生成し、署名した後、データをAPP側に転送する.
ステップ2:ユーザーがクリックした後に支払い操作を開始して、微信のインタフェースに入って、微信の支払いを調整して、支払いを確認するインタフェースが現れます
手順3:ユーザーは受取人と金額を確認して、クリックして直ちに支払った後にパスワードのインターフェースを入力して現れて、小銭あるいは銀行カードの支払いを選択することができます
手順4:正しいパスワードを入力した後、支払いが完了し、ユーザー側の微信に支払い詳細ページが表示される
手順5:商戸APPに戻り、商戸APPは支払い結果に基づいて注文処理結果を個性的に展示するソースマップhttp://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=8_3 Android開発要点説明
小結支付宝のapiと比較すると、微信支付のこのバージョンのdemoは粗すぎて、例えば:関連定数の定義が集中していない;apiは簡単ではありません.まずaccessTokenを取得してprePayIdを取得して完全に1つのapiを閉じることができて、それからユーザーは1山の必要なパラメータを入力してapiの内部で判断組織をフィルタして、まだこんなに多くのapiのurlを露出する必要はありません.(後記:上記の総業務フローと併せて見ると、このdemoはまるで開発者を誤導しているようだ.総業務はaccess_tokenの取得がなく、prepayIdの取得は業者のバックグラウンドにあるが、androidのdemoにはaccess_tokenの取得手順があり、APP_SECRETも用いられており、prepayIdの取得もクライアントに置かれている.コードでは重要情報hard codeをコードに渡すことができないことを強調する一方で、これらの重要情報についてはあちこちで... 支払い過程の3部は1.アクセス権を取得します.2.prePayIdを取得する;3.支払いを開始する.(後述のように、1と2をサーバ側で処理することを提案し、クライアントは必要なパラメータを提供する) は支付宝と同じように先に登録しなければならない.詳しくは、上記の商戸応用アクセス微信支付申請 を参照してください.構築バックグラウンド モバイルクライアント を構築する.プロセス全体で使用する情報
後記上記のパラメータのソース不明の問題に対して、googleの後に一時的な答えを見つけました.結局、バージョンは 更新されています.同時に私の小結の中の第1点のネットユーザーに対しても既成の提案あるいは方案があります(微信demoは最初からこのように書くと人に回り道をさせません)
リファレンスリンク推奨http://fangjie.info/?p=393 微信オープンプラットフォームリソースセンターhttps://open.weixin.qq.com/cgi-bin/frame?t=resource/res_main_tmpl&verify=1&lang=zh_CN ビジネスプラットフォームドキュメントhttp://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=8_1 http://blog.csdn.net/janice0529/article/details/38051987
商戸APPは微信が提供するSDKを呼び出して微信支払いモジュールを呼び出し、商戸APPは微信にジャンプして支払いを完了する.
支払いが終わったら、商家アプリに戻り、最後に支払い結果を表示します.
インタラクションの詳細は次のとおりです.
手順1:ユーザーは商家アプリに入り、商品の注文を選択し、購入を確認し、支払いの一環に入る.取引先サービスバックグラウンドは支払い注文を生成し、署名した後、データをAPP側に転送する.
ステップ2:ユーザーがクリックした後に支払い操作を開始して、微信のインタフェースに入って、微信の支払いを調整して、支払いを確認するインタフェースが現れます
手順3:ユーザーは受取人と金額を確認して、クリックして直ちに支払った後にパスワードのインターフェースを入力して現れて、小銭あるいは銀行カードの支払いを選択することができます
手順4:正しいパスワードを入力した後、支払いが完了し、ユーザー側の微信に支払い詳細ページが表示される
手順5:商戸APPに戻り、商戸APPは支払い結果に基づいて注文処理結果を個性的に展示する
1) , APP APPID。 , , 。 【 】 【 / / 】 。 : APP AndroidManifest.xml package , DEMO package="net.sourceforge.simcpux"。 : keystore, 32 md5 , , 。 https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk 2) APPID APP JAR , API , APPID, : API , APP, : final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null); // app msgApi.registerApp("wxd930ea5d5a258f4f"); 3) , API( 7 ) , prepay_id APP 。 : IWXAPI api; PayReq request = new PayReq(); request. appId = "wxd930ea5d5a258f4f"; request. partnerId = "1900000109"; request.prepayId= "1101000000140415649af9fc314aa427",; request. packageValue = "prepay_id=1101000000140415649af9fc314aa427"; request.nonceStr= "1101000000140429eb40476f8896f4c9"; request.timeStamp= "1398746574"; request.sign= "7ffecb600d7157c5aa49810d2d8f28bc2811827b"; api.sendReq(req); 4) SDK Sample, WXPayEntryActivity onResp , , APP APP onResp , , , 。 , API
示例代码解读
-> ->android https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/Android2_SDK221cbf.zip
【 APP 】Sample_For_Android //demo,
【 APP 】SDK_For_Android //jar api
【 APP 】 demo //
【 】 demo //
【 APP 】 V1.2_For_Android.pdf //
【 】 .pdf //
- 【微信APP支付】Sample_For_Android, (围绕支付,其他略。 sdk demo里面的功能包含有支付 分享 收藏等)
1. jar, libammsdk.jar
2. AndroidManifest.xml
3.
3.1 activity WXEntryActivity
payBtn = (Button) findViewById(R.id.goto_pay_btn);
payBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// PayActivity finish
startActivity(new Intent(WXEntryActivity.this, PayActivity.class));
finish();
}
});
3.2 PayActivity
public class PayActivity extends Activity {
private static final String TAG = "MicroMsg.SDKSample.PayActivity";
//key api
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay);
// , APP_ID( appId)
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
Button payBtn = (Button) findViewById(R.id.pay_btn);
payBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//1. access token
new GetAccessTokenTask().execute();
}
});
Button checkPayBtn = (Button) findViewById(R.id.check_pay_btn);
checkPayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//
boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
Toast.makeText(PayActivity.this, String.valueOf(isPaySupported), Toast.LENGTH_SHORT).show();
}
});
}
/**
*
*
* : hardcode , genPackage
*/
private static final String PARTNER_KEY = "8934e7d15453e97507ef794cf7b0519d";
private String genPackage(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(PARTNER_KEY); // : hardcode , genPackage
// md5 ,params , url encode
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
return URLEncodedUtils.format(params, "utf-8") + "&sign=" + packageSign;
}
/**
*
*
* : hardcode , genSign
*/
private static final String APP_SECRET = "db426a9829e4b49a0dcac7b4162da6b6"; // wxd930ea5d5a258f4f
/**
*
*
* : hardcode , genSign
*/
private static final String APP_KEY = "L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K"; // wxd930ea5d5a258f4f
private class GetAccessTokenTask extends AsyncTask<Void, Void, GetAccessTokenResult> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
//
dialog = ProgressDialog.show(PayActivity.this, getString(R.string.app_tip), getString(R.string.getting_access_token));
}
@Override
protected void onPostExecute(GetAccessTokenResult result) {
if (dialog != null) {
dialog.dismiss();
}
if (result.localRetCode == LocalRetCode.ERR_OK) {
Toast.makeText(PayActivity.this, R.string.get_access_token_succ, Toast.LENGTH_LONG).show();
Log.d(TAG, "onPostExecute, accessToken = " + result.accessToken);
//3. access token , prePayId
GetPrepayIdTask getPrepayId = new GetPrepayIdTask(result.accessToken);
getPrepayId.execute();
} else {
Toast.makeText(PayActivity.this, getString(R.string.get_access_token_fail, result.localRetCode.name()), Toast.LENGTH_LONG).show();
}
}
@Override
protected GetAccessTokenResult doInBackground(Void... params) {
GetAccessTokenResult result = new GetAccessTokenResult();
//2.http get access token
String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
Constants.APP_ID, APP_SECRET);
Log.d(TAG, "get access token, url = " + url);
byte[] buf = Util.httpGet(url);
if (buf == null || buf.length == 0) {
result.localRetCode = LocalRetCode.ERR_HTTP;
return result;
}
String content = new String(buf);
result.parseFrom(content);
return result;
}
}
private class GetPrepayIdTask extends AsyncTask<Void, Void, GetPrepayIdResult> {
private ProgressDialog dialog;
private String accessToken;
public GetPrepayIdTask(String accessToken) {
this.accessToken = accessToken;
}
@Override
protected void onPreExecute() {
// prepay id
dialog = ProgressDialog.show(PayActivity.this, getString(R.string.app_tip), getString(R.string.getting_prepayid));
}
@Override
protected void onPostExecute(GetPrepayIdResult result) {
if (dialog != null) {
dialog.dismiss();
}
if (result.localRetCode == LocalRetCode.ERR_OK) {
Toast.makeText(PayActivity.this, R.string.get_prepayid_succ, Toast.LENGTH_LONG).show();
//5. prepay id
sendPayReq(result);
} else {
Toast.makeText(PayActivity.this, getString(R.string.get_prepayid_fail, result.localRetCode.name()), Toast.LENGTH_LONG).show();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected GetPrepayIdResult doInBackground(Void... params) {
//4. http post prepay id
String url = String.format("https://api.weixin.qq.com/pay/genprepay?access_token=%s", accessToken);
String entity = genProductArgs();
Log.d(TAG, "doInBackground, url = " + url);
Log.d(TAG, "doInBackground, entity = " + entity);
GetPrepayIdResult result = new GetPrepayIdResult();
byte[] buf = Util.httpPost(url, entity);
if (buf == null || buf.length == 0) {
result.localRetCode = LocalRetCode.ERR_HTTP;
return result;
}
String content = new String(buf);
Log.d(TAG, "doInBackground, content = " + content);
result.parseFrom(content);
return result;
}
}
private static enum LocalRetCode {
ERR_OK, ERR_HTTP, ERR_JSON, ERR_OTHER
}
// ,
private static class GetAccessTokenResult {
private static final String TAG = "MicroMsg.SDKSample.PayActivity.GetAccessTokenResult";
public LocalRetCode localRetCode = LocalRetCode.ERR_OTHER;
public String accessToken;
public int expiresIn;
public int errCode;
public String errMsg;
public void parseFrom(String content) {
if (content == null || content.length() <= 0) {
Log.e(TAG, "parseFrom fail, content is null");
localRetCode = LocalRetCode.ERR_JSON;
return;
}
try {
JSONObject json = new JSONObject(content);
if (json.has("access_token")) { // success case
accessToken = json.getString("access_token");
expiresIn = json.getInt("expires_in");
localRetCode = LocalRetCode.ERR_OK;
} else {
errCode = json.getInt("errcode");
errMsg = json.getString("errmsg");
localRetCode = LocalRetCode.ERR_JSON;
}
} catch (Exception e) {
localRetCode = LocalRetCode.ERR_JSON;
}
}
}
// ,
private static class GetPrepayIdResult {
private static final String TAG = "MicroMsg.SDKSample.PayActivity.GetPrepayIdResult";
public LocalRetCode localRetCode = LocalRetCode.ERR_OTHER;
public String prepayId;
public int errCode;
public String errMsg;
public void parseFrom(String content) {
if (content == null || content.length() <= 0) {
Log.e(TAG, "parseFrom fail, content is null");
localRetCode = LocalRetCode.ERR_JSON;
return;
}
try {
JSONObject json = new JSONObject(content);
if (json.has("prepayid")) { // success case
prepayId = json.getString("prepayid");
localRetCode = LocalRetCode.ERR_OK;
} else {
localRetCode = LocalRetCode.ERR_JSON;
}
errCode = json.getInt("errcode");
errMsg = json.getString("errmsg");
} catch (Exception e) {
localRetCode = LocalRetCode.ERR_JSON;
}
}
}
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
/**
* traceid ,
*/
private String getTraceId() {
return "crestxu_" + genTimeStamp();
}
/**
* : ,32 、 ,
*/
private String genOutTradNo() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
private long timeStamp;
private String nonceStr, packageValue;
private String genSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
int i = 0;
for (; i < params.size() - 1; i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
String sha1 = Util.sha1(sb.toString());
Log.d(TAG, "genSign, sha1 = " + sha1);
return sha1;
}
private String genProductArgs() {
JSONObject json = new JSONObject();
try {
json.put("appid", Constants.APP_ID);
String traceId = getTraceId(); // traceId , , id
json.put("traceid", traceId);
nonceStr = genNonceStr();
json.put("noncestr", nonceStr);
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("bank_type", "WX"));
packageParams.add(new BasicNameValuePair("body", " "));
packageParams.add(new BasicNameValuePair("fee_type", "1"));
packageParams.add(new BasicNameValuePair("input_charset", "UTF-8"));
packageParams.add(new BasicNameValuePair("notify_url", "http://weixin.qq.com"));
packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo()));
packageParams.add(new BasicNameValuePair("partner", "1900000109"));
packageParams.add(new BasicNameValuePair("spbill_create_ip", "196.168.1.1"));
packageParams.add(new BasicNameValuePair("total_fee", "1"));
packageValue = genPackage(packageParams);
json.put("package", packageValue);
timeStamp = genTimeStamp();
json.put("timestamp", timeStamp);
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
signParams.add(new BasicNameValuePair("appkey", APP_KEY));
signParams.add(new BasicNameValuePair("noncestr", nonceStr));
signParams.add(new BasicNameValuePair("package", packageValue));
signParams.add(new BasicNameValuePair("timestamp", String.valueOf(timeStamp)));
signParams.add(new BasicNameValuePair("traceid", traceId));
json.put("app_signature", genSign(signParams));
json.put("sign_method", "sha1");
} catch (Exception e) {
Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
return json.toString();
}
private void sendPayReq(GetPrepayIdResult result) {
PayReq req = new PayReq();
req.appId = Constants.APP_ID;
req.partnerId = Constants.PARTNER_ID;
req.prepayId = result.prepayId;
req.nonceStr = nonceStr;
req.timeStamp = String.valueOf(timeStamp);
req.packageValue = "Sign=" + packageValue;
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", req.appId));
signParams.add(new BasicNameValuePair("appkey", APP_KEY));
signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
signParams.add(new BasicNameValuePair("package", req.packageValue));
signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
req.sign = genSign(signParams);
// , , IWXMsg.registerApp
api.sendReq(req);
}
}
PayActivity , 1. accessTonken; 2. prePayId; 3. ; 4.
小結
PARTNER_ID,
: demo sendPayReq
: ,
PARTNER_KEY,
: demo genPackage 。
hardcode
:
APP_KEY,
: demo prepayID , genProductArgs() + sendPayReq 。
hardcode
:
APP_SECRET,
: demo GetAccessTokenTask doInBackground 。
hardcode
:http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=3_1
AppSecret APPID , access_token 。
, OAuth2.0 openid, openid 。
AppSecret( )。
APP_ID,
: : IWXAPI, accessToken, prepayID,sendPayReq
:http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=3_1
appid APP , APP ,
appid, 。 。
後記
(open.weixin.qq.com) , :
public static final String APP_ID = “wxd930ea5d5a258f4f”;
private static final String APP_SECRET = “db426a9829e4b49a0dcac7b4162da6b6″;
, , , ,
private static final String APP_KEY(PaySignKey) = “L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K”; // wxd930ea5d5a258f4f
, , :
public static final String PARTNER_ID = “1900000109″;
private static final String PARTNER_KEY = “8934e7d15453e97507ef794cf7b0519d”;
, ,
,
, 。
リファレンスリンク