I used wechat payment in a project I just finished. From access to wechat Payment to the encapsulation of tool classes, I have made an accumulation in this paper for convenient use in the future.

1. Start the preparation for wechat Pay

First of all, you need to go to the wechat open platform to register an account, here to make fun of, do not know the wechat platform account password verification mechanism, forget the previous password, log in again, all kinds of password retrieval is not good, really have no solution, go to register a Gmail😑, after logging in successfully, you can see the following interface.

Click the create Mobile Application in the upper right corner and fill in the necessary information step by step. There is no superfluous description here. Note that the Bundle ID entered here needs to correspond to the project

The document

pod 'WechatOpenSDK'
Copy the code

In Xcode, select your project Settings, select TARGETS, and add “URL Scheme” as the ID of your registered application under “URL Type” under “Info” TAB (as shown below).

Appid (unique identification code generated by wechat Open Platform for application), merchant ID and merchant secretKey can be obtained after completion. For the APP end, only appID is used. The merchant ID is best obtained from the server through the interface. The secretKey of the merchant is used to sign, and generally only the server can use it.

2. Payment process

This flowchart may be very complicated at the beginning, so the process of our comparison is summarized as follows:

  1. The APP client sends a payment request to the server
  2. After receiving the request from the client, the server invokes the unified order API to the wechat background to obtain the pre-paid order information
  3. The server generates signed client payment information to the app
  4. The APP client user confirms payment, and the APP wakes up the wechat client for payment
  5. After obtaining the payment result, APP queries the final result to the server and displays it
Work on app side:
  • Access the wechat Payment SDK
  • Send a payment request to the server
  • The payment message wakes up the wechat app and the payment is made
  • Confirm the payment result to the server after receiving wechat Pay callback
  • Display results page according to query results to inform users of payment results
Server-side work:
  • After receiving the payment request from app client, request pre-payment order to wechat background
  • The server signs and returns the information to the APP client
  • Receive the payment results returned by wechat background for app query

The fields returned by the server are described as follows:

  • AppId: Indicates the returned appId
  • PartnerId: the parent id
  • PrepayId: payment id
  • Packages: names of packages (default ‘Sign=WXPay’)
  • NonceStr: Generated random string
  • TimesTamp: the time stamp
  • Signature sign:

3. The iOS end use

In appdelegate. m, import wechat SDK header file wxapi.h

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"Registered and obtained APPID"]; / / appid registrationreturnYES; } // all iOS callbacks are supported - (BOOL)application:(UIApplication *)application openURL:(NSURL *)urlsourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//    [self handleOpenURL:url];
    BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];
    if(! Result) {// Other SDK callbacks such as payment [self handleOpenURL:url]; }return YES;
}
- (void)handleOpenURL:(NSURL*)url {
    if ([url.host isEqualToString:@"pay"[WXApi :url delegate:[WXPayService sharedInstance]]; }}Copy the code

The WXPayService here is a separate class that was written in its own right, following the WXApiManagerDelegate protocol

WXPayService.h
#import <Foundation/Foundation.h>
#import "WXApi.h"@interface WXPayService: NSObject <WXApiDelegate> /// singleton to receive wechat request callback + (instanceType)sharedInstance; + (PayReq *)getPayRequest:(NSDictionary *)prepayData; - (void)onRespCallBack:(void(^)(BaseResp * resp))callback; - (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback; @endCopy the code
WXPayService.m

#import "WXPayService.h"
@interface WXPayService ()
@property (nonatomic,copy) void(^RespCallBack)(BaseResp *);
@end
static WXPayService *sharedInstance;

@implementation WXPayService
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [super allocWithZone:zone];
    });
    returnsharedInstance; + (instanceType)sharedInstance {static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self alloc] init]; });returnsharedInstance; + (PayReq *)getPayRequest:(NSDictionary *)prepayData {ifPayReq *req = [[PayReq alloc] init]; PayReq *req = [PayReq alloc] init];if ([Tools dicContain:prepayData withKey:@"partnerid"]) {
            req.partnerId = prepayData[@"partnerid"];
        }
        if ([Tools dicContain:prepayData withKey:@"prepayid"]) {
            req.prepayId = prepayData[@"prepayid"];
        }
        if ([Tools dicContain:prepayData withKey:@"noncestr"]) {
            req.nonceStr = prepayData[@"noncestr"];
        }
        if ([Tools dicContain:prepayData withKey:@"timestamp"]) {
            req.timeStamp = [prepayData[@"timestamp"] intValue];
        }

        req.package =@"Sign=WXPay";
        req.sign =  @"null"; // The log output NSLog(@"appid=%@/npartid=%@/nprepayid=%@/nnoncestr=%@/ntimestamp=%ld/npackage=%@/nsign=%@",[prepayData objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign);
        return req;
    }
    returnnil; } // handle callback for non-payment requests - (void)onRespCallBack:(void(^)(BaseResp * resp))callback {self. } - (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback { NSAssert(req ! =nil , @"Failed to create wechat payment request");
    self.RespCallBack = callback;
    if([WXApi isWXAppInstalled]) {// -- determine whether tO install wechat app // initiate wechat payment, set parameters [WXApi sendReq:req]; }else{ self.RespCallBack(nil); }}#pragma mark WXApiDelegate
- (void)onResp:(BaseResp *)resp {
    if([resp isKindOfClass:[PayResp class]]) {// -- Check whether the callback is paid self.respcallback (resp); } } @endCopy the code

Import the utility class WXPayService in the ViewController that you want to pay for

4. Attention points and problems

Note:

  • If Scheme is set, the application cannot switch to the wechat client
  • The key value of the payment signature is all lowercase
  • Try setting Packages to default (Sign=WXPay) if the payment display validation signature fails

Question:

If the system version is greater than or equal to iOS9, after activating the wechat client, you can directly click the button on the left of the status bar to return. At this time, the callback method is not used.

Solution: the AppDelegate. M applicationWillEnterForeground method, called check payment results interface and then refresh the page, of course. The bool variable needs to be set as a flag, otherwise the application will be queried every time it comes to the foreground, which is not in line with business requirements.

After entering the wechat payment page, do not do any operation, switch to your application, exit the current payment page, and then enter the wechat client and click Pay or cancel. At this time, your application will crash and blink back

Cause: The page has been destroyed after exiting the stack, but the wX callback still calls the proxy method in the page, there will be a wild pointer. Solution: Add it to the viewWillDisappear method on the page

[WXPayService sharedManager].delegate = nil;
Copy the code

5. Conclusion

It is recommended to negotiate with the server to make a second signature to ensure the security of payment. Ps: If there is any wrong place, welcome to criticize and correct, more articles please click here

If you need to, please follow JackerooChu for more articles